# 采购订单生成与审批检查 > 本报告记录的是修复前提交 `4876d88`。随后已按建议修改本地 v2 源码;当前运行规则和升级步骤见 [运行与升级说明](运行与升级说明.md),验证结果见该文档末尾。 检查日期:2026-09-16。分支:`master`。远端和本地提交均为 `4876d8805d029702be92ec397bc5e9d6c9c25503`,最新提交时间为 2026-09-10 16:57 +0800。 目前是可以演示完整流程的初版。普通订单能生成、提交、两级审批并导出 PDF;正式多人使用前,仍需解决身份认证、数据权限、审批职责、金额一致性和事务恢复问题。 本次没有修改业务源码。使用 Flask test client 在 `tools/out/` 下复制代码、创建独立数据库进行验证,未向正式服务提交数据。审查脚本为 `tools/out/review_probe.py`,本次结果在 `tools/out/audit_geghi4ic/results.json`。这些测试文件被现有 `.gitignore` 排除。 ## 已验证通过的基础能力 - 采购单 3 行、委外生产订单 30 行,均能完成草稿 → 待主管审核 → 待经理批准 → 已批准。 - 主管和经理未提交盖章确认标记时,接口拒绝通过;普通制单员不能调用通过接口。 - 审批动作会生成记录;已批准订单通过编辑接口修改会被拒绝。 - 草稿 PDF 有水印,已批准 PDF 无水印;采购样本 1 页,委外样本 3 页,有重复明细表头、签署信息和图形印章。 - 英文文件名的标准 XLSX 明细能导入。 这些结果只证明对应样本通过,不能作为所有边界情况、多人并发或正式签章有效性的验收结论。 ## P0:正式使用前必须解决 ### 1. 固定会话密钥可导致冒充管理员【已复现】 位置:`po_app/app.py:40`、`:52`。 会话签名密钥写在源码里。隔离测试使用该密钥签出的管理员会话,在未输入管理员密码的情况下成功访问 `/users`。仅修改默认密码不能解决这个问题。 修复方向:每个部署使用独立的随机密钥并外置保存,轮换现有密钥、使旧会话失效;上线初始化强制设置密码。 ### 2. 订单权限只过滤了列表,详情和导出仍越权【已复现】 位置:`po_app/app.py:326`、`:435`、`:473`、`:1010`、`:1034`。 第二个制单员在列表看不到第一个制单员的订单,但直接访问订单 ID 能查看详情、导出 PDF、复制为自己的订单;导出台账还能得到其他人的订单。导出文件下载入口也仅检查是否登录。 修复方向:明确谁可看哪些订单,统一检查详情、编辑读取、复制、PDF、台账、统计、历史文件的权限。 ### 3. 一个数据库错误会影响其他用户继续操作【已复现;并发风险为代码检查】 位置:`po_app/app.py:44`、`:966`、`:1071`。 所有请求共用一个数据库 Session。新增重名用户触发 `IntegrityError` 后没有回滚,另一个用户打开订单列表随即触发 `PendingRollbackError`。此时实际网页请求会报错,需要恢复会话或重启服务。服务还启用了多线程,共用 Session 带来的并发事务风险尚未经过压力测试。 修复方向:每请求独立 Session,结束时关闭,异常时回滚;对唯一性冲突提供明确提示。 ## P1:直接影响制单与审批正确性 ### 4. 审批职责和环节限制不完整【已复现】 位置:`po_app/app.py:89`、`:265`、`:360`、`:382`、`:403`。 - 主管账号可以新建、编辑、提交订单,再审核自己制作的订单。 - 经理可以在主管审核前驳回;主管可以驳回已经进入经理批准环节的订单。 - 管理员可执行全部环节是现有设计;如果公司要求制单、审核、批准分人,应显式限制并规定例外操作。 修复方向:服务端同时校验操作角色、当前环节、制单人和前一审批人;新建及复制权限也需一致。 ### 5. 必填内容和明细数值未有效校验【已复现】 位置:`po_app/app.py:132`、`:297`、`:339`、`:488`。 提交只判断是否存在明细行。本次以下单据均走到“已批准”: | 输入 | 实际结果 | |---|---| | 供应商为空,数量 -2,单价 10 | 批准金额 -20 元 | | 数量为 `abc` | 静默变成 0,批准金额 0 元 | | 单价为 0 | 无异常提示,批准金额 0 元 | 修复方向:按业务规则验证供应商、有效明细、数量、价格、日期及必要的结算信息;非法数字不得静默归零。零价是否允许应有明确业务规则。 ### 6. 页面金额、保存金额与 PDF 单价不一致【已复现】 位置:`po_app/templates/order_edit.html:158`、`po_app/app.py:118`、`po_app/pdf_export.py:288`、`po_app/models.py:134`。 - 两行“数量 1、单价 0.334”:页面每行 0.33,页面合计 0.67;保存后合计 0.66。前端先累加原始乘积,后端先将每行金额保留两位。 - “数量 3、单价 0.3333”:金额为 1.00,但 PDF 把单价显示为 0.33,读者按打印内容只能算出 0.99。订单详情也将单价限制为两位。 - 金额与单价采用浮点数,舍入规则没有形成统一业务定义。 修复方向:统一定点金额、单价精度和舍入规则,前端、后端及导出使用相同口径,并明确展示价格精度。 ### 7. 编辑后直接“提交审核”会提交旧数据【代码确认,未做浏览器点击测试】 位置:`po_app/templates/order_edit.html:7`、`:116`;`po_app/app.py:339`。 保存订单与提交审核是两个独立表单。已有明细的订单在页面修改价格、供应商等内容后,不先点保存而直接点“提交主管审核”,请求只携带提交说明,服务端提交的是数据库中的旧内容。首次填写尚未保存时则被当成明细为空。 修复方向:提供原子性的“保存并提交”,或检测未保存更改并阻止提交;跳转预览和导入时也应处理未保存内容。 ### 8. 中文 Excel 文件名及日期类型处理有缺陷【已复现】 位置:`po_app/app.py:498`、`:527`、`:536`;`po_app/templates/order_edit.html:72`。 - 相同内容使用 `items.xlsx` 导入成功,改名为 `采购明细.xlsx` 导入失败。文件名清理后丢失可识别的扩展名,解析器选择错误。 - XLSX 原生日期单元格被保存为 `2026-10-01 00:00:00`;编辑页的日期控件要求日期格式,两者不匹配,存在编辑保存时清空交期的风险。已验证数据库值;未用浏览器验证最终清空行为。 - 供应商和物料导入使用相同文件名处理方式,存在同类问题,未逐个进行接口复测。 修复方向:服务器生成独立文件名并保留已验证的扩展名;统一规范日期格式,并为 XLS 日期序号单独处理。 ### 9. 用户维护不完整,停用不能立即终止旧会话【部分已复现,部分代码确认】 位置:`po_app/templates/users.html:5`、`:22`;`po_app/app.py:52`、`:966`。 说明文档让用户在“用户”页改默认密码,但页面只有新增和列表,没有编辑、改密码、停用入口。后端存在按 ID 修改用户的逻辑,没有设置 active 的逻辑。 隔离测试将主管 active 改为 False 后,其已登录的会话仍能审核通过;请求时只获取用户,没有重新检查 active。 修复方向:补齐用户维护与改密页面,检查账号启用状态,支持强制失效会话,并约束角色和用户名输入。 ### 10. 单号唯一性缺乏数据库和事务保证【约束缺失已复现,实际并发未测】 位置:`po_app/app.py:98`;`po_app/models.py:79`。 编号通过读取当天最大号再加一生成,数据库没有唯一约束。隔离测试成功插入两个相同单号。并发或重复请求可能产生重复单号,但本次没有做真实并发压测,不将其表述为已复现的线上并发故障。 修复方向:单号唯一索引、事务内分配或冲突重试,以及新建/复制请求的重复提交保护。 ## 仍需补齐或按业务确认的流程 以下是代码和数据模型中尚未具备的能力,不代表公司已经要求全部实现: - **撤回、作废、批准后变更重审**:现有状态只有草稿、待审核、待批准、已批准、已驳回。尚无提交后主动撤回及正式订单作废/修订流程。 - **审批版本追溯**:现有日志记录姓名、动作、时间、意见,但没有修改前后内容、订单版本、审批内容快照和稳定的操作人 ID。驳回修改后,无法从旧审批记录还原当时审核的明细。 - **审批分派和提醒**:按角色统一进入待办;没有指定主管/经理、部门、金额阈值、代理人、催办或消息通知。若仅需固定两级流程,可后置复杂审批规则。 - **正式文件归档**:批准后 PDF 按当前模板重新生成,没有冻结当时的模板和文件摘要。现有“章”是根据审批状态绘制的图形,`stamped=1` 是确认标记;没有独立的服务端盖章凭证或文件数字签名。是否需要签章服务须按使用场景确定。 - **多人部署与恢复**:源码以开发服务器方式运行,数据库位于运行电脑本地。需要确定统一服务主机、启动方式、备份恢复和升级迁移;每台电脑各运行一个 EXE 会形成各自独立的数据库。README 已提到其他电脑通过主机 IP 访问,这个部署方式应落地验证。 - **采购前置及后续流程**:请购、预算、询比价、附件、供应商回签、到货和付款跟踪均不在现有实现中。若目标只到订单生成与内部审批,不必把这些全部纳入首期。 ## PDF 和测试的其他问题 - 已查看采购正式样本 1 页、委外正式样本 3 页、价格精度样本 1 页的渲染图。大写金额已经包含“元整”或“角/分”,模板右侧仍固定再打印“元整”,例如 `壹佰壹拾贰元伍角` 后又出现 `元整`。位置:`po_app/pdf_export.py:314`。 - 委外版规格列较窄,短规格也发生多行折行;样本合计与条款/签署分到不同页。基本可读,需按实际单据样本确定版式要求。原始 Excel 套打模板未入库,因此未验证“完全复刻原模板”。 - `tools/e2e_test.py:75` 和 `:78` 没有传目前必需的盖章标记,也未断言审批后的状态,随后直接打印“审核流程 ok”。该脚本可误报成功;部分工具仍硬编码原开发电脑路径。仓库另有盖章专项脚本,不能据此推定所有测试都失效。 - 测试范围不含真实浏览器全流程、EXE 打包运行、局域网部署、压力测试及真实采购数据验收。未将既有测试脚本全部执行,因为部分脚本会操作实际运行数据库和固定外部目录。 ## 建议修复顺序与验收标准 1. 身份认证、统一数据权限、按请求管理事务:不能伪造登录或跨制单员读单,单个失败请求不影响其他用户。 2. 输入校验、金额精度、保存并提交、Excel 导入、用户维护:页面、数据库和 PDF 金额一致,修改后的内容确实进入审批,中文文件和日期正常。 3. 审批角色及环节约束、唯一单号、撤回/作废/版本记录:每次审批能对应明确的人、环节和单据版本。 4. 修正 PDF 和自动化检查,在统一部署方式下用真实模板、常见订单和多账号并发完成验收。 完成前两步和核心审批约束后,再开展小范围试用;是否扩展预算、分部门流程和外部签章,单独按业务决定。