Commit c6dc2406 authored by wenwen.tang's avatar wenwen.tang 😕

docs(memory): 记录行粒度核对/账期汇总/楼层总表,以及回归脚本污染真实 data 的事故与闸门

parent 57cf814d
This diff is collapsed.
# 2026-10-14 工作日志(租金通知系统)
## 第十三轮:列显示菜单收不回来(用户报「当前缩不回去,会遮挡页面」)
巴特菲要求直接改、不回测。
### 根因
`web/style.css` 的 `.colpick-menu` 写了 `display: flex`,**类选择器盖掉 UA 的
`[hidden] { display: none }`**(同为 0,1,0 但后加载的应用样式胜出),
所以 `menu.hidden = true` 完全不起作用 —— 菜单一旦生成就永远挂在页面上。
次生问题:`bindVCols()` 每次 `renderEModeBar()` 都被调用(勾选一行就重渲染一次),
里面的 `document.addEventListener('click', …)` 会**无限累积**,且旧闭包持有已被
`innerHTML` 移除的 `menu` 节点,点击时反而会把当前菜单误关。
### 改动
- `web/style.css`
- 加 `.colpick-menu[hidden] { display: none; }`(**核心修复**:凡带 `display` 声明的
组件类,都要显式配 `[hidden]` 规则)
- `left:0` → `right:0`;加 `max-height:60vh; overflow:auto`
- 标题行加 `×` 关闭按钮样式;加 `.colpick-menu.up`(向上弹)
- `web/app.js`
- 新增模块级 `VCOLS_OPEN`(菜单开关状态)—— 模式条重渲染不再丢状态
- 新增 `VCOLS_DOC_BOUND`:document 级「点外部收起」+ Esc 监听**只绑一次**,
且每次点击动态查 `#vcolsMenu`(不再捕获旧节点)
- `setVColsOpen(on)` 统一开关;按钮文案「列显示」↔「收起列显示」;空间不足自动 `up`
- `cancelElecMode()` 与 `enterVerify()` 里调 `setVColsOpen(false)` 复位
### 验证
`node --check web/app.js` 通过;静态资源已由 8899 服务直接生效(前端改动免重启,强刷即可)。
**按用户要求未跑单测 / UI 回归。**
### 教训
- HTML `hidden` 属性**不是** `!important`,任何组件类上的 `display: flex/grid/block`
都会让它失效 —— 用 `hidden` 控制显隐时必须补 `[hidden]` 选择器。
- 会 `innerHTML` 重渲染的绑定函数里,**不要挂 document 级监听**;要么加一次性标志,
要么事件委托到稳定容器。
## 待办
- 本轮改动**未提交、未部署**(线上仍是旧口径)
- 9 月电费批次错计(10 行 ¥167,947.41 / 少计 601B ¥299.67 / 出租方错记精锐)仍待处置
\ No newline at end of file
......@@ -13,7 +13,8 @@
- AJ「下一账单日」**只用于定时排期**(推送日 = AJ − 提前天数);出单口径看 AC;出单后 AC 与 AJ 一起推进
- **AD~AI 房产/房产税六列已删**(`RETIRED_TAX_COLS`,守护 `test_retired_cols_not_used_by_billing`)
- 默认锁定只读;改单元格/增行/删行必须 `confirm=true`(否则 428);备份 `data/tables/.backup/`
- **电费批次** `data/batches/{id}.json`:只留原始数据(details/totals/documents/发送状态),按账期月份留档
- **电费批次** `data/batches/{id}.json`:只留原始数据(details/totals/documents/发送状态),按账期月份留档;
测试残留移入 `data/batches/_trash/`(store 只 listdir 顶层 `*.json`,子目录隐身、可恢复)
## 免租(`rentos/rentfree.py`,2026-10-13 重写为两种类型)
- `首N月免租`:窗口 `[I, I+L月)`,含起始不含结束;0.5 月 = 15 天
......@@ -37,6 +38,23 @@
- 两张账单(`plans.py`):`elec` 触发日 = 缴费期限 − 提前天数;`rent_parking` 触发日 = 台账 **AJ − 提前天数**,
按行判定(`rent_state()`),到点自动出单+发送(`service.auto_issue_rent()`)
## 电费核对(2026-10-13 改「行」粒度)
- 行键 = `单元|类目`(如 `302室|照明`);`verify = {units:[], rows:[], done, at, by, scope}`
(旧 `units` 按整室自动展开,向后兼容;归一后只留 `rows`,否则取消某行会被 units 抵消)
- `verify_summary()["ok"] = done`(**已点确认即可,允许部分核对**);`partial` = done 且有未勾行
- **自动撤销**:确认时把勾选快照存 `scope`;之后进度保存若勾选少于 scope → 撤销确认
- 发送闸门:未确认 → 409;部分核对发送前前端 `partialVerifyWarn()` 二次提醒
- 账期级:`period_summary` 行并集,一行算已核对 ⇔ **含它的每张批次都勾了它**;
`POST /api/periods/verify` 一次写全账期
- 前端:核对模式按行勾选 + 列显示菜单(`localStorage['rentos_vcols']`,「核对」列不可隐藏);
**重新编辑/核对入口只在批次详情**;台账列表按账期汇总、默认折叠(`tbody.pgrp.collapsed`)
- 列显示菜单(`setVColsOpen`):开关状态存模块级 `VCOLS_OPEN`(模式条重渲染不丢),
收起方式 = 再点按钮 / `×` / 点外部 / Esc;空间不足自动 `.up` 向上弹
- ⚠️ **HTML `hidden` 属性不是 `!important`**:组件类上只要写了 `display:flex/grid`,
`hidden=true` 就**完全失效** → 凡用 `hidden` 控制显隐,必须补 `[hidden]{display:none}`
- ⚠️ **会 `innerHTML` 重渲染的绑定函数里不要挂 document 级监听**:每渲染一次堆一个,
旧闭包持有已移除的节点 → 用一次性模块标志(`VCOLS_DOC_BOUND`)或事件委托
## 房租车位费出单
链路:`rent_parser.py` → `rent_render.py`(→ `notice_pdf`)→ `service.ingest_rent` → 批次
- 计费:期间起 = **AC**,止 = 起 + N 个自然月 − 1 天;`房屋租赁费 = P × N`、`物业费 = O × N`;
......@@ -88,6 +106,8 @@
## 启动 / 部署(192.168.68.121 · CentOS 7)
- `start.bat [safe] [端口]` / `stop.bat [端口]`;`notify.enabled=True` 时双击 `start.bat` **会开定时发送**
→ **会话内启动一律 `start.bat safe`**
- ⚠️ 会话里跑 `start.bat safe` 时,其内层 `start` 开新控制台会被环境拦(SIGTERM、无输出)→
改用后台任务直起等价命令:`python -m rentos.server --port 8899 --no-scheduler`(`run_in_background`)
- 云端 `http://192.168.68.121:8899/`(admin / 1989@rent05),容器 `rentos`,root / 12345678
- **主用 Git 同步**(⚠️ **必须用 venv python** `…/envs/default/Scripts/python.exe`,3.13.12 无 paramiko):
`RENTOS_SSH_PASSWORD=12345678 …python tools/deploy_git.py sync`(setup/pull/build/run/status/logs)
......@@ -106,16 +126,19 @@
`* text=auto eol=lf`、`*.bat -text`、**Dockerfile 必须 LF**
## 验证脚本(tools/)
- 单测 **245 项**:`test_rules` 45 · `test_directory` 33 · `test_rent` 53 · `test_round5` 54 · `test_accounts` 60
- 单测 **303 项**:`test_rules` 45 · `test_directory` 33 · `test_rent` 53 · `test_round5` 54 ·
`test_accounts` 60 · `test_round6` 39 · `test_masters` 19
(`test_scheduler.py` 需活跃 8899 服务,无服务时失败属预期)
- UI 回归:**自带沙箱** `ui_verify7/8/9/10.py`;**需连服务** `ui_verify`·`2`·`3`·`4`·`5`·`6.py`
- UI 回归:**自带沙箱** `ui_verify7/8/9/10/11.py`;**需连服务** `ui_verify`·`2`·`3`·`4`·`5`·`6.py`
→ 依次覆盖 台账+电费录入 / 设置+锁定+批量暂存 / 带入+照明+图片 / 公司管理 / 房租出单全链 /
收款开票+导出 / 访客(纯只读 + guest 仅电费)+收款同步 / 账期区间 / 删房产列+免租两类型+批量编辑 /
**访客能力三方对照(guest 69 项)**
访客能力三方对照 / **行粒度核对+部分确认+账期汇总+列筛选(ui_verify11 85 项)**
- ⚠️ `ui_verify7` 的只读样本是脚本自建的 `ro_verify`(无能力)—— guest 已改成「电费通知单操作员」,
不能再当纯只读样本用
- **`tools/ui_verify_runner.py <脚本…>`**:每个脚本起**全新沙箱**(复制 `data/` + 改写 config 常量 +
另起端口 + 注入 `RENTOS_BASE`),真实 `data/` 零改动 —— 跑本次的 3/4/5/6 必用
另起端口 + 注入 `RENTOS_BASE`),真实 `data/` 零改动 —— 跑 1~6 必用
- ⚠️ **1~6 号脚本已加硬闸门**:未设 `RENTOS_BASE` 且未设 `RENTOS_ALLOW_REAL=1` 直接退出
(2026-10-13 直连 8899 曾误写 17 个测试批次进真实 `data/batches/`)
- 端到端 `e2e_round5.py`(PDF 出单 → 收款开票 → 导出 xlsx → 排期 → 删除并回滚)
- 迁移:`migrate_rentfree_type.py`(删 AD~AI + 加 AK + 回填) · `import_park_notes.py`(车位备注→AA) · `migrate_next_bill.py`(AJ=AC)
- **断言不要写死行数/列数/日期** —— 读接口现取;表格**按列 id / 表头文字定位**,不按第 N 列
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment