fix(energy): 单价直接取 MAX(cost_price),不重算不返 null
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

之前用 MIN=MAX...ELSE NULL 判定,再 NULLIF 排零,遇到「1 笔 0 元免费单 + 多笔 35 元正价单」
仍可能误判混合,最终页面显示「—」(如佛山豪汇石油加氢站)。

按业务约定:单价就是订单上记录的成本价,不做"统一性"判定,也不返 null。
改用 MAX(b.cost_price):
  - 自然忽略 0 元免费/赠送单(被正价 max 掉)
  - 同价组等于原价
  - 极少数真正混合价组也展示该日付出过的最高单价(仍是订单上的真实数字)

回退类型:HydrogenStationRow.pricePerKg 重新固定为 number。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-29 19:56:26 +08:00
parent 3851335843
commit c788dd4577
3 changed files with 8 additions and 8 deletions

View File

@@ -197,9 +197,9 @@ export default function HydrogenDaily() {
> >
<span className="text-[12px] text-slate-600 truncate"> <span className="text-[12px] text-slate-600 truncate">
{s.name} {s.name}
<span className="md:hidden text-slate-400 text-[10px]"> · {s.pricePerKg == null ? '—' : s.pricePerKg}</span> <span className="md:hidden text-slate-400 text-[10px]"> · {s.pricePerKg}</span>
</span> </span>
<span className="hidden md:block text-right text-[12px] text-slate-500 font-bold tabular-nums">{s.pricePerKg == null ? '—' : s.pricePerKg}</span> <span className="hidden md:block text-right text-[12px] text-slate-500 font-bold tabular-nums">{s.pricePerKg}</span>
<span className="text-right text-[12px] text-slate-700 font-bold tabular-nums"> <span className="text-right text-[12px] text-slate-700 font-bold tabular-nums">
{s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })} {s.kg.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}
</span> </span>

View File

@@ -31,7 +31,7 @@ export interface HydrogenRegionShare {
export interface HydrogenStationRow { export interface HydrogenStationRow {
name: string; name: string;
pricePerKg: number | null; pricePerKg: number;
kg: number; kg: number;
chainPct: number; chainPct: number;
} }

View File

@@ -175,8 +175,8 @@ app.get('/hydrogen/daily', async (c) => {
CASE WHEN b.hydrogen_station_id IS NULL THEN '未关联站点' CASE WHEN b.hydrogen_station_id IS NULL THEN '未关联站点'
ELSE CONCAT('未知站点 #', b.hydrogen_station_id) END) AS stationName, ELSE CONCAT('未知站点 #', b.hydrogen_station_id) END) AS stationName,
ROUND(SUM(b.hydrogen_quantity), 2) AS kg, ROUND(SUM(b.hydrogen_quantity), 2) AS kg,
CASE WHEN MIN(b.cost_price) = MAX(b.cost_price) THEN MIN(b.cost_price) -- 单价直接取订单中的成本价不重算。MAX 自然忽略 0 元的免费/赠送单
ELSE NULL END AS pricePerKg MAX(b.cost_price) AS pricePerKg
FROM tab_energy_hydrogen_bill b FROM tab_energy_hydrogen_bill b
LEFT JOIN tab_hydrogen_site s ON s.id = b.hydrogen_station_id LEFT JOIN tab_hydrogen_site s ON s.id = b.hydrogen_station_id
LEFT JOIN tab_outside_hydrogen_site os ON os.inner_site_id = b.hydrogen_station_id LEFT JOIN tab_outside_hydrogen_site os ON os.inner_site_id = b.hydrogen_station_id
@@ -188,13 +188,13 @@ app.get('/hydrogen/daily', async (c) => {
// 站点环比:同站点上一条记录的 kg // 站点环比:同站点上一条记录的 kg
// 按 stationId 分组、按日期升序计算 // 按 stationId 分组、按日期升序计算
type StationRow = { date: string; stationId: number; name: string; kg: number; pricePerKg: number | null }; type StationRow = { date: string; stationId: number; name: string; kg: number; pricePerKg: number };
const flat: StationRow[] = stationRows.map(r => ({ const flat: StationRow[] = stationRows.map(r => ({
date: r.d as string, date: r.d as string,
stationId: Number(r.stationId), stationId: Number(r.stationId),
name: r.stationName as string, name: r.stationName as string,
kg: Number(r.kg) || 0, kg: Number(r.kg) || 0,
pricePerKg: r.pricePerKg == null ? null : Number(r.pricePerKg), pricePerKg: Number(r.pricePerKg) || 0,
})); }));
// 计算日级总量 + 日级环比 // 计算日级总量 + 日级环比
@@ -244,7 +244,7 @@ app.get('/hydrogen/daily', async (c) => {
.sort((a, b) => b.kg - a.kg) .sort((a, b) => b.kg - a.kg)
.map(s => ({ .map(s => ({
name: s.name, name: s.name,
pricePerKg: s.pricePerKg == null ? null : Math.round(s.pricePerKg * 100) / 100, pricePerKg: Math.round(s.pricePerKg * 100) / 100,
kg: Math.round(s.kg * 100) / 100, kg: Math.round(s.kg * 100) / 100,
chainPct: stationChain.get(`${s.date}|${s.stationId}`) ?? 0, chainPct: stationChain.get(`${s.date}|${s.stationId}`) ?? 0,
})), })),