Generate ticket, dashboard, excess luggage rate updates

This commit is contained in:
Stephanos A
2026-07-16 08:41:35 +03:00
parent 2d2fcfbda9
commit b2b31f30bb
16 changed files with 585 additions and 315 deletions

View File

@@ -1,6 +1,6 @@
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Request, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { IsInt, IsPositive, IsString } from 'class-validator';
import { IsInt, IsOptional, IsPositive, IsString } from 'class-validator';
import { ExcessBaggageService } from './excess-baggage.service';
import {
LogExcessBaggageDto,
@@ -12,8 +12,8 @@ import { PassengerAdmin } from '../../common/passenger-guards';
class UpsertBaggageAllowanceDto {
@IsString() seatClassId: string;
@IsInt() @IsPositive() maxWeightKg: number;
@IsInt() @IsPositive() maxPiecesCount: number;
@IsOptional() @IsInt() maxWeightKg?: number;
@IsOptional() @IsInt() maxPiecesCount?: number;
@IsInt() @IsPositive() excessFeePerKg: number;
}

View File

@@ -42,7 +42,6 @@ export class ExcessBaggageService {
const booking = await this.prisma.booking.findUnique({
where: { id: dto.bookingId },
include: {
seats: { take: 1, include: { seat: { include: { coach: { include: { coachType: true } } } } } },
passenger: { include: { user: true } },
},
});
@@ -51,20 +50,9 @@ export class ExcessBaggageService {
throw new BadRequestException('Booking must be CONFIRMED or BOARDED to log excess baggage');
}
// Resolve fee per kg from BaggageAllowance via seat class
const coachTypeId = booking.seats[0]?.seat?.coach?.coachTypeId;
let feePerKgMinor = 5000; // 50 ETB default fallback (in minor)
if (coachTypeId) {
const seatClass = await this.prisma.seatClass.findFirst({
where: { coachTypeId },
});
if (seatClass) {
const allowance = await this.prisma.baggageAllowance.findFirst({
where: { seatClassId: seatClass.id },
});
if (allowance) feePerKgMinor = allowance.excessFeePerKg;
}
}
const allowance = await this.prisma.baggageAllowance.findFirst({ orderBy: { createdAt: 'asc' } });
if (!allowance) throw new BadRequestException('No excess baggage rate configured. Please set a rate in Tariff Rates.');
const feePerKgMinor = allowance.excessFeePerKg;
const totalMinor = feePerKgMinor * dto.excessWeightKg;
const expiresAt = new Date(Date.now() + CHARGE_TTL_MS);
@@ -289,11 +277,16 @@ export class ExcessBaggageService {
return allowances.map(a => ({ ...a, seatClass: scMap.get(a.seatClassId) ?? null }));
}
async upsertAllowance(dto: { seatClassId: string; maxWeightKg: number; maxPiecesCount: number; excessFeePerKg: number }) {
return this.prisma.baggageAllowance.upsert({
where: { seatClassId: dto.seatClassId } as any,
update: { maxWeightKg: dto.maxWeightKg, maxPiecesCount: dto.maxPiecesCount, excessFeePerKg: dto.excessFeePerKg },
create: { seatClassId: dto.seatClassId, maxWeightKg: dto.maxWeightKg, maxPiecesCount: dto.maxPiecesCount, excessFeePerKg: dto.excessFeePerKg },
async upsertAllowance(dto: { seatClassId: string; maxWeightKg?: number; maxPiecesCount?: number; excessFeePerKg: number }) {
const existing = await this.prisma.baggageAllowance.findFirst({ where: { seatClassId: dto.seatClassId } });
if (existing) {
return this.prisma.baggageAllowance.update({
where: { id: existing.id },
data: { maxWeightKg: dto.maxWeightKg ?? 0, maxPiecesCount: dto.maxPiecesCount ?? 0, excessFeePerKg: dto.excessFeePerKg },
});
}
return this.prisma.baggageAllowance.create({
data: { seatClassId: dto.seatClassId, maxWeightKg: dto.maxWeightKg ?? 0, maxPiecesCount: dto.maxPiecesCount ?? 0, excessFeePerKg: dto.excessFeePerKg },
});
}
@@ -302,7 +295,7 @@ export class ExcessBaggageService {
}
async deleteAllowance(id: string) {
await this.prisma.baggageAllowance.delete({ where: { id } });
await this.prisma.baggageAllowance.deleteMany({ where: { id } });
return { deleted: true };
}