上禾自动体重目标实现与验证
2026-09-08 · 本地实现与隔离验证完成;ai_api、store、ai_app 已提交并推送 develop_haerbin,尚未部署。
已实现手机号匹配、扫码认领及同会话后续补传自动设置体重目标。实际体重使用 weight,目标体重使用 idealWeight(结构化指标 weight_target),速度默认 0.5 kg/周。自动与手动调用同一完整保存业务;同企业用户只有一条有效目标,同一报告只成功自动保存一次。
1. 已实现行为
| 场景 | 行为 |
|---|---|
| 手机号匹配 | 确定本人后,检测两项体重齐全即设置目标 |
| 扫码认领 | 本人认领成功后,两项体重齐全即设置目标 |
| 分阶段上传 | 先体重后理想体重、先理想体重后体重均支持;从同一会话结构化指标取值,不依赖最后一份数据包 |
| 未关联或缺项 | 未归属本人不设置;缺项等待补传,不删除当前目标或排课 |
| 保存规则 | 自动与手动共用初始/目标体重校验、方向、速度枚举、结束日期计算、旧目标及课程软删除、新目标写入、setWeight、积分及原同步业务 |
| 默认速度 | 自动增减重写 adjust_speed=2,代表 0.5 kg/周;相等体重沿用保持状态,速度和结束日期均为 0 |
| 每人一条有效目标 | 两入口在应用库事务中锁定同一 user 行,再替换该企业用户的有效目标;已有异常多条有效记录也在该次保存中一并退役 |
| 同报告去重 | 目标表保存 shanghe_session_id;成功目标以后被替换、软删除,仍保留同报告成功凭据,不能再触发重设 |
| 新报告 | 不同有效报告按实际保存顺序分别重设;手动和设备来源没有永久优先级 |
| 无设备手动设置 | 原请求、返回、速度选择、保存与后续使用不要求设备表、检测记录或新增来源字段;不需要设备额外配置即可手动保存 |
| 自动失败 | 返回内部 FAILED 状态,不伪造目标成功;已提交的检测/认领保留,重扫、重复上传或修复命令可重试 |
| 失败修复 | 不设置自动生成功能开关;shangheClaimRepair 同时报告目标状态,目标失败时不再仅凭体重同步成功返回全部完成 |
2. 实际改动文件
| 仓库/文件 | 改动 |
|---|---|
| ai_api/app/api/service/user/UserWeight.php | 原 weightManage 手动入口保留;新增受信任的显式用户入口,抽取完整保存方法;用户行锁保护目标替换和每日体重/积分并发;报告来源与目标同事务保存 |
| ai_api/app/api/service/ShangheWeightGoal.php | 校验用户/企业/设备/报告归属,读取同报告两项指标,默认速度 2,调用完整保存业务 |
| ai_api/app/api/service/ShangheV306.php | syncClaimWeight 的目标处理独立于体重 raw 水位,覆盖手机号、扫码及后续补传;返回目标状态供修复命令判断 |
| ai_api/app/command/ShangheClaimRepair.php | 将目标失败计入重试结果,输出 SAVED、WAITING_DATA、FAILED 或 UNAVAILABLE |
| ai_api/tests/ShangheWeightGoalTest.php | 隔离 MySQL 的手动基线、自动等价、双入口、事务/并发、排课与营养计算验证 |
| store/db/v2/v2.35.17.sql | 现有目标表增加一个可空来源字段及唯一索引,无新增业务表 |
ai_app 未修改,原设置页及公共请求保持原状。现存登录修改保留,未拉取覆盖、暂存、提交或推送它们。方案中配套目标卡/完整回显属于另行评审的展示建议,本轮没有将这些 UI 改进混入目标保存功能。
3. 数据库迁移
在应用库 aizhct_haerbin 执行 store/db/v2/v2.35.17.sql,不是在健康库 zhct_haerbin 执行。
| 对象 | 定义/作用 |
|---|---|
| yoshop_user_weight_status.shanghe_session_id | BIGINT NULL DEFAULT NULL;NULL 代表普通手动目标 |
| uk_weight_goal_shanghe | 唯一索引 (shanghe_session_id, store_id),不包含 delete_flag,保留跨软删除的报告幂等 |
| 现有手动历史 | 保留全部目标及历史数据;允许多条 NULL 来源的手动历史 |
| 单有效目标 | 由手动/自动公共入口的用户行锁及替换事务保证,不能通过直接绕过服务写库破坏此约束 |
正式 SQL 已在专用本地 MySQL 5.6 测试库实际执行,并回读确认字段可空、唯一索引及列顺序。业务数据库尚未执行。迁移后发布新代码并刷新 PHP 常驻进程/数据库字段缓存;代码额外核验报告来源确已写入,避免旧字段缓存静默丢弃来源却返回成功。
4. 验证结果
| 验证 | 结果与范围 |
|---|---|
| 改动前手动基线 | 在没有设备表和没有 shanghe_session_id 列的测试库运行原手动保存,增重/减重/保持、三种速度、日期、替换、课程范围、体重及积分通过 |
| RED 证据 | 原手动基线通过后,首次自动用例因 ShangheWeightGoal 尚不存在失败;实现后通过 |
| 自动/手动等价 | 相同用户初始数据与表单参数,比较目标、实际体重、积分、人员档案和出站调用;结果一致,显式报告用户不受另一人的登录缓存影响 |
| 双入口 | 真实 ShangheV306.receive 与 ShangheClaim.bind 服务链路通过;手机号晚到 idealWeight、扫码先 idealWeight 后 weight、重复扫码/上传通过 |
| 幂等及替换 | 同报告重复不换目标、不删新课、不重复副作用;新报告替换当前目标;手动介入后重扫已成功旧报告不再覆盖 |
| 有效目标并发 | 本地 PHP pcntl_fork 验证同报告、两个不同报告、手动与自动三类并发;每个预期成功写入者均成功,最终只有一条有效目标,同日体重/积分仅一份 |
| 故障回滚 | 注入体重写入故障,目标及课表软删除回滚、原每日体重保留、无成功报告来源;撤销故障后成功一次 |
| 数据/权限 | 零、负数、非数值、非 kg、删除用户、错误用户、跨企业被拒绝;满足条件直接自动生成,之后手动仍正常 |
| 同日与跨日 | 新报告按保存顺序处理,结果与相同输入手动保存一致;不额外添加未获确认的仅当日/旧目标保护规则 |
| 页面所需数据 | 真实 UserWeight.info/status 回读比较通过;没有实际手机 UI 操作验证 |
| 真实按需排课 | UserCourse.getTodayPlan 验证增重/减重/保持、四周上限、短目标结束日、课程热量、手动自动等价、替换及重复读取 |
| 推荐计算 | 真实 StaffPower.getWeightConsumePower/getRatio 验证目标方向与速度计算、手动自动比例相同、手动营养目标优先 |
| 原有 MySQL 集成 | 使用原 ShangheClaimIntegrationTest 的专用库副本回归真实 UserWeight、两侧人员同步测试替身、下游拒绝、重复上传修复、手机号补偿、历史体重保护;通过 |
| 原有协议与契约 | 二维码、旧入口兼容、V3.06 映射、协议、控制器契约、体重门控、附件存储七组测试全部通过 |
| 语法与差异 | 改动 PHP 使用本地 Docker PHP 7.4 lint;ai_api/store 的 git diff --check 通过 |
| 独立审查 | 只读审查确认双入口、完整共用、租户校验、锁及来源幂等,无本次新增阻塞性缺陷 |
详细新增测试输出:evidence/mysql-weight-goal-tests.log。测试连接仅指向本机 Docker MySQL、专用 codex_shanghe_goal_test 与 codex_shanghe_goal_regression;未加载或查询生产数据库。测试替换出站 UserApi/Serve,因此“出站行为一致”不等于真实生产餐厅或队列已联调完成。临时数据库和测试账号在验证后清理。
5. 发布与现场验收
- 审阅 ai_api 和 store 当前 develop_haerbin 的本地差异,按团队流程提交/发布业务代码。
- 先对应用库执行 v2.35.17.sql,一次性添加来源字段/索引;不要重复执行,也不要修改健康库目标之外的表。
- 部署 ai_api 并刷新字段缓存/常驻 PHP 进程;不需要因本功能重新发布小程序。
- 用一个测试用户先手动设置目标,再分别测试手机号上传与扫码认领;核对新目标、旧目标及课表软删除、实际体重、每日积分和推荐结果。
- 同报告重复上传/扫码、新报告重新检测、理想体重晚到各验证一次;用户目标查询应始终只有一条有效记录。
- 用未接设备用户验证原手动设置和三种速度;确认目标、推荐与课程继续正常使用。
本功能不新增开关;关联本人且两项指标齐全后直接按保存逻辑处理。需要版本回退时按正式发布流程处理代码,不自动还原旧目标/课程,以免覆盖用户后续操作。
6. 兼容边界与执行记录
老项目兼容性复核:普通手动设置不进入上禾入口,也不读取新增报告字段;此场景已在无设备表、无新增字段的本地MySQL基线验证。其他厂商仅沿用公共体重保存,并增加同用户串行保护。使用本版代码的上禾项目会在满足条件时启用自动目标,须先执行新SQL;未迁移时自动目标失败被捕获,已提交的检测上传和认领保留,但自动目标不会生成。不能把公共路径测试等同于所有历史项目现网已经逐个验收。
按照已确认方案,完整自动保存与手动保存保持同一业务语义。原手动方法在数据库提交前投递推荐并调用外部人员同步,这个时序未在本次重构;数据库回滚不能撤销已经发送的外部请求,不宣称跨系统原子回滚。实际生产队列消费时序、餐厅接口和手机真机仍需现场联调。
已有完成判定、到期处理和课程最多四周等逻辑保留;未顺手修改。不同报告按实际保存顺序替换;单独设备实际体重同步仍保留旧水位逻辑,而“自动设置目标”的完整保存效果与同参数手动操作一致。
业务基线:ai_api develop_haerbin/0cc1c822;store develop_haerbin/73be78c90。两仓开始前均快进拉取,未切分支、未覆盖他人文件。实现阶段未执行 commit/push/deploy;后续用户已提交并推送 ai_api 19b031d0、store 60304829b。ai_app 本地与远端登录修复已合并为 246892ba 并推送。三仓本地与远端 SHA 已核对一致,尚未部署。
组织方式:执行模式路由命中复杂集成;本机无可用 Ruflo 运行时且未提供安全隔离根,降级常规 Codex,由一个生产代码写入者、一名独立测试编写者和一名只读审查者完成。不初始化用户级配置,不把角色登记当作执行证据。本次无可用精确 Token 或完整准备时长统计,不提供估算数。