feat(energy): 电能统计切到 bi_ele_charge_record,外部数据接通
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- /api/energy/electric/overview & /electric/monthly 不再读 tab_energy_electricity_bill - 改读 bi_ele_charge_record:kwh/fee/start_time - 外部/我司用 vehicle_kind 区分(external/internal) - 电能默认 customer 由 'external' 改 'lingniu',与导入页约定一致 - ElectricDaily 移除「数据对接中…」友好空状态(外部已有数据) ele 导入页同步收紧: - 命中系统车辆=internal,未命中(含车牌为空)一律 external - 移除 unknown 分类、KPI 卡、批次列、过滤按钮、UploadResult 字段 - 历史 unknown 行已 UPDATE 为 external Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -244,24 +244,21 @@ app.get('/hydrogen/daily', async (c) => {
|
||||
});
|
||||
|
||||
// =========================================================
|
||||
// 电能 总览:KPI + 本月每日柱图数据
|
||||
// 电能 总览:KPI + 本月每日柱图数据 —— 数据源:bi_ele_charge_record
|
||||
// =========================================================
|
||||
app.get('/electric/overview', async (c) => {
|
||||
const data = await cached('electric/overview', async () => {
|
||||
const [kpiRows] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT
|
||||
SUM(charging_degree) AS totalKwh,
|
||||
SUM(cost_expense) AS totalFee,
|
||||
SUM(CASE WHEN DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN charging_degree ELSE 0 END) AS monthKwh,
|
||||
SUM(CASE WHEN DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN cost_expense ELSE 0 END) AS monthFee,
|
||||
SUM(CASE WHEN DATE(${ELECTRIC_LOCAL}) = CURDATE()
|
||||
THEN charging_degree ELSE 0 END) AS todayKwh,
|
||||
SUM(CASE WHEN DATE(${ELECTRIC_LOCAL}) = CURDATE()
|
||||
THEN cost_expense ELSE 0 END) AS todayFee
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE is_deleted = 0`,
|
||||
SUM(kwh) AS totalKwh,
|
||||
SUM(fee) AS totalFee,
|
||||
SUM(CASE WHEN DATE_FORMAT(start_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN kwh ELSE 0 END) AS monthKwh,
|
||||
SUM(CASE WHEN DATE_FORMAT(start_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
THEN fee ELSE 0 END) AS monthFee,
|
||||
SUM(CASE WHEN DATE(start_time) = CURDATE() THEN kwh ELSE 0 END) AS todayKwh,
|
||||
SUM(CASE WHEN DATE(start_time) = CURDATE() THEN fee ELSE 0 END) AS todayFee
|
||||
FROM bi_ele_charge_record`,
|
||||
);
|
||||
const k = kpiRows[0] ?? {};
|
||||
const totalKwh = Number(k.totalKwh) || 0;
|
||||
@@ -273,29 +270,25 @@ app.get('/electric/overview', async (c) => {
|
||||
|
||||
// 本月每日(用于柱图)
|
||||
const [trendRows] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m-%d') AS date,
|
||||
SUM(charging_degree) AS kwh,
|
||||
SUM(cost_expense) AS fee
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE is_deleted = 0
|
||||
AND DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
`SELECT DATE_FORMAT(start_time, '%Y-%m-%d') AS date,
|
||||
SUM(kwh) AS kwh,
|
||||
SUM(fee) AS fee
|
||||
FROM bi_ele_charge_record
|
||||
WHERE DATE_FORMAT(start_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
|
||||
GROUP BY date
|
||||
ORDER BY date ASC`,
|
||||
);
|
||||
// 若本月无数据(电能数据滞后),降级展示最近一个有数据的自然月
|
||||
// 若本月无数据,降级展示最近一个有数据的自然月
|
||||
let trend = trendRows;
|
||||
if (trend.length === 0) {
|
||||
const [fallback] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m-%d') AS date,
|
||||
SUM(charging_degree) AS kwh,
|
||||
SUM(cost_expense) AS fee
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE is_deleted = 0
|
||||
AND DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m') = (
|
||||
SELECT DATE_FORMAT(MAX(${ELECTRIC_LOCAL}), '%Y-%m')
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE is_deleted = 0
|
||||
)
|
||||
`SELECT DATE_FORMAT(start_time, '%Y-%m-%d') AS date,
|
||||
SUM(kwh) AS kwh,
|
||||
SUM(fee) AS fee
|
||||
FROM bi_ele_charge_record
|
||||
WHERE DATE_FORMAT(start_time, '%Y-%m') = (
|
||||
SELECT DATE_FORMAT(MAX(start_time), '%Y-%m') FROM bi_ele_charge_record
|
||||
)
|
||||
GROUP BY date
|
||||
ORDER BY date ASC`,
|
||||
);
|
||||
@@ -307,20 +300,17 @@ app.get('/electric/overview', async (c) => {
|
||||
fee: Math.round((Number(r.fee) || 0) * 100) / 100,
|
||||
chainPct: 0,
|
||||
}));
|
||||
// 计算环比
|
||||
for (let i = 1; i < trendArr.length; i++) {
|
||||
const prev = trendArr[i - 1].kwh;
|
||||
trendArr[i].chainPct = prev > 0 ? (trendArr[i].kwh - prev) / prev : 0;
|
||||
}
|
||||
|
||||
// 今日环比 = 今日 kwh / 上一个有数据的自然日 kwh - 1
|
||||
let todayChainPct = 0;
|
||||
if (todayKwh > 0) {
|
||||
const [prevRow] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT SUM(charging_degree) AS kwh
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE is_deleted = 0
|
||||
AND DATE(${ELECTRIC_LOCAL}) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)`,
|
||||
`SELECT SUM(kwh) AS kwh
|
||||
FROM bi_ele_charge_record
|
||||
WHERE DATE(start_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)`,
|
||||
);
|
||||
const prevKwh = Number(prevRow[0]?.kwh) || 0;
|
||||
todayChainPct = prevKwh > 0 ? (todayKwh - prevKwh) / prevKwh : 0;
|
||||
@@ -335,27 +325,27 @@ app.get('/electric/overview', async (c) => {
|
||||
});
|
||||
|
||||
// =========================================================
|
||||
// 电能 每日:月份分组 + 日级行
|
||||
// 电能 每日:月份分组 + 日级行 —— 数据源:bi_ele_charge_record
|
||||
// =========================================================
|
||||
app.get('/electric/monthly', async (c) => {
|
||||
const customer = (c.req.query('customer') || 'external') as CustomerKind;
|
||||
const customer = (c.req.query('customer') || 'lingniu') as CustomerKind;
|
||||
|
||||
const data = await cached(`electric/monthly?customer=${customer}`, async () => {
|
||||
|
||||
const where = [
|
||||
'is_deleted = 0',
|
||||
customerClause('truck_id', customer),
|
||||
].join(' AND ');
|
||||
// bi_ele_charge_record 用 vehicle_kind 区分:internal=我司,external=外部
|
||||
let kindClause = '1=1';
|
||||
if (customer === 'lingniu') kindClause = `vehicle_kind = 'internal'`;
|
||||
if (customer === 'external') kindClause = `vehicle_kind = 'external'`;
|
||||
|
||||
// 取最近 6 个月
|
||||
const [rows] = await pool.query<RowDataPacket[]>(
|
||||
`SELECT DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m') AS month,
|
||||
DATE_FORMAT(${ELECTRIC_LOCAL}, '%Y-%m-%d') AS date,
|
||||
SUM(charging_degree) AS kwh,
|
||||
SUM(cost_expense) AS fee
|
||||
FROM tab_energy_electricity_bill
|
||||
WHERE ${where}
|
||||
AND ${ELECTRIC_LOCAL} >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
|
||||
`SELECT DATE_FORMAT(start_time, '%Y-%m') AS month,
|
||||
DATE_FORMAT(start_time, '%Y-%m-%d') AS date,
|
||||
SUM(kwh) AS kwh,
|
||||
SUM(fee) AS fee
|
||||
FROM bi_ele_charge_record
|
||||
WHERE ${kindClause}
|
||||
AND start_time >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
|
||||
GROUP BY month, date
|
||||
ORDER BY date DESC`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user