mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
feat: enhance booking management with shipping line support and cargo handling improvements
This commit is contained in:
@@ -80,6 +80,8 @@ export interface BookingListFilterOptions {
|
||||
originYardId?: string;
|
||||
destinationYardId?: string;
|
||||
isGovernment?: 'true' | 'false';
|
||||
/** Shipping-line bookings vs ordinary customer bookings (exactly one owner is set). */
|
||||
customerKind?: 'SHIPPING_LINE' | 'CUSTOMER';
|
||||
consolidationPaired?: string;
|
||||
}
|
||||
|
||||
@@ -1043,6 +1045,11 @@ export class BookingsRepository extends BaseRepository<Booking> {
|
||||
} else if (options.isGovernment === 'false') {
|
||||
qb.andWhere('booking.is_government = FALSE');
|
||||
}
|
||||
if (options.customerKind === 'SHIPPING_LINE') {
|
||||
qb.andWhere('booking.shipping_line_company_id IS NOT NULL');
|
||||
} else if (options.customerKind === 'CUSTOMER') {
|
||||
qb.andWhere('booking.shipping_line_company_id IS NULL');
|
||||
}
|
||||
if (omit !== 'tradeDirection' && options.tradeDirection) {
|
||||
qb.andWhere('booking.trade_direction = :tradeDirection', {
|
||||
tradeDirection: options.tradeDirection,
|
||||
|
||||
@@ -1766,6 +1766,38 @@ export class BookingsService {
|
||||
pending.has(b.id);
|
||||
}
|
||||
this.attachPaymentDrainEnds(bookings);
|
||||
await this.attachShippingLineCompanies(bookings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batched name lookup for shipping-line-owned bookings (`companyId` null,
|
||||
* `shippingLineCompanyId` set). No relation on the entity — the shipping-line
|
||||
* module sits above bookings — so a raw query keyed off the loaded ids fills
|
||||
* `shippingLineCompany` the way `company` is filled for customers.
|
||||
*/
|
||||
private async attachShippingLineCompanies(bookings: Booking[]): Promise<void> {
|
||||
const ids = [
|
||||
...new Set(
|
||||
bookings
|
||||
.map((b) => b.shippingLineCompanyId)
|
||||
.filter((id): id is string => id != null),
|
||||
),
|
||||
];
|
||||
if (!ids.length) return;
|
||||
const rows: Array<{ id: string; name: string; email: string | null; phoneNumber: string | null }> =
|
||||
await this.dataSource.query(
|
||||
`SELECT id, name, email, phone_number AS "phoneNumber"
|
||||
FROM freight.shipping_line_companies
|
||||
WHERE id = ANY($1::uuid[]) AND deleted_at IS NULL`,
|
||||
[ids],
|
||||
);
|
||||
const byId = new Map(rows.map((r) => [r.id, r]));
|
||||
for (const b of bookings) {
|
||||
const line = b.shippingLineCompanyId ? byId.get(b.shippingLineCompanyId) : undefined;
|
||||
if (line) {
|
||||
(b as Booking & { shippingLineCompany?: typeof line }).shippingLineCompany = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1822,6 +1854,7 @@ export class BookingsService {
|
||||
originYardId: filter.originYardId,
|
||||
destinationYardId: filter.destinationYardId,
|
||||
isGovernment: filter.isGovernment,
|
||||
customerKind: filter.customerKind,
|
||||
consolidationPaired: filter.consolidationPaired,
|
||||
// DTO carries 'true'/'false' strings (query params); the repo option is a
|
||||
// real boolean — convert, preserving "not filtered" when absent.
|
||||
@@ -2048,6 +2081,7 @@ export class BookingsService {
|
||||
originYardId: filter.originYardId,
|
||||
destinationYardId: filter.destinationYardId,
|
||||
isGovernment: filter.isGovernment,
|
||||
customerKind: filter.customerKind,
|
||||
consolidationPaired: filter.consolidationPaired,
|
||||
};
|
||||
|
||||
@@ -2134,6 +2168,8 @@ export class BookingsService {
|
||||
{ path: "booking" },
|
||||
);
|
||||
|
||||
await this.attachShippingLineCompanies([booking]);
|
||||
|
||||
if (booking.files && booking.files.length > 0) {
|
||||
booking.files = await Promise.all(
|
||||
booking.files.map(async (file: FileRecord) => {
|
||||
|
||||
@@ -111,6 +111,14 @@ export class FilterBookingDto {
|
||||
@IsIn(['true', 'false'])
|
||||
isGovernment?: 'true' | 'false';
|
||||
|
||||
@ApiPropertyOptional({
|
||||
enum: ['SHIPPING_LINE', 'CUSTOMER'],
|
||||
description: 'Who booked: a shipping line (owned by shipping_line_company_id) or an ordinary customer company',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(['SHIPPING_LINE', 'CUSTOMER'])
|
||||
customerKind?: 'SHIPPING_LINE' | 'CUSTOMER';
|
||||
|
||||
@ApiPropertyOptional({
|
||||
enum: ['true', 'false'],
|
||||
description: 'Filter customs vs self-clearance (non-customs) bookings',
|
||||
|
||||
Reference in New Issue
Block a user