mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Reports (overall, seats report, passenger export) updates
This commit is contained in:
@@ -30,6 +30,12 @@ export class ReportsController {
|
||||
return this.service.getPassengerList(scheduleId);
|
||||
}
|
||||
|
||||
@Get('seats')
|
||||
@ApiOperation({ summary: 'Seat status report for a specific schedule' })
|
||||
getSeatStatusReport(@Query('scheduleId') scheduleId: string) {
|
||||
return this.service.getSeatStatusReport(scheduleId);
|
||||
}
|
||||
|
||||
@Get('passengers')
|
||||
@ApiOperation({ summary: 'Passengers report for a specific schedule' })
|
||||
getOccupancyReport(@Query('scheduleId') scheduleId: string) {
|
||||
|
||||
@@ -378,6 +378,101 @@ export class ReportsService {
|
||||
}));
|
||||
}
|
||||
|
||||
async getSeatStatusReport(scheduleId: string) {
|
||||
// Booked seats — exclude dining coaches
|
||||
const bookingSeats = await this.prisma.bookingSeat.findMany({
|
||||
where: {
|
||||
leg: 1,
|
||||
booking: { scheduleId, status: { in: ['CONFIRMED', 'BOARDED', 'PENDING_PAYMENT'] } },
|
||||
seat: { coach: { coachType: { type: { not: 'dining' } } } },
|
||||
},
|
||||
include: {
|
||||
booking: {
|
||||
select: {
|
||||
bookingRef: true,
|
||||
status: true,
|
||||
totalMinor: true,
|
||||
currency: true,
|
||||
createdAt: true,
|
||||
paymentIntent: { select: { status: true } },
|
||||
},
|
||||
},
|
||||
seat: {
|
||||
select: {
|
||||
seatNumber: true,
|
||||
bedPosition: true,
|
||||
coach: {
|
||||
select: {
|
||||
number: true,
|
||||
coachType: { select: { name: true, type: true, seatClasses: { select: { name: true, bedPosition: true } } } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: [{ seat: { coach: { number: 'asc' } } }, { seat: { seatNumber: 'asc' } }],
|
||||
});
|
||||
|
||||
// Manually blocked seats for this schedule — exclude MAINTENANCE entries
|
||||
const blocks = await this.prisma.seatBlock.findMany({
|
||||
where: {
|
||||
scheduleId,
|
||||
NOT: { reason: { startsWith: 'MAINTENANCE:' } },
|
||||
},
|
||||
include: {
|
||||
seat: {
|
||||
select: {
|
||||
seatNumber: true,
|
||||
bedPosition: true,
|
||||
coach: {
|
||||
select: {
|
||||
number: true,
|
||||
coachType: { select: { name: true, type: true, seatClasses: { select: { name: true, bedPosition: true } } } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { blockedAt: 'desc' },
|
||||
});
|
||||
|
||||
const resolveSeatClass = (seat: any): string | null => {
|
||||
const classes = seat?.coach?.coachType?.seatClasses ?? [];
|
||||
const matched = seat?.bedPosition
|
||||
? classes.find((sc: any) => sc.bedPosition?.toLowerCase() === seat.bedPosition.toLowerCase())
|
||||
: null;
|
||||
return (matched ?? classes[0])?.name ?? seat?.coach?.coachType?.name ?? null;
|
||||
};
|
||||
|
||||
return {
|
||||
bookedSeats: bookingSeats.map(bs => ({
|
||||
bookingRef: bs.booking.bookingRef,
|
||||
passengerName: bs.passengerName,
|
||||
passengerCategory: bs.passengerCategory,
|
||||
coachNumber: bs.seat?.coach?.number ?? null,
|
||||
seatNumber: bs.seat?.seatNumber ?? null,
|
||||
seatClassName: resolveSeatClass(bs.seat),
|
||||
fareMinor: bs.fareMinor,
|
||||
currency: bs.booking.currency ?? 'ETB',
|
||||
bookingStatus: bs.booking.status,
|
||||
paymentStatus: bs.booking.paymentIntent?.status ?? 'PENDING',
|
||||
bookedAt: bs.booking.createdAt,
|
||||
})),
|
||||
blockedSeats: blocks
|
||||
.filter(b => b.seat?.coach?.coachType?.type !== 'dining')
|
||||
.map(b => ({
|
||||
id: b.id,
|
||||
coachNumber: b.seat?.coach?.number ?? null,
|
||||
seatNumber: b.seat?.seatNumber ?? null,
|
||||
seatClassName: resolveSeatClass(b.seat),
|
||||
reason: b.reason,
|
||||
blockedBy: b.blockedBy,
|
||||
blockedAt: b.blockedAt,
|
||||
unblockAt: b.unblockAt,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async getReport(reportId: string) {
|
||||
return this.prisma.operationalReport.findUnique({ where: { id: reportId } });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user