feat: 月度模式全面参数化 - 移除硬编码日期,前后端按月动态查询

This commit is contained in:
freedakgmail
2026-08-01 13:10:22 +08:00
parent a90c133578
commit dab06ba109
43 changed files with 9135 additions and 309 deletions
+12 -9
View File
@@ -1,6 +1,6 @@
import { Router } from 'express'
import { query } from '../config/database.js'
import { sendSuccess, sendError, parsePagination } from '../middleware/error.js'
import { sendSuccess, sendError, parsePagination, parseMonth } from '../middleware/error.js'
import type { AuthRequest } from '../middleware/auth.js'
const router = Router()
@@ -725,6 +725,7 @@ router.get('/unmatched-materials', async (req: AuthRequest, res) => {
// 门店成本总览
router.get('/store-overview', async (req: AuthRequest, res) => {
try {
const month = parseMonth(req)
const result = await query(`
SELECT
count(*) AS total_stores,
@@ -733,8 +734,8 @@ router.get('/store-overview', async (req: AuthRequest, res) => {
count(*) FILTER (WHERE variance_level = '绿色-基本正常') AS green_count,
count(*) FILTER (WHERE variance_level = '灰色-口径异常') AS gray_count,
round(sum(food_cost_variance)::numeric, 2) AS total_variance
FROM analytics.mv_store_theoretical_actual_cost_april
`)
FROM analytics.fn_store_theoretical_actual_cost($1)
`, [month])
sendSuccess(res, result.rows[0])
} catch (err: any) {
sendError(res, err.message)
@@ -744,16 +745,17 @@ router.get('/store-overview', async (req: AuthRequest, res) => {
// 门店地图数据
router.get('/store-map', async (req: AuthRequest, res) => {
try {
const month = parseMonth(req)
const result = await query(`
SELECT c.store_code, c.store_name, c.variance_level,
round(c.food_cost_variance::numeric, 2) AS variance,
round(c.theoretical_cost_rate_pct::numeric, 2) AS theo_cost_rate,
round(c.actual_food_cost_rate_pct::numeric, 2) AS actual_cost_rate,
l.latitude_gcj02, l.longitude_gcj02
FROM analytics.mv_store_theoretical_actual_cost_april c
FROM analytics.fn_store_theoretical_actual_cost($1) c
LEFT JOIN analytics.v_store_location_operating l ON l.store_code = c.store_code
WHERE l.latitude_gcj02 IS NOT NULL
`)
`, [month])
sendSuccess(res, result.rows)
} catch (err: any) {
sendError(res, err.message)
@@ -777,7 +779,8 @@ router.get('/store-ranking', async (req: AuthRequest, res) => {
const validSorts = ['food_cost_variance', 'theoretical_cost_rate_pct', 'actual_food_cost_rate_pct', 'variance_to_theoretical_pct', 'negative_item_lines', 'store_name']
const sortCol = validSorts.includes(sort) ? sort : 'food_cost_variance'
const countResult = await query(`SELECT count(*) FROM analytics.mv_store_theoretical_actual_cost_april ${where}`)
const month = parseMonth(req)
const countResult = await query(`SELECT count(*) FROM analytics.fn_store_theoretical_actual_cost($1) ${where}`, [month])
const total = countResult.rows[0].count
const result = await query(`
@@ -788,10 +791,10 @@ router.get('/store-ranking', async (req: AuthRequest, res) => {
round(food_cost_variance::numeric, 2) AS variance_amount,
negative_item_lines,
variance_level
FROM analytics.mv_store_theoretical_actual_cost_april
FROM analytics.fn_store_theoretical_actual_cost($1)
${where}
ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $1 OFFSET $2
`, [pageSize, offset])
ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $2 OFFSET $3
`, [month, pageSize, offset])
sendSuccess(res, result.rows, { page, pageSize, total })
} catch (err: any) {
sendError(res, err.message)