Files
edr-platform/apps/edr-freight-api/src/modules/last-mile/last-mile.service.ts
2026-06-22 07:58:56 +00:00

114 lines
3.5 KiB
TypeScript

import { Injectable, NotFoundException } from '@nestjs/common';
import { FindOptionsWhere } from 'typeorm';
import { CreateLastMileDto } from './dto/create-last-mile.dto';
import { UpdateLastMileDto } from './dto/update-last-mile.dto';
import { LastMile, LastMileStatus } from './entities/last-mile.entity';
import { LastMileRepository } from './last-mile.repository';
type LastMileListFilter = {
status?: LastMileStatus;
bookingId?: string;
vehicleId?: string;
page?: number;
pageSize?: number;
sortBy?: string;
sortOrder?: string;
};
const SORTABLE_FIELDS: (keyof LastMile)[] = [
'status',
'advancedPayment',
'remainingPayment',
'createdAt',
];
@Injectable()
export class LastMileService {
constructor(private readonly lastMileRepository: LastMileRepository) {}
async findAll(filter: LastMileListFilter = {}): Promise<{
data: LastMile[];
meta: { total: number; page: number; pageSize: number; totalPages: number };
}> {
const page = filter.page ?? 1;
const pageSize = filter.pageSize ?? 50;
const sortBy = SORTABLE_FIELDS.includes(filter.sortBy as keyof LastMile)
? (filter.sortBy as keyof LastMile)
: 'createdAt';
const sortOrder = filter.sortOrder?.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
const where: FindOptionsWhere<LastMile> = {};
if (filter.status) where.status = filter.status;
if (filter.bookingId) where.bookingId = filter.bookingId;
if (filter.vehicleId) where.vehicleId = filter.vehicleId;
const [data, total] = await this.lastMileRepository.findAndCount({
where,
relations: { booking: true, vehicle: true },
order: { [sortBy]: sortOrder },
skip: (page - 1) * pageSize,
take: pageSize,
});
return {
data,
meta: {
total,
page,
pageSize,
totalPages: Math.max(1, Math.ceil(total / pageSize)),
},
};
}
async findById(id: string): Promise<LastMile> {
const record = await this.lastMileRepository.findById(id, {
relations: { booking: true, vehicle: true },
});
if (!record) {
throw new NotFoundException(`Last-mile record ${id} not found`);
}
return record;
}
async create(dto: CreateLastMileDto): Promise<LastMile> {
return this.lastMileRepository.create({
bookingId: dto.bookingId,
status: dto.status ?? 'PAYMENT_PENDING',
advancedPayment: dto.advancedPayment ?? 0,
remainingPayment: dto.remainingPayment ?? 0,
estimatedKm: dto.estimatedKm ?? null,
exactKm: dto.exactKm ?? null,
vehicleId: dto.vehicleId ?? null,
});
}
async update(id: string, dto: UpdateLastMileDto): Promise<LastMile> {
await this.findById(id);
const updated = await this.lastMileRepository.update(id, {
...(dto.bookingId !== undefined ? { bookingId: dto.bookingId } : {}),
...(dto.status !== undefined ? { status: dto.status } : {}),
...(dto.advancedPayment !== undefined ? { advancedPayment: dto.advancedPayment } : {}),
...(dto.remainingPayment !== undefined ? { remainingPayment: dto.remainingPayment } : {}),
...(dto.estimatedKm !== undefined ? { estimatedKm: dto.estimatedKm } : {}),
...(dto.exactKm !== undefined ? { exactKm: dto.exactKm } : {}),
...(dto.vehicleId !== undefined ? { vehicleId: dto.vehicleId } : {}),
});
if (!updated) {
throw new NotFoundException(`Last-mile record ${id} not found`);
}
return updated;
}
async remove(id: string): Promise<void> {
await this.findById(id);
await this.lastMileRepository.softDelete(id);
}
}