diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts index 662122438..988efea54 100644 --- a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts +++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts @@ -194,6 +194,10 @@ export interface EligibleBookingRow { customer: string | null; customerTin: string | null; customerPhone: string | null; + containerNumber: string | null; + containerQuantity: number | null; + containerPackagingType: string | null; + cargoDescription: string | null; lastMileRequested: boolean; direction: string; origin: string | null; @@ -657,6 +661,9 @@ export class WarehouseInventoryService { company.name AS "customer", company.tin AS "customerTin", COALESCE(company.contact_person_phone, company.phone, company.general_manager_phone, company.etrade_phone) AS "customerPhone", + bc.container_numbers AS "containerNumber", + bc.container_quantity AS "containerQuantity", + bc.container_packaging_type AS "containerPackagingType", (NULLIF(TRIM(COALESCE(b.last_mile_delivery_address, '')), '') IS NOT NULL OR COALESCE(st.includes_last_mile, false)) AS "lastMileRequested", oy.code AS "origin", @@ -665,6 +672,7 @@ export class WarehouseInventoryService { dy.country AS "destinationCountry", b.freight_type AS "freightType", COALESCE(ct.cargo_type_name, b.cargo_free_text) AS "cargo", + COALESCE(ct.cargo_type_name, b.cargo_free_text) AS "cargoDescription", b.cargo_total_weight_vgm AS "weight", b.payment_status AS "paymentStatus", b.status AS "status", @@ -689,6 +697,22 @@ export class WarehouseInventoryService { LEFT JOIN freight.cargo_types ct ON ct.id = b.cargo_type_id LEFT JOIN freight.service_types st ON st.id = b.service_type_id LEFT JOIN freight.warehouse_inventory inv ON inv.booking_id = b.id AND inv.deleted_at IS NULL + LEFT JOIN LATERAL ( + SELECT string_agg(NULLIF(booking_container.container_number, ''), ', ' ORDER BY booking_container.container_number) AS container_numbers, + SUM(booking_container.quantity)::int AS container_quantity, + CASE + WHEN COUNT(booking_container.id) = 0 THEN NULL + WHEN bool_or(container_type.is_reefer) THEN 'REEFER_CONTAINER' + WHEN bool_or(container_type.is_open_top) THEN 'OPEN_TOP_CONTAINER' + WHEN MIN(container_type.size_ft) = 20 THEN 'CONTAINER_20FT' + WHEN MIN(container_type.size_ft) = 40 THEN 'CONTAINER_40FT' + WHEN MIN(container_type.size_ft) = 45 THEN 'CONTAINER_45FT' + ELSE 'OTHER_CONTAINER' + END AS container_packaging_type + FROM freight.booking_container booking_container + LEFT JOIN freight.container_types container_type ON container_type.id = booking_container.container_type_id + WHERE booking_container.booking_id = b.id AND booking_container.deleted_at IS NULL + ) bc ON true LEFT JOIN LATERAL ( SELECT first_mile.id, first_mile.status, first_mile.vehicle_id FROM freight.first_mile first_mile @@ -739,6 +763,10 @@ export class WarehouseInventoryService { company.name AS "customer", company.tin AS "customerTin", COALESCE(company.contact_person_phone, company.phone, company.general_manager_phone, company.etrade_phone) AS "customerPhone", + bc.container_numbers AS "containerNumber", + bc.container_quantity AS "containerQuantity", + bc.container_packaging_type AS "containerPackagingType", + COALESCE(ct.cargo_type_name, b.cargo_free_text) AS "cargoDescription", oy.country AS "originCountry", dy.country AS "destinationCountry", (NULLIF(TRIM(COALESCE(b.first_mile_pickup_address, '')), '') IS NOT NULL OR COALESCE(st.includes_first_mile, false)) AS "hasFirstMile", @@ -758,6 +786,23 @@ export class WarehouseInventoryService { LEFT JOIN freight.yards oy ON oy.id = b.origin_yard_id LEFT JOIN freight.yards dy ON dy.id = b.destination_yard_id LEFT JOIN freight.service_types st ON st.id = b.service_type_id + LEFT JOIN freight.cargo_types ct ON ct.id = b.cargo_type_id + LEFT JOIN LATERAL ( + SELECT string_agg(NULLIF(booking_container.container_number, ''), ', ' ORDER BY booking_container.container_number) AS container_numbers, + SUM(booking_container.quantity)::int AS container_quantity, + CASE + WHEN COUNT(booking_container.id) = 0 THEN NULL + WHEN bool_or(container_type.is_reefer) THEN 'REEFER_CONTAINER' + WHEN bool_or(container_type.is_open_top) THEN 'OPEN_TOP_CONTAINER' + WHEN MIN(container_type.size_ft) = 20 THEN 'CONTAINER_20FT' + WHEN MIN(container_type.size_ft) = 40 THEN 'CONTAINER_40FT' + WHEN MIN(container_type.size_ft) = 45 THEN 'CONTAINER_45FT' + ELSE 'OTHER_CONTAINER' + END AS container_packaging_type + FROM freight.booking_container booking_container + LEFT JOIN freight.container_types container_type ON container_type.id = booking_container.container_type_id + WHERE booking_container.booking_id = b.id AND booking_container.deleted_at IS NULL + ) bc ON true LEFT JOIN LATERAL ( SELECT first_mile.id, first_mile.status, first_mile.vehicle_id FROM freight.first_mile first_mile @@ -2591,6 +2636,11 @@ export class WarehouseInventoryService { customer?: string | null; customerTin?: string | null; customerPhone?: string | null; + containerNumber?: string | null; + containerQuantity?: number | string | null; + containerPackagingType?: string | null; + cargoDescription?: string | null; + weight?: number | string | null; firstMileTruckPlateNumber?: string | null; firstMileTrailerPlateNumber?: string | null; firstMileDriverName?: string | null; @@ -2605,6 +2655,17 @@ export class WarehouseInventoryService { edrDigitalBookingId: booking.reference?.trim() || submitted.edrDigitalBookingId, tin: booking.customerTin?.trim() || submitted.tin, customerPhone: booking.customerPhone?.trim() || submitted.customerPhone, + assignedEquipmentNumber: booking.containerNumber?.trim() || submitted.assignedEquipmentNumber, + itemDescription: booking.cargoDescription?.trim() || submitted.itemDescription, + packagingType: booking.containerPackagingType?.trim() || submitted.packagingType, + unitCount: + booking.containerQuantity !== undefined && booking.containerQuantity !== null + ? Number(booking.containerQuantity) + : submitted.unitCount, + grossWeightKg: + booking.weight !== undefined && booking.weight !== null + ? Number(booking.weight) + : submitted.grossWeightKg, truckPlateNumber: booking.firstMileTruckPlateNumber?.trim() || submitted.truckPlateNumber, trailerPlateNumber: booking.firstMileTrailerPlateNumber?.trim() || submitted.trailerPlateNumber, driverName: booking.firstMileDriverName?.trim() || submitted.driverName, @@ -2622,6 +2683,11 @@ export class WarehouseInventoryService { customer?: string | null; customerTin?: string | null; customerPhone?: string | null; + containerNumber?: string | null; + containerQuantity?: number | string | null; + containerPackagingType?: string | null; + cargoDescription?: string | null; + weight?: number | string | null; firstMileTruckPlateNumber?: string | null; firstMileTrailerPlateNumber?: string | null; firstMileDriverName?: string | null; @@ -2634,6 +2700,11 @@ export class WarehouseInventoryService { company.name AS "customer", company.tin AS "customerTin", COALESCE(company.contact_person_phone, company.phone, company.general_manager_phone, company.etrade_phone) AS "customerPhone", + b.cargo_total_weight_vgm AS "weight", + COALESCE(cargo_type.cargo_type_name, b.cargo_free_text) AS "cargoDescription", + bc.container_numbers AS "containerNumber", + bc.container_quantity AS "containerQuantity", + bc.container_packaging_type AS "containerPackagingType", v.plate_number AS "firstMileTruckPlateNumber", v.trailer_plate_no AS "firstMileTrailerPlateNumber", COALESCE( @@ -2645,6 +2716,23 @@ export class WarehouseInventoryService { v.vehicle_type AS "firstMileTruckType" FROM freight.bookings b LEFT JOIN freight.companies company ON company.id = b.company_id + LEFT JOIN freight.cargo_types cargo_type ON cargo_type.id = b.cargo_type_id + LEFT JOIN LATERAL ( + SELECT string_agg(NULLIF(booking_container.container_number, ''), ', ' ORDER BY booking_container.container_number) AS container_numbers, + SUM(booking_container.quantity)::int AS container_quantity, + CASE + WHEN COUNT(booking_container.id) = 0 THEN NULL + WHEN bool_or(container_type.is_reefer) THEN 'REEFER_CONTAINER' + WHEN bool_or(container_type.is_open_top) THEN 'OPEN_TOP_CONTAINER' + WHEN MIN(container_type.size_ft) = 20 THEN 'CONTAINER_20FT' + WHEN MIN(container_type.size_ft) = 40 THEN 'CONTAINER_40FT' + WHEN MIN(container_type.size_ft) = 45 THEN 'CONTAINER_45FT' + ELSE 'OTHER_CONTAINER' + END AS container_packaging_type + FROM freight.booking_container booking_container + LEFT JOIN freight.container_types container_type ON container_type.id = booking_container.container_type_id + WHERE booking_container.booking_id = b.id AND booking_container.deleted_at IS NULL + ) bc ON true LEFT JOIN LATERAL ( SELECT first_mile.vehicle_id FROM freight.first_mile first_mile diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx index df282e224..1503718e5 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx @@ -174,11 +174,23 @@ const truckEntranceFromBookings = (bookings: EligibleBooking[]): { const ownerName = commonNonEmptyValue(bookings.map((booking) => booking.customer)); const tin = commonNonEmptyValue(bookings.map((booking) => booking.customerTin)); const customerPhone = commonNonEmptyValue(bookings.map((booking) => booking.customerPhone)); + const consigneeDetails = commonNonEmptyValue(bookings.map((booking) => booking.customer)); + const assignedEquipmentNumber = commonNonEmptyValue(bookings.map((booking) => booking.containerNumber)); + const itemDescription = commonNonEmptyValue(bookings.map((booking) => booking.cargoDescription ?? booking.cargo)); + const packagingType = commonNonEmptyValue(bookings.map((booking) => booking.containerPackagingType)); const edrDigitalBookingId = bookings.length === 1 ? bookings[0]?.reference ?? bookings[0]?.id ?? '' : commonNonEmptyValue(bookings.map((booking) => booking.reference)); const firstMileBooking = bookings.length === 1 ? bookings[0] : null; + const unitCount = + bookings.length === 1 && bookings[0]?.containerQuantity != null + ? Number(bookings[0].containerQuantity) + : ''; + const grossWeightKg = + bookings.length === 1 && bookings[0]?.weight != null + ? Number(bookings[0].weight) + : ''; const freightTypes = [...new Set(bookings.map((booking) => booking.freightType).filter(Boolean))]; const packagingFreightType = freightTypes.length === 1 && freightTypes[0] === 'CONTAINER' @@ -191,9 +203,15 @@ const truckEntranceFromBookings = (bookings: EligibleBooking[]): { form: { ...emptyTruckEntrance(), ownerName, + consigneeDetails, tin, customerPhone, edrDigitalBookingId, + assignedEquipmentNumber, + itemDescription, + packagingType, + unitCount, + grossWeightKg, truckPlateNumber: firstMileBooking?.firstMileTruckPlateNumber ?? '', trailerPlateNumber: firstMileBooking?.firstMileTrailerPlateNumber ?? '', driverName: firstMileBooking?.firstMileDriverName ?? '', diff --git a/apps/edr-freight-web/backoffice/src/types/warehouse.ts b/apps/edr-freight-web/backoffice/src/types/warehouse.ts index 08de17728..2866f6ef3 100644 --- a/apps/edr-freight-web/backoffice/src/types/warehouse.ts +++ b/apps/edr-freight-web/backoffice/src/types/warehouse.ts @@ -358,6 +358,10 @@ export interface EligibleBooking { customer: string | null; customerTin: string | null; customerPhone: string | null; + containerNumber: string | null; + containerQuantity: number | null; + containerPackagingType: string | null; + cargoDescription: string | null; lastMileRequested: boolean; direction: string; origin: string | null;