fix: 修复费用总览API两个错误
1. 费用率公式反转: (1-expense/received)*100 → expense/matched_received*100 修复前: 46.83%(实际是非费用率)→ 修复后: 53.77%(正确费用率) 2. 利润口径不一致: sum(received)含全部94家门店,但费用只含92家匹配门店 修复: 利润和各项率指标分母改为仅匹配门店实收(matched_received) 实际贡献利润: 7,703,472→6,982,110 贡献率: 11.96%→10.96%
This commit is contained in:
@@ -57,6 +57,7 @@ router.get('/overview', async (req: AuthRequest, res) => {
|
|||||||
round(sum(consumption)::numeric, 2) AS total_consumption,
|
round(sum(consumption)::numeric, 2) AS total_consumption,
|
||||||
round(sum(discount)::numeric, 2) AS total_discount,
|
round(sum(discount)::numeric, 2) AS total_discount,
|
||||||
round(sum(received)::numeric, 2) AS total_received,
|
round(sum(received)::numeric, 2) AS total_received,
|
||||||
|
round(sum(received) FILTER (WHERE operating_expense IS NOT NULL)::numeric, 2) AS matched_received,
|
||||||
round(sum(received) / nullif(sum(bill_count), 0), 2) AS avg_bill_value,
|
round(sum(received) / nullif(sum(bill_count), 0), 2) AS avg_bill_value,
|
||||||
round(sum(operating_expense)::numeric, 2) AS total_expense,
|
round(sum(operating_expense)::numeric, 2) AS total_expense,
|
||||||
round(sum(wage_expense)::numeric, 2) AS total_wage,
|
round(sum(wage_expense)::numeric, 2) AS total_wage,
|
||||||
@@ -70,18 +71,18 @@ router.get('/overview', async (req: AuthRequest, res) => {
|
|||||||
round(sum(theoretical_cost)::numeric, 2) AS total_theoretical_cost,
|
round(sum(theoretical_cost)::numeric, 2) AS total_theoretical_cost,
|
||||||
round(sum(actual_store_contribution)::numeric, 2) AS total_contribution,
|
round(sum(actual_store_contribution)::numeric, 2) AS total_contribution,
|
||||||
round(sum(theoretical_store_contribution)::numeric, 2) AS total_theoretical_contribution,
|
round(sum(theoretical_store_contribution)::numeric, 2) AS total_theoretical_contribution,
|
||||||
round(sum(received) - sum(theoretical_cost) - sum(operating_expense), 2) AS theoretical_net_profit,
|
round(sum(received) FILTER (WHERE operating_expense IS NOT NULL) - sum(theoretical_cost) - sum(operating_expense), 2) AS theoretical_net_profit,
|
||||||
round(sum(received) - sum(actual_food_cost) - sum(operating_expense), 2) AS actual_net_profit,
|
round(sum(received) FILTER (WHERE operating_expense IS NOT NULL) - sum(actual_food_cost) - sum(operating_expense), 2) AS actual_net_profit,
|
||||||
round(sum(area_sqm)::numeric, 2) AS total_area,
|
round(sum(area_sqm)::numeric, 2) AS total_area,
|
||||||
round((1 - sum(operating_expense) / nullif(sum(received), 0)) * 100, 2) AS overall_expense_rate_pct,
|
round(sum(operating_expense) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS overall_expense_rate_pct,
|
||||||
round((1 - (sum(actual_food_cost) + sum(operating_expense)) / nullif(sum(received), 0)) * 100, 2) AS overall_contribution_rate_pct,
|
round((sum(received) FILTER (WHERE operating_expense IS NOT NULL) - sum(actual_food_cost) - sum(operating_expense)) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS overall_contribution_rate_pct,
|
||||||
round((sum(received) - sum(theoretical_cost) - sum(operating_expense)) / nullif(sum(received), 0) * 100, 2) AS theoretical_net_margin_pct,
|
round((sum(received) FILTER (WHERE operating_expense IS NOT NULL) - sum(theoretical_cost) - sum(operating_expense)) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS theoretical_net_margin_pct,
|
||||||
round((sum(received) - sum(actual_food_cost) - sum(operating_expense)) / nullif(sum(received), 0) * 100, 2) AS actual_net_margin_pct,
|
round((sum(received) FILTER (WHERE operating_expense IS NOT NULL) - sum(actual_food_cost) - sum(operating_expense)) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS actual_net_margin_pct,
|
||||||
round(sum(theoretical_cost) / nullif(sum(received), 0) * 100, 2) AS theoretical_food_cost_rate_pct,
|
round(sum(theoretical_cost) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS theoretical_food_cost_rate_pct,
|
||||||
round(sum(actual_food_cost) / nullif(sum(received), 0) * 100, 2) AS actual_food_cost_rate_pct,
|
round(sum(actual_food_cost) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS actual_food_cost_rate_pct,
|
||||||
round(sum(wage_expense) / nullif(sum(received), 0) * 100, 2) AS overall_wage_rate_pct,
|
round(sum(wage_expense) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS overall_wage_rate_pct,
|
||||||
round(sum(rent_expense) / nullif(sum(received), 0) * 100, 2) AS overall_rent_rate_pct,
|
round(sum(rent_expense) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS overall_rent_rate_pct,
|
||||||
round(sum(utility_expense) / nullif(sum(received), 0) * 100, 2) AS overall_utility_rate_pct
|
round(sum(utility_expense) / nullif(sum(received) FILTER (WHERE operating_expense IS NOT NULL), 0) * 100, 2) AS overall_utility_rate_pct
|
||||||
FROM full_scope
|
FROM full_scope
|
||||||
`, [month])
|
`, [month])
|
||||||
sendSuccess(res, result.rows[0])
|
sendSuccess(res, result.rows[0])
|
||||||
|
|||||||
Reference in New Issue
Block a user