Merge pull request #438 from Tria-plc/freight/feature/first_mile_invoice

Freight/feature/first mile invoice
This commit is contained in:
yaschalew10
2026-07-04 03:27:35 +03:00
committed by GitHub
3 changed files with 19 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
import {
BadRequestException,
Body,
Controller,
Delete,
@@ -93,7 +94,13 @@ export class FirstMileController {
@ApiOperation({ summary: 'Generate the first-mile delivery-fee invoice' })
async generateInvoice(@Param('id', ParseUUIDPipe) id: string) {
const record = await this.firstMileService.findById(id);
return this.firstMileInvoiceService.ensureInvoiceFor(record);
const invoice = await this.firstMileInvoiceService.ensureInvoiceFor(record);
if (!invoice) {
throw new BadRequestException(
'Cannot generate invoice: the leg has no billable amount. Add distance and ensure a FIRST_MILE rate is configured, and the booking has a company.',
);
}
return invoice;
}
@Delete(':id')

View File

@@ -1,4 +1,5 @@
import {
BadRequestException,
Body,
Controller,
Delete,
@@ -118,6 +119,12 @@ export class LastMileController {
@ApiOperation({ summary: 'Generate the delivery-fee invoice for a last-mile leg' })
async generateInvoice(@Param('id', ParseUUIDPipe) id: string) {
const record = await this.lastMileService.findById(id);
return this.lastMileInvoiceService.ensureInvoiceFor(record);
const invoice = await this.lastMileInvoiceService.ensureInvoiceFor(record);
if (!invoice) {
throw new BadRequestException(
'Cannot generate invoice: the leg has no billable amount. Add distance and ensure a LAST_MILE rate is configured, and the booking has a company.',
);
}
return invoice;
}
}

View File

@@ -415,6 +415,9 @@ private async seedWeightLimits(wlRepo: any, ctRepo: any): Promise<void> {
{ appliesTo: "OTHER", trigger: "REEFER", rateType: "REEFER_SURCHARGE", rateValue: 2, rateUnit: "PER_TON" },
{ appliesTo: "OTHER", trigger: "SHIPPING_LINE", rateType: "DOUBLE_HANDLING", rateValue: 100, rateUnit: "PER_CONTAINER" },
{ appliesTo: "OTHER", trigger: "CONSOLIDATION", rateType: "LASHING", rateValue: 50, rateUnit: "PER_CONTAINER" },
// ── First/last-mile road haulage (per km) — drives the mile invoices ──
{ appliesTo: "OTHER", trigger: "ALWAYS", rateType: "FIRST_MILE", rateValue: 20, rateUnit: "PER_KM" },
{ appliesTo: "OTHER", trigger: "ALWAYS", rateType: "LAST_MILE", rateValue: 25, rateUnit: "PER_KM" },
];
// Idempotent: insert each canonical rate only if no row with the same