UAT issues resolution

This commit is contained in:
Stephanos A
2026-07-05 20:38:49 +03:00
parent 21122069a5
commit cacced8edf
5 changed files with 73 additions and 44 deletions

View File

@@ -61,11 +61,12 @@ export class SeatsService {
const resolvedBedPosition = isBedCoach
? this.resolveBedPosition(s.col, s.bedPosition)
: s.bedPosition;
const effectiveStatus = effectiveStatuses.get(s.id) ?? (s.status === 'BLOCKED' || s.status === 'BOOKED' ? s.status : 'AVAILABLE');
return {
id: s.id,
seatNumber: s.seatNumber,
label: s.seatNumber,
status: effectiveStatuses.get(s.id) ?? s.status,
status: effectiveStatus,
kind: s.kind,
row: s.row,
col: s.col,
@@ -245,11 +246,16 @@ export class SeatsService {
holdFrom === undefined || holdTo === undefined ||
(holdFrom < reqTo && reqFrom < holdTo);
if (!legsOverlap) continue;
// Check direction conflict
const directionsConflict = this.checkDirectionConflict(reqDirection, holdDirection);
if (!directionsConflict) continue;
if (!legsOverlap || !directionsConflict) {
// This hold does not conflict with the requested leg/direction.
// Explicitly mark AVAILABLE so the DB's HELD status (set by the
// opposing-direction hold) does not bleed through via the fallback.
if (!statusMap.has(seatId)) statusMap.set(seatId, 'AVAILABLE');
continue;
}
statusMap.set(seatId, 'HELD');
}
@@ -653,7 +659,7 @@ export class SeatsService {
const seats = a.coach.seats.filter(s => s.seatNumber && !s.seatNumber.startsWith('-'));
const totalSeats = seats.length;
const unavailable = seats.filter(s => {
const status = effectiveStatuses.get(s.id) ?? s.status;
const status = effectiveStatuses.get(s.id) ?? (s.status === 'BLOCKED' || s.status === 'BOOKED' ? s.status : 'AVAILABLE');
return status === 'HELD' || status === 'BOOKED' || status === 'BLOCKED';
}).length;
@@ -665,8 +671,8 @@ export class SeatsService {
seatClasses: a.coach.coachType?.seatClasses.map(sc => sc.name) ?? [],
totalSeats,
availableSeats: totalSeats - unavailable,
heldSeats: seats.filter(s => (effectiveStatuses.get(s.id) ?? s.status) === 'HELD').length,
bookedSeats: seats.filter(s => (effectiveStatuses.get(s.id) ?? s.status) === 'BOOKED').length,
heldSeats: seats.filter(s => (effectiveStatuses.get(s.id) ?? (s.status === 'BLOCKED' || s.status === 'BOOKED' ? s.status : 'AVAILABLE')) === 'HELD').length,
bookedSeats: seats.filter(s => (effectiveStatuses.get(s.id) ?? (s.status === 'BLOCKED' || s.status === 'BOOKED' ? s.status : 'AVAILABLE')) === 'BOOKED').length,
};
});
}
@@ -861,11 +867,21 @@ export class SeatsService {
if (expired.length === 0) return;
const expiredSeatIds = expired.flatMap(h => h.seatIds as string[]);
// Only reset seats that are still HELD — BOOKED seats have been confirmed and must not be touched.
await this.prisma.seat.updateMany({
where: { id: { in: expiredSeatIds }, status: 'HELD' },
data: { status: 'AVAILABLE' },
// Only reset seats that have no remaining active holds
const stillHeld = await this.prisma.seatHold.findMany({
where: { expiresAt: { gte: new Date() }, seatIds: { hasSome: expiredSeatIds } },
select: { seatIds: true },
});
const stillHeldIds = new Set(stillHeld.flatMap(h => h.seatIds as string[]));
const toRelease = expiredSeatIds.filter(id => !stillHeldIds.has(id));
if (toRelease.length > 0) {
await this.prisma.seat.updateMany({
where: { id: { in: toRelease }, status: 'HELD' },
data: { status: 'AVAILABLE' },
});
}
await this.prisma.seatHold.deleteMany({ where: { expiresAt: { lt: new Date() } } });
}
}