fix(clearance): flag bookings with documents still awaiting GL approval

This commit is contained in:
Marshal
2026-08-20 07:37:35 +00:00
committed by Hagernesh
parent 21a611f1b7
commit bcf684814d
6 changed files with 82 additions and 7 deletions

View File

@@ -620,6 +620,29 @@ export class BookingsRepository extends BaseRepository<Booking> {
});
}
/**
* Bookings (of those given) that have at least one customer document still
* waiting on GL — PENDING or QUERIED. Includes ad-hoc `custom_*` documents,
* which no milestone tracks, so a file added after clearance was finalized
* still surfaces as needing review. One query for a whole queue page.
*/
async findBookingsWithUnreviewedDocuments(
bookingIds: string[],
): Promise<Set<string>> {
if (bookingIds.length === 0) return new Set();
const rows = (await this.dataSource
.getRepository(BookingDocumentReview)
.createQueryBuilder('r')
.select('DISTINCT r.booking_id', 'bookingId')
.where('r.booking_id IN (:...bookingIds)', { bookingIds })
.andWhere('r.status IN (:...statuses)', {
statuses: ['PENDING', 'QUERIED'],
})
.andWhere('r.deleted_at IS NULL')
.getRawMany()) as Array<{ bookingId: string }>;
return new Set(rows.map((r) => r.bookingId));
}
findDocumentReview(
bookingId: string,
settingCode: string,

View File

@@ -40,6 +40,9 @@ function makeService(overrides?: {
findDocumentReviews: jest.fn().mockResolvedValue([]),
update: jest.fn().mockResolvedValue(booking),
findByStatuses: jest.fn().mockResolvedValue([]),
findBookingsWithUnreviewedDocuments: jest
.fn()
.mockResolvedValue(new Set<string>()),
};
const bookingsService = {
findById: jest.fn().mockResolvedValue(booking),

View File

@@ -1175,6 +1175,19 @@ export class BookingClearanceService {
);
filtered.push(b);
}
// A document added after clearance was finalized lands as PENDING without
// moving the booking's status — the row would otherwise still read
// "Clearance ready" while GL has something waiting. Ad-hoc documents are
// tracked by no milestone, so this reads the review rows directly.
const pending = await this.bookingsRepository.findBookingsWithUnreviewedDocuments(
filtered.map((b) => b.id),
);
for (const b of filtered) {
(b as Booking & { hasDocumentsAwaitingReview?: boolean })
.hasDocumentsAwaitingReview = pending.has(b.id);
}
const rows = await this.attachContractSummary(filtered);
return this.narrowToYardScope(rows, user);
}