Files
skills/dameng-salary/make_menu_lib.py
T

88 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""从「菜品销售明细」导出反推菜品库(6月起使用)
用法: python3 make_menu_lib.py <月度账务目录>
背景:build_analysis.py 依赖菜品库做部门归类,但本地菜品库是旧月份快照,
当月新上的 SKU 不在库里会掉进关键词兜底、容易归错。
菜品销售明细自带「菜品大类/菜品小类」= POS 系统里的真实归类,用它生成菜品库覆盖率 100%。
输出: 大梦_可能实验室_{店}店_菜品库_自销售明细生成_{YYYYMM}.xlsx
(文件名符合 build_analysis.py 的 glob 模式,会被自动读到)
"""
import openpyxl, glob, sys, os, re
from collections import Counter, defaultdict
BASE = (sys.argv[1] if len(sys.argv) > 1 else ".").rstrip("/")
def build(store):
fs = glob.glob(f"{BASE}/*{store}店__菜品销售明细*.xlsx")
if not fs:
print(f" [{store}] 未找到菜品销售明细,跳过")
return
wb = openpyxl.load_workbook(fs[0], data_only=True)
ws = wb["已销售"]
# 表头在第 3 行
hr = None
for r in range(1, 8):
row = [ws.cell(r, c).value for c in range(1, ws.max_column + 1)]
if any(v and "菜品大类" in str(v) for v in row):
hr = r
H = [str(v).strip() if v else "" for v in row]
break
if hr is None:
print(f" [{store}] 找不到含「菜品大类」的表头行,跳过")
return
ci_nm = H.index("菜品名称") + 1
ci_d = H.index("菜品大类") + 1
ci_x = H.index("菜品小类") + 1
# 同名多类时取众数(如"深烘拿铁"既有 咖啡/经典 也有 经典咖啡)
name2cats = defaultdict(Counter)
ym = None
ci_date = H.index("营业日期") + 1 if "营业日期" in H else None
for r in range(hr + 1, ws.max_row + 1):
nm = ws.cell(r, ci_nm).value
if not nm:
continue
d = ws.cell(r, ci_d).value
x = ws.cell(r, ci_x).value
if d:
name2cats[str(nm).strip()][(str(d).strip(), str(x).strip() if x else "")] += 1
if ym is None and ci_date:
dv = str(ws.cell(r, ci_date).value or "")
m = re.search(r"(\d{4})[/-](\d{2})", dv)
if m:
ym = m.group(1) + m.group(2)
wb.close()
conflicts = {n: c for n, c in name2cats.items() if len(c) > 1}
out = openpyxl.Workbook()
ws2 = out.active
ws2.title = "菜品"
ws2.append(["菜品编码(SPUID", "菜品名称", "基础分类"])
for n, c in sorted(name2cats.items()):
(d, x), _ = c.most_common(1)[0]
ws2.append(["", n, f"{d}/{x}" if x else d])
fn = f"{BASE}/大梦_可能实验室_{store}店_菜品库_自销售明细生成_{ym or 'latest'}.xlsx"
out.save(fn)
cats = Counter()
for n, c in name2cats.items():
cats[c.most_common(1)[0][0][0]] += 1
print(f" [{store}] {len(name2cats)} 个 SKU → {os.path.basename(fn)}")
print(f" 大类分布: {dict(cats.most_common(8))}")
if conflicts:
print(f" 同名多类 {len(conflicts)} 个(已取众数,正常现象): "
+ ", ".join(list(conflicts)[:4]))
if __name__ == "__main__":
print(f"从菜品销售明细生成菜品库 — {BASE}")
for st in ["滨江", "西湖"]:
build(st)
print("完成。接着跑: python3 build_analysis.py <目录> <YYYY-MM>")