72 lines
4.5 KiB
Markdown
72 lines
4.5 KiB
Markdown
# PROGRESS_AGI_ITERATION_6 · P0 收口 + 财务闭环 + PG 并发复跑
|
||
|
||
> 实跑基线(2026-09-12,`pytest` 全量口径):
|
||
> - SQLite:**509 passed / 4 skipped**(4 skipped 均为 `tests/test_concurrency.py` 的 PG 专用用例)
|
||
> - PostgreSQL(127.0.0.1:5433,`config.settings.pgtest`):**499 passed / 0 skipped**(含 `-m postgres` 4 并发用例全绿)
|
||
> - 前端:`npm run build` ✅ 6.32s;`npm test` ✅ 11/11
|
||
> `manage.py check` 0 issues;`makemigrations --check` No changes。
|
||
|
||
## 本轮做了什么
|
||
|
||
P0-1(交接计划 `NEXT_PLAN.md` §P0-1)收口。接管时工作区已有未提交的半成品
|
||
(permissions 超管放行 + 未知租户 400 分层、viewset 未知租户显式 400、
|
||
seed_demo/demo 幂等兜底、两个测试侧 membership 修补、exceptions 去 `exc_type`
|
||
+ 补 `_with_error_code`),本轮在其上完成最后闭环:
|
||
|
||
1. `tests/test_membership.py`(新建,8 用例):无 membership→403+code、
|
||
跨租户→403、inactive membership→403、未知租户→400、超管放行、
|
||
API Key 分支(单元级)+ 集成接线现实、demo token 只读可读、
|
||
`seed_initial_data` membership 幂等。
|
||
2. `tests/test_exception_handler.py::test_handler_returns_structured_500_for_unknown`:
|
||
期望从 `exc_type == "RuntimeError"` 改为 `"exc_type" not in resp.data`,
|
||
对齐 P0-4 已落地的去泄露修复(实现先于测试更新)。
|
||
|
||
## 语义决策(理由)
|
||
|
||
- **未知租户 → 400 而非 403**:参数错误与授权失败分离,未知 code 走视图层
|
||
`ValidationError({"tenant": "无法识别租户"})`,不泄露租户存在性判断给授权层。
|
||
- **超管直通**:与 `seed_initial_data` 的 bootstrap 契约一致
|
||
("existing superusers are operators for every seeded tenant")。
|
||
- **demo 幂等兜底**:demo token 流 bypass 正常登录路径,`enter_demo` 内
|
||
`get_or_create` 保证手工建的 demo 租户也能进。
|
||
- **API Key 分支的接线现实**(实测,非假设):
|
||
`TenantMembershipPermission` 的 APIKey 分支目前没有视图同时接线——
|
||
`BaseTenantViewSet` 系用 JWT/Session,`Open*` 系用 `require_scope`。
|
||
所以用例 6 按"单元级分支验证 + 集成级现实记录"写,不伪造 403。
|
||
若后续要把 APIKey 接进租户系视图,再把该用例升级为端到端。
|
||
|
||
## 踩坑
|
||
|
||
- `test_demo.py`、`test_printing.py` 的 membership 修补在接管时已在工作区,
|
||
本轮只验证了它们变绿,没有重写。
|
||
- `pytest -q` 不打印 passed 汇总行(只有 dots + warnings + FAILED/SKIPPED),
|
||
用例数用 `--collect-only | grep -c "::"` 拿:全量 490(tests/ 476 + core 14)。
|
||
- 交接计划写的"482 全量 / 477 passed"是旧基线数字,本轮实测已是 490,
|
||
差异来自期间新增用例;文档数字以本轮实跑为准。
|
||
|
||
## 本轮新增(2026-09-12 续)
|
||
|
||
1. **P0 级阻塞修复**:`BaseTenantViewSet.acreate()` 在 async 上下文同步跑
|
||
`serializer.is_valid()`,凡带 FK 的创建(收款/付款单等)全 500
|
||
`SynchronousOnlyOperation`。修法:包进 `sync_to_async`(与 printing 已有写法对齐)。
|
||
验证:收款单 201 / 付款单 201 / 重复编码 400。
|
||
落点:`backend/apps/core/viewset.py`(+3 行注释)。
|
||
2. **前端财务入口闭环**(`NEXT_PLAN.md` §附录 A #1#2 + f7eb4325"补前端财务入口与错误状态"):
|
||
- `Receivables.vue`:"+登记收款"按钮 → 收款单创建 dialog(客户下拉/单号留空自生成/日期/金额>0/方式/备注)
|
||
+ 每行"核销"按钮 → 收款单选择 + 金额 dialog(默认未结余额,超额后端 400 透出)。
|
||
- `Payables.vue`:镜像实现(登记付款 + 核销应付)。
|
||
- 后端字段级错误(customer/bill_no/amount/allocations/detail)本地透出 `ElMessage.error`,
|
||
全局拦截器兜底其余状态。
|
||
- 验证:`npm run build` ✅ 6.32s;后端 finance 22 用例绿;全量 509 绿无带崩。
|
||
3. **P1-1 PG 并发复跑**:`python scripts/setup_pg.py` 连通 127.0.0.1:5433;
|
||
`-m postgres` 4/4 绿;PG 全量 499 绿。
|
||
4. **日志清理**:删 `backend/g8060/g8070/g8080/g8090.log`(P0-4 现场 g8070 已无保留价值,
|
||
`*.log` 已在 `.gitignore`)。
|
||
|
||
## 遗留(诚实记录)
|
||
|
||
- §附录 A #4–#10(库存流水/预警规则/打印模板/自定义报表/库存大盘/科目管理/价格等级页)
|
||
仍是后端有、前端无——超出本轮 27 条真源范围,未动。
|
||
- P2-2 部署 readiness gate + 上线 192.168.5.7:需 Docker/服务器凭证,未动。
|
||
- P2-3/D2 移动开单、P3-1 行业专版:按客户驱动,未动。
|