Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c319a6a428 | ||
|
|
b86eaf2b00 | ||
|
|
71df9a16ed | ||
|
|
980628bb8f |
No files matched your search
@@ -144,9 +144,9 @@ uv run pytest tests/integration -q # 仅集成
|
|||||||
| `tests/unit/test_report_helpers.py` | 区间分桶边界与 8 档编码唯一;标签覆盖全部枚举;Excel 模板页眉/签字栏/空数据/金额格式/合计/公式注入/维度 sheet/状态中文;**部门汇总签字稿五块顺序、零成员团队与未分配行、5% 按计入次数累计、应发合计取对账口径、聚合行舍入差单列、比例标题参数化** | 17 |
|
| `tests/unit/test_report_helpers.py` | 区间分桶边界与 8 档编码唯一;标签覆盖全部枚举;Excel 模板页眉/签字栏/空数据/金额格式/合计/公式注入/维度 sheet/状态中文;**部门汇总签字稿五块顺序、零成员团队与未分配行、5% 按计入次数累计、应发合计取对账口径、聚合行舍入差单列、比例标题参数化** | 17 |
|
||||||
| `tests/unit/test_month_validation.py` | 非法月份(`2026-13`/`2026-00`/`0000-01` 等)在报表、月结、调整单 schema 入口即拒绝;可选月份空串规范为 None | 17 |
|
| `tests/unit/test_month_validation.py` | 非法月份(`2026-13`/`2026-00`/`0000-01` 等)在报表、月结、调整单 schema 入口即拒绝;可选月份空串规范为 None | 17 |
|
||||||
|
|
||||||
运行:`uv run pytest tests/integration/test_reports.py -q` → **24 passed**(2026-10-19 修复回归);`uv run pytest tests/unit/test_report_helpers.py tests/unit/test_month_validation.py -q` → **33 passed**;全量 **847 passed**(2026-10-19)。
|
运行:`uv run pytest tests/integration/test_reports.py -q` → **27 passed**(2026-10-20 复核);`uv run pytest tests/unit/test_report_helpers.py tests/unit/test_month_validation.py -q` → **34 passed**;全量 **862 passed**(2026-10-20,11:32)。
|
||||||
|
|
||||||
**e2e**:`frontend/e2e/report_flow.py` 已补回款多桶同时展开、部门下钻筛选生效、打印截断提示、部门汇总打印五块结构;需 `E2E_ADMIN_PASSWORD` 与前后端在跑。
|
**e2e 实跑(2026-10-20)**:`frontend/e2e/report_flow.py` 12/12 通过。回款统计改为展开目标桶后按**本次业务编号**定位下钻行(不依赖桶累计值,可重复运行);另覆盖多桶同时展开、部门下钻筛选、打印截断提示、部门汇总打印五块结构。
|
||||||
|
|
||||||
### 工作台(M4 ⑧,2026-10-19 完成)
|
### 工作台(M4 ⑧,2026-10-19 完成)
|
||||||
|
|
||||||
@@ -183,6 +183,7 @@ uv run pytest tests/integration -q # 仅集成
|
|||||||
| 2026-10-19 | 全部 | 852 | ✅ 852 passed(9:17) | **M4 ⑧ 工作台完成**(四区块实时聚合 + ECharts 5.6 前端 + V10 预警参数三项;新增 5 例;参数注册表 19→22;同步模块显式降级)。期间修复:alembic `--sql` 导出 GBK 导致 schema 同步误报 |
|
| 2026-10-19 | 全部 | 852 | ✅ 852 passed(9:17) | **M4 ⑧ 工作台完成**(四区块实时聚合 + ECharts 5.6 前端 + V10 预警参数三项;新增 5 例;参数注册表 19→22;同步模块显式降级)。期间修复:alembic `--sql` 导出 GBK 导致 schema 同步误报 |
|
||||||
| 2026-10-19 | **code-review 修复回归** | 全量 862 | ✅ 862 passed(9:36) | **M4 工作台 + 报表 3 必须 + 8 建议修复**:普通用户落地页/守卫(报表集成 27、工作台集成 11、报表单元 17,新增 10 例);部门汇总 5% 按计入次数累计并与月结 `total_payable` 对拍、聚合行舍入差;工作台待办按角色过滤、逾期命中与阈值生效、终止业务排除、`warnings.total` 截断、趋势跨月归属。ruff 绿;type-check + build 绿 |
|
| 2026-10-19 | **code-review 修复回归** | 全量 862 | ✅ 862 passed(9:36) | **M4 工作台 + 报表 3 必须 + 8 建议修复**:普通用户落地页/守卫(报表集成 27、工作台集成 11、报表单元 17,新增 10 例);部门汇总 5% 按计入次数累计并与月结 `total_payable` 对拍、聚合行舍入差;工作台待办按角色过滤、逾期命中与阈值生效、终止业务排除、`warnings.total` 截断、趋势跨月归属。ruff 绿;type-check + build 绿 |
|
||||||
| 2026-10-20 | e2e 全链路 | — | ✅ login 8 / system 13 / role_home 4 / report 12 / calc_settlement 8 | 重启后端加载新代码后实跑:普通用户落地页与受限页回退、报表四页/导出/打印、核算与月结链路全过。`report_flow` 回款统计改为展开目标桶后按本次业务编号定位明细,不依赖桶累计值,可重复运行 |
|
| 2026-10-20 | e2e 全链路 | — | ✅ login 8 / system 13 / role_home 4 / report 12 / calc_settlement 8 | 重启后端加载新代码后实跑:普通用户落地页与受限页回退、报表四页/导出/打印、核算与月结链路全过。`report_flow` 回款统计改为展开目标桶后按本次业务编号定位明细,不依赖桶累计值,可重复运行 |
|
||||||
|
| 2026-10-20 | 全量回归 | 862 | ✅ 862 passed(11:32) | **工作台/报表修复提交后的全量复核**;e2e 三脚本复跑:role_home 4/4、report 12/12、calc_settlement 8/8;calc 审批开关已还原为 1,无 `e2e_role_*` 残留 |
|
||||||
| 2026-10-19 | 单元全量 + 报表定点 | 484 | ✅ 484 passed(45.94s);报表单元 11 例 0.70s | **M4 报表模块收尾**(前端四页/打印视图/导出与单元测试补齐)。ruff 绿;前端 `pnpm type-check` 绿。报表集成 7 例记录见上节 |
|
| 2026-10-19 | 单元全量 + 报表定点 | 484 | ✅ 484 passed(45.94s);报表单元 11 例 0.70s | **M4 报表模块收尾**(前端四页/打印视图/导出与单元测试补齐)。ruff 绿;前端 `pnpm type-check` 绿。报表集成 7 例记录见上节 |
|
||||||
| 2026-10-19 | 全部 | 806 | ✅ 806 passed(7:59) | **M4 ⑤ 报表统计全量回归**(报表新增 18 例:集成 7 + 单元 11;另含并行会话并入的 M3 前端修复与字体合规)。ruff 绿。e2e:`calc_settlement_flow` 8 步由并行会话跑通;`report_flow.py` 待 `E2E_ADMIN_PASSWORD` 运行 |
|
| 2026-10-19 | 全部 | 806 | ✅ 806 passed(7:59) | **M4 ⑤ 报表统计全量回归**(报表新增 18 例:集成 7 + 单元 11;另含并行会话并入的 M3 前端修复与字体合规)。ruff 绿。e2e:`calc_settlement_flow` 8 步由并行会话跑通;`report_flow.py` 待 `E2E_ADMIN_PASSWORD` 运行 |
|
||||||
|
|
||||||
@@ -253,7 +254,7 @@ uv run pytest tests/integration -q # 仅集成
|
|||||||
| 基础数据管理 | ✅ 已完成 | 2026-10-13 完成(48 例,见上表);「被业务数据引用」的删除保护已随 T11 的业务/发货禁删用例覆盖 |
|
| 基础数据管理 | ✅ 已完成 | 2026-10-13 完成(48 例,见上表);「被业务数据引用」的删除保护已随 T11 的业务/发货禁删用例覆盖 |
|
||||||
| 业务数据管理 | ✅ 后端已完成 | 2026-10-13 完成(70 例,见上表);前端页面与绩效核算联动(M3 台账核销回写 settlement_status)待 M3 补测 |
|
| 业务数据管理 | ✅ 后端已完成 | 2026-10-13 完成(70 例,见上表);前端页面与绩效核算联动(M3 台账核销回写 settlement_status)待 M3 补测 |
|
||||||
| M3 增量(设置/分配/审批) | ✅ 已完成 | 2026-10-16 完成(44 例,见上表);审批流的**月结审批对象**(order_type=2)随 ④ 月结子块接入时补测 |
|
| M3 增量(设置/分配/审批) | ✅ 已完成 | 2026-10-16 完成(44 例,见上表);审批流的**月结审批对象**(order_type=2)随 ④ 月结子块接入时补测 |
|
||||||
| 绩效工资核算(M3-core) | ✅ 已完成 | 2026-10-17 完成(核算/月结/调整单,见运行记录);2026-10-19 code-review 21 项修复并补回归约 20 例。**待补**:e2e `calc_settlement_flow`(台账/月结两页真实浏览器链路);业务答复回填批次(88 会话:首日 10‰/聚合基数开关/二次分摊拆行)落地后按同粒度补测 |
|
| 绩效工资核算(M3-core) | ✅ 已完成 | 2026-10-17 完成(核算/月结/调整单,见运行记录);2026-10-19 code-review 21 项修复并补回归约 20 例;2026-10-20 e2e `calc_settlement_flow` 8/8 实跑通过(台账/月结真实浏览器链路) |
|
||||||
| 报表统计 | ✅ 已完成 | 2026-10-19 完成并补齐回归;e2e 用例已写好,需完整环境用 `E2E_ADMIN_PASSWORD` 实跑 |
|
| 报表统计 | ✅ 已完成 | 2026-10-19 完成并补齐回归;2026-10-20 e2e `report_flow` 12/12 实跑通过,全量 862 passed |
|
||||||
|
|
||||||
> 系统管理模块(用户/角色/日志查询)已于 2026-10-10 完成并补齐用例,见上表。
|
> 系统管理模块(用户/角色/日志查询)已于 2026-10-10 完成并补齐用例,见上表。
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
### 已按默认执行、无需回复的项(供核阅)
|
### 已按默认执行、无需回复的项(供核阅)
|
||||||
|
|
||||||
#7 月结审批链默认开启、#8 人工确认回款可手动关闭、#9 调整单同链且跨月需授权、#10 风险预警参数化、#11 待办范围(待审批+同步失败+回款未指定批次)、#13 支付环节 5 默认值、#15 一期仅 FULL 模式、#17 参数查看放开/修改限管理员、#18 企业户 2‰ 回溯、#21 退货当期冲减已结算走调整单、#22 预收/保证金/代收款暂不计入、#23 按到账金额、#24 负绩效照算不归零。
|
\#7 月结审批链默认开启、#8 人工确认回款可手动关闭、#9 调整单同链且跨月需授权、#10 风险预警参数化、#11 待办范围(待审批+同步失败+回款未指定批次)、#13 支付环节 5 默认值、#15 一期仅 FULL 模式、#17 参数查看放开/修改限管理员、#18 企业户 2‰ 回溯、#21 退货当期冲减已结算走调整单、#22 预收/保证金/代收款暂不计入、#23 按到账金额、#24 负绩效照算不归零。
|
||||||
|
|
||||||
## 二、IT / T+ 侧(建议回复期限:____)
|
## 二、IT / T+ 侧(建议回复期限:____)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# 衍水集团营销人员工资管理系统项目阶段报告
|
||||||
|
|
||||||
|
- **报告日期**:2026-10-20
|
||||||
|
- **报告范围**:M4 ⑤ 报表统计、⑧ 工作台完成情况与 M4 收尾结论
|
||||||
|
- **项目分支**:`feat/m3-increments`(已合并 `main`,merge commit `3611474`)
|
||||||
|
- **阶段结论**:除 ⑥ T+ 数据同步受外部答复阻塞外,十大功能块全部交付;后端全量 **862 用例通过**,报表、工作台、核算月结三条 e2e 链路实跑通过。
|
||||||
|
|
||||||
|
## 一、3P 阶段摘要
|
||||||
|
|
||||||
|
### Progress(进展)
|
||||||
|
|
||||||
|
M4 两块(⑤ 报表统计、⑧ 工作台)已完成并通过 code-review 修复。报表侧交付个人绩效明细、部门汇总、业务统计、回款统计四张报表、Excel 签字导出与独立打印视图;工作台侧交付经营总览、待办事项、风险预警、最近动态四区块,待办与预警实时派生并参数化。本阶段同时完成 M4 修复批次的提交、全量回归与 e2e 实跑,开发计划 3.3 答复状态已回填。
|
||||||
|
|
||||||
|
### Plans(计划)
|
||||||
|
|
||||||
|
下一步优先解析 T+12.3 数据字典,形成六类单据字段映射草案并自答 IT 清单中可自答部分;其次补齐 code-review 遗留的方案版本承载与审批单快照;需规 V2.2 修订与对照表回填择期进行。
|
||||||
|
|
||||||
|
### Problems(问题)
|
||||||
|
|
||||||
|
⑥ T+ 数据同步仍受 IT 18 项答复阻塞,同步失败类待办/预警暂以「模块未启用」显式降级。业务方仍有 #1–#3 二次分摊、#20 含税口径、#4/#6/#12 补值与两处勘误待确认;审批角色权限细目未给出,当前按 `role_code` 粗粒度运行。需规仍含已作废条款,对外引用需注明以对照表/计划第三章为准。
|
||||||
|
|
||||||
|
## 二、阶段定位与完成度
|
||||||
|
|
||||||
|
| 维度 | 当前状态 | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 项目阶段 | 开发收尾期 | M1–M3 与 M4 ⑤⑧ 已交付,仅 ⑥ 待外部输入 |
|
||||||
|
| 整体完成度 | 90% | 十大功能块交付;⑥ 按 0% 计入 |
|
||||||
|
| 交付主线 | M4 报表统计 + 工作台 | 前后端闭环,已合并 main |
|
||||||
|
| 质量状态 | 全绿 | 后端 862 passed(11:32);e2e role_home 4/4、report 12/12、calc_settlement 8/8 |
|
||||||
|
| 主要风险 | 外部对接与口径变更 | T+ 映射未定;含税口径未答复可能触发历史绩效重算 |
|
||||||
|
|
||||||
|
## 三、已完成成果
|
||||||
|
|
||||||
|
### 1. 报表统计(M4 ⑤)
|
||||||
|
|
||||||
|
- 四表接口 `/api/v1/reports/*`:个人绩效明细、部门绩效汇总、业务统计、回款区间统计。
|
||||||
|
- 部门归属按 `personnel.manager_id` 实时上溯;回款区间 8 档(≤0 / 1-30 / 31-60 / 61-90 / 91-180 / 181-360 / 361+ / 无天数)。
|
||||||
|
- 全公司 5% 按「有聚合行经理各计一次」计算,并与月结 `total_payable` 对拍;对账块单列聚合行舍入差。
|
||||||
|
- Excel 签字导出(openpyxl + StreamingResponse,ASCII 文件名)与独立打印视图(五块结构、每页表头、签字栏)。
|
||||||
|
- 权限 `admin/finance/leader` 前后端双层。
|
||||||
|
|
||||||
|
### 2. 工作台(M4 ⑧)
|
||||||
|
|
||||||
|
- 单端点 `/api/v1/dashboard` 一次返回四区块:经营总览、待办事项、风险预警、最近动态。
|
||||||
|
- 待办与预警**实时派生**(不落表、不引调度器);待办按角色过滤;逾期预警排除已终止业务。
|
||||||
|
- 预警阈值参数化:`warning.enabled`、`warning.receipt.overdue.days=90`、`warning.approval.timeout.days=3`(V10,参数注册表 22 项)。
|
||||||
|
- 前端 `/dashboard` 四区块 + ECharts 5.6 按需引入(SVG,显式思源黑体,规避 Windows 默认雅黑)。
|
||||||
|
- 普通用户落地页统一由 `router/access.ts` 解析(工作台 → 业务数据 → 回款),修复无限重定向。
|
||||||
|
|
||||||
|
### 3. 质量与收尾
|
||||||
|
|
||||||
|
- 后端全量 `uv run pytest -q` → **862 passed(11:32)**;`pnpm type-check` 与 `pnpm build` 通过。
|
||||||
|
- e2e 实跑:`role_home_flow` 4/4、`report_flow` 12/12、`calc_settlement_flow` 8/8;`report_flow` 回款统计改为按本次业务编号下钻断言,脚本可重复运行。
|
||||||
|
- 运行后核对:月结审批开关恢复为 1,无 `e2e_role_*` 残留账号。
|
||||||
|
- 开发计划 3.3.1 与《待确认事项汇总》已按 24 项答复分组回填(13 默认 / 4 按答复 / 3 部分 / 4 开放)。
|
||||||
|
|
||||||
|
## 四、当前进行中工作
|
||||||
|
|
||||||
|
无。M4 代码与文档已提交并合并 `main`(`3611474`)。
|
||||||
|
|
||||||
|
## 五、下一步计划
|
||||||
|
|
||||||
|
1. **T+ 同步前置**:解析 `docs/T_12.3数据字典/`,产出人员/产品/业务/发货/回款/客户六类字段映射草案,自答 IT 18 项中可从数据字典确认的部分。
|
||||||
|
2. **code-review 遗留 2 项**:方案生效版本承载、审批单内容快照(orders 加方案 JSON 快照列 + 前端详情展示)。
|
||||||
|
3. **需规 V2.2**:修订 26 天示例、含运费公式、协助 25% 等过时条款,回填 2026-10-15 补充需求;对照表 v2 收编 24 项答复。
|
||||||
|
4. **清理类**:5 处超长函数、散参数 DTO、`useDropdownOptions` 余两页、前端菜单图标。
|
||||||
|
5. **待外部输入**:业务方催办、审批权限清单、IT 18 项答复。
|
||||||
|
|
||||||
|
## 六、风险与应对
|
||||||
|
|
||||||
|
| 风险 | 影响 | 应对 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| IT 答复持续缺失 | ⑥ 无法开工,同步类待办/预警无法真实展示 | 先做数据字典映射草案;催办清单已含高优 9 项与三缺口 |
|
||||||
|
| 含税口径(#20)改变 | 历史绩效可能需要重算 | 当前按不含税实现;答复后评估重算范围并授权留痕 |
|
||||||
|
| 二次分摊口径(#1–#3)改变 | 已生成台账/月结可能需要调整 | 暂定口径已标注;变更走口径调整,重算需授权留痕 |
|
||||||
|
| 需规含作废条款 | 对外交付物误导 | 引用以对照表/计划第三章为准;V2.2 修订前排期 |
|
||||||
|
|
||||||
|
## 七、报告结论
|
||||||
|
|
||||||
|
M4 报表统计与工作台已完成交付并合并 `main`,系统除 ⑥ T+ 数据同步外具备完整业务闭环。质量证据充分(全量测试与三条 e2e 链路),剩余工作以外部输入与审计性技术债为主,可按计划推进。
|
||||||
+12
-16
@@ -23,7 +23,6 @@ import os
|
|||||||
import time
|
import time
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
from playwright.sync_api import Page, sync_playwright
|
from playwright.sync_api import Page, sync_playwright
|
||||||
|
|
||||||
@@ -75,15 +74,6 @@ def step_setup_via_api(page: Page) -> dict:
|
|||||||
if not token:
|
if not token:
|
||||||
fail("API 预置", "localStorage 中未取到 ys_token")
|
fail("API 预置", "localStorage 中未取到 ys_token")
|
||||||
|
|
||||||
# 回款统计断言取增量:脚本可重复运行(上次失败/历史 e2e 数据会累计到桶)
|
|
||||||
baseline = _api(
|
|
||||||
"GET", f"/api/v1/reports/payment-stats?settlement_month={MONTH}", token
|
|
||||||
)
|
|
||||||
baseline_bucket = next(b for b in baseline["buckets"] if b["code"] == "61-90")
|
|
||||||
expected_receipt_amount = (
|
|
||||||
Decimal(str(baseline_bucket["receipt_amount"])) + Decimal("10000.00")
|
|
||||||
)
|
|
||||||
|
|
||||||
roles = _api("GET", "/api/v1/system/business-roles?pageNum=1&pageSize=50", token)["list"]
|
roles = _api("GET", "/api/v1/system/business-roles?pageNum=1&pageSize=50", token)["list"]
|
||||||
salesperson_role = next((r["id"] for r in roles if r["role_code"] == "salesperson"), None)
|
salesperson_role = next((r["id"] for r in roles if r["role_code"] == "salesperson"), None)
|
||||||
manager_role = next((r["id"] for r in roles if r["role_code"] == "sales_manager"), None)
|
manager_role = next((r["id"] for r in roles if r["role_code"] == "sales_manager"), None)
|
||||||
@@ -172,7 +162,6 @@ def step_setup_via_api(page: Page) -> dict:
|
|||||||
"personnel_id": person["id"],
|
"personnel_id": person["id"],
|
||||||
"personnel_name": person["personnel_name"],
|
"personnel_name": person["personnel_name"],
|
||||||
"manager_name": manager["personnel_name"],
|
"manager_name": manager["personnel_name"],
|
||||||
"expected_receipt_amount": f"{expected_receipt_amount:.2f}",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +235,18 @@ def step_payment_stats(page: Page, ctx: dict) -> None:
|
|||||||
).first
|
).first
|
||||||
if bucket.count() == 0:
|
if bucket.count() == 0:
|
||||||
fail("回款统计", "未找到 61-90 天区间行")
|
fail("回款统计", "未找到 61-90 天区间行")
|
||||||
bucket_text = bucket.inner_text()
|
# 按本次业务编号在下钻明细中定位,不依赖桶聚合值(历史 e2e 数据会累计到同桶)
|
||||||
expected = ctx["expected_receipt_amount"]
|
bucket.locator(".el-table__expand-icon").click()
|
||||||
if expected not in bucket_text:
|
page.wait_for_timeout(1000)
|
||||||
fail("回款统计", f"61-90 天桶回款金额不符(期望含 {expected}):{bucket_text[:120]}")
|
drill_row = page.locator(
|
||||||
print("✓ 8. 回款统计 8 档区间与目标桶金额正确")
|
".drill-wrap .el-table__row", has_text=ctx["business_no"]
|
||||||
|
).first
|
||||||
|
if drill_row.count() == 0:
|
||||||
|
fail("回款统计", f"61-90 天桶下钻未找到本次业务 {ctx['business_no']}")
|
||||||
|
drill_text = drill_row.inner_text()
|
||||||
|
if "10000.00" not in drill_text:
|
||||||
|
fail("回款统计", f"本次业务下钻行金额不符:{drill_text[:120]}")
|
||||||
|
print("✓ 8. 回款统计 8 档区间与本次业务下钻金额正确")
|
||||||
|
|
||||||
|
|
||||||
def step_payment_multi_expand(page: Page, ctx: dict) -> None:
|
def step_payment_multi_expand(page: Page, ctx: dict) -> None:
|
||||||
|
|||||||
Reference in new issue
Block a user