70 lines
4.2 KiB
TypeScript
70 lines
4.2 KiB
TypeScript
import type { RowDataPacket } from 'mysql2';
|
|
import pool from '../../db.js';
|
|
import { mapFault, type RawFault } from './model.js';
|
|
|
|
// OneOS fault ledger: latest delivery first; do not reuse the active-asset WHERE clause.
|
|
export const FAULT_SQL = `SELECT
|
|
f.fault_level, f.fault_categories, f.solve_process, f.report_method,
|
|
CAST(f.source_work_order_id AS CHAR) source_work_order_id,
|
|
CAST(f.id AS CHAR) id, f.fault_code, f.plate_number, f.fault_desc, f.handling_status,
|
|
DATE_FORMAT(f.fault_report_time, '%Y-%m-%d %H:%i:%s') reported_at,
|
|
DATE_FORMAT(f.archived_at, '%Y-%m-%d %H:%i:%s') archived_at,
|
|
DATE_FORMAT(f.deadline_at, '%Y-%m-%d %H:%i:%s') deadline_at,
|
|
DATE_FORMAT(receipt.received_at, '%Y-%m-%d %H:%i:%s') received_at,
|
|
CAST(vi.id AS CHAR) matched_vehicle_id, vi.operation_city,
|
|
COALESCE(city.NAME, district.NAME) city_name, vi.registered_ownership subject,
|
|
COALESCE(province.NAME, vi.province_name) province_name,
|
|
vm.brand, vm.model model_name, vm.vehicle_type model_type, vi.body_color, vi.vehicle_source, vi.actual_ownership, vi.rental_company,
|
|
vs.operation_status, vs.vehicle_status, lease.customer_name, lease.business_dept,
|
|
lease.business_manager,
|
|
CAST(COALESCE(contract.business_manager_id, vi.business_id) AS CHAR) manager_id,
|
|
CAST(f.inspection_operator_id AS CHAR) handler_id, f.inspection_operator_name handler_name,
|
|
f.inspection_operator_ids_json handler_ids, f.inspection_operator_names_json handler_names,
|
|
CAST(wo.current_executor_user_id AS CHAR) work_id, wo.current_executor_name work_name,
|
|
CAST(wo.current_executor_user_ids_json AS CHAR) work_ids,
|
|
CAST(wo.current_executor_names_json AS CHAR) work_names
|
|
FROM vehicle_fault_manage f
|
|
LEFT JOIN (
|
|
SELECT fault_id, MIN(create_time) received_at
|
|
FROM vehicle_fault_operation_log
|
|
WHERE del_flag='0' AND action_code='SAVE_PROGRESS'
|
|
AND COALESCE(TRIM(before_status), '') IN ('', '待处理', '待处置', '未处理')
|
|
AND TRIM(after_status) IN ('处理中', '处置中', '处理')
|
|
GROUP BY fault_id
|
|
) receipt ON receipt.fault_id=f.id
|
|
LEFT JOIN vehicle_info vi ON vi.id=f.vehicle_id AND vi.del_flag='0'
|
|
LEFT JOIN vehicle_model vm ON vm.id=vi.vehicle_model_id AND vm.del_flag='0'
|
|
LEFT JOIN common_district province ON province.CODE=CONCAT(LEFT(vi.operation_city,2),'0000') COLLATE utf8mb4_unicode_ci AND province.STATUS='VALID'
|
|
LEFT JOIN vehicle_status vs ON vs.id=(
|
|
SELECT s.id FROM vehicle_status s WHERE s.vehicle_id=vi.id AND s.del_flag=0
|
|
ORDER BY s.update_time DESC, s.id DESC LIMIT 1
|
|
)
|
|
LEFT JOIN vehicle_lease_order_record lease ON lease.id=(
|
|
SELECT r.id FROM vehicle_lease_order_record r WHERE r.vehicle_id=vi.id AND r.del_flag='0'
|
|
ORDER BY r.last_delivery_time DESC, r.id DESC LIMIT 1
|
|
)
|
|
LEFT JOIN vehicle_lease_contract_info contract ON contract.id=lease.contract_id AND contract.del_flag='0'
|
|
LEFT JOIN common_district district ON district.CODE=vi.operation_city COLLATE utf8mb4_unicode_ci AND district.STATUS='VALID'
|
|
LEFT JOIN common_district city ON city.CODE=(CASE
|
|
WHEN LEFT(vi.operation_city,2) IN ('11','12','31','50') THEN CONCAT(LEFT(vi.operation_city,2),'0000')
|
|
ELSE CONCAT(LEFT(vi.operation_city,4),'00') END) COLLATE utf8mb4_unicode_ci AND city.STATUS='VALID'
|
|
LEFT JOIN task_work_order wo ON wo.id=f.source_work_order_id AND wo.del_flag='0'
|
|
WHERE f.del_flag='0' AND f.is_submit IN (0,1)`;
|
|
|
|
export async function loadFaults() {
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
await connection.query('START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY');
|
|
const [raw] = await connection.query<RowDataPacket[]>({ sql: FAULT_SQL, timeout: 20000 });
|
|
const [users] = await connection.query<RowDataPacket[]>({ sql: `SELECT CAST(user_id AS CHAR) id, nick_name name
|
|
FROM \`ry-cloud\`.sys_user WHERE del_flag='0' AND status='0'
|
|
AND (user_type IS NULL OR user_type='sys_user')`, timeout: 10000 });
|
|
const directory = new Map<string, string>(users.map(row => [String(row.id), String(row.name || '').trim()]));
|
|
// Defensive ID de-duplication keeps imperfect lookup tables from multiplying tickets.
|
|
const rows = [...new Map(raw.map(row => [String(row.id), mapFault(row as RawFault, directory)])).values()];
|
|
return { rows, updatedAt: new Date().toISOString() };
|
|
} finally {
|
|
try { await connection.rollback(); } finally { connection.release(); }
|
|
}
|
|
}
|