import assert from 'node:assert/strict'; import test from 'node:test'; import router from '../vehicles.js'; import { vehicleRepository, type FlowDetailRow } from './repository.js'; import type { Vehicle } from '../../types.js'; test('replacement trips are included in delivery counts without inflating totals or duplicating export rows', async (t) => { t.mock.method(vehicleRepository, 'getVehicles', async () => [{ id: '1' } as Vehicle]); const row = (id: string, type: FlowDetailRow['type'], date: string): FlowDetailRow => ({ id, type, type_label: type === 'replaced' ? '替换交车' : type === 'delivered' ? '交车' : '还车', stat_date: date, truck_id: '1', plate_number: '测试车牌', event_time: `${date} 12:00:00`, submit_time: '2026-09-01 12:00:00', department: null, manager: null, customer_name: null, }); t.mock.method(vehicleRepository, 'getFlowDetailRows', async () => [ row('delivered-1', 'delivered', '2026-09-15'), row('replaced-2', 'replaced', '2026-09-15'), row('returned-1', 'returned', '2026-09-15'), row('replaced-3', 'replaced', '2026-09-16'), ]); const response = await router.request('/flow-stats?start=2026-09-15&end=2026-09-17'); assert.equal(response.status, 200); const data = await response.json(); assert.deepEqual(data.totals, { delivered: 3, returned: 1, replaced: 2, total: 4 }); assert.deepEqual(data.daily, [ { date: '2026-09-15', delivered: 2, returned: 1, replaced: 1, total: 3 }, { date: '2026-09-16', delivered: 1, returned: 0, replaced: 1, total: 1 }, { date: '2026-09-17', delivered: 0, returned: 0, replaced: 0, total: 0 }, ]); assert.equal(data.details.length, 4); assert.equal(new Set(data.details.map((x: { id: string }) => x.id)).size, 4); assert.ok(data.details.filter((x: { type: string }) => x.type === 'replaced') .every((x: { typeLabel: string }) => x.typeLabel === '替换交车')); }); test('inventory excludes abnormal vehicles in totals, type rollups, regions and drilldowns', async (t) => { const vehicles = ['Inventory', 'Abnormal', 'Pending', 'Operating'].map((status, i) => ({ id: String(i), status, operationStatus: status === 'Operating' ? '1' : '3', plateNumber: `测试${i}`, model: '现代4.5T普货', type: '4.5T', location: '广东', subjectOrg: i === 1 ? '乙公司' : '甲公司', } as Vehicle)); t.mock.method(vehicleRepository, 'getVehicles', async () => vehicles); t.mock.method(vehicleRepository, 'getWeeklyTruckIds', async () => ({ pending: new Set(), delivered: new Set(), returned: new Set(), replaced: new Set(), })); const get = async (path: string) => { const response = await router.request(path); assert.equal(response.status, 200); return response.json(); }; const summary = await get('/summary'); assert.equal(summary.totalAssets, 4); assert.equal(summary.inventory.total, 1); assert.equal(summary.inventory.abnormal, 1); assert.equal(summary.totalAssets, summary.inventory.total + summary.inventory.abnormal + summary.operating.total + summary.pendingDelivery); assert.deepEqual((await get('/list?category=Inventory')).map((v: Vehicle) => v.id), ['0']); assert.deepEqual((await get('/list?category=Abnormal')).map((v: Vehicle) => v.id), ['1']); assert.deepEqual(await get('/list?category=Abnormal&subject=甲公司'), []); const groups = await get('/by-type'); assert.equal(groups.reduce((n: number, g: { totalInventory: number }) => n + g.totalInventory, 0), 1); assert.equal(groups.reduce((n: number, g: { totalAbnormal: number }) => n + g.totalAbnormal, 0), 1); const model = groups.flatMap((g: { models: unknown[] }) => g.models).find((m: { abnormal: number }) => m.abnormal === 1); assert.equal(model.inventory, 1); assert.equal(model.inventoryRegions['广东'], 1); const inventory = await get('/inventory-stats'); assert.equal(inventory.reduce((n: number, row: { quantity: number }) => n + row.quantity, 0), 1); });