Boarding, ticketing, class fare edit updates

This commit is contained in:
Stephanos A
2026-07-02 16:20:15 +03:00
parent b511da2821
commit 9494d57343
15 changed files with 370 additions and 325 deletions

View File

@@ -1,4 +1,4 @@
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, ParseIntPipe, UseGuards } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, ParseIntPipe, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiResponse } from '@nestjs/swagger';
import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator';
import { SchedulesService } from './schedules.service';
@@ -132,6 +132,23 @@ export class SchedulesController {
@Body() dto: UpdateStopTimeDto,
) { return this.service.updateStop(id, sequence, dto); }
@Put(':scheduleId/fares/:seatClassId')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@ApiOperation({
summary: 'Override fare for a specific seat class on a schedule',
description: 'Upserts a schedule-scoped FareRule. Expires any existing active rule for the same schedule+seatClass and creates a new one.',
})
@ApiParam({ name: 'scheduleId', description: 'TrainSchedule UUID' })
@ApiParam({ name: 'seatClassId', description: 'SeatClass UUID' })
@ApiResponse({ status: 200, description: 'Fare rule upserted' })
upsertScheduleFare(
@Param('scheduleId') scheduleId: string,
@Param('seatClassId') seatClassId: string,
@Body() dto: { baseFareMinor: number; validFrom?: string; validUntil?: string },
) {
return this.service.upsertScheduleFare(scheduleId, seatClassId, dto);
}
@Get(':scheduleId/fares/stored')
@ApiOperation({ summary: 'Get stored fare rules for a schedule' })
@ApiParam({ name: 'scheduleId', description: 'TrainSchedule UUID' })

View File

@@ -402,6 +402,34 @@ export class SchedulesService {
});
}
async upsertScheduleFare(
scheduleId: string,
seatClassId: string,
dto: { baseFareMinor: number; validFrom?: string; validUntil?: string },
) {
const [schedule, seatClass] = await Promise.all([
this.prisma.trainSchedule.findUnique({ where: { id: scheduleId } }),
this.prisma.seatClass.findUnique({ where: { id: seatClassId } }),
]);
if (!schedule) throw new NotFoundException('Schedule not found');
if (!seatClass) throw new NotFoundException('Seat class not found');
const now = new Date();
const validFrom = dto.validFrom ? parseEthiopianTime(dto.validFrom) : now;
const validUntil = dto.validUntil ? parseEthiopianTime(dto.validUntil) : null;
return this.prisma.$transaction(async (tx) => {
await tx.fareRule.updateMany({
where: { tripId: scheduleId, seatClassId, validUntil: null },
data: { validUntil: now },
});
return tx.fareRule.create({
data: { tripId: scheduleId, seatClassId, baseFareMinor: dto.baseFareMinor, currency: 'ETB', validFrom, validUntil },
include: { seatClass: true },
});
});
}
createFareRule(dto: CreateFareRuleDto) {
const { validFrom, validUntil, scheduleId, nationality, passengerCategory, ...rest } = dto;
return this.prisma.fareRule.create({