feat(assets): align flow statistics and separate abnormal inventory
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline failed
Use operations signing times and delivery completion statuses; include replacement deliveries in delivery totals with range drilldowns and exports. Separate abnormal vehicles from inventory, add a date range picker, and enable CI for feature/asset-statistics.
This commit is contained in:
@@ -70,7 +70,7 @@ app.get('/summary', async (c) => {
|
||||
hanging: 0,
|
||||
},
|
||||
inventory: {
|
||||
total: vehicles.filter((v) => v.status === 'Inventory' || v.status === 'Abnormal').length,
|
||||
total: vehicles.filter((v) => v.status === 'Inventory').length,
|
||||
inStock: vehicles.filter((v) => v.status === 'Inventory').length,
|
||||
abnormal: vehicles.filter((v) => v.status === 'Abnormal').length,
|
||||
},
|
||||
@@ -111,6 +111,7 @@ app.get('/by-type', async (c) => {
|
||||
type: t.name,
|
||||
totalAssets: typeVehicles.length,
|
||||
totalInventory: typeStats.inventory,
|
||||
totalAbnormal: typeStats.abnormal,
|
||||
totalOperating: typeStats.operating,
|
||||
inventoryRegions: typeStats.inventoryRegions,
|
||||
pending: typeStats.pending,
|
||||
@@ -273,6 +274,7 @@ app.get('/region-stats', async (c) => {
|
||||
total: tv.length,
|
||||
operating: tv.filter((v) => v.status === 'Operating').length,
|
||||
inventory: tv.filter((v) => v.status === 'Inventory').length,
|
||||
abnormal: tv.filter((v) => v.status === 'Abnormal').length,
|
||||
pending: tv.filter((v) => v.status === 'Pending').length,
|
||||
customers: Array.from(new Set(tv.map((v) => v.customerName).filter(Boolean))) as string[],
|
||||
});
|
||||
@@ -405,7 +407,9 @@ app.get('/list', async (c) => {
|
||||
}
|
||||
if (category) {
|
||||
if (category === 'Inventory') {
|
||||
filtered = filtered.filter((v) => v.status === 'Inventory' || v.status === 'Abnormal');
|
||||
filtered = filtered.filter((v) => v.status === 'Inventory');
|
||||
} else if (category === 'Abnormal') {
|
||||
filtered = filtered.filter((v) => v.status === 'Abnormal');
|
||||
} else if (category === 'Operating') {
|
||||
filtered = filtered.filter((v) => v.status === 'Operating');
|
||||
} else if (category === 'Pending') {
|
||||
@@ -461,7 +465,7 @@ app.get('/list', async (c) => {
|
||||
// GET /api/vehicles/inventory-stats — 库存统计,不设数据权限,对所有人开放
|
||||
app.get('/inventory-stats', async (c) => {
|
||||
const vehicles = applySubjectFilter(c, await vehicleRepository.getVehicles());
|
||||
const inventory = vehicles.filter((v) => v.status === 'Inventory' || v.status === 'Abnormal');
|
||||
const inventory = vehicles.filter((v) => v.status === 'Inventory');
|
||||
|
||||
const TYPE_NAME_MAP: Record<string, string> = {
|
||||
t4_5: '4.5T普货',
|
||||
@@ -525,7 +529,7 @@ app.get('/weekly-detail', async (c) => {
|
||||
});
|
||||
|
||||
// GET /api/vehicles/flow-stats?start=YYYY-MM-DD&end=YYYY-MM-DD
|
||||
// 资产流转日报:按提交时间(create_time)统计交车、还车、替换车,并返回可点击明细。
|
||||
// 资产流转日报:按运维签章时间统计业务车次;交车包含关联替换单的记录,替换作为其中的子项,同车多笔业务分别累计。
|
||||
app.get('/flow-stats', async (c) => {
|
||||
const { start, end } = normalizeDateRange(c.req.query('start'), c.req.query('end'));
|
||||
const allowedVehicles = await getVehiclesForUser(c);
|
||||
@@ -555,6 +559,7 @@ app.get('/flow-stats', async (c) => {
|
||||
const stat = dailyMap.get(item.date);
|
||||
if (!stat) continue;
|
||||
stat[item.type] += 1;
|
||||
if (item.type === 'replaced') stat.delivered += 1;
|
||||
stat.total += 1;
|
||||
}
|
||||
|
||||
@@ -585,7 +590,7 @@ app.get('/subjects', async (c) => {
|
||||
if (!map.has(name)) map.set(name, { total: 0, inventory: 0, operating: 0 });
|
||||
const s = map.get(name)!;
|
||||
s.total += 1;
|
||||
if (v.status === 'Inventory' || v.status === 'Abnormal') s.inventory += 1;
|
||||
if (v.status === 'Inventory') s.inventory += 1;
|
||||
if (v.status === 'Operating') s.operating += 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user