fix(analytics): restore period-linked report APIs
Some checks failed
CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
ogt
2026-07-15 16:54:33 +08:00
parent 4443beb3af
commit 9cffe9f8e4
3 changed files with 34 additions and 4 deletions

View File

@@ -414,7 +414,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
SYSTEM_VERSION = "V10.804"
SYSTEM_VERSION = "V10.805"
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
public_url = PUBLIC_URL # 用於模板顯示

View File

@@ -280,3 +280,14 @@ def test_monthly_frontend_has_replayable_period_and_no_fixed_years():
assert "data-analysis-target" in tabs
assert "renderChartEmpty" in script
assert "未以其他月份回填" in script
def test_sales_frontend_uses_live_period_linked_api_routes():
script = (ROOT / "web/static/js/page-sales-analysis.js").read_text(encoding="utf-8")
assert "buildPeriodApiUrl" in script
assert "new URLSearchParams(window.location.search)" in script
assert "/api/sales_analysis/yoy_comparison" in script
assert "/api/sales_analysis/table_data" in script
assert "fetch(`/api/yoy?" not in script
assert "'/api/sales_table?'" not in script

View File

@@ -30,6 +30,17 @@
// mix helper browser already supports color-mix; fallback to manual rgba
const mix = (c, pct) => `color-mix(in srgb, ${c} ${pct}%, transparent)`;
const buildPeriodApiUrl = (path, overrides = {}) => {
const url = new URL(path, window.location.origin);
new URLSearchParams(window.location.search).forEach((value, key) => {
url.searchParams.append(key, value);
});
Object.entries(overrides).forEach(([key, value]) => {
url.searchParams.set(key, value);
});
return url.toString();
};
// ─── Loading overlay ────────────────────────────────────
const overlay = document.getElementById('loadingOverlay');
const showLoading = (text) => {
@@ -466,8 +477,16 @@
const y1 = document.getElementById('yoy-year1').value;
const y2 = document.getElementById('yoy-year2').value;
const m = document.getElementById('yoy-metric').value;
fetch(`/api/yoy?year1=${y1}&year2=${y2}&metric=${m}&${window.location.search.slice(1)}`)
.then(r => r.json())
const url = buildPeriodApiUrl('/api/sales_analysis/yoy_comparison', {
year1: y1,
year2: y2,
metric: m
});
fetch(url)
.then((response) => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then(d => {
document.getElementById('yoy-year1-label').textContent = `${y1}`;
document.getElementById('yoy-year2-label').textContent = `${y2}`;
@@ -510,7 +529,7 @@
const initDataTable = () => {
const $tbl = window.jQuery && jQuery('#dataTable');
if (!$tbl || !$tbl.length || !jQuery.fn.DataTable) return;
const url = '/api/sales_table?' + window.location.search.slice(1);
const url = buildPeriodApiUrl('/api/sales_analysis/table_data');
$tbl.DataTable({
ajax: { url, dataSrc: 'data' },
processing: true, serverSide: false,