mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
133 lines
4.3 KiB
TypeScript
133 lines
4.3 KiB
TypeScript
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
|
|
import { PrismaService } from '../../common/prisma.service';
|
|
import { CreateAgentBookingDto, OpenShiftDto, CloseShiftDto } from './agents.dto';
|
|
import { IdDocumentType } from '@prisma/client';
|
|
|
|
function generateRef(): string {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
return Array.from({ length: 6 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
|
|
}
|
|
|
|
@Injectable()
|
|
export class AgentsService {
|
|
constructor(private prisma: PrismaService) {}
|
|
|
|
async createAgentBooking(dto: CreateAgentBookingDto) {
|
|
const agent = await this.prisma.agent.findUnique({ where: { id: dto.agentId }, include: { user: { include: { passenger: true } } } });
|
|
if (!agent || !agent.active) throw new NotFoundException('Agent not found or inactive');
|
|
if (!agent.user.passenger) throw new BadRequestException('Agent must have passenger account');
|
|
|
|
const schedule = await this.prisma.trainSchedule.findUnique({ where: { id: dto.scheduleId } });
|
|
if (!schedule) throw new NotFoundException('Schedule not found');
|
|
|
|
const seatIds = dto.passengers.map(p => p.seatId);
|
|
const seats = await this.prisma.seat.findMany({ where: { id: { in: seatIds } } });
|
|
if (seats.length !== seatIds.length) throw new BadRequestException('Invalid seat selection');
|
|
|
|
const baseFare = 45000 * dto.passengers.length;
|
|
const totalMinor = baseFare;
|
|
|
|
const booking = await this.prisma.booking.create({
|
|
data: {
|
|
bookingRef: generateRef(),
|
|
passengerId: agent.user.passenger.id,
|
|
scheduleId: dto.scheduleId,
|
|
status: dto.paymentMethod === 'CASH' ? 'CONFIRMED' : 'PENDING_PAYMENT',
|
|
totalMinor,
|
|
seats: {
|
|
create: dto.passengers.map(p => ({
|
|
seat: { connect: { id: p.seatId } },
|
|
passengerName: p.fullName,
|
|
idDocumentType: p.idDocumentType as IdDocumentType | undefined,
|
|
idDocumentNumber: p.idDocumentNumber
|
|
}))
|
|
}
|
|
},
|
|
include: { seats: true }
|
|
});
|
|
|
|
await this.prisma.seat.updateMany({
|
|
where: { id: { in: seatIds } },
|
|
data: { status: 'BOOKED' }
|
|
});
|
|
|
|
const changeGiven = dto.cashReceived ? dto.cashReceived - totalMinor : 0;
|
|
await this.prisma.agentBooking.create({
|
|
data: {
|
|
agentId: dto.agentId,
|
|
bookingId: booking.id,
|
|
paymentMethod: dto.paymentMethod,
|
|
cashReceived: dto.cashReceived,
|
|
changeGiven,
|
|
paperTicket: dto.paperTicket ?? false
|
|
}
|
|
});
|
|
|
|
const commissionAmount = Math.floor(totalMinor * agent.commissionRate / 100);
|
|
await this.prisma.agentCommission.create({
|
|
data: {
|
|
agentId: dto.agentId,
|
|
bookingId: booking.id,
|
|
amountMinor: commissionAmount,
|
|
rate: agent.commissionRate
|
|
}
|
|
});
|
|
|
|
return { booking, commission: commissionAmount };
|
|
}
|
|
|
|
async openShift(dto: OpenShiftDto) {
|
|
const agent = await this.prisma.agent.findUnique({ where: { id: dto.agentId } });
|
|
if (!agent) throw new NotFoundException('Agent not found');
|
|
|
|
const openShift = await this.prisma.agentShift.findFirst({
|
|
where: { agentId: dto.agentId, closedAt: null }
|
|
});
|
|
if (openShift) throw new BadRequestException('Shift already open');
|
|
|
|
return this.prisma.agentShift.create({
|
|
data: {
|
|
agentId: dto.agentId,
|
|
openingBalance: dto.openingBalance ?? 0
|
|
}
|
|
});
|
|
}
|
|
|
|
async closeShift(dto: CloseShiftDto) {
|
|
const shift = await this.prisma.agentShift.findUnique({ where: { id: dto.shiftId } });
|
|
if (!shift) throw new NotFoundException('Shift not found');
|
|
if (shift.closedAt) throw new BadRequestException('Shift already closed');
|
|
|
|
return this.prisma.agentShift.update({
|
|
where: { id: dto.shiftId },
|
|
data: {
|
|
closedAt: new Date(),
|
|
closingBalance: dto.closingBalance,
|
|
notes: dto.notes,
|
|
reconciled: true
|
|
}
|
|
});
|
|
}
|
|
|
|
async getCommissions(agentId: string, dateFrom?: Date, dateTo?: Date) {
|
|
return this.prisma.agentCommission.findMany({
|
|
where: {
|
|
agentId,
|
|
createdAt: {
|
|
gte: dateFrom,
|
|
lte: dateTo
|
|
}
|
|
},
|
|
orderBy: { createdAt: 'desc' }
|
|
});
|
|
}
|
|
|
|
async getShifts(agentId: string) {
|
|
return this.prisma.agentShift.findMany({
|
|
where: { agentId },
|
|
orderBy: { openedAt: 'desc' },
|
|
take: 20
|
|
});
|
|
}
|
|
}
|