Files
order_system/项目检查-20260916.md

145 lines
11 KiB
Markdown
Raw Permalink 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.
# 采购订单生成与审批检查
> 本报告记录的是修复前提交 `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 和自动化检查,在统一部署方式下用真实模板、常见订单和多账号并发完成验收。
完成前两步和核心审批约束后,再开展小范围试用;是否扩展预算、分部门流程和外部签章,单独按业务决定。