mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 20:05:41 +00:00
fix
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Freight } from '@edr/types';
|
||||
|
||||
@@ -66,13 +66,37 @@ export class FirstMileInvoiceService {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Reject mixed-currency truck sets — a single invoice can only be one
|
||||
// currency, and amounts across currencies can't be summed.
|
||||
const billableTrucks = (record.vehicleAssignments ?? []).filter(
|
||||
(a) => Number(a.distanceKm) > 0,
|
||||
);
|
||||
const currencies = [
|
||||
...new Set(
|
||||
billableTrucks
|
||||
.map((a) => (a.vehicle as { currency?: string } | undefined)?.currency)
|
||||
.filter((c): c is string => Boolean(c)),
|
||||
),
|
||||
];
|
||||
if (currencies.length > 1) {
|
||||
throw new BadRequestException(
|
||||
`Cannot generate invoice: assigned trucks use mixed currencies (${currencies.join(', ')}). Assign trucks that share one currency.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Currency follows the truck (price/km is quoted per vehicle), falling back
|
||||
// to the booking's currency, then ETB.
|
||||
const truckCurrency =
|
||||
(record.vehicle as { currency?: string } | undefined)?.currency ||
|
||||
(record.vehicleAssignments?.[0]?.vehicle as { currency?: string } | undefined)?.currency;
|
||||
|
||||
return this.billing.generateInvoice({
|
||||
source: 'first_mile' as Freight.InvoiceSource,
|
||||
sourceId: record.id,
|
||||
type: 'DELIVERY_FEE',
|
||||
companyId: fm.booking!.companyId,
|
||||
companyProfileId: fm.booking!.companyProfileId || '',
|
||||
currency: fm.booking!.paymentCurrency || 'ETB',
|
||||
currency: truckCurrency || fm.booking!.paymentCurrency || 'ETB',
|
||||
lines: [
|
||||
{
|
||||
chargeType: 'DELIVERY',
|
||||
|
||||
@@ -640,10 +640,24 @@ export class FirstMileService {
|
||||
{ distanceKm: d.distanceKm },
|
||||
);
|
||||
}
|
||||
const total = distances.reduce((s, d) => s + (Number(d.distanceKm) || 0), 0);
|
||||
|
||||
// Billing is per truck: amount = Σ (truck distance × truck price/km). The
|
||||
// per-vehicle rate + currency live on the vehicle, so we ignore the legacy
|
||||
// FIRST_MILE flat rate and any client-sent amount. `remainingPayment` param
|
||||
// kept only for signature back-compat.
|
||||
void remainingPayment;
|
||||
const assignments = await this.dataSource.manager.find(FirstMileVehicleAssignment, {
|
||||
where: { firstMileId: id },
|
||||
relations: { vehicle: true },
|
||||
});
|
||||
const total = assignments.reduce((s, a) => s + (Number(a.distanceKm) || 0), 0);
|
||||
const amount = assignments.reduce(
|
||||
(s, a) => s + (Number(a.distanceKm) || 0) * (Number(a.vehicle?.pricePerKm) || 0),
|
||||
0,
|
||||
);
|
||||
await this.firstMileRepository.update(id, {
|
||||
exactKm: total,
|
||||
...(remainingPayment != null ? { remainingPayment } : {}),
|
||||
remainingPayment: amount,
|
||||
} as any);
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user