mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 16:35:42 +00:00
feat: add BookingWagonsPanel component for displaying allocated wagons in booking details
- Implemented BookingWagonsPanel to show allocated wagons, their containers, and export functionality. - Integrated the new panel into BookingRequestDetailPage and BookingRequestsPage. - Enhanced wagon cancellation modal to support rebooking of wagon cancellations with partner units. - Updated API service to include a method for downloading wagons workbook. - Modified types and constants to accommodate new features related to wagons. - Adjusted various components and pages to ensure compatibility with the new wagon-related functionality.
This commit is contained in:
@@ -43,6 +43,9 @@ function makeService(overrides?: {
|
||||
findBookingsWithUnreviewedDocuments: jest
|
||||
.fn()
|
||||
.mockResolvedValue(new Set<string>()),
|
||||
findBookingsWithRedeemableCredit: jest
|
||||
.fn()
|
||||
.mockResolvedValue(new Map<string, string>()),
|
||||
};
|
||||
const bookingsService = {
|
||||
findById: jest.fn().mockResolvedValue(booking),
|
||||
|
||||
@@ -1347,6 +1347,17 @@ export class BookingClearanceService {
|
||||
.hasDocumentsAwaitingReview = pending.has(b.id);
|
||||
}
|
||||
|
||||
// A cancelled booking may still hold a paid-for wagon-cancellation credit.
|
||||
// GL redeems it from this queue, so the row carries the cancellation id the
|
||||
// rebook action needs.
|
||||
const credits = await this.bookingsRepository.findBookingsWithRedeemableCredit(
|
||||
filtered.map((b) => b.id),
|
||||
);
|
||||
for (const b of filtered) {
|
||||
(b as Booking & { rebookableCancellationId?: string | null })
|
||||
.rebookableCancellationId = credits.get(b.id) ?? null;
|
||||
}
|
||||
|
||||
const rows = await this.attachContractSummary(filtered);
|
||||
return this.narrowToYardScope(rows, user);
|
||||
}
|
||||
|
||||
@@ -183,8 +183,8 @@ describe('ContractBookingService — manual odd-20ft consolidation', () => {
|
||||
{ quantity: 4, containerType: { sizeFt: 20 } },
|
||||
],
|
||||
},
|
||||
// A bare instance has no cargo yet — GL enters it on the split form, so it
|
||||
// stays a candidate.
|
||||
// Cargo not entered yet — its 20ft count is unknown, so it cannot be
|
||||
// shown to fill the wagon and is not offered.
|
||||
{ id: 'bare', reference: 'BK-BARE', bookingContainers: [] },
|
||||
];
|
||||
|
||||
@@ -198,7 +198,7 @@ describe('ContractBookingService — manual odd-20ft consolidation', () => {
|
||||
rows.filter((row) => {
|
||||
void booking;
|
||||
const lines = row.bookingContainers ?? [];
|
||||
if (lines.length === 0) return true;
|
||||
if (lines.length === 0) return false;
|
||||
const ft20 = lines
|
||||
.filter((l) => Number(l.containerType?.sizeFt) === 20)
|
||||
.reduce((sum, l) => sum + Number(l.quantity || 0), 0);
|
||||
@@ -209,8 +209,8 @@ describe('ContractBookingService — manual odd-20ft consolidation', () => {
|
||||
});
|
||||
|
||||
const candidates = await service.listConsolidationCandidates('c-1', 'b-1');
|
||||
expect(candidates.map((c) => c.reference)).toEqual(['BK-ODD', 'BK-BARE']);
|
||||
expect(candidates.map((c) => c.reference)).toEqual(['BK-ODD']);
|
||||
expect(candidates[0].ft20Quantity).toBe(3);
|
||||
expect(candidates[1].hasCargo).toBe(false);
|
||||
expect(candidates[0].hasCargo).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user