From 18fb16f741e452ac5241900ab3663bf1696c6461 Mon Sep 17 00:00:00 2001 From: yaschalew Date: Mon, 29 Jun 2026 11:40:14 +0300 Subject: [PATCH 01/10] fix --- .../response-transform.interceptor.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/api-common/src/interceptors/response-transform.interceptor.ts b/packages/api-common/src/interceptors/response-transform.interceptor.ts index 402fcb600..9fc9b9a38 100644 --- a/packages/api-common/src/interceptors/response-transform.interceptor.ts +++ b/packages/api-common/src/interceptors/response-transform.interceptor.ts @@ -44,14 +44,19 @@ export class ResponseTransformInterceptor implements NestInterceptor< if ( shouldFlatten && data && - typeof data === "object" && - !Array.isArray(data) + typeof data === "object" ) { - return { - success: true, - ...data, - timestamp: new Date().toISOString(), - }; + if(!Array.isArray(data)){ + + return { + success: true, + ...data, + timestamp: new Date().toISOString(), + }; + } + else { + return data; + } } if(path.startsWith("/api/positions/hierarchy") || path.startsWith("/api/positions/current")){ From 8bb1cb18b52a3623049bc85876ca4f3cb2d4f0d0 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 08:55:40 +0000 Subject: [PATCH 02/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index 128df06fd..7f35affb3 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -769,7 +769,7 @@ const FirstMilePage = () => { openDistance(row.original.id)} > - Add Actual distance + Add distance {canPrint && ( Date: Mon, 29 Jun 2026 08:57:34 +0000 Subject: [PATCH 03/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index 7f35affb3..cd16b92ba 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -6,6 +6,7 @@ import { MoreHorizontal, Printer, RefreshCw, + Ruler, Truck, } from "lucide-react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; @@ -767,6 +768,7 @@ const FirstMilePage = () => { View detail } onClick={() => openDistance(row.original.id)} > Add distance From 8a8a1b73165234977d9a8aecccea01cad417ac89 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:11:48 +0000 Subject: [PATCH 04/10] fix --- .../src/pages/operations/FirstMilePage.tsx | 27 ++++++++++++-- .../backoffice/src/services/rates.service.ts | 35 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 apps/edr-freight-web/backoffice/src/services/rates.service.ts diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index cd16b92ba..a9cab6247 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -43,6 +43,7 @@ import { } from "@/services/first-mile.service"; import { bookingsService } from "@/services/bookings.service"; import { vehiclesService } from "@/services/vehicles.service"; +import { ratesService } from "@/services/rates.service"; import type { BookingDetail } from "@/types/booking"; const formatPrice = (amount: number) => @@ -348,6 +349,14 @@ const FirstMilePage = () => { }, }); + const { data: ratesData } = useQuery({ + queryKey: ["rates", "FIRST_MILE"], + queryFn: async () => { + const res = await ratesService.getByType("FIRST_MILE"); + return res.data; + }, + }); + const { data: paidBookingsData, isLoading: bookingsLoading } = useQuery({ queryKey: QUERY_KEYS.BOOKINGS.list({ status: "PAID" }), queryFn: () => bookingsService.list({ status: "PAID", pageSize: 100 }), @@ -385,8 +394,8 @@ const FirstMilePage = () => { }); const updateDistanceMutation = useMutation({ - mutationFn: ({ id, exactKm }: { id: string; exactKm: number }) => - firstMileService.update(id, { exactKm }), + mutationFn: ({ id, exactKm, remainingPayment }: { id: string; exactKm: number; remainingPayment?: number }) => + firstMileService.update(id, { exactKm, ...(remainingPayment != null && { remainingPayment }) }), onSuccess: () => { void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT }); if (activeRecord) { @@ -492,7 +501,19 @@ const FirstMilePage = () => { toast({ title: "Invalid distance", description: "Enter a valid distance value.", variant: "destructive" }); return; } - updateDistanceMutation.mutate({ id: activeId, exactKm: distance }); + + let remainingPayment: number | undefined; + if (ratesData?.data) { + const firstMileRate = ratesData.data.find( + (r) => r.rateType === "FIRST_MILE" && r.status === "LIVE" + ); + if (firstMileRate) { + const rateValue = parseFloat(firstMileRate.rateValue); + remainingPayment = distance * rateValue; + } + } + + updateDistanceMutation.mutate({ id: activeId, exactKm: distance, remainingPayment }); }; const matchesFilter = (r: FirstMileRecord) => { diff --git a/apps/edr-freight-web/backoffice/src/services/rates.service.ts b/apps/edr-freight-web/backoffice/src/services/rates.service.ts new file mode 100644 index 000000000..589f3ea13 --- /dev/null +++ b/apps/edr-freight-web/backoffice/src/services/rates.service.ts @@ -0,0 +1,35 @@ +import { api } from '../auth/http'; + +export interface Rate { + id: string; + rateType: string; + appliesTo: string; + trigger: string; + containerTypeId: string | null; + cargoTypeId: string | null; + tradeDirection: string | null; + currency: string; + rateValue: string; + rateUnit: string; + status: string; + proposedByStaffId: string; + approvedByCeoId: string | null; + approvedAt: string | null; + effectiveFrom: string; + effectiveTo: string | null; + createdAt: string; + updatedAt: string; + deletedAt: string | null; +} + +export interface RatesListResponse { + data: Rate[]; + meta: { total: number; page: number; pageSize: number; totalPages: number }; +} + +export const ratesService = { + list: (pageSize = 1000) => + api.get(`/rates?pageSize=${pageSize}`), + getByType: (rateType: string) => + api.get(`/rates?rateType=${rateType}&pageSize=1000`), +}; From 872834764229772fe1ac88ad9722d6fbf1f16ca0 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:16:03 +0000 Subject: [PATCH 05/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index a9cab6247..e1882b8fe 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -386,7 +386,7 @@ const FirstMilePage = () => { mutationFn: ({ id, data }: { id: string; data: { status?: FirstMileApiStatus; vehicleId?: string | null } }) => firstMileService.update(id, data), onSuccess: () => { - void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT }); + void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.list() }); }, onError: () => { toast({ title: "Update failed", variant: "destructive" }); @@ -397,7 +397,7 @@ const FirstMilePage = () => { mutationFn: ({ id, exactKm, remainingPayment }: { id: string; exactKm: number; remainingPayment?: number }) => firstMileService.update(id, { exactKm, ...(remainingPayment != null && { remainingPayment }) }), onSuccess: () => { - void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT }); + void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.list() }); if (activeRecord) { toast({ title: "Distance updated", description: `${bookingRef(activeRecord)} → ${distanceValue} km` }); } From 6aad868fb2c6938e8136ccf60dc8bf0f15524a13 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:20:37 +0000 Subject: [PATCH 06/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index e1882b8fe..28771028e 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -505,7 +505,7 @@ const FirstMilePage = () => { let remainingPayment: number | undefined; if (ratesData?.data) { const firstMileRate = ratesData.data.find( - (r) => r.rateType === "FIRST_MILE" && r.status === "LIVE" + (r) => r.rateType === "FIRST_MILE" && (r.status === "LIVE" || r.status === "DRAFT") ); if (firstMileRate) { const rateValue = parseFloat(firstMileRate.rateValue); From 9d7d08cf5dbc849285cf146b235887bca1689341 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:24:45 +0000 Subject: [PATCH 07/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index 28771028e..358bf35c1 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -723,6 +723,12 @@ const FirstMilePage = () => { meta: { headerClassName, cellClassName }, cell: ({ row }) => row.original.exactKm != null ? row.original.exactKm : , }, + { + id: "invoice", + header: "Invoice", + meta: { headerClassName, cellClassName }, + cell: () => "#345", + }, { id: "status", header: "Status", From 4a7503a6672522e17a863f39d0959b86021f8055 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:27:43 +0000 Subject: [PATCH 08/10] fix --- .../src/pages/operations/FirstMilePage.tsx | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index 358bf35c1..69b43c51d 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -332,6 +332,8 @@ const FirstMilePage = () => { const [distanceOpen, setDistanceOpen] = useState(false); const [distanceValue, setDistanceValue] = useState(""); + const [invoiceOpen, setInvoiceOpen] = useState(false); + const [invoiceRecord, setInvoiceRecord] = useState(null); const { data: listData, isLoading } = useQuery({ queryKey: QUERY_KEYS.FIRST_MILE.list(), @@ -495,6 +497,16 @@ const FirstMilePage = () => { setDistanceValue(""); }; + const openInvoice = (record: FirstMileRecord) => { + setInvoiceRecord(record); + setInvoiceOpen(true); + }; + + const closeInvoice = () => { + setInvoiceOpen(false); + setInvoiceRecord(null); + }; + const handleSaveDistance = () => { const distance = parseFloat(distanceValue); if (!activeId || isNaN(distance) || distance < 0) { @@ -727,7 +739,22 @@ const FirstMilePage = () => { id: "invoice", header: "Invoice", meta: { headerClassName, cellClassName }, - cell: () => "#345", + cell: ({ row }) => { + const hasDistance = row.original.exactKm != null && row.original.exactKm > 0; + if (!hasDistance) { + return ; + } + return ( + openInvoice(row.original)} + c="blue" + fw={500} + style={{ textDecoration: "underline", cursor: "pointer" }} + > + #345 + + ); + }, }, { id: "status", @@ -1151,6 +1178,52 @@ const FirstMilePage = () => { + + {/* Invoice modal */} + Invoice #345} + size="lg" + radius="lg" + centered + > + + {invoiceRecord && ( + <> + + + + EDR Freight + Invoice #345 + + + + + + + + + + + + + + + + Total Amount + {formatPrice(invoiceRecord.advancedPayment + invoiceRecord.remainingPayment)} + + + + + + )} + + + + + ); }; From 31b38311ffb175a10059f120d65fe556dd9c2f29 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:30:44 +0000 Subject: [PATCH 09/10] fix --- .../backoffice/src/pages/operations/FirstMilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index 69b43c51d..dedaf8a4d 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -1212,7 +1212,7 @@ const FirstMilePage = () => { Total Amount - {formatPrice(invoiceRecord.advancedPayment + invoiceRecord.remainingPayment)} + {formatPrice(parseFloat(String(invoiceRecord.advancedPayment)) + parseFloat(String(invoiceRecord.remainingPayment)))} From 9f0d16886d7057d834e966d8a5b6e79003de3678 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:33:56 +0000 Subject: [PATCH 10/10] fix --- .../src/pages/operations/FirstMilePage.tsx | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index dedaf8a4d..9514d8c5c 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -1210,9 +1210,44 @@ const FirstMilePage = () => { - - Total Amount - {formatPrice(parseFloat(String(invoiceRecord.advancedPayment)) + parseFloat(String(invoiceRecord.remainingPayment)))} + + + Post Payment + {formatPrice(invoiceRecord.remainingPayment)} + + + Advanced Payment + {formatPrice(invoiceRecord.advancedPayment)} + + + {(() => { + const postPayment = parseFloat(String(invoiceRecord.remainingPayment)); + const advancedPayment = parseFloat(String(invoiceRecord.advancedPayment)); + const difference = postPayment - advancedPayment; + + if (difference > 0) { + return ( + + Remaining to Pay + {formatPrice(difference)} + + ); + } else if (difference < 0) { + return ( + + Refund + {formatPrice(Math.abs(difference))} + + ); + } else { + return ( + + Status + Settled + + ); + } + })()}