Files
ln-bi/src/server/routes/energy/query-model.ts
T
2026-09-29 10:03:45 +08:00

81 lines
2.6 KiB
TypeScript

export type CustomerKind = 'external' | 'lingniu' | 'all';
export type EnergyDateRangeKind = 'thisWeek' | 'thisMonth' | 'last15';
export interface EnergyDateRange {
start: string;
end: string;
}
const YMD_RE = /^\d{4}-\d{2}-\d{2}$/;
// 主数据 ID 341:佛山南海羚牛加氢站。车牌文字存在不代表已关联车辆。
const FOSHAN_LINGNIU_STATION_ID = 341;
// 日明细账本使用别名 b;两类互斥,其他订单继续保留在原羚牛范围内。
export function customerClause(customer: CustomerKind): string {
const external = `(COALESCE(b.station_id, 0) = ${FOSHAN_LINGNIU_STATION_ID} AND b.vehicle_id IS NULL)`;
if (customer === 'external') return external;
if (customer === 'lingniu') return `NOT ${external}`;
return '1=1';
}
function formatYmd(date: Date): string {
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}
function addDays(date: Date, days: number): Date {
const next = new Date(date);
next.setDate(next.getDate() + days);
return next;
}
function parseYmd(value: string | undefined): string | null {
if (!value || !YMD_RE.test(value)) return null;
const date = new Date(`${value}T00:00:00`);
return Number.isNaN(date.getTime()) ? null : value;
}
export function resolveDateRange(
range: EnergyDateRangeKind,
startParam?: string,
endParam?: string,
now: Date = new Date(),
): EnergyDateRange {
const customStart = parseYmd(startParam);
const customEnd = parseYmd(endParam);
if (customStart && customEnd) {
return customStart <= customEnd
? { start: customStart, end: customEnd }
: { start: customEnd, end: customStart };
}
const today = new Date(now);
today.setHours(0, 0, 0, 0);
if (range === 'thisWeek') {
const day = today.getDay() || 7;
return { start: formatYmd(addDays(today, -(day - 1))), end: formatYmd(today) };
}
if (range === 'thisMonth') {
return {
start: formatYmd(new Date(today.getFullYear(), today.getMonth(), 1)),
end: formatYmd(today),
};
}
return { start: formatYmd(addDays(today, -14)), end: formatYmd(today) };
}
export function dateRangeClause(localExpression: string): string {
return `${localExpression} >= ? AND ${localExpression} < DATE_ADD(?, INTERVAL 1 DAY)`;
}
export function enumerateDateRange(startYmd: string, endYmd: string): string[] {
const result: string[] = [];
const cursor = new Date(`${startYmd}T00:00:00`);
const end = new Date(`${endYmd}T00:00:00`);
while (cursor <= end) {
result.push(formatYmd(cursor));
cursor.setDate(cursor.getDate() + 1);
}
return result;
}