mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 21:20:57 +00:00
feat: add warehouse gate times editor modal for import trucks
Enable per-truck editing of warehouse gate arrival/departure times (arrivedAt/departedAt) via modal on Import Trucks page. Accessible via row action menu for EDR-haulage trucks. Includes backend endpoint POST /last-mile/:id/warehouse-gate-times and frontend modal with DateTimePicker inputs. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsArray, IsDateString, IsOptional, IsUUID, ValidateNested } from 'class-validator';
|
||||
|
||||
export class TruckWarehouseGateTimeInput {
|
||||
@IsUUID()
|
||||
vehicleId!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
arrivedAt?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
departedAt?: string | null;
|
||||
}
|
||||
|
||||
export class SetWarehouseGateTimesDto {
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => TruckWarehouseGateTimeInput)
|
||||
trucks!: TruckWarehouseGateTimeInput[];
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import { CreateLastMileDto } from './dto/create-last-mile.dto';
|
||||
import { UpdateLastMileDto } from './dto/update-last-mile.dto';
|
||||
import { SetVehiclesDto } from './dto/set-vehicles.dto';
|
||||
import { SetDetentionTimesDto } from './dto/set-detention-times.dto';
|
||||
import { SetWarehouseGateTimesDto } from './dto/set-warehouse-gate-times.dto';
|
||||
import { SetDistancesDto } from './dto/set-distances.dto';
|
||||
import { RecordProofOfDeliveryDto } from './dto/record-proof-of-delivery.dto';
|
||||
import { LastMileStatus } from './entities/last-mile.entity';
|
||||
@@ -144,6 +145,18 @@ export class LastMileController {
|
||||
return this.lastMileService.setDetentionTimes(id, dto.trucks);
|
||||
}
|
||||
|
||||
@Post(':id/warehouse-gate-times')
|
||||
@BookingStaff(FREIGHT_PERMS.lastMile.update)
|
||||
@ApiOperation({
|
||||
summary: 'Set each truck\'s warehouse gate arrival/departure times',
|
||||
})
|
||||
async setWarehouseGateTimes(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: SetWarehouseGateTimesDto,
|
||||
) {
|
||||
return this.lastMileService.setWarehouseGateTimes(id, dto.trucks);
|
||||
}
|
||||
|
||||
@Post(':id/proof-of-delivery')
|
||||
@BookingStaff(FREIGHT_PERMS.lastMile.update)
|
||||
@UseInterceptors(AnyFilesInterceptor())
|
||||
|
||||
@@ -913,6 +913,41 @@ export class LastMileService {
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
async setWarehouseGateTimes(
|
||||
id: string,
|
||||
trucks: Array<{
|
||||
vehicleId: string;
|
||||
arrivedAt?: string | null;
|
||||
departedAt?: string | null;
|
||||
}>,
|
||||
): Promise<LastMile> {
|
||||
await this.findById(id);
|
||||
|
||||
const invoices = await this.billing.findBySourceIds('last_mile', [id]);
|
||||
if (invoices.length) {
|
||||
throw new BadRequestException(
|
||||
'Warehouse gate times cannot be changed after the invoice is generated',
|
||||
);
|
||||
}
|
||||
|
||||
for (const t of trucks) {
|
||||
const arrived = t.arrivedAt ? new Date(t.arrivedAt) : null;
|
||||
const departed = t.departedAt ? new Date(t.departedAt) : null;
|
||||
if (arrived && departed && departed.getTime() < arrived.getTime()) {
|
||||
throw new BadRequestException(
|
||||
'A truck cannot depart before it arrived — check the warehouse gate times',
|
||||
);
|
||||
}
|
||||
await this.dataSource.manager.update(
|
||||
LastMileVehicleAssignment,
|
||||
{ lastMileId: id, vehicleId: t.vehicleId },
|
||||
{ arrivedAt: arrived, departedAt: departed },
|
||||
);
|
||||
}
|
||||
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
async setDistances(
|
||||
id: string,
|
||||
distances: Array<{ vehicleId: string; distanceKm: number }>,
|
||||
|
||||
Reference in New Issue
Block a user