feat(warehouses): filters, pagination and charts on container returns

Returned-containers list now uses the shared DataTable + useListControls
(search, inclusive date range, status select, pagination) instead of a
hand-rolled table. Adds two charts below the list — returns per day by
truck type and returns by status — driven by the same filtered rows.
Series colors validated for CVD separation and surface contrast.
This commit is contained in:
Hagernesh
2026-08-04 09:54:15 +00:00
parent 87b04973d8
commit 50fab52b1c
3 changed files with 287 additions and 79 deletions

View File

@@ -2,8 +2,10 @@ import { Injectable, Logger } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { Booking } from '../modules/bookings/entities/booking.entity';
import { CustomerTruckAssignment } from '../modules/bookings/entities/customer-truck-assignment.entity';
import { CargoType } from '../modules/rule-engine/entities/cargo-type.entity';
import { CompanyProfile } from '../modules/companies/entities/company-profile.entity';
import { EmptyContainerReturn } from '../modules/import-operations/entities/empty-container-return.entity';
import { Locomotive } from '../modules/locomotives/entities/locomotive.entity';
import { ServiceType } from '../modules/rule-engine/entities/service-type.entity';
import { Yard } from '../modules/rule-engine/entities/yard.entity';
@@ -23,6 +25,8 @@ import { WarehouseZone } from '../modules/warehouses/entities/warehouse-zone.ent
* Import → Arrive Queue : an ARRIVED import train with IN_TRANSIT bookings (no inventory)
* Import → Unloaded Queue : UNLOADED import inventory
* Import → Dispatch Queue : READY_FOR_PICKUP import inventory (PASSED)
* Import → Import Trucks : a customer self-haul truck assigned to an unloaded booking
* Import → Container Returns : empty container returns at two different statuses
*
* Idempotent: guarded on a sentinel booking reference. Uses dedicated WH-DEMO-* references so it
* never collides with other seeders. To repopulate after items are walked through their lifecycle,
@@ -166,16 +170,19 @@ export class WarehouseDemoSeeder {
}
// 4) Import Unloaded Queue — UNLOADED import inventory (not inspected, not stored).
let firstUnloadedBooking: Booking | null = null;
for (let i = 1; i <= 3; i++) {
const b = await makeBooking(`WH-DEMO-UNL-${i}`, 'IMPORT', 'IN_TRANSIT', 5000 + i * 500, i);
await makeInventory(b, 'UNLOADED', 5000 + i * 500, {
arrivedAt: ago(90),
unloadedAt: ago(45),
});
firstUnloadedBooking ??= b;
created++;
}
// 5) Import Dispatch Queue — READY_FOR_PICKUP import inventory (inspection PASSED).
let firstPickupBooking: Booking | null = null;
for (let i = 1; i <= 3; i++) {
const b = await makeBooking(`WH-DEMO-PKR-${i}`, 'IMPORT', 'IN_TRANSIT', 5500 + i * 500, i);
await makeInventory(b, 'READY_FOR_PICKUP', 5500 + i * 500, {
@@ -185,6 +192,50 @@ export class WarehouseDemoSeeder {
inspectedAt: ago(120),
readyForPickupAt: ago(60),
});
firstPickupBooking ??= b;
created++;
}
// 6) Import Trucks / booking Trucks tab — a customer self-haul truck on the unloaded booking.
if (firstUnloadedBooking) {
await this.dataSource.getRepository(CustomerTruckAssignment).save(
this.dataSource.getRepository(CustomerTruckAssignment).create({
bookingId: firstUnloadedBooking.id,
plateNumber: 'WH-DEMO-3210',
driverName: 'Demo Driver',
truckType: 'FLATBED',
assignedAt: ago(80),
arrivedAt: ago(50),
}),
);
created++;
}
// 7) Container Returns — two empty returns at different stages of the return workflow.
if (firstPickupBooking) {
const returnRepo = this.dataSource.getRepository(EmptyContainerReturn);
await returnRepo.save(
returnRepo.create({
containerNumber: 'WHDU1234561',
bookingId: firstPickupBooking.id,
returnDate: ago(20),
facility: 'Indode',
status: 'RETURNED',
returnedBy: 'CUSTOMER',
statusHistory: [],
}),
);
await returnRepo.save(
returnRepo.create({
containerNumber: 'WHDU1234562',
bookingId: firstPickupBooking.id,
returnDate: ago(90),
facility: 'Indode',
status: 'DOCUMENTATION_CLEARED',
returnedBy: 'CUSTOMER',
statusHistory: [],
}),
);
created++;
}