Commit Graph
8 Commits
Author SHA1 Message Date
tamakyi 40441ba900 工具:tools/dedup_site_visits.py —— 以手机包为参照清掉站点侧的历史重复到访
站点数据里有一批「到达时间 + 地点与手机包里某条完全相同、但 UUID 不同」的到访副本(站点侧生成的
UUID)。差异页/合并按 UUID 认人,于是它们被当成「备份新增」,导出到 rond 后就是成对的两条重复记录
(2026-09-29 站长实测:导入后 app 里出现成对的重复条目)。

工具以手机导出的包为参照(数据集的基线):
  * 站点到访的 UUID 在参照里能找到 → 保留(手机自己也有成对条目,那是合法的,不能动)
  * UUID 找不到、且 (到达时间, 地点) 与参照里某条一致 → 判为副本
副本的附属记录(位移/天气/留档)一并删除;若有别的到访的留档指向副本(ZMERGEDTO / ZPARENT),
改指到保留的那条,避免导出时留下悬空引用。**默认只预演,--apply 才动手。**

踩坑记录(都在此提交里修掉):
  * `raw->>` 取出的是 text,与数字比较会报「text = integer 操作符不存在」,导致工具在动手前整个退出;
  * 同一个 UPDATE 里不能给 raw 赋两次值(「对同一列 raw 进行了多次分配」),jsonb_set 要嵌套。

演练验证(本地真实数据:导入含 72 条副本的包 → 执行 → 核对):
  到访 1026 → 954、位移 833 → 809、天气 621 → 589(与手机包一致);
  「同时间同地点」重复组 101 → **31**(= 手机包自身)、悬空引用 0/0。
2026-09-29 17:38:50 +08:00
tamakyi f26537b1e9 导出:新建活动没选颜色时补占位色,别再写 ZCOLOR_=NULL(真机拒收整包)
症状:生产导出的包导不回 rond,提示「错误,备份恢复失败,你的当前数据未被更改」。

根因链:站内「地点补全」新建活动时写的是 color=''、icon=''(fillup.go 的 INSERT),而导出侧
ns() 把空串也当空(返回 nil)——图标那侧早就有 📍 兜底(注释还写着「站点自己渲染时缺省用 📍」),
颜色这侧漏了,于是写出 ZACTIVITY.ZCOLOR_ = NULL。真机这一列在任何包里都是 0 NULL/0 空串
(扫了 data/ 与 storage/ 下全部 15 个包,只有出事的那份有 1 个空),Core Data 拿到非可选属性上的
NULL 会判成损坏数据 → 整包拒收。

修复:加 activityPlaceholderColor = "gray"(与 transportPlaceholderColor 同一套写法),
活动颜色为空时兜底。

用例:TestExportNeverNullsColumnsTheDeviceAlwaysFills 补上「没选颜色的活动」场景——它守的通用
不变量是「基线里 0 个 NULL 的列,导出新行也不许 NULL」,但此前只造过交通方式,没覆盖活动。
变异验证:去掉兜底 → 两条断言都红(提示语正好复刻生产现象)。

另新增 tools/audit_export_nulls.py:拿参照包做逐列空值画像 + 全部关系列悬空 + Z_MAX 检查,
是排查「导出被拒收」最快的一步(这次就是它一击命中的)。注意判据必须是「参照里 0 个 NULL」——
ZLOCATION.ZISOCOUNTRYCODE 真机自己就漏过 1 个 NULL,说明它容忍 NULL,不要当违规去修。

全量验收 293 PASS / 0 FAIL / 0 SKIP。
2026-09-29 11:50:06 +08:00
tamakyi 256620ee3d 验收:覆盖率改用 -coverpkg 口径,新增关键页冒烟 2026-09-24 22:48:31 +08:00
tamakyi d2e4392a88 验收脚本、工具整理与排查报告
- scripts/verify.sh:把「带齐六个环境变量、且必须 0 skip」这条纪律固化下来
  * DSN 自己从 conf/app-test.ini 取,不把口令写进脚本
  * 库名不含 test 就拒跑(指到维护库会多出「users 不存在」+ 一堆假 skip)
  * 数 SKIP,非 0 直接失败 —— 不带环境变量时 go test 依然回 ok,最容易被当成通过
  * 支持 --fast / --race / --cover / --pkg / --run
- tools/:删掉 6 个一次性探针(git 历史里可翻)和误入库的 __pycache__,
  只留在用的 4 个工具并补 README;.gitignore 补 __pycache__ / *.pyc
- audit-2026-09-21.md:全量排查报告(含 11 批修复记录与收尾审查)
2026-09-24 20:38:18 +08:00
tamakyi 78865fc736 导出:删掉到访后,别把它指向的原始采样点留成悬空引用
真机报「备份恢复失败,你的当前数据未被更改」——这句说明它是先校验、整体回滚。
往下查的第一个醒悟:**Core Data 的 SQLite 表里根本没有外键约束**(关系由 Core Data
自己维护),所以之前跑的 PRAGMA foreign_key_check 报 0 违例毫无意义,它压根没得可查。

按关系列手查悬空引用,结果:

  原版:悬空 0
  导出:ZRAWVISIT.ZVISIT 有 2 条指向不存在的 ZVISIT —— (2051→到访46, 465→到访200)

正是用户在站点上删掉的那两条到访。ZRAWVISIT(原始 GPS 采样点)是不托管实体、
导出时原样保留,于是删到访就留下了指向已删记录的悬空关系;而真机删到访时
采样点是跟着级联删的,所以这是它自己绝不会产生的形状。

修法:visit.finish() 之后,删掉 ZVISIT 指向不存在到访的 ZRAWVISIT 行。
选「删」而不是「把 ZVISIT 置空」:真机的「未归并采样点」虽有 1461/2246 条(置空合法),
但留成未归并会让 app 重新推出一条到访,把用户删掉的记录复活。

顺带加固:
- verify_export_structure.py 新增 1.45 节「关系完整性」,手查 8 组关系列的悬空引用,
  有悬空就把结论判成「有差异」——这条 foreign_key_check 查不出来的坑进了标准验收清单。
- TestExportDropsOrphanedRawVisits:删一条带采样点的到访 → 导出 → 断言没有悬空;已做变异验证。
2026-09-20 18:05:47 +08:00
tamakyi 30c502ce7b 备份与迷雾的差异分析、合并执行,附属数据改挂坐标键
备份(.rondbackup)与迷雾(.fwss)各加一层「先看差异再动手」:

- 迷雾:上传先出差异页,说清叠加能补多少、整体替换会丢多少,并在真实底图上
  用绿/灰/红标出会新增 / 不变 / 会丢的区域
- 备份:与当前数据集按 UUID 逐条比对(rond 每次导出都会重排 Z_PK,编号认不出人),
  新增合入、冲突逐条选、仅站内有逐条勾选删除,全在一个事务里执行;
  合入的行写回 entity_raw,保证再传同一份备份时差异归零
- 地点按坐标对齐:站点的「补全地址」会把地点改名,拿名称当键会让一整个地点的
  到访全变成假冲突
- 附属数据(备注/结论/访客票/图片)从 dataset_id+src_pk 换成坐标键,换数据集不再失联;
  访客票没有 dataset_id,回填按活跃数据集认领
- 修正 contentHash 拿 Z_PK 当指纹的隐患,以及两处「src_pk 跨快照稳定」的错误注释

导出格式(.rondbackup / .fwss)保持原样,往返测试通过。
2026-09-19 16:04:00 +08:00
tamakyi ad2531c113 修复图片上传分类无法新增、潜在movementWindow容差问题、404页面未生效问题 2026-09-18 17:06:22 +08:00
tamakyi b327bc1230 first release 2026-09-18 13:05:49 +08:00