fix(scheduling): include soft-deleted trucks and infer type from target name

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) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-16 20:47:00 +08:00
parent 253cc2f2c0
commit 033af15814

View File

@@ -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<string, { typeName: string; modelRaw: string }>();
@@ -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)