From 033af1581497b47360c8336262894aab3a265669 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Thu, 16 Apr 2026 20:47:00 +0800 Subject: [PATCH] fix(scheduling): include soft-deleted trucks and infer type from target name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 411 of 451 assessment vehicles had is_deleted=1 in tab_truck, causing type classification to fall back to "其他" and miss all inventory matches. Fix: - Remove is_deleted=0 filter from truck type query (assessment vehicles need type info regardless) - Add inferTypeFromTargetName() fallback deriving type from target name when truck record is missing Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server/routes/scheduling/suggestions.ts | 29 ++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/server/routes/scheduling/suggestions.ts b/src/server/routes/scheduling/suggestions.ts index d1cf8cb..67ebba6 100644 --- a/src/server/routes/scheduling/suggestions.ts +++ b/src/server/routes/scheduling/suggestions.ts @@ -12,6 +12,20 @@ import type { AuthUser } from '../../auth/types.js'; // Helper: vehicle type classification // --------------------------------------------------------------------------- +/** + * Infer vehicle type from target name when truck table has no match. + * e.g. "交投190辆4.5T冷链车" → "4.5T冷链", "羚牛100辆18T" → "18T" + */ +function inferTypeFromTargetName(targetName: string): string { + const t = targetName || ''; + if (t.includes('冷链')) return '4.5T冷链'; + if (t.includes('普货') || (t.includes('4.5') && !t.includes('冷链'))) return '4.5T普货'; + if (t.includes('18T') || t.includes('18t')) return '18T'; + if (t.includes('49') || t.includes('牵引')) return '49T'; + if (t.includes('挂车')) return '挂车'; + return '其他'; +} + /** * Classify vehicle type from dic_type.dic_name (e.g. "4.5吨冷链车", "4.5吨货车", "18吨双飞翼货车"). * The typeName is the full label from the dictionary, modelRaw is the numeric dic_code. @@ -63,12 +77,14 @@ app.get('/', async (c) => { const vehicleInfoMap = await fetchVehicleInfoMap(); // ---- Query 4: Vehicle types from tab_truck ---- + // Include soft-deleted trucks: many assessment vehicles have is_deleted=1 in tab_truck + // but are still active in the assessment. We need their type info. const [truckTypeRows] = await pool.execute(` SELECT truck.plate_number, dic_type.dic_name AS type_name, truck.model AS model_raw FROM tab_truck truck LEFT JOIN tab_dic dic_type ON dic_type.parent_code = 'dic_truck_type' AND dic_type.dic_code = truck.model AND dic_type.is_deleted = 0 - WHERE truck.is_deleted = 0 AND truck.is_operation = 1 + WHERE truck.is_operation = 1 `) as [any[], unknown]; const truckTypeMap = new Map(); @@ -170,9 +186,14 @@ app.get('/', async (c) => { const city = loc?.city || ''; const region = mapRegion(province, city); - const vehicleType = truckType - ? classifyVehicleType(truckType.typeName, truckType.modelRaw) - : '其他'; + // Determine vehicle type: prefer truck table, fallback to target name + let vehicleType = '其他'; + if (truckType) { + vehicleType = classifyVehicleType(truckType.typeName, truckType.modelRaw); + } else { + // Fallback: infer from target name (e.g. "交投190辆4.5T冷链车" → "4.5T冷链") + vehicleType = inferTypeFromTargetName(target.targetName); + } const endDate = row.current_year_assessment_end_date ? new Date(row.current_year_assessment_end_date)