fix: 加固日历日期与动态错误合同(09-05-error-explainability-payment-readiness,09-08-reimbursement-payment-closeout)
这个提交包含在:
@@ -18,6 +18,16 @@ QA script patterns over new abstractions.
|
||||
|
||||
## Common Checks
|
||||
|
||||
### Calendar Date Inputs
|
||||
|
||||
- For reimbursement, payment-batch, travel-request and asset date-only input schemas,
|
||||
combine the YYYY-MM-DD shape with isValidDateOnlyString. Reject calendar overflow
|
||||
before persistence; a regex alone accepts February 30 and JavaScript normalizes it.
|
||||
- Keep optional and nullable wrappers outside the string validator. Validate leap-day,
|
||||
month-end, invalid month and empty/null boundaries without changing stored historical dates.
|
||||
- parseDateOnlyString retains its legacy conversion contract for unaudited consumers;
|
||||
it is not validation. Do not claim the shared parser or other domains are all hardened.
|
||||
|
||||
### Payment Account And Invoice Read Errors
|
||||
|
||||
- Payment-account maintenance and invoice-pool read validation use registered
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
|
||||
## Source Of Truth
|
||||
|
||||
- Reminder cooldown hints render server UTC timestamps in Asia/Shanghai with an
|
||||
explicit Beijing-time label and second precision. Reuse formatDisplayDateTime's
|
||||
opt-in includeSeconds; existing callers retain minute precision. Both registered
|
||||
reason and legacy details paths reject malformed/non-finite timestamps without
|
||||
reflecting arbitrary values. Cover a UTC-to-Beijing cross-year case.
|
||||
|
||||
Frontend visual and interaction design uses the installed `frontend-design`
|
||||
skill as the primary design authority. `docs/产品设计规则.md` remains a product
|
||||
experience and business-boundary fact source, not a visual, brand or aesthetic
|
||||
|
||||
@@ -243,3 +243,18 @@ R1包及其manifest不变;本轮代码已偏离R1,必须重冻R2后交增量
|
||||
- 下一项统一待办需求仅以该真实流程的三个交接观察为输入:交给财务组批、交给经理/CEO 复核、交回财务登记付款;每处记录谁交给谁、接收人通过什么现有入口或提醒知道轮到自己、是否需要口头催办。尚未发生的交接不预填结论,不记录真实银行资料。
|
||||
- 独立待办仍保留:财务测试账号 403 需要单独解决并补财务身份真实验收(管理员代验不等于该角色验收);合同只读超时需单独复现归因,不计入通过;“三张单的答复”仅作为用户提醒保留,未明确具体单据和答复内容,不自行推断或代答。
|
||||
- Trellis 升级另行审查:逐条核对 workflow.md 与 project-governance.md 删除或弱化的规则及理由,独立检查 hooks 行为变化;不以模型升级为整批删除保障的理由。本次仅记录后续事项,不启动新产品任务、不修改配置或真实资料、不自动提交、部署或归档。
|
||||
# 2026-09-16 上线后契约补强
|
||||
|
||||
后续日期批次方案:共享date工具新增纯isValidDateOnlyString谓词(严格YYYY-MM-DD、有限UTC日期、回读同日),保持旧parseDateOnlyString行为以免无关服务突然抛500;先接报销/付款/差旅申请/资产四路由的既有Zod日期schema,optional/nullable外层语义不变,失败沿原输入错误合同且写入前拒绝。催办复用前端displayFormat的Asia/Shanghai格式并明确“北京时间”,旧details分支也校验UTC形状/有限性,不回显任意字符串。验证单测正反边界、各域实际入口/解析器、无副作用及前端typecheck/build;采购、合同、考勤等剩余消费者继续单列,不冒称所有日期解析债务清零。不迁移或改生产历史日期,不提交/部署本轮未审代码。
|
||||
|
||||
日期批次已本地实施:9文件450/450定向回归通过(日期工具/客户端映射/四域验证/报销统计/金额/草稿分类)。付款导出两项首跑因系统Python缺BIFF8依赖返回409,改用已有隔离Python(xlrd2.0.2/xlwt1.3.0)后整轮通过,没有修改生产依赖或产品导出门禁。命令:`cd server && PAYMENT_ORDER_PYTHON_BIN=<已有隔离Python> npm test -- tests/unit/utils/date.test.js tests/unit/scripts/error-reason-client.test.js tests/unit/routes/assets.validation.test.js tests/unit/routes/travelRequests.test.js tests/unit/routes/reimbursements.create.test.js tests/unit/routes/paymentBatches.reimbursement.test.js tests/unit/routes/reimbursements.stats.test.js tests/unit/routes/reimbursements.amount-guard.test.js tests/unit/routes/reimbursements.draft-classification.test.js`。资产覆盖实际create解析器的4字段无效/闰日/null,不冒充真实DB写入;差旅覆盖PATCH两日期输入前拒绝;报销/付款另有正常日期/清空/无写入反例。催办保留秒且显示北京时间,默认格式消费者仍分钟精度。
|
||||
|
||||
消费者盘点:已收口4路由输入schema;invoicePool局部日期函数已有独立严格校验,未重写。contractsRegistry/purchaseRequests/travelOrders/travelReconciliation/weeklyReports/presence/portal、contractRegistryFilters/attendance/employeeStats/feeControl/presenceHistory及export-small-team-observation仍调用旧解析器,需按外部输入与内部派生分类后逐项迁移,不因共享谓词新增就算已修。无生产历史日期扫描/修订;原到期日未改。当前主会话自检不计独立复核,整批新变更待只读内容复核与单独提交/发布批准。
|
||||
|
||||
最终增量合并验证:上述9文件再加auth.login、invoicePool.patch、workflow.batch共12文件526/526通过。`cd client && npm run typecheck && npm run build`退出0;Node语法检查、原因码注册229/遗留612/零finding、process baseline、Trellis治理及git diff --check通过。构建有既有Browserslist数据过期与大chunk提示,未升级依赖或修改拆包。当前未执行浏览器/生产登录业务链,不把旧22项记录当新输入重跑。准备calendar-contract-review-20260916-r1独立只读交审,旧R1/R2交付包保持原字节;本轮不提交或部署,生产仍842c61e6。
|
||||
|
||||
842c61e6已部署,公网只读验收通过,发布回执见error-explainability-r2-release。用户批准继续后续工作;本轮先处理独立复核F-1/F-2/F-3的本地测试缺口,不改已上线业务逻辑、不重冻旧包、不自动提交或部署。验收:服务端当前VAT必填集合逐字段投影、密码校验实际输出逐规则投影;路由断言missingFields/password兼容键与具体值;严格UTC形状但非有限日期安全回落。票种扩展、时区展示仍需分别核验,测试覆盖不扩称全集已完成。
|
||||
|
||||
最终同输入验证:`cd server && npm test -- tests/unit/scripts/error-reason-client.test.js tests/unit/routes/auth.login.test.js tests/unit/routes/invoicePool.patch.test.js tests/unit/routes/workflow.batch.test.js`,4文件323/323通过。新增4项(VAT集合、密码策略、非有限日期、催办精确24小时冷却负载);两项已有路由用例加强动态键断言。催办409同时核nextAllowedAt、查询时间窗、无历史/通知/任务写入;只用合成actor/存储替身,不是生产登录链。首轮1项失败是新测试把已有“总金额”误写为“价税合计”,已校正测试预期而未修改产品文案;最终整轮通过。存在Node既有punycode弃用警告,无测试失败。
|
||||
|
||||
流程baseline、Trellis治理及git diff --check通过。本轮仅测试/文档,无运行时代码或schema变化,未重跑前端build/浏览器,未独立复核、提交、推送或发布。扩展票种buyerName、密码新规则的输入覆盖、时区与共享日历校验仍不是这组测试能全量保证的事项。
|
||||
|
||||
@@ -756,3 +756,12 @@ T0 是新增代码工作的前置;T1 数据库路径获成功证据后推进 T
|
||||
- [ ] 功能交付后回到统一待办投影;同期维护原错误豁免截止日队列,不批量归档或延期。
|
||||
|
||||
首个实施动作明确为“用空报销合成数据复现发票顺序问题,并核查退回删除事务/材料关系”,不是继续生产清理或让 majianyong 再尝试一次。主工作树在旧基线且有治理差异,执行副本须从最新 origin/main 核验建立,按任务登记分批文件清单与测试命令。
|
||||
# 2026-09-16 发布后后续执行
|
||||
|
||||
最新已上线候选842c61e69645b2c753b41593686701854e25ea3a,树831557fd8f5c26445bd66eef574332eb8314fe59。R2独立内容审查通过后已按批准提交、推送、重新预检和部署;公网只读/运行身份验收通过,数据库未重启、.env未覆盖。证据归artifacts/qa-layout/error-explainability-r2-release,不能再将下方09-15历史“未提交/未部署”当当前事实。
|
||||
|
||||
用户要求继续后续工作,本轮先在09-05补复核低级发现对应的动态错误负载/白名单契约/无效时间反例,只有测试和执行记录修改,线上版本不变,未自动提交或部署。原09-04两文档及统一审批中心三处旧差异保持隔离。
|
||||
|
||||
接续批次已增加四域日期输入严格校验及明确北京时间的催办提示,当前变更不再仅测试/记录。最终12文件526/526及前端typecheck/build、原因码和流程治理通过;详细范围与未覆盖消费者见09-05本日记录。交审包calendar-contract-review-20260916-r1待独立内容复核,不沿用上一轮R2通过结论;未提交、未部署,线上仍842c61e6。其余需要真实对象/专项授权的C/E/F不通过修改测试造完成记录。
|
||||
|
||||
仍待项:A历史task全量验收映射不以祖先关系替代;B真实通知送达与E自然回单不制造业务;C同源DB+附件+应用恢复仍未实测完成,08-23中固定历史源方案待专项批准,不能将本次部署批准当恢复授权;F密钥来源UNKNOWN保留且不再向用户索取密钥。D共享日期/时区、其他域遗留原因与扩展票种仍按既有期限逐项治理,不统一延期。镜像归档完整性不是恢复演练,当前部署通过不自动关闭上述事项。
|
||||
|
||||
在新工单中引用
屏蔽一个用户