mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
fix
This commit is contained in:
@@ -39,6 +39,7 @@ import { ContractRendererService } from "../../contracts/contract-renderer.servi
|
||||
import { ContractTemplateResolver } from "../../contracts/contract-template.resolver";
|
||||
import { ContractViewModelBuilder } from "../../contracts/contract-view-model.builder";
|
||||
import { TrainSchedulingModule } from "../train-scheduling/train-scheduling.module";
|
||||
import { VehiclesModule } from "../vehicles/vehicles.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -58,6 +59,7 @@ import { TrainSchedulingModule } from "../train-scheduling/train-scheduling.modu
|
||||
forwardRef(() => TrainSchedulingModule),
|
||||
FilesModule,
|
||||
MinioModule,
|
||||
VehiclesModule,
|
||||
CompaniesModule,
|
||||
// CustomersModule,
|
||||
RuleEngineModule,
|
||||
|
||||
@@ -31,6 +31,8 @@ import { ServiceType } from '../rule-engine/entities/service-type.entity';
|
||||
import { TrainSchedule } from '../train-schedules/entities/train-schedule.entity';
|
||||
import { BookingsRepository } from './bookings.repository';
|
||||
import { ConsolidationService } from './consolidation.service';
|
||||
import { VehiclesService } from '../vehicles/vehicles.service';
|
||||
import { VehicleAvailability } from '../vehicles/entities/vehicle.entity';
|
||||
import { assertFreightShape } from './booking-freight.util';
|
||||
import { CreateBookingContainerDto, CreateBookingDto } from './dto/create-booking.dto';
|
||||
import { mapStatusCountsToTabs } from './booking-list-tabs.config';
|
||||
@@ -81,6 +83,7 @@ export class BookingsService {
|
||||
private readonly ruleEngineService: RuleEngineService,
|
||||
private readonly containerTypesService: ContainerTypesService,
|
||||
private readonly consolidationService: ConsolidationService,
|
||||
private readonly vehiclesService: VehiclesService,
|
||||
) {}
|
||||
|
||||
/** Resolve trade direction from yard countries; reject client mismatch. */
|
||||
@@ -1348,6 +1351,16 @@ export class BookingsService {
|
||||
throw new NotFoundException(`Booking ${bookingId} not found`);
|
||||
}
|
||||
|
||||
const previousAllocations = await this.dataSource.manager.find(BookingContainerAllocation, {
|
||||
where: {
|
||||
bookingId,
|
||||
containerId: In(allocations.map((a) => a.containerId)),
|
||||
},
|
||||
});
|
||||
const previousVehicleIds = previousAllocations
|
||||
.map((a) => a.vehicleId)
|
||||
.filter((id): id is string => Boolean(id));
|
||||
|
||||
await this.dataSource.transaction(async (manager) => {
|
||||
for (const allocation of allocations) {
|
||||
await manager.delete(BookingContainerAllocation, {
|
||||
@@ -1364,6 +1377,16 @@ export class BookingsService {
|
||||
}
|
||||
});
|
||||
|
||||
const vehicleIds = new Set(allocations.map((a) => a.vehicleId));
|
||||
await Promise.all(
|
||||
[...vehicleIds].map((vehicleId) =>
|
||||
this.vehiclesService.setAvailability(vehicleId, VehicleAvailability.BUSY),
|
||||
),
|
||||
);
|
||||
await this.vehiclesService.releaseIfUnused(
|
||||
previousVehicleIds.filter((id) => !vehicleIds.has(id)),
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
allocated: allocations.length,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FirstMile, FirstMileStatus } from '../first-mile/entities/first-mile.en
|
||||
import { FirstMileContainerAllocation } from '../first-mile/entities/first-mile-container-allocation.entity';
|
||||
import { LastMile, LastMileStatus } from '../last-mile/entities/last-mile.entity';
|
||||
import { LastMileContainerAllocation } from '../last-mile/entities/last-mile-container-allocation.entity';
|
||||
import { BookingContainerAllocation } from '../bookings/entities/booking-container-allocation.entity';
|
||||
|
||||
@Injectable()
|
||||
export class VehiclesService {
|
||||
@@ -113,7 +114,7 @@ export class VehiclesService {
|
||||
async releaseIfUnused(vehicleIds: string[]): Promise<void> {
|
||||
const manager = this.vehicleRepo.manager;
|
||||
for (const vehicleId of [...new Set(vehicleIds)]) {
|
||||
const [fmRecords, lmRecords, fmAllocations, lmAllocations] = await Promise.all([
|
||||
const [fmRecords, lmRecords, fmAllocations, lmAllocations, bookingAllocations] = await Promise.all([
|
||||
manager.count(FirstMile, {
|
||||
where: { vehicleId, status: Not<FirstMileStatus>('RECEIVED_TO_PORT') },
|
||||
}),
|
||||
@@ -134,8 +135,9 @@ export class VehiclesService {
|
||||
.andWhere('lm.status != :done', { done: 'DELIVERED' })
|
||||
.andWhere('lm.deletedAt IS NULL')
|
||||
.getCount(),
|
||||
manager.count(BookingContainerAllocation, { where: { vehicleId } }),
|
||||
]);
|
||||
if (fmRecords + lmRecords + fmAllocations + lmAllocations === 0) {
|
||||
if (fmRecords + lmRecords + fmAllocations + lmAllocations + bookingAllocations === 0) {
|
||||
await this.setAvailability(vehicleId, VehicleAvailability.FREE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ const BookingDetailPage = () => {
|
||||
onSuccess: () => {
|
||||
toast.success("Containers allocated");
|
||||
qc.invalidateQueries({ queryKey: QUERY_KEYS.BOOKINGS.byId(id ?? "") });
|
||||
qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
},
|
||||
onError: () => {
|
||||
toast.error("Failed to allocate containers");
|
||||
|
||||
@@ -400,6 +400,7 @@ const FirstMilePage = () => {
|
||||
firstMileService.update(id, data),
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.list() });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: "Update failed", variant: "destructive" });
|
||||
@@ -444,6 +445,7 @@ const FirstMilePage = () => {
|
||||
},
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
toast({ title: "Booking accepted", description: "First-mile leg created successfully." });
|
||||
closeAccept();
|
||||
},
|
||||
@@ -460,6 +462,7 @@ const FirstMilePage = () => {
|
||||
onSuccess: () => {
|
||||
toast({ title: "Containers allocated" });
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.byId(containerAllocationFirstMileId ?? "") });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
setContainerAllocationOpen(false);
|
||||
setContainerAllocationFirstMileId(null);
|
||||
},
|
||||
|
||||
@@ -377,6 +377,7 @@ const LastMilePage = () => {
|
||||
lastMileService.update(id, data),
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.ROOT });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: "Update failed", variant: "destructive" });
|
||||
@@ -415,6 +416,7 @@ const LastMilePage = () => {
|
||||
onSuccess: () => {
|
||||
toast({ title: "Containers allocated", variant: "default" });
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.byId(activeId ?? "") });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
closeAllocation();
|
||||
},
|
||||
onError: () => {
|
||||
@@ -453,6 +455,7 @@ const LastMilePage = () => {
|
||||
},
|
||||
onSuccess: (created) => {
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.ROOT });
|
||||
void qc.invalidateQueries({ queryKey: ["vehicles"] });
|
||||
toast({
|
||||
title: "Last-mile leg created",
|
||||
description: `${created.length} ${created.length === 1 ? "delivery" : "deliveries"} accepted successfully.`,
|
||||
|
||||
Reference in New Issue
Block a user