mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 08:48:11 +00:00
enhance booking and contract notification systems
- Added detailed logging for socket connection events in useBookingWindowSocket. - Introduced new notification types for contract status and schedule updates. - Updated notification visuals to include new icons for contract status. - Enhanced notification href resolution for contract status and schedule updates. - Implemented booking lifecycle notifier service for customer and staff notifications. - Created contract notifier service for managing contract lifecycle notifications. - Added end-to-end tests for booking window socket functionality.
This commit is contained in:
@@ -78,6 +78,11 @@ describe('SchedulingRescheduleService', () => {
|
||||
bookingsRepository as never,
|
||||
trainSchedulingService as never,
|
||||
schedulingRescheduleRepository as never,
|
||||
{
|
||||
rescheduled: jest.fn(),
|
||||
removedFromTrain: jest.fn(),
|
||||
maintenanceMoved: jest.fn(),
|
||||
} as never, // notifier
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { BookingsRepository } from '../bookings/bookings.repository';
|
||||
import { compareSchedulingPriority } from '../scheduling/compare-scheduling-priority.util';
|
||||
import { TrainSchedulesRepository } from '../train-schedules/train-schedules.repository';
|
||||
import { TrainSchedulingService } from '../train-scheduling/train-scheduling.service';
|
||||
import { BookingNotifierService } from '../train-scheduling/booking-notifier.service';
|
||||
import { ExecuteRescheduleDto, PreviewRescheduleDto } from './dto/preview-reschedule.dto';
|
||||
import { SchedulingRescheduleRepository } from './scheduling-reschedule.repository';
|
||||
|
||||
@@ -38,6 +39,7 @@ export class SchedulingRescheduleService {
|
||||
private readonly bookingsRepository: BookingsRepository,
|
||||
private readonly trainSchedulingService: TrainSchedulingService,
|
||||
private readonly schedulingRescheduleRepository: SchedulingRescheduleRepository,
|
||||
private readonly notifier: BookingNotifierService,
|
||||
) {}
|
||||
|
||||
/** Preview who is retained, displaced, and readmitted on a schedule. */
|
||||
@@ -193,9 +195,64 @@ export class SchedulingRescheduleService {
|
||||
displacedBookingIds: dto.displacedBookingIds,
|
||||
});
|
||||
|
||||
// Notify affected customers (SMS + email). Best-effort — a notification
|
||||
// failure must never fail the reschedule, so each send is fire-and-forget
|
||||
// inside the notifier. Government pre-empt already notifies via the batch
|
||||
// displaced() path, so skip removed-from-train notices for that trigger.
|
||||
// Use the new departure date when the reschedule moved it (the in-memory
|
||||
// `schedule` still holds the pre-update date).
|
||||
const effectiveDeparture = dto.newDepartureDate
|
||||
? new Date(dto.newDepartureDate)
|
||||
: schedule.scheduledDepartureDate;
|
||||
await this.notifyRescheduleOutcome(dto, effectiveDeparture);
|
||||
|
||||
return { plan, schedule: assignResult };
|
||||
}
|
||||
|
||||
/**
|
||||
* Fan out reschedule notifications: bookings that stayed on the train hear the
|
||||
* new departure date; bookings dropped off the train (staff reschedule, not a
|
||||
* government pre-empt) hear they were removed. Loads each booking with its
|
||||
* company so the notifier has a phone/email to reach.
|
||||
*/
|
||||
private async notifyRescheduleOutcome(
|
||||
dto: ExecuteRescheduleDto,
|
||||
newDeparture: Date | null,
|
||||
): Promise<void> {
|
||||
const isMaintenance = dto.trigger === 'TRAIN_MAINTENANCE';
|
||||
const isGovPreempt = dto.trigger === 'GOVERNMENT_PREEMPT';
|
||||
|
||||
if (newDeparture) {
|
||||
for (const bookingId of dto.finalBookingIds) {
|
||||
const booking = await this.loadBookingForNotify(bookingId);
|
||||
if (!booking) continue;
|
||||
if (isMaintenance) {
|
||||
this.notifier.maintenanceMoved(booking, newDeparture);
|
||||
} else {
|
||||
this.notifier.rescheduled(booking, newDeparture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Government pre-empt displacements are already announced by the batch
|
||||
// displaced() notice — don't double-notify. Staff reschedules are not.
|
||||
if (!isGovPreempt) {
|
||||
for (const bookingId of dto.displacedBookingIds) {
|
||||
const booking = await this.loadBookingForNotify(bookingId);
|
||||
if (!booking) continue;
|
||||
this.notifier.removedFromTrain(booking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async loadBookingForNotify(bookingId: string): Promise<Booking | null> {
|
||||
try {
|
||||
return await this.bookingsRepository.findByIdWithFiles(bookingId);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Maintenance shortcut: new departure + rebalance. */
|
||||
async maintenanceReschedule(
|
||||
scheduleId: string,
|
||||
|
||||
Reference in New Issue
Block a user