Files
dealerhub/PROGRESS_AGI_ITERATION_7.md

117 lines
6.7 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.
# PROGRESS_AGI_ITERATION_7 · D2 业务员 H5 + P2-2 部署清单
> 跑法口径:后端 `pytest` 全量(`tests/` + `apps/core/tests`),前端 `npm run build` + `npm test`。
> - 后端 SQLite:**510 passed / 4 skipped**(4 skipped 均为 PG 专用并发用例)
> - 后端 PG 5433 `-m postgres`:**4 passed**
> - 前端:`npm run build` ✅ 5.64s;`npm test` ✅ 11 pass / 0 fail
> - `manage.py check` 0 issues;`makemigrations --check` No changes
> - D2 移动模拟:`backend/scripts/verify_salesman_h5.py` 全 10 步通过,0 console errors
> - P2-2:`docker compose config` exit 0 + `docs/DEPLOY_CHECKLIST.md` 落地;镜像构建/上线因无凭证未做,不虚报
> - P3-1:按规格跳过,未建模
## 一、P2-3 D2 业务员移动开单 H5(`PROGRESS_BATCH_D.md:236` + `NEXT_PLAN.md` §P2-3)
规格原文:复用 `Storefront.vue` 外壳 + `SalesBills` 取价/单位/抹零组件,
换业务员角色(外勤开单/查欠款/收款登记),Chrome 移动模拟全流程走通。
### 交付
- 新建 `frontend/src/pages/Salesman.vue`(约 550 行,`dist/assets/Salesman-*.js` 16.26 kB):
- 外壳:复用 Storefront 的 `sf-wrap` 移动布局(max-width 560px + 480px 断点纵排),
登录用后台用户 JWT(`POST /auth/token/`,与 PC 同一套账号),公开路由 `/#/salesman`。
- 外勤开单:客户/仓库下拉 + 商品搜索 + 单位下拉 + 数量;
取价走 `GET /partner/price-quote/`(客户专属价→等级价→上次成交价→默认价,
与 SalesBills 同源,source 标签同文案);单位换算走
`GET /catalog/products/<id>/units/` + `utils/transaction.js` 的 `unitRate/lineAmount`
(与 SalesBills 同口径);税率/税额行内显示(价内拆分,与 D4 同公式);
抹零(不抹/抹分/抹角/抹元)+ 应收合计;保存走 `POST /sales/bills/create-bill/`
后自动 `POST /sales/bills/<id>/confirm/`(402 超限弹强制过账确认,与 SalesBills 同流程)。
- 查欠款:`GET /finance/receivables/` 只留 open/partial(前端过滤,BaseTenantViewSet
无精确 customer 过滤器,不伪造后端参数),显示单号/客户/日期/共欠/已收/未结余额 + 状态标签 + 未结合计。
- 收款登记:`POST /finance/receipts/`(客户/单号必填/日期/金额>0/方式/备注),
单号必填是实测结论(Receipt.bill_no 无自生成,漏填 400),表单 rules 与
`Receivables.vue` 登记 dialog 同约束。
- 路由:`frontend/src/router/index.js` 加 `/salesman` + `PUBLIC_ROUTES` 加 `salesman`
(P0-3 同类坑:不加则匿名被踢回 login)。
### 验证(干净库实跑,非残留数据)
`backend/scripts/verify_salesman_h5.py`(Playwright Chromium,Pixel 5 移动模拟
393×851 + touch + 移动 UA),dev 后端 :18099 + vite :15173(临时 verify 配置代理 /api):
```
[pre] customer=C001 warehouse=WH01 product=B001 token=ok
[1] login ok (mobile viewport 393x851)
[2] customer: OK:C001 张三便利店 / warehouse: OK:WH01 主仓库
[3] add-to-order ok (qty=2)
[4] round_to: OK:抹角(0.1)/ submit+confirm clicked
[5] debt tab: 未结 ¥31.00(1 单)RC202609120001 … 未收
[6] receipt customer OK / submit clicked
[7] console errors: 0
[8] latest bill: XS202609120001 state=confirmed total=31.0000
[9] receipt SMH50002 ok amount=50.0000
[10] open receivables: 1, first balance=31.0000
ALL SALESMAN-H5 CHECKS PASSED
```
验证后残留(XS202609120001/SMH50002/RC202609120001)已删,`default` 租户恢复 0 单据。
为验证造的最小数据保留(alice/alice12345 + B001/C001/WH01/1000 库存),属可用 fixture。
### 踩坑
1. 密码框无 placeholder(只有前两个 input 有),用 `.sm-login input` 序号定位。
2. 移动视口下 `li[role=option]`(非 `.el-select-dropdown .el-option`)且常判不可见,
Playwright click(连 force)会被 visible 挡 → 一律用 JS `offsetParent` 过滤可见项后 `.click()`。
3. 收款 tab 切换用 `#tab-receipt/#pane-receipt` 稳定选择器,不用 role 或 is-active。
4. 填单号前先 `Escape` 关残留 popper,否则输入框被浮层挡住无法 fill。
## 二、P2-2 部署 readiness(`NEXT_PLAN.md` §P2-2)
- `docs/DEPLOY_CHECKLIST.md`(新建):本地校验表(7 项全 ✅ exit 0/实测值)+
上线 gate(环境变量/构建/迁移/collectstatic/DEBUG/PG/HTTPS/日志轮转/备份/冒烟)+
诚实记录(未构建镜像、未上线、无备份脚本,均不虚报)。
- 附带真缺口修复:`backend/config/settings/prod.py` 拒绝 `DJANGO_ALLOWED_HOSTS` 含 `*`。
根因:`base.py:read_env` 把 dev `.env`(`DJANGO_ALLOWED_HOSTS=*`)写进 `os.environ`,
prod 空值门读到 `*` 静默通过。验证:不传变量 → `ImproperlyConfigured(通配符)`;
`=example.com` → check 0 issues。全仓 grep `settings.prod` 零命中,无测试依赖。
- 本地校验实测:`docker compose config` exit 0(插值全展开);
prod `check` 0 issues;`collectstatic` 216 files;prod 基线
(DEBUG=False / dealerhub INFO / PG pool 2/10/10 / HSTS 30 天+include+preload /
Secure Cookie / proxy https / DENY)逐项打印确认。
## 三、P3-1 跳过声明
按 `NEXT_PLAN.md` §P3-1 与 `PROGRESS_BATCH_D.md:238` 定调"按客户驱动,不提前做":
本轮未建 `Serial`/辅助属性/套装拆件,未动 inventory/catalog 模型,
`makemigrations --check` No changes 即为预期状态。
## 四、最终验证数字(本轮实跑)
```
backend pytest tests/(SQLite): 496 passed / 4 skipped
backend pytest 全量(含 core/tests): 510 passed / 4 skipped
backend PG -m postgres: 4 passed
frontend npm run build: ✓ 5.64s(含 Salesman-*.js 16.26 kB)
frontend npm test: 11 pass / 0 fail
manage.py check: 0 issues;makemigrations --check: No changes
D2 verify_salesman_h5.py: ALL PASSED(0 console errors)
```
## 五、变更文件清单
```
frontend/src/pages/Salesman.vue [新] D2 业务员 H5 三职一页
frontend/src/router/index.js [改] +/salesman 路由 + PUBLIC_ROUTES
backend/scripts/verify_salesman_h5.py [新] D2 移动模拟全流程脚本(10 步断言)
backend/config/settings/prod.py [改] ALLOWED_HOSTS 拒绝通配符 *
docs/DEPLOY_CHECKLIST.md [新] P2-2 readiness gate 清单
frontend/dist/ [重建]
```
## 六、遗留
- 镜像构建 + 上线 192.168.5.7:无 Docker 目标机/服务器凭证,停在清单 + 本地校验。
- 日志轮转/备份:运维侧动作,仓库无实现(清单已如实标注)。
- D2 欠款页用前端过滤(open/partial + 按客户),数据量大时应补后端 `customer/status`
精确过滤;当前为 H5 外勤场景可接受范围。