fix(product): 聚水潭 allsku 模板隐藏列错位致 daily 销量全 0
2026-10-11 模板重置把 38 列置隐藏后可见列整体左移,固定索引 45/57 落到 「今日实退货量/今日仅退款量」。daily 改表头名匹配「昨日销量/昨日退货量」 (weekly 暂留老索引待实测);backfill 恢复自定义列可见(window._Cols + _RptRefresh),并把表头索引按可见列换算成行内位置防 td 缺位错读。
This commit is contained in:
1 parent
9a91ce80e4
commit
0cc4fafc7c
4 files changed
+292
-19
No files matched your search
@@ -125,6 +125,57 @@ def test_style_records_sum_product_rows_and_keep_zero_styles() -> None:
|
||||
assert records[1]["matched_product_rows"] == 0
|
||||
|
||||
|
||||
def test_style_extraction_maps_hidden_columns_via_visible_positions() -> None:
|
||||
class Frame:
|
||||
def __init__(self) -> None:
|
||||
self.script = ""
|
||||
self.args = {}
|
||||
|
||||
def evaluate(self, script, args):
|
||||
self.script = script
|
||||
self.args = args
|
||||
return {"ok": True, "rows": []}
|
||||
|
||||
frame = Frame()
|
||||
backfill.extract_style_rows(frame, requested_codes=("10416",))
|
||||
|
||||
assert "window._Cols" in frame.script
|
||||
assert "visibleIdx.indexOf" in frame.script
|
||||
assert "cells[stylePos]" in frame.script
|
||||
assert "cells.length <= Math.max(stylePos, salesPos, returnsPos)" in frame.script
|
||||
|
||||
|
||||
def test_ensure_custom_columns_visible_only_touches_allsku_frames() -> None:
|
||||
class AllskuFrame:
|
||||
url = "https://bi.erp321.com/app/report/subject/itemskuanalysis/allsku.aspx?r=1"
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.scripts: list[str] = []
|
||||
|
||||
def evaluate(self, script):
|
||||
self.scripts.append(script)
|
||||
return 2
|
||||
|
||||
class OtherFrame:
|
||||
url = "https://bi.erp321.com/app/report/subject/itemskuanalysis/filter.aspx"
|
||||
|
||||
def evaluate(self, script):
|
||||
raise AssertionError("must not touch non-allsku frames")
|
||||
|
||||
class Page:
|
||||
frames = [OtherFrame(), AllskuFrame()]
|
||||
|
||||
page = Page()
|
||||
changed = backfill.ensure_custom_columns_visible(page)
|
||||
|
||||
assert changed == 2
|
||||
allsku = page.frames[1]
|
||||
assert len(allsku.scripts) == 1
|
||||
assert "'自定义销量'" in allsku.scripts[0]
|
||||
assert "'自定义退货量'" in allsku.scripts[0]
|
||||
assert "_RptRefresh" in allsku.scripts[0]
|
||||
|
||||
|
||||
def test_range_collector_queries_once_per_date_not_once_per_style(monkeypatch) -> None:
|
||||
filter_frame = object()
|
||||
monkeypatch.setattr(
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import collect_erp_yesterday_metrics as erp_mod
|
||||
|
||||
|
||||
class _StubFrame:
|
||||
"""frame.evaluate 的最小桩: 记录入参并返回固定 payload。"""
|
||||
|
||||
def __init__(self, payload):
|
||||
self._payload = payload
|
||||
self.calls = []
|
||||
|
||||
def evaluate(self, script, *args):
|
||||
self.calls.append((script, args))
|
||||
return self._payload
|
||||
|
||||
|
||||
class ErpDailyHeaderRoutingTest(unittest.TestCase):
|
||||
"""2026-10-11 聚水潭模板重置隐藏 38 列后, 固定可见索引 45/57 错位到
|
||||
「今日实退货量/今日仅退款量」, daily 销量全 0。daily 必须走表头名匹配,
|
||||
且不能落入 backfill 的 _extract_by_header (自定义列 SPU 求和) 分支。"""
|
||||
|
||||
def test_daily_mode_uses_yesterday_headers(self):
|
||||
with mock.patch.object(erp_mod, "MODE", "daily"):
|
||||
self.assertEqual(
|
||||
erp_mod._sales_returns_idx(),
|
||||
("昨日销量", "昨日退货量"),
|
||||
)
|
||||
|
||||
def test_weekly_mode_keeps_legacy_index(self):
|
||||
with mock.patch.object(erp_mod, "MODE", "weekly"):
|
||||
self.assertEqual(
|
||||
erp_mod._sales_returns_idx(),
|
||||
("__idx__45", "__idx__57"),
|
||||
)
|
||||
|
||||
def test_backfill_mode_keeps_custom_headers(self):
|
||||
with mock.patch.object(erp_mod, "MODE", "backfill"):
|
||||
self.assertEqual(
|
||||
erp_mod._sales_returns_idx(),
|
||||
("自定义销量", "自定义退货量"),
|
||||
)
|
||||
|
||||
def test_daily_header_keys_bypass_extract_by_header(self):
|
||||
payload = {
|
||||
"ok": True,
|
||||
"yesterday_sales": 2,
|
||||
"yesterday_returns": 0,
|
||||
"bodyText": "",
|
||||
}
|
||||
frame = _StubFrame(payload)
|
||||
with mock.patch.object(erp_mod, "MODE", "daily"):
|
||||
metrics, _body = erp_mod._extract_with_text(frame)
|
||||
self.assertEqual(metrics["yesterday_sales"], 2)
|
||||
self.assertEqual(len(frame.calls), 1)
|
||||
script, args = frame.calls[0]
|
||||
js_args = args[0] if args else script
|
||||
self.assertEqual(js_args["mode"], "header")
|
||||
self.assertEqual(js_args["salesHeader"], "昨日销量")
|
||||
self.assertEqual(js_args["returnsHeader"], "昨日退货量")
|
||||
|
||||
def test_backfill_mode_routes_to_extract_by_header(self):
|
||||
frame = _StubFrame({})
|
||||
with mock.patch.object(erp_mod, "MODE", "backfill"):
|
||||
with mock.patch.object(
|
||||
erp_mod,
|
||||
"_extract_by_header",
|
||||
return_value={"ok": True, "yesterday_sales": 5, "summary_text": "X"},
|
||||
) as by_header:
|
||||
metrics, _body = erp_mod._extract_with_text(frame)
|
||||
by_header.assert_called_once()
|
||||
self.assertEqual(metrics["yesterday_sales"], 5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user