设计院、科研院所办一场评审会(咨询会 / 验收会 / 函审),真正难的从来不是开会,是会后那一沓报销材料。这套系统把「该出哪些件、谁出、专家费到底几个数」固定下来,人只负责签字盖章。
办会的人换了一茬又一茬,每次都在同一批坑里翻车。这四条是反复被财务打回后才固化下来的规则:
| 三个金额不是一个数 | 跟专家谈的是「实际劳务费」,专家去税务代开的发票写的是「开票含税」,最后打到卡上的是「实发」。三者相差几百元。谈的时候说错一个,事后要么专家不认账,要么财务对不平。下面的计算器就是为这件事做的。 |
| 函审和开会是两套件 | 函审没有会场、没有餐费、没有现场签到,却多出邀请函和专家签字的评审意见书。早期的清单是按「会议序」排的(01 预算表、02 会议通知、03 参会签到…),函审这两样在清单里根本没有位置 —— 于是每次函审都被打回。现在清单按会型切换,函审的目录序直接等于财务认的 4 样序。 |
| 「—」不等于「缺件」 | 函审没开会 → 会议通知 / 参会签到 / 会议费发票本就不存在;当天没安排会餐 → 会议费发票同样无此项。曾经有人把「当日无会餐」记成「缺会议费发票」,后来人真的去补一张根本不存在的票。所以清单上把「不适用」和「待补」用两种符号分开。 |
| 两个人别搞混 | 给通知盖章的经手人,和 OA 里审批预算的部门负责人,是两个不同的人。填反了,报销单退回重走一遍流程。系统把这两个字段做成两个独立参数,强制你分别填。 |
这一块本来就不含任何个人信息 —— 输入一个金额,输出六个口径。所以它可以整个搬到公网上,你现在就能用。
| 不含税基数 R | — | 开票的计税基数,一切从它算起 |
| 增值税(小规模 1%) | — | R × 1% |
| 开票含税 | — | 专家去税务代开发票时写的金额 |
| 个税(劳务报酬预扣) | — | — |
| 实际劳务费 | — | 跟专家谈的就是这个数 = R − 个税 |
| 实发 | — | 实际打到卡上 = 开票含税 − 个税 |
| N 人合计(开票含税) | — | 报销单上的总额按这个填 |
每位专家的档次可能不同(组长比组员高),发放清单上要的是逐人金额 + 合计。姓名列随便填,本页不上传。
| 专家 | 输入口径 | 金额 | 开票含税 | 个税 | 实发 | 实际劳务费 |
|---|
05 专家费发放汇总清单 与 06 函审专家清单及工作量统计表 两个 Word 件,
并自动核对两表合计是否一致 —— 财务对账时先看的就是这个总数。
这套系统是切成两半做的,切口就在「有没有个人信息」这条线上:
| 这一半 | 装什么 | 在哪 | 为什么 |
|---|---|---|---|
| 上网的半边 就是你现在看的这页 | 流程 SOP、出件清单、报销对照、费用算法 | 公网静态页,无后端、无数据库 | 这些东西本来就不含任何个人信息。算法搬上来,同行直接能用;没有后端就没有可攻击面。 |
| 不上网的半边 | 专家库(姓名 / 身份证 / 银行账号 / 电话)、会务台账、签名图片 | 只在本机,跟着项目工作区走 | 它的第二读者是零。上网只多一条泄露路径,换不来任何东西。 |
这是个取舍,不是偷懒。代价很具体:你在这页上查不了「某某专家的账号是多少」,也看不到「上一场会办到哪一步了」 —— 那些得回本机跑命令。换来的是这页可以随便发给任何人,不需要登录、不需要闸、不需要担心哪天配置错了泄一批身份证。
配套的纪律有两条,都写死在生成引擎里:① 库里查不到这个专家 → 该行只填姓名、其余留空并报警告,绝不编一个看着合理的值;② 读不到的字段留空并写明为什么读不到。编造的个人信息,任何机器检查都抓不到 —— 它长得和真的一模一样。
| 材料生成 | Python 确定性填充:一套 token 化的 Word 母版(母版本身无个人信息),命令行传参一次生成全套件。会型(咨询会 / 验收会 / 函审)决定生成哪些件、删哪些件 —— 函审自动删掉会议通知与参会签到,自动加上专家清单与工作量统计表。 |
| 金额口径 | 只有一个 compute_fee 函数,Word 件、Excel 计算表、给专家的话术、本页计算器,全从它派生。三个金额对不上账的根因是「几个地方各算各的」,所以做成单一算法源。 |
| 本页与引擎的一致性 | 浏览器里跑不了 Python,本页是复刻,复刻就会漂。所以发布前有一道门:从页面 HTML 里把计算函数原样抽出来用 Node 跑,与 Python 引擎逐值比对 —— 22 组输入 × 6 个字段,差 0.005 元就红。样本特意含分段边界(3999 / 4000 / 4001)和税率档口(20000 / 25000)。 关键是「抽真代码跑」而不是照着重写一份来测 —— 重写一份等于测了个替身,会假绿。 |
| fail-closed | 那道门缺 Node、缺引擎、抽不出函数、样本为空 —— 一律非零退出。拒绝在空集上报绿。并且反向验过:把页面里的 1% 改成 1.1%,门立刻变红并逐条打印不符项;改回来才绿。没反向验证过的守卫不算数。 |
| 版式为什么锁死 | 验收意见的签名区是「验收组:」一行全体签,不分组长 / 成员行、不加下划线;标题里的书名号内容禁断行,长了就缩字号。判据不是审美,是过去已签字的成品实物 —— 版式固化在生成代码里,重新生成即恢复,谁也改不动。 |
| 这一页 | 单文件 HTML,零外部请求:没有 CDN、没有外部字体、没有任何 fetch。计算全在你浏览器里跑,勾选状态存 localStorage。 |