Merge branch 'alpha' of github.com:Tria-plc/edr-platform into alpha

This commit is contained in:
Abubeker Yasin
2026-07-14 20:17:02 +03:00
152 changed files with 9371 additions and 1278 deletions

View File

@@ -69,6 +69,40 @@ export class SchedulesController {
@ApiOperation({ summary: 'Create a segment fare rule' })
createSegmentFareRule(@Body() dto: any) { return this.service.createSegmentFareRule(dto); }
// Static sub-path MUST come before routes/:routeId/* to avoid :routeId swallowing 'fare-rules'
@Delete('routes/fare-rules/:id')
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'Delete a route-level fare override' })
@ApiParam({ name: 'id', description: 'RouteFareRule UUID' })
deleteRouteFareRule(@Param('id') id: string) {
return this.service.deleteRouteFareRule(id);
}
@Patch('routes/fare-rules/:id')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Update a route-level fare override' })
@ApiParam({ name: 'id', description: 'RouteFareRule UUID' })
updateRouteFareRule(@Param('id') id: string, @Body() dto: any) {
return this.service.updateRouteFareRule(id, dto);
}
@Get('routes/:routeId/fare-rules')
@IsPublic()
@ApiOperation({ summary: 'List route-level fare overrides for a route' })
@ApiParam({ name: 'routeId', description: 'Route UUID' })
listRouteFareRules(@Param('routeId') routeId: string) {
return this.service.listRouteFareRules(routeId);
}
@Post('routes/:routeId/fare-rules')
@UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Create a route-level fare override' })
@ApiParam({ name: 'routeId', description: 'Route UUID' })
createRouteFareRule(@Param('routeId') routeId: string, @Body() dto: any) {
return this.service.createRouteFareRule({ ...dto, routeId });
}
@Get('routes/:routeId/segment-fares')
@IsPublic()
@ApiOperation({ summary: 'List all segment fare rules for a route' })

View File

@@ -676,4 +676,63 @@ export class SchedulesService {
await this.prisma.coachAssignment.delete({ where: { id: assignment.id } });
return { message: 'Coach assignment removed' };
}
// ── Route Fare Rule Overrides ──────────────────────────────────────────────
listRouteFareRules(routeId: string) {
return this.prisma.routeFareRule.findMany({
where: { routeId },
include: { seatClass: true, route: true },
orderBy: { createdAt: 'desc' },
});
}
async createRouteFareRule(dto: {
routeId: string;
seatClassId: string;
passengerCategory?: string;
baseFareMinor: number;
validFrom: string;
validUntil?: string;
}) {
const [route, seatClass] = await Promise.all([
this.prisma.route.findUnique({ where: { id: dto.routeId } }),
this.prisma.seatClass.findUnique({ where: { id: dto.seatClassId } }),
]);
if (!route) throw new NotFoundException('Route not found');
if (!seatClass) throw new NotFoundException('Seat class not found');
return this.prisma.routeFareRule.create({
data: {
routeId: dto.routeId,
seatClassId: dto.seatClassId,
passengerCategory: (dto.passengerCategory as any) ?? 'ADULT',
baseFareMinor: dto.baseFareMinor,
validFrom: parseEthiopianTime(dto.validFrom),
validUntil: dto.validUntil ? parseEthiopianTime(dto.validUntil) : null,
},
include: { seatClass: true, route: true },
});
}
async updateRouteFareRule(id: string, dto: { baseFareMinor?: number; surchargeMinor?: number; validFrom?: string; validUntil?: string }) {
const rule = await this.prisma.routeFareRule.findUnique({ where: { id } });
if (!rule) throw new NotFoundException('Route fare rule not found');
return this.prisma.routeFareRule.update({
where: { id },
data: {
...(dto.baseFareMinor !== undefined && { baseFareMinor: dto.baseFareMinor }),
...(dto.surchargeMinor !== undefined && { surchargeMinor: dto.surchargeMinor }),
...(dto.validFrom && { validFrom: parseEthiopianTime(dto.validFrom) }),
...(dto.validUntil !== undefined && { validUntil: dto.validUntil ? parseEthiopianTime(dto.validUntil) : null }),
},
include: { seatClass: true, route: true },
});
}
async deleteRouteFareRule(id: string) {
const rule = await this.prisma.routeFareRule.findUnique({ where: { id } });
if (!rule) throw new NotFoundException('Route fare rule not found');
await this.prisma.routeFareRule.delete({ where: { id } });
return { deleted: true, id };
}
}