Files
ShiErFeng/shierfeng-fastapi-backend/sql/pallet-workflow-deployment.md

14 KiB
Raw Permalink Blame History

托盘流转业务部署说明

2026-10-08 会议流程补齐(本机开发库已执行)

本轮源码增加物料日期、原发货标签、收货核对、隧道报表,以及“允许跳过先到托盘但必须填写原因”。用户明确批准开发库迁移和该 FIFO 规则后,已在本机开发库执行下列三份增量补丁并恢复9099后端。其他环境未执行,不能沿用本记录当作已迁移证明。

本机开发库执行与恢复验证记录

  • 目标:.env.dev 对应 127.0.0.1:3306/shierfeng-fastapi,MySQL 8.0.36;43张业务及系统表均为 InnoDB。
  • 已核实并停止本项目 app.py --env=dev 服务;迁移前无其他活跃目标库查询、无启用的 MySQL Event。
  • 完整备份:/private/tmp/shierfeng-dev-migration-20261008-6ce_sy6c/before.sql,262663字节,文件权限600、父目录700。SHA-256:c70393e09574f24820e252c9cfb084e9e15d86b185c8a7aa981a8088cd21a15b。备份包括全部表、触发器、存储过程和事件;口令不进入命令行,临时口令文件已删除。
  • 备份已实际恢复到隔离库 shierfeng_rehearsal_20261008_6ce_sy6c;43张表逐行摘要及数量与源库一致。三份补丁先在隔离库试跑通过,然后核对源库未变化、脚本摘要一致,再执行开发库迁移。
  • 开发库执行顺序:20261008_material_dates_mysql.sql → 20261008_shipment_receipt_mysql.sql → 20261008_usage_fifo_mysql.sql,均成功。没有重跑初始化或旧隧道脚本。
  • 迁移后按迁移前列集比对43张表的全部原数据摘要,结果一致;仅新增收货菜单1119。原库存、包数、编号、批号及历史事件未变;旧确认发货单收货状态为 LEGACY,其他为 PENDING;新增日期、收货人/时间和 FIFO 历史列均为空。新 CHECK 约束已核对;未自动授予任何普通角色。
  • 后端已按原 Python 环境与 --env=dev 恢复,MySQL、Redis连接正常,/docs HTTP200;未登录访问收货接口返回业务401。没有修改 .env.dev。
  • 实际恢复的隔离 MySQL 库还运行了完整业务服务验收:两托100包、原标签/日期、在途禁止入隧、无现场权限拒绝、确认收货、跳过原因校验、同隧道跨批使用、20包使用/80包原托退回、原标签快照不变、收货幂等不恢复已消耗数量,以及三条独立连接同时重放同键只扣减一次。数据仅新建于隔离库;另有一组新建夹具使用正式scope验证两托并发,排除测试批次总锁掩盖冲突,未向实际开发库灌入测试业务。
  • 真实 MySQL 验收同时发现并修复入隧事务结束后访问过期 ORM 属性导致的 MissingGreenlet;ID及返回模型现在在事务结束前取值。验收使用与应用一致的提交后属性过期行为。

备份与验收产物位于系统临时目录,可能被系统清理;需长期留存时应转存到受控备份位置,不提交仓库。隔离演练库暂保留用于复核,不接业务服务。恢复到业务库将覆盖迁移后变化,必须另行确认停写及恢复目标;失败时不得直接重跑增量补丁。

开发库只读预检记录(2026-10-08)

使用 .env.dev 指向的 127.0.0.1:3306/shierfeng-fastapi,在只读事务中查询版本、结构元数据和收货菜单冲突,随后回滚并关闭连接;未执行备份、DDL、业务数据写入、角色授权或服务重启。

  • 实际版本:MySQL 8.0.36;相关业务表均为 InnoDB。
  • biz_test_batch、biz_tunnel、库存隧道/溯源列和事件隧道/溯源快照列已存在。
  • biz_filling_record.production_date/expiry_date 尚不存在。
  • 发货单5个收货字段以及 biz_pallet_inventory.site_arrived_at 尚不存在。
  • 父菜单510为预期的 business:shipment:list 页面;菜单1119、business:shipment:receive 权限及1119的孤立角色授权均不存在。
  • 后端9099端口仍有服务监听。执行迁移前仍须获准停写、完成备份与恢复方案核对;上述检查不代表已进入维护窗口,也不替代脚本内完整前置约束检查。

上述为执行前的只读预检历史记录;实际执行结果见上节。不要直接重跑已有补丁或初始化脚本。其他环境必须重新核对现状。

迁移顺序与风险

  1. 只读核对目标库、MySQL版本、既有补丁和约束;不要仅凭文件存在判断已迁移。旧库需先具备 20260922_test_data_batch_mysql.sql 及 20261005_tunnel_material_flow_mysql.sql 的结构,不可重复执行已落库补丁。
  2. 确认维护窗口、停写,完整备份结构、业务数据、菜单及角色关联,并验证恢复方案。
  3. 执行 sql/patches/20261008_material_dates_mysql.sql:新增生产日期、有效期及日期关系约束;历史记录保持空值,不按装填时间补造日期。
  4. 执行 sql/patches/20261008_shipment_receipt_mysql.sql:新增收货状态、人员、时间和幂等字段,库存实际收货时间,以及 IN_TRANSIT 状态和 SHIPMENT_RECEIVED 事件。旧已确认发货单标记 LEGACY;原库存位置、状态、包数和历史事件不变。
  5. 执行 sql/patches/20261008_usage_fifo_mysql.sql,为使用记录和托盘事件新增可空原因及推荐快照列;旧记录保持空值。三份脚本均应在代码启用前完成。
  6. 新权限 business:shipment:receive 不自动授予普通角色。先核对菜单 ID 1119 未被其他菜单占用;按职责授权发货页面入口、收货核对按钮及目标现场数据范围。接收方不需要来源仓库权限,发货方原双范围校验不放宽。
  7. 逐项核对表结构、约束、历史保留结果后再发布三端代码。旧数据库直接运行新后端会因缺少列而报错,不能仅重启服务解决。MySQL DDL 隐式提交,出错必须停止;不可依赖 ROLLBACK 恢复整个迁移。

新建空库可使用已同步的 sql/shierfeng-fastapi.sql;禁止将包含重建语句的初始化脚本用于现有业务库升级。

新流程与历史兼容

  • 新发货:仓库有料 → 出库在途 → 接收方逐托核对、整单确认 → 现场未使用 → 扫码入隧 → 实际使用 → 原托盘余料退回。未收货不可入隧;未全部核对不能确认,不支持部分收货。
  • 收货不新增托盘号、生产批号或装填记录,不增加/扣减发货快照数量;重复确认采用独立幂等键,不把后续已消耗的余量恢复。
  • 标签从原发货装填快照读取品种、生产批号、日期、数量;可补打,历史日期显示“未登记”。印刷托盘号可作为扫码入口,写操作统一使用返回的规范二维码标识。
  • 混批与隧道溯源保留在后台及报表;普通操作页面不以内部溯源号代替生产批号。
  • 先进先出采用已批准的“允许跳过但必须记录原因”:入隧和实际使用均在后端锁定原业务记录后用当前读复核同现场、同品种的可用候选;其他隧道或旧溯源周期物料不推荐。存在严格更早的实际到货候选时,必须填写不超过500字的原因,原因和推荐托盘/批号/数量/到货时间快照随原事件及使用记录提交。相同到货时间不强排ID;当前历史到货时间未知时不伪造先后,保留人工核对提示。
  • FIFO 原因参与幂等摘要;无原因时保持旧摘要兼容。已成功请求重试直接返回原结果,不因候选变化再次扣减。仅服务端明确返回 code=500, data=FIFO_SKIP_REASON_REQUIRED 的已回滚请求可解除本机对应凭据以便补原因;网络结果未知和其他失败继续沿用原payload/key。
  • 候选当前读使用 FOR UPDATE NOWAIT,锁冲突不会跳过早到候选或持有现场/隧道锁等待候选锁。仅 MySQL 3572/1213/1205 触发最多3次整事务原键重试,每次先完成回滚;断连等提交结果未知错误不会自动重放。持续繁忙时仍需客户端按原键恢复核对。
  • APP 的 HTTP 非2xx或不完整业务结果不视为成功,入隧、使用及恢复重试均在确认结果后才解除原凭据。PC 成功回调仅清理与该请求完全一致的持久化记录,避免旧页面响应删除新操作;恢复时已确认的 FIFO 必填要求,不会因推荐刷新失败或延迟而丢失。

运行态验收门禁

迁移获批且完成后,用获准测试批次验证:两托各100包 → 标签与收货核对 → 同隧道跨批使用 → 20包使用/80包原托退回 → 原批号不变;同时验证重复点击、断网结果未知后重试、无现场权限、收货前使用、漏扫与错扫均被正确处理。核对四类隧道报表和两端日期展示。

本机隔离 MySQL 已验证完整流程、同键并发,以及正式scope两托交错入隧/使用的锁冲突回滚重试。普通角色菜单配置、打印机出纸和东集 CRUISE Gep/D737P_V1.0.5 实机 HID/回车行为仍需现场验收;构建成功不能替代设备验证,未接入设备原生广播 SDK。

适用范围与当前状态

本文适用于 MySQL 增量补丁:

shierfeng-fastapi-backend/sql/patches/20260724_pallet_workflow_mysql.sql

2026-07-27 已在本地主工作区 .env.dev 指向的 MySQL 8.0.36 执行该补丁,且完成下述本地核对。其他环境尚未执行,Redis 缓存也未清理;本记录不能替代其他环境的上线审批、备份及恢复演练。

上线前门禁

执行补丁前必须完成以下准备:

  1. 对目标 MySQL 实例进行完整备份,至少覆盖库结构、业务数据、菜单和角色关联数据,并验证备份可读。
  2. 在隔离环境完成恢复演练,确认恢复步骤、耗时和责任人,不能只以“备份命令成功”代替可恢复性验证。
  3. 由 DBA 人工审查补丁、目标库现状、已有同名表结构、固定菜单 ID 和回退方案。
  4. 申请维护窗口,在补丁执行和缓存清理完成前保持后端停止,不接入业务流量。

任一门禁未满足时,不得执行补丁。

MySQL 补丁执行与核对

MySQL DDL 会隐式提交,因此必须将补丁的 DDL、DML 分节执行,并在每一节后逐项核对结果。执行失败时不能假设整个补丁已自动回滚,应立即停止后续步骤,由 DBA 根据实际已提交状态决定人工修复或从已验证备份恢复。

1. DDL 节

  1. 先执行补丁中的 DDL 节,逐表核对表结构、索引、外键和约束。
  2. CREATE TABLE IF NOT EXISTS 只会跳过已经存在的同名表,不会修复已存在但结构发生漂移的表。发现同名表时,必须先人工比对实际结构;存在差异时停止执行并制定独立修复方案。
  3. DDL 节核对通过前,不得继续执行 DML 节。

2. DML 节

  1. DML 节包含固定 64 行菜单 seed。执行后必须核对结果恰为 64 行,并确认稳定字段与补丁定义一致。
  2. 任一固定 ID 与未知既有数据冲突时,必须停止并由 DBA、业务负责人共同人工处理;不得覆盖、改写或复用未知 ID,也不得绕过冲突继续执行。
  3. DML 节核对失败时,不得清理缓存或启动后端。

3. 2026-07-27 本地执行记录

  1. 执行前备份:/private/tmp/shierfeng-fastapi-before-pallet-workflow-20260727-1925.sql,文件权限 600,大小 69,180 字节,SHA-256 为 a217a7b071c7e3ecda0d4c94dd1010711b6061025148689156405b70a02f6c7e。已校验文件非空、可读且包含核心系统表;未执行恢复演练。
  2. DDL 分节执行成功:新增 18 张 biz_* InnoDB 表,业务域幂等键的复合唯一索引列顺序已核对。
  3. DML 分节使用标准 mysql 批处理执行,未使用 --force 或 continue-on-error 模式。64 条新业务菜单已写入,旧 AI/外链菜单、AI 字典及旧角色映射已核对为 0。
  4. 新菜单没有自动授予普通角色;后续应通过现有角色菜单机制按实际职责分配。

历史 AI/Agno 遗留表

曾运行过历史 AI/Agno 版本的数据库可能残留以下 11 张表:

  • ai_models
  • ai_chat_config
  • ai_sessions
  • ai_memories
  • ai_metrics
  • ai_eval_runs
  • ai_knowledge
  • ai_culture
  • ai_traces
  • ai_spans
  • ai_schema_versions

本补丁不会删除或修改这些表。未经另行确认,不得处理这些历史表。后续如需清理,应单独盘点表结构、数据量和外部依赖,完成备份与恢复验证,确认无消费者后,再通过独立变更审批和维护窗口人工执行。

Redis 缓存清理

只有 MySQL 补丁全部执行成功且核对通过后,才能在目标 Redis 实例定向清理以下缓存:

  • api_cache:login:user:routers:*
  • api_cache:login:user:info:*
  • sys_dict:ai_provider_type

对前两类模式应使用 SCAN 定位后逐项删除,只处理明确匹配的键;禁止使用 FLUSHALL。本轮未执行任何 Redis 缓存清理,不能把上述清单视为已清理证明。

启动与运行态验收

正式环境只有在 MySQL 补丁成功、逐节核对通过并完成上述定向缓存清理后,才可启动后端并开展运行态验收。至少应核对 /getRouters 返回的托盘业务菜单、真实角色权限,以及真实用户与仓库/客户现场映射下的业务访问范围,再验证响应式 Web 页面和 Android PDA HID 扫码回车流程。

本地环境已使用独立查询参数验证管理员 /getRouters:包含 3 个新业务目录和 17 个业务页面,不包含 AI 管理或“施尔丰仓库”。该结果不等于已完成 Redis 清理,也不代表普通角色已完成授权验收。

2026-07-27 当时未验证项(历史记录)

以下事项需要在后续真实环境中验证,本轮没有完成:

  • 备份恢复演练。
  • 真实角色与仓库/客户现场映射的端到端(E2E)流程。
  • MySQL 行锁、并发和事务回滚行为。
  • Redis 缓存清理。