在中小餐饮连锁店,每个月最令人头疼的除了盘点,就是算工资。

在大梦(可能实验室),两家门店涵盖了侍酒师、调酒师、咖啡师、主厨、出品厨师和兼任店长等多种角色。看似人不多,背后的算薪逻辑却极其复杂:

  • 考勤源散落各处:有人在群里发手写考勤表照片,有人交 .xlsx,店长交 .xls 评估表,西湖夜班员工在腾讯文档里打卡。
  • 提成与多维营收挂钩:薪酬不仅看基本工资,还挂钩部门业绩(精酿/调酒/咖啡/厨房)、班次业绩(白班/中班/晚班),甚至需要按部门 × 班次矩阵进行交叉剥离。
  • 新 SKU 归口漂移:每个月两家店都会上新酒水或新菜品,如果菜品库没有及时维护,POS 导出的几百条订单就会分错部门。
  • 输出要求高:算完不仅要在腾讯文档 43 列大表里逐行填平并标注店色,还要给每位员工生成带有公章、大写金额、社保代扣明细的精美工资单。

这篇文章记录我如何通过一套组合拳(Claude Fable 5 驱动的 Python 管道 + 腾讯文档 API + 响应式 HTML 工资单 + Rails 8 HR 系统集成),将原本需要耗费一整天的结薪工作缩减为 10 分钟自动化流程。


一、 考勤与数据清洗:手写照片与多格式兼容

结薪的第一步是收集出勤、法定假日、加班与请假数据。

面对不同来源的考勤资料,我们建立了一条标准化的数据摄取流水线:

  1. 手写纸质排班表:通过多模态 Vision 模型直接识别出勤天数与请假备注(休、年假、调休)。
  2. 员工个人提交的 xlsx/xls:使用 openpyxl 和 xlrd 脚本批量读取出勤字段。
  3. 腾讯文档夜班表:调用腾讯文档 API 自动拉取最新的夜班排班记录。

考勤规则的程序化

在计算出勤时,有几条必须严格执行的业务口径:

  • 法定节假日:按国家法定假日天数计算双倍津贴(基本工资 / 计薪基准 × 天数 × 2)。
  • 加班是「存」还是「换钱」:员工备注若为「存」,则计入调休池,不折现发放;若为「换钱」,则按小时工资折算为加班费。
  • 月计薪基准的口径区分:国家劳动法标准的月计薪天数是 21.75 天,而门店按「月休 4 天」的排班体系内部约定了自己的计薪基准。两者绝不可混用——这是薪酬计算里最容易犯的低级错误之一。

二、 破解营收交叉难题:伪菜品库与部门×班次矩阵

很多餐饮店算提成算不准,根源在于POS 订单数据无法自动归口到部门和班次

1. 「伪菜品库」反向生成法(100% 覆盖新 SKU)

早先我们维护了一份静态的「菜品库.xlsx」,但每月一到结薪,发现上月新上的十几款精酿或特调都在库外,脚本只能靠关键词模糊匹配,导致大量调酒被误归入精酿。

为了彻底根治这个问题,我们从 6 月起设计了**「伪菜品库生成器」**(make_menu_lib.py):

  • 直接读取美团/收钱吧 POS 导出的当月「菜品销售明细」(包含 POS 真实的「菜品大类」和「菜品小类」)。
  • 脚本根据 POS 大类自动映射四部门,反向为两家门店各生成一份当月专用的全覆盖菜品库(数百个在售 SKU 全部自动归口)。
  • 实测除扑克牌、雨伞等 2 笔杂物外,全部 SKU 100% 自动归口,彻底告别了人工维护。

2. 部门 × 班次交叉聚合算法

有了准确的菜品归属后,流水线运行 build_analysis.py 进行多维交叉切片:

  • 部门业绩:从全渠道订单中提取含团购套餐的实际到账金额。
  • 班次业绩:按结账时间(17:00 前为白班,17:00 后为晚班,特定时段为中班)切分。
  • 特殊规则硬编码:例如滨江后厨团队(主厨与出品厨师)只考核整体后厨部门业绩,班次业绩置 0;前厅运营无特定部门归属,部门业绩置 0。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# build_analysis 核心交叉切片逻辑示意
def compute_cross_matrix(orders_df, menu_lib):
    # 结合伪菜品库匹配部门
    merged = orders_df.merge(menu_lib, on='sku_id', how='left')
    # 结合结账时间戳划分班次
    merged['shift'] = merged['pay_time'].apply(classify_shift)
    
    # 交叉透视表:店 x 部门 x 班次
    cross_pivot = merged.pivot_table(
        index=['store', 'department'],
        columns='shift',
        values='actual_amount',
        aggfunc='sum',
        fill_value=0
    )
    return calibrate_totals(cross_pivot)

最终脚本自动输出包含 13 个分析页签的月度 Excel,并将部门起伏 MoM 根因下钻到具体 SKU(例如:精酿本月下滑主要由于哪几款酒头缺货)。


三、 腾讯文档 V2 自动回写与店色渲染

大梦团队日常使用腾讯文档「员工档案 V2」作为薪酬管理中枢。整个表结构多达 43 列。

算薪脚本在核算完成后,会调用腾讯文档开放接口完成自动化回填:

  1. 行号探测与防偏移:自动读取表格末行,锁定当月全员的起始写入行(与上月行段空一行隔开),写完后立即回读校验。
  2. 写入动态计算字段:出勤天数、法假天数、部门业绩、班次业绩、基本工资、加班费、KPI 倍数、管理倍数、全勤行为规范奖、出品提成、社保个人代扣(在册员工按月代扣)、最终私账剩余应发。
  3. 自动化店色美化
    • 西湖店:全行设置浅绿底色(#FFE2EFDA
    • 滨江店:全行设置浅蓝底色(#FFDDEBF7

四、 双轨工资单:从 HTML 模板到 Rails 8 系统集成

算完薪后,如何将工资条体面、私密、优雅地分发给每位员工?

我们采取了「双轨制」交付方案:

1. 独立 HTML/JS 工资单生成器

在本地提供一个自包含的单页应用:

  • 复古票据设计:两店分色边框、水印防伪印章、应发金额自动转换为中文大写(如「肆仟捌佰伍拾元整」)。
  • 智能字段收起:没有提成的员工自动隐藏提成明细行;加班小时选择「存」的员工自动将加班费显示为 0 并附带文字备注。
  • 一键导出 PNG:内置 html2canvas 引擎,右上角提供「EXPORT ALL」批量打包,单卡片下方支持单张保存。

2. 水龙头 HR 系统(Rails 8 + SQLite + Tailwind)

为了让店长和管理层具备更系统的历史查询与入职管理能力,我们将这套工资单生成逻辑无损移植进了内网 HR 系统 shuilongtou

  • 无损组件复用:将 HTML 模板的 CSS 与 JS 渲染核心原样封装为 Rails View Component。
  • 服务端数据注入SalarySlipBuilder 服务从 SQLite 读取当月评定记录,构造成标准 JSON 挂载在前端 window.SALARY_DATA 上。
  • 批量与单人导出:在后台 /salary-slips 页面,店长可以按月份一键预览全员并导出高清图片分发微信。

结语

在服务实体餐饮的过程中,我们往往容易走向两个极端:要么沉迷于引入庞大昂贵的全套 SaaS 软件,结果员工根本不会用;要么退回原始的手工复制粘贴,每个月重复踩坑。

这套以 Python 脚本打通数据流、腾讯文档作为协作底座、轻量 HTML/Rails 提供交互展示的架构,恰好找到了那个平衡点:低成本、极度灵活,并且能在业务规则演进时随手调整。

当技术真正落进日常的柴米油盐与账目明细里,解决真实世界的琐碎麻烦,那种踏实感才是最迷人的。


🛠️ 项目环境与模型署名

  • 主导逻辑与代码构建:Anthropic Claude Fable 5(桌面端默认模型)
  • 多模态考勤识别:Claude Fable 5 视觉能力(手写纸质排班表与多源照片读取)
  • 客户端与执行环境Claude Desktop 桌面端(定制 dameng-salary Skill + tencent-docs MCP)
  • 系统技术栈:Python 3 (pandas, openpyxl, xlrd) + 腾讯文档 OpenAPI + Rails 8 (shuilongtou 员工管理系统) + HTML/CSS 矢量打印模板