mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 07:08:18 +00:00
enhance contract and booking services with server-side search and validation improvements
- Added parameter to and for server-side free-text search on contract reference, company name, and booking details. - Introduced new validation errors in for container clashes and space issues when creating bookings. - Implemented paginated dropdown settings retrieval in . - Updated to fetch active yards using a new method that handles pagination. - Enhanced with a method to fetch all records by walking through pages. - Refactored to support filtering and pagination in schedule listings. - Improved to return a paginated list of facilities. - Updated UI components in and to utilize debounced search inputs for better performance. - Added alerts in to inform users about booking constraints related to splits and capacity. - Enhanced to display notifications for split bookings and capacity usage.
This commit is contained in:
@@ -605,6 +605,7 @@ export class BookingsRepository extends BaseRepository<Booking> {
|
||||
async findAllPaginated(options: BookingListFilterOptions & {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
search?: string;
|
||||
sortBy?: string;
|
||||
sortOrder?: 'ASC' | 'DESC';
|
||||
}): Promise<{
|
||||
@@ -640,6 +641,16 @@ export class BookingsRepository extends BaseRepository<Booking> {
|
||||
|
||||
this.applyListFilters(qb, options);
|
||||
|
||||
// Free-text search spans joined columns (company, contract) that only this
|
||||
// list query joins — so it lives here, not in applyListFilters (shared
|
||||
// with getListSummaryMetrics, whose query builder has no joins).
|
||||
if (options.search) {
|
||||
qb.andWhere(
|
||||
'(booking.reference ILIKE :search OR company.name ILIKE :search OR contract.reference ILIKE :search)',
|
||||
{ search: `%${options.search}%` },
|
||||
);
|
||||
}
|
||||
|
||||
if (options.sortBy === 'isGovernment') {
|
||||
qb.orderBy('booking.isGovernment', 'DESC')
|
||||
.addOrderBy('booking.priorityScore', 'DESC')
|
||||
|
||||
@@ -1211,6 +1211,7 @@ export class BookingsService {
|
||||
destinationYardId: filter.destinationYardId,
|
||||
isGovernment: filter.isGovernment,
|
||||
consolidationPaired: filter.consolidationPaired,
|
||||
search: filter.search,
|
||||
sortBy: filter.sortBy,
|
||||
sortOrder: filter.sortOrder,
|
||||
});
|
||||
@@ -1262,6 +1263,7 @@ export class BookingsService {
|
||||
// Global Logistics only clears customs bookings; non-customs clearance is
|
||||
// reviewed by Marketing from the booking detail, not this queue.
|
||||
customsClearingEnabled: true,
|
||||
search: filter.search,
|
||||
sortBy: filter.sortBy,
|
||||
sortOrder: filter.sortOrder,
|
||||
});
|
||||
@@ -1286,6 +1288,7 @@ export class BookingsService {
|
||||
// Company-wide: payables span all of the customer's services.
|
||||
companyId: company.id,
|
||||
companyProfileId: filter.companyProfileId,
|
||||
search: filter.search,
|
||||
sortBy: filter.sortBy,
|
||||
sortOrder: filter.sortOrder,
|
||||
});
|
||||
|
||||
@@ -125,6 +125,16 @@ export class FilterBookingDto {
|
||||
@IsOptional()
|
||||
consolidationPaired?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
'Free-text search across booking reference, company name, and contract reference.',
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) =>
|
||||
typeof value === 'string' && value.trim() ? value.trim() : undefined,
|
||||
)
|
||||
search?: string;
|
||||
|
||||
@ApiPropertyOptional({ default: 1 })
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => (value ? parseInt(value, 10) : 1))
|
||||
|
||||
@@ -166,6 +166,24 @@ export class Booking extends BaseEntity {
|
||||
@Column({ name: 'contract_kind', type: 'varchar', length: 20, nullable: true })
|
||||
contractKind?: string | null;
|
||||
|
||||
/**
|
||||
* The customer paid a partial batch offer and this booking was reduced to the
|
||||
* offered part (see BookingSplitService.applySplit). On a ONE_TIME contract a
|
||||
* split booking releases the single-active-booking slot for the remainder —
|
||||
* the contract kind itself is never changed.
|
||||
*/
|
||||
@Column({ name: 'is_split', type: 'boolean', default: false })
|
||||
isSplit!: boolean;
|
||||
|
||||
/**
|
||||
* Quantities this booking carried BEFORE it was reduced by a split — the
|
||||
* split chain's source of truth for the outstanding remainder (ONE_TIME
|
||||
* contracts have no quantity cap to derive it from). Bulk: total tons;
|
||||
* container: units per size. Null until the booking is split.
|
||||
*/
|
||||
@Column({ name: 'pre_split_quantities', type: 'jsonb', nullable: true })
|
||||
preSplitQuantities?: { bulkTons?: number; bySize?: Record<string, number> } | null;
|
||||
|
||||
/** Who created this booking: CUSTOMER (Path A), GL_ET (Path B), or STAFF. */
|
||||
@Column({ name: 'created_by_role', type: 'varchar', length: 20, default: 'CUSTOMER', nullable: true })
|
||||
createdByRole?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user