117 lines
6.7 KiB
Markdown
117 lines
6.7 KiB
Markdown
# 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 外勤场景可接受范围。
|