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.
438 lines
18 KiB
TypeScript
438 lines
18 KiB
TypeScript
import pool from '../../db.js';
|
|
import type { Vehicle, VehicleRow } from '../../types.js';
|
|
import { transformRow } from './model.js';
|
|
import type { WeeklyTruckIds } from './types.js';
|
|
|
|
interface Database {
|
|
query<T = any[]>(sql: string, values?: any[]): Promise<[T, ...any[]]>;
|
|
}
|
|
|
|
type FlowType = 'delivered' | 'returned' | 'replaced';
|
|
|
|
export type WeeklyDetailType = FlowType | 'pending' | 'new';
|
|
|
|
export interface FlowDetailRow {
|
|
id: string;
|
|
type: FlowType;
|
|
type_label: string;
|
|
stat_date: string;
|
|
truck_id: string;
|
|
plate_number: string;
|
|
event_time: string | null;
|
|
submit_time: string | null;
|
|
department: string | null;
|
|
manager: string | null;
|
|
customer_name: string | null;
|
|
}
|
|
|
|
interface WeeklyStats {
|
|
pendingDelivery: number;
|
|
weeklyNew: number;
|
|
weeklyRemoved: number;
|
|
weeklyDelivered: number;
|
|
weeklyReturned: number;
|
|
weeklyReplaced: number;
|
|
}
|
|
|
|
export const MAIN_SQL = `SELECT
|
|
CAST(vi.id AS CHAR) AS id,
|
|
vi.plate_number AS 车牌号,
|
|
vi.vin AS vin,
|
|
vm.brand AS 车辆品牌,
|
|
vm.model AS 车辆型号,
|
|
vi.body_color AS 车辆颜色,
|
|
vi.rental_company AS 租赁公司,
|
|
CASE vi.vehicle_source
|
|
WHEN '0' THEN '自有'
|
|
WHEN '1' THEN '挂靠'
|
|
WHEN '2' THEN '外租'
|
|
WHEN '3' THEN '自有'
|
|
ELSE vi.actual_ownership
|
|
END AS 车辆归属状态Label,
|
|
vm.model AS 车辆型号Label,
|
|
vm.vehicle_type AS 车辆类型参数,
|
|
vi.operation_city AS 库存区域,
|
|
vs.vehicle_status AS 车辆租赁状态,
|
|
vs.operation_status AS 车辆租赁状态Label,
|
|
CASE WHEN COALESCE(vs.operation_status, '') = '5' THEN 0 ELSE 1 END AS 是否营运,
|
|
COALESCE(info_province.NAME, NULLIF(info.province, ''), vi.province_name, vi_province.NAME, NULLIF(vi.province, '')) AS 省,
|
|
COALESCE(info_city.NAME, NULLIF(info.city, ''), vi.city_name, vi_city.NAME, vi_operation_city.NAME, NULLIF(vi.city, ''), NULLIF(vi.operation_city, '')) AS 市,
|
|
info.lat AS 纬度,
|
|
info.lng AS 经度,
|
|
CASE vm.brand
|
|
WHEN 'hyundai' THEN CASE WHEN vm.model LIKE '%帕力安%' OR vm.model LIKE '%冷链%' OR vm.model LIKE '%双飞翼%' THEN '帕力安牌' ELSE '现代' END
|
|
WHEN 'yuejin' THEN '跃进'
|
|
WHEN 'feichi' THEN '飞驰'
|
|
WHEN 'sulong' THEN '苏龙'
|
|
WHEN 'higer' THEN '海格'
|
|
WHEN 'dongfeng' THEN '东风'
|
|
WHEN 'yutong' THEN '宇通'
|
|
WHEN 'chufeng' THEN '楚风'
|
|
WHEN 'tonghua' THEN '通华'
|
|
WHEN 'maxus' THEN '大通'
|
|
WHEN 'mingwei' THEN '明威'
|
|
WHEN 'wanfeng' THEN '万风'
|
|
WHEN 'shujie' THEN '舒捷'
|
|
WHEN 'denza' THEN '腾势'
|
|
WHEN 'hongyan' THEN '红岩'
|
|
WHEN 'yuanchang brand' THEN '远程牌'
|
|
WHEN 'others' THEN '其他'
|
|
ELSE vm.brand
|
|
END AS 车辆品牌Label,
|
|
c.id AS 合同ID,
|
|
COALESCE(c.contract_code, vor.contract_code, vi.contract_code) AS 合同编码,
|
|
COALESCE(c.customer_name, vor.customer_name, ci.customer_name) AS 客户名称,
|
|
c.signing_company AS 合同归属公司,
|
|
COALESCE(c.business_department_name, vor.business_dept) AS 合同归属部门,
|
|
NULLIF(vi.registered_ownership, '') AS 主体,
|
|
COALESCE(c.project_name, vor.project_name) AS 项目名称,
|
|
COALESCE(c.business_manager_name, vor.business_manager) AS 客户经理,
|
|
CAST(COALESCE(c.business_manager_id, vi.business_id) AS CHAR) AS 经理ID
|
|
FROM vehicle_info vi
|
|
LEFT JOIN vehicle_status vs
|
|
ON vs.vehicle_id = vi.id
|
|
AND vs.del_flag = 0
|
|
LEFT JOIN vehicle_model vm
|
|
ON vm.id = vi.vehicle_model_id
|
|
AND vm.del_flag = '0'
|
|
LEFT JOIN tab_truck_remote_sync_realtime_info info
|
|
ON info.plate_number = vi.plate_number
|
|
AND info.is_deleted = 0
|
|
LEFT JOIN common_district info_province
|
|
ON info_province.CODE = info.province COLLATE utf8mb4_unicode_ci
|
|
AND info_province.STATUS = 'VALID'
|
|
LEFT JOIN common_district info_city
|
|
ON info_city.CODE = info.city COLLATE utf8mb4_unicode_ci
|
|
AND info_city.STATUS = 'VALID'
|
|
LEFT JOIN common_district vi_province
|
|
ON vi_province.CODE = vi.province COLLATE utf8mb4_unicode_ci
|
|
AND vi_province.STATUS = 'VALID'
|
|
LEFT JOIN common_district vi_city
|
|
ON vi_city.CODE = vi.city COLLATE utf8mb4_unicode_ci
|
|
AND vi_city.STATUS = 'VALID'
|
|
LEFT JOIN common_district vi_operation_city
|
|
ON vi_operation_city.CODE = vi.operation_city COLLATE utf8mb4_unicode_ci
|
|
AND vi_operation_city.STATUS = 'VALID'
|
|
LEFT JOIN vehicle_lease_order_record vor
|
|
ON vor.vehicle_id = vi.id
|
|
AND vor.del_flag = '0'
|
|
AND vor.id = (
|
|
SELECT MAX(vor2.id)
|
|
FROM vehicle_lease_order_record vor2
|
|
WHERE vor2.vehicle_id = vi.id
|
|
AND vor2.del_flag = '0'
|
|
)
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.order_id = vor.contract_id
|
|
AND c.del_flag = '0'
|
|
LEFT JOIN customer_info ci
|
|
ON ci.id = vi.customer_id
|
|
AND ci.del_flag = '0'
|
|
WHERE vi.del_flag = '0'
|
|
AND COALESCE(vs.operation_status, '') <> '5'`;
|
|
|
|
// Week range: last Saturday 00:00 to this Friday 23:59
|
|
// MySQL: WEEKDAY() returns 0=Monday..6=Sunday, Saturday=5
|
|
// "上周六-本周五": offset from today to last Saturday
|
|
export const WEEK_START_SQL = `DATE_SUB(CURDATE(), INTERVAL (WEEKDAY(CURDATE()) + 2) % 7 DAY)`;
|
|
export const WEEK_END_SQL = `DATE_ADD(${WEEK_START_SQL}, INTERVAL 7 DAY)`;
|
|
|
|
export const WEEKLY_TRUCK_ID_SQLS = [
|
|
`SELECT CAST(vehicle_id AS CHAR) AS truck_id
|
|
FROM vehicle_status
|
|
WHERE del_flag=0 AND vehicle_status='4' AND COALESCE(operation_status, '') <> '5'`,
|
|
`SELECT CAST(vehicle_id AS CHAR) AS truck_id
|
|
FROM delivery_vehicle
|
|
WHERE del_flag='0'
|
|
AND vehicle_id IS NOT NULL
|
|
AND delivery_time >= ${WEEK_START_SQL} AND delivery_time < ${WEEK_END_SQL}
|
|
AND delivery_status IN (2,3,5)`,
|
|
`SELECT CAST(vehicle_id AS CHAR) AS truck_id
|
|
FROM return_vehicle_task
|
|
WHERE del_flag='0'
|
|
AND vehicle_id IS NOT NULL
|
|
AND arrival_time >= ${WEEK_START_SQL} AND arrival_time < ${WEEK_END_SQL}
|
|
AND status IN (2,3,5)`,
|
|
`SELECT CAST(new_vehicle_id AS CHAR) AS truck_id
|
|
FROM vehicle_replacement
|
|
WHERE del_flag='0'
|
|
AND new_vehicle_id IS NOT NULL
|
|
AND replace_time >= ${WEEK_START_SQL} AND replace_time < ${WEEK_END_SQL}
|
|
AND status=20`,
|
|
] as const;
|
|
|
|
// 交车单 SQL
|
|
const DELIVERED_SQL = `SELECT
|
|
dv.id, DATE(dv.delivery_time) AS handover_date,
|
|
CAST(dv.vehicle_id AS CHAR) AS truck_id, dv.plate_number,
|
|
c.contract_type,
|
|
COALESCE(dts.customer_name, c.customer_name) AS customer_name
|
|
FROM delivery_vehicle dv
|
|
LEFT JOIN delivery_task_subject dts
|
|
ON dts.id = dv.delivery_task_subject_id
|
|
AND dts.del_flag = '0'
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.order_id = dv.contract_id
|
|
AND c.del_flag = '0'
|
|
WHERE dv.del_flag = '0'
|
|
AND dv.vehicle_id IS NOT NULL
|
|
AND dv.delivery_time IS NOT NULL
|
|
AND dv.delivery_status IN (2,3,5)`;
|
|
|
|
// 还车单 SQL
|
|
const RETURNED_SQL = `SELECT
|
|
r.id, DATE(r.arrival_time) AS handover_date,
|
|
CAST(r.vehicle_id AS CHAR) AS truck_id, r.plate_number,
|
|
c.contract_type,
|
|
COALESCE(dts.customer_name, c.customer_name) AS customer_name
|
|
FROM return_vehicle_task r
|
|
LEFT JOIN delivery_task_subject dts
|
|
ON dts.id = r.delivery_task_subject_id
|
|
AND dts.del_flag = '0'
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.order_id = r.contract_id
|
|
AND c.del_flag = '0'
|
|
WHERE r.del_flag = '0'
|
|
AND r.vehicle_id IS NOT NULL
|
|
AND r.arrival_time IS NOT NULL
|
|
AND r.status IN (2,3,5)`;
|
|
|
|
// 替换车单 SQL
|
|
const REPLACED_SQL = `SELECT
|
|
vr.id, DATE(vr.replace_time) AS handover_date,
|
|
CAST(vr.new_vehicle_id AS CHAR) AS truck_id, vr.new_vehicle_plate AS plate_number,
|
|
c.contract_type,
|
|
c.customer_name
|
|
FROM vehicle_replacement vr
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.id = vr.contract_id
|
|
AND c.del_flag = '0'
|
|
WHERE vr.del_flag = '0'
|
|
AND vr.new_vehicle_id IS NOT NULL
|
|
AND vr.replace_time IS NOT NULL
|
|
AND vr.status = 20`;
|
|
|
|
export const WEEKLY_DETAIL_SQL: Record<WeeklyDetailType, string> = {
|
|
delivered: `${DELIVERED_SQL} AND dv.delivery_time >= ${WEEK_START_SQL} AND dv.delivery_time < ${WEEK_END_SQL} ORDER BY dv.delivery_time DESC`,
|
|
returned: `${RETURNED_SQL} AND r.arrival_time >= ${WEEK_START_SQL} AND r.arrival_time < ${WEEK_END_SQL} ORDER BY r.arrival_time DESC`,
|
|
replaced: `${REPLACED_SQL} AND vr.replace_time >= ${WEEK_START_SQL} AND vr.replace_time < ${WEEK_END_SQL} ORDER BY vr.replace_time DESC`,
|
|
pending: `SELECT CAST(vi.id AS CHAR) AS truck_id, vi.plate_number, NULL AS handover_date, NULL AS contract_type, NULL AS customer_name
|
|
FROM vehicle_info vi
|
|
LEFT JOIN vehicle_status vs ON vs.vehicle_id=vi.id AND vs.del_flag=0
|
|
WHERE vi.del_flag='0' AND vs.vehicle_status='4' AND COALESCE(vs.operation_status, '') <> '5'`,
|
|
new: `SELECT CAST(vi.id AS CHAR) AS truck_id, vi.plate_number, vi.create_time AS handover_date, NULL AS contract_type, NULL AS customer_name
|
|
FROM vehicle_info vi
|
|
LEFT JOIN vehicle_status vs ON vs.vehicle_id=vi.id AND vs.del_flag=0
|
|
WHERE vi.del_flag='0' AND COALESCE(vs.operation_status, '') <> '5'
|
|
AND vi.create_time >= ${WEEK_START_SQL} AND vi.create_time < ${WEEK_END_SQL} ORDER BY vi.create_time DESC`,
|
|
};
|
|
|
|
export const FLOW_STATS_SQL = `
|
|
SELECT *
|
|
FROM (
|
|
SELECT
|
|
CONCAT(CASE WHEN dv.vehicle_replacement_id IS NOT NULL THEN 'replaced-' ELSE 'delivered-' END, dv.id) AS id,
|
|
CASE WHEN dv.vehicle_replacement_id IS NOT NULL THEN 'replaced' ELSE 'delivered' END AS type,
|
|
CASE WHEN dv.vehicle_replacement_id IS NOT NULL THEN '替换交车' ELSE '交车' END AS type_label,
|
|
DATE_FORMAT(dv.delivery_completion_processed_time, '%Y-%m-%d') AS stat_date,
|
|
CAST(dv.vehicle_id AS CHAR) AS truck_id,
|
|
dv.plate_number,
|
|
DATE_FORMAT(dv.delivery_completion_processed_time, '%Y-%m-%d %H:%i:%s') AS event_time,
|
|
DATE_FORMAT(dv.create_time, '%Y-%m-%d %H:%i:%s') AS submit_time,
|
|
c.business_department_name AS department,
|
|
c.business_manager_name AS manager,
|
|
COALESCE(dts.customer_name, c.customer_name) AS customer_name
|
|
FROM delivery_vehicle dv
|
|
LEFT JOIN delivery_task_subject dts
|
|
ON dts.id = dv.delivery_task_subject_id
|
|
AND dts.del_flag = '0'
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.order_id = dv.contract_id
|
|
AND c.del_flag = '0'
|
|
WHERE dv.del_flag = '0'
|
|
AND dv.vehicle_id IS NOT NULL
|
|
AND dv.delivery_completion_processed_time IS NOT NULL
|
|
AND dv.delivery_status IN (2,3,20)
|
|
AND (dts.status IS NULL OR dts.status <> 10)
|
|
AND dv.delivery_completion_processed_time >= ?
|
|
AND dv.delivery_completion_processed_time < DATE_ADD(?, INTERVAL 1 DAY)
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
CONCAT('returned-', r.id) AS id,
|
|
'returned' AS type,
|
|
'还车' AS type_label,
|
|
DATE_FORMAT(r.return_completion_processed_time, '%Y-%m-%d') AS stat_date,
|
|
CAST(r.vehicle_id AS CHAR) AS truck_id,
|
|
r.plate_number,
|
|
DATE_FORMAT(r.return_completion_processed_time, '%Y-%m-%d %H:%i:%s') AS event_time,
|
|
DATE_FORMAT(r.create_time, '%Y-%m-%d %H:%i:%s') AS submit_time,
|
|
c.business_department_name AS department,
|
|
c.business_manager_name AS manager,
|
|
COALESCE(dts.customer_name, c.customer_name) AS customer_name
|
|
FROM return_vehicle_task r
|
|
LEFT JOIN delivery_task_subject dts
|
|
ON dts.id = r.delivery_task_subject_id
|
|
AND dts.del_flag = '0'
|
|
LEFT JOIN vehicle_lease_contract_info c
|
|
ON c.order_id = r.contract_id
|
|
AND c.del_flag = '0'
|
|
WHERE r.del_flag = '0'
|
|
AND r.vehicle_id IS NOT NULL
|
|
AND r.return_completion_processed_time IS NOT NULL
|
|
-- 与还车管理历史记录一致:完成、已签章、待签署;日期按运维签章时间归属。
|
|
AND r.status IN (2,3,5)
|
|
AND r.return_completion_processed_time >= ?
|
|
AND r.return_completion_processed_time < DATE_ADD(?, INTERVAL 1 DAY)
|
|
|
|
) flow
|
|
ORDER BY flow.event_time DESC, flow.id DESC
|
|
`;
|
|
|
|
const CACHE_TTL = 60 * 1000;
|
|
|
|
export class VehicleRepository {
|
|
private cachedVehicles: Vehicle[] = [];
|
|
private lastFetchTime = 0;
|
|
private cachedWeeklyTruckIds: WeeklyTruckIds | null = null;
|
|
private weeklyTruckIdsLastFetch = 0;
|
|
private cachedWeeklyStats: WeeklyStats | null = null;
|
|
private weeklyStatsLastFetch = 0;
|
|
|
|
constructor(
|
|
private readonly db: Database,
|
|
private readonly now: () => number = Date.now,
|
|
private readonly mapVehicleRow: (row: VehicleRow) => Vehicle = transformRow,
|
|
) {}
|
|
|
|
async getVehicles(): Promise<Vehicle[]> {
|
|
const now = this.now();
|
|
if (this.cachedVehicles.length > 0 && now - this.lastFetchTime < CACHE_TTL) {
|
|
return this.cachedVehicles;
|
|
}
|
|
const [rows] = await this.db.query<any[]>(MAIN_SQL);
|
|
this.cachedVehicles = (rows as VehicleRow[]).map(this.mapVehicleRow);
|
|
this.lastFetchTime = now;
|
|
return this.cachedVehicles;
|
|
}
|
|
|
|
async getWeeklyTruckIds(): Promise<WeeklyTruckIds> {
|
|
const now = this.now();
|
|
if (this.cachedWeeklyTruckIds && now - this.weeklyTruckIdsLastFetch < CACHE_TTL) {
|
|
return this.cachedWeeklyTruckIds;
|
|
}
|
|
|
|
const [[pendingRows], [deliveredRows], [returnedRows], [replacedRows]] = await Promise.all(
|
|
WEEKLY_TRUCK_ID_SQLS.map((sql) => this.db.query<any[]>(sql)),
|
|
);
|
|
const toSet = (rows: any[]) => new Set(rows.map((r) => String(r.truck_id)).filter((s) => s && s !== 'null'));
|
|
this.cachedWeeklyTruckIds = {
|
|
pending: toSet(pendingRows as any[]),
|
|
delivered: toSet(deliveredRows as any[]),
|
|
returned: toSet(returnedRows as any[]),
|
|
replaced: toSet(replacedRows as any[]),
|
|
};
|
|
this.weeklyTruckIdsLastFetch = now;
|
|
return this.cachedWeeklyTruckIds;
|
|
}
|
|
|
|
async getWeeklyStats(): Promise<WeeklyStats> {
|
|
const now = this.now();
|
|
if (this.cachedWeeklyStats && now - this.weeklyStatsLastFetch < CACHE_TTL) {
|
|
return this.cachedWeeklyStats;
|
|
}
|
|
|
|
const [[pendingRows], [newRows], [removedRows], [deliveredRows], [returnedRows], [replacedRows]] = await Promise.all([
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM vehicle_status WHERE del_flag=0 AND vehicle_status='4' AND COALESCE(operation_status, '') <> '5'`),
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM vehicle_info WHERE del_flag='0' AND create_time >= ${WEEK_START_SQL} AND create_time < ${WEEK_END_SQL}`),
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM vehicle_info vi LEFT JOIN vehicle_status vs ON vs.vehicle_id=vi.id AND vs.del_flag=0 WHERE (vi.del_flag='1' OR vs.operation_status='5') AND vi.update_time >= ${WEEK_START_SQL} AND vi.update_time < ${WEEK_END_SQL}`),
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM delivery_vehicle
|
|
WHERE del_flag='0' AND delivery_time IS NOT NULL AND delivery_status IN (2,3,5)
|
|
AND delivery_time >= ${WEEK_START_SQL} AND delivery_time < ${WEEK_END_SQL}`),
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM return_vehicle_task
|
|
WHERE del_flag='0' AND arrival_time IS NOT NULL AND status IN (2,3,5)
|
|
AND arrival_time >= ${WEEK_START_SQL} AND arrival_time < ${WEEK_END_SQL}`),
|
|
this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM vehicle_replacement
|
|
WHERE del_flag='0' AND replace_time IS NOT NULL AND status=20
|
|
AND replace_time >= ${WEEK_START_SQL} AND replace_time < ${WEEK_END_SQL}`),
|
|
]);
|
|
|
|
this.cachedWeeklyStats = {
|
|
pendingDelivery: (pendingRows as any[])[0]?.cnt || 0,
|
|
weeklyNew: (newRows as any[])[0]?.cnt || 0,
|
|
weeklyRemoved: (removedRows as any[])[0]?.cnt || 0,
|
|
weeklyDelivered: (deliveredRows as any[])[0]?.cnt || 0,
|
|
weeklyReturned: (returnedRows as any[])[0]?.cnt || 0,
|
|
weeklyReplaced: (replacedRows as any[])[0]?.cnt || 0,
|
|
};
|
|
this.weeklyStatsLastFetch = now;
|
|
return this.cachedWeeklyStats;
|
|
}
|
|
|
|
invalidateRefreshCaches(): void {
|
|
this.lastFetchTime = 0;
|
|
this.weeklyStatsLastFetch = 0;
|
|
}
|
|
|
|
async getRealtimeMileageRows(): Promise<any[]> {
|
|
const [rows] = await this.db.query<any[]>(`
|
|
SELECT plate_number, day_mileage
|
|
FROM tab_truck_remote_sync_realtime_info
|
|
WHERE is_deleted = 0 AND plate_number IS NOT NULL
|
|
`);
|
|
return rows;
|
|
}
|
|
|
|
async getAttendanceMileageRows(): Promise<any[]> {
|
|
const [rows] = await this.db.query<any[]>(`SELECT plate_number, day_mileage FROM tab_truck_remote_sync_realtime_info WHERE is_deleted = 0 AND plate_number IS NOT NULL`);
|
|
return rows;
|
|
}
|
|
|
|
async getWeeklyDetailRows(type: WeeklyDetailType): Promise<any[]> {
|
|
const [rows] = await this.db.query<any[]>(WEEKLY_DETAIL_SQL[type]);
|
|
return rows;
|
|
}
|
|
|
|
async getFlowDetailRows(start: string, end: string): Promise<FlowDetailRow[]> {
|
|
const [rows] = await this.db.query<any[]>(FLOW_STATS_SQL, [start, end, start, end]);
|
|
return rows as FlowDetailRow[];
|
|
}
|
|
|
|
async getWeeklyDebugData(): Promise<{
|
|
dateRange: any;
|
|
deliveredAll: any;
|
|
deliveredRecent: any;
|
|
latestTake: any;
|
|
returnedRecent: any;
|
|
latestReturn: any;
|
|
}> {
|
|
const [[dateRange]] = await this.db.query<any[]>(`SELECT
|
|
${WEEK_START_SQL} AS week_start,
|
|
${WEEK_END_SQL} AS week_end,
|
|
CURDATE() AS today,
|
|
WEEKDAY(CURDATE()) AS weekday`);
|
|
const [[deliveredAll]] = await this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM delivery_vehicle
|
|
WHERE del_flag='0' AND delivery_time IS NOT NULL AND delivery_status IN (2,3,5)`);
|
|
const [[deliveredRecent]] = await this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM delivery_vehicle
|
|
WHERE del_flag='0' AND delivery_time IS NOT NULL AND delivery_status IN (2,3,5)
|
|
AND delivery_time >= ${WEEK_START_SQL} AND delivery_time < ${WEEK_END_SQL}`);
|
|
const [[latestTake]] = await this.db.query<any[]>(`SELECT MAX(delivery_time) AS latest FROM delivery_vehicle
|
|
WHERE del_flag='0' AND delivery_time IS NOT NULL AND delivery_status IN (2,3,5)`);
|
|
const [[returnedRecent]] = await this.db.query<any[]>(`SELECT COUNT(*) AS cnt FROM return_vehicle_task
|
|
WHERE del_flag='0' AND arrival_time IS NOT NULL AND status IN (2,3,5)
|
|
AND arrival_time >= ${WEEK_START_SQL} AND arrival_time < ${WEEK_END_SQL}`);
|
|
const [[latestReturn]] = await this.db.query<any[]>(`SELECT MAX(arrival_time) AS latest FROM return_vehicle_task
|
|
WHERE del_flag='0' AND arrival_time IS NOT NULL AND status IN (2,3,5)`);
|
|
|
|
return { dateRange, deliveredAll, deliveredRecent, latestTake, returnedRecent, latestReturn };
|
|
}
|
|
|
|
async getRealtimeProvinceRows(): Promise<any[]> {
|
|
const [rows] = await this.db.query<any[]>(`SELECT plate_number, province FROM tab_truck_remote_sync_realtime_info WHERE is_deleted = 0 AND plate_number IS NOT NULL`);
|
|
return rows;
|
|
}
|
|
}
|
|
|
|
export const vehicleRepository = new VehicleRepository(pool as unknown as Database);
|