feat(pl): 实现合同产品用证与额度结转以支持购买证和运输证全流程管理。

This commit is contained in:
wuzilong committed 2026-11-01 18:56:05 +08:00
1 parent cb0344498a
commit fb866c7fa7
104 files changed
+10187 -3833

No files matched your search

@@ -0,0 +1,193 @@
# 完整改造方案
## 1. 已确认的业务规则
取消“证书齐备”的业务概念。安排运输的依据是合同上适用证件能否覆盖本次数量以及证件使用条件是否满足,不再有人工点一下即可放行的状态。不以图片是否存在作为放行条件,不再把动态判断结果固化为可编辑布尔值。
山峡与A签销售合同,实际可送到A的客户B;采购也可由供应商直接送到山峡客户。合同交易方和实际装送方分别记录;管理山峡自身交易证件,不要求录入A-B下游合同。合同产品发生量继续按原合同口径统计,证件发生量由明确的用证分配明细统计。
## 2. 档案与编辑
手工录入可无图片;图片解析先预填可编辑表单,用户对照原图修改后保存。识别失败或缺字段可手填,不能猜测数量、单位和证号。所有证面字段可在确认前编辑;再次解析不得覆盖人工数据或自动启用、扣量。补图不新建档案、不重置余额。
购买证9组:购买方(名称/姓名、法定代表人、住所/地址、电话);销售方(名称、法定代表人、住所、电话);购买物品;用途;数量;有效次数;有效期限;编号;核发日期。
运输证9组:货主(名称/姓名、法定代表人、住所/地址、电话);运输物品(品名、数量、包装、购买许可/备案/出口许可证号);运输单位(名称、运输方式、住所/电话、车号次、运输路线);收货单位名称;有效期限;有效次数;申请单位名称;编号;核发日期。
数量与单位分别存储,多个车牌和引用证号完整保存。系统字段包括建档方式、附件、状态、确认信息及余额,不改变证面9组范围。用户确认的档案才可用于额度计算,保留已有复核信息,但不额外创造“齐备审批”。已有使用记录时禁止直接修改单位、证号等业务身份;核定量修订需依据与流水,不低于已用加预占,不自动重算历史折算量。
## 3. 合同、产品、证件关系
合同绑定证件,每条绑定可勾选多个合同产品。同一产品可以适用于多张购买证、运输证,多个规格如50%和98%硫酸可以共用证面“硫酸”的证。人工明确适用范围,不依赖品名相似匹配、不按浓度折纯。
证件只有一份总额度,不能因多个产品、合同绑定或车辆而复制。绑定仅表示可用范围,实际安排才分配和预占。子集合差量保存,遗漏不变、显式空集合须先校验引用;已有未结清用量的范围不能直接移除。历史明细和原ID保留。
## 4. 自动匹配、跨证分配和预占
可安排余量 = total_qty - used_qty - reserved_qty。两证独立逐证校验,各自覆盖相应交易来源量,不能把购买证和运输证数量相加作一份需求。
候选条件:当前租户与数据权限、合同绑定、适用产品、有效状态和期限/次数、实际参与方与装送条件。运输证还要匹配本次车辆及路线,引用购买证号须覆盖其所承担的相应购买证分配。自由文本路线不能靠模糊字符串匹配宣称自动核验,无法可靠判断时返回需确认原因。
默认策略建议:先满足可选证少的产品,在可行组合中优先较早到期证件,其次同单位下可用量较少者,最后证ID稳定排序。日期空值不得当作长期有效。此排序为方案推荐,不改变用户已确认的跨证分配规则。
算法须联合考虑全部产品、购买证与运输证引用关系。简单逐行贪心失败后须尝试重新分配(同单位可用容量网络/回溯验证),不能仅凭余额合计足够即通过,也不能因先抢占稀缺证而错误报缺口。不同单位不在同一数值排序池直接比较。
同单位自动分配;第一张余20吨,本次30吨,则第一张20、第二张10。两类证都适用,必要时继续第三张。每个来源的同种证分配之和必须等于需求,不能漏分、超分或重复分配。不同单位的分配由用户填写来源分配量与本证单位量,系统不推算密度、浓度、吨千克换算或历史系数。
预览仅计算不占用。点击安排后,服务端重读计划、证件及范围版本,在一个事务中重新计算/验证分配并预占;陈旧人工折算须重确认。计划、所有证件、绑定、usage按统一顺序加锁,逐证校验后写计划和流水,任一失败全部回滚。客户端重试用同operation_id和请求摘要,重复提交不重复扣;同幂等号不同载荷拒绝。
次数按实际使用事件独立控制,一次有效证被其他计划占用或使用后不可再选,不因本次有多个产品计为多次。未执行取消释放本次次数占用;已执行不能靠取消重置次数。多次有效仍受数量上限约束。
## 5. 多车共享与归档结算
运输证Y核定100吨,列车辆A/B/C。A已用20,B预占30,C预占10,则全证余40。各车都从同一余额池取量,其他未列车辆不能使用。并发跨车安排同样锁Y,不能每车各获100吨。
同单位归档按每个合同业务来源实际量、该来源的原分配顺序(allocation_seq)结转,不按比例平均,不使用其他产品未用额度补本产品归档。逐项实际量是上限,总计量按证汇总。保留证件、计划、产品、车辆及来源快照。
例:本次计划30吨,购买证G1预占20、G2预占10;运输证Y1预占20、Y2预占10,两运输证均允许本次车辆且引用关系匹配。实际29吨时:
| 证件 | 释放预占 | 增加已用 | 恢复可安排余量 |
|---|---:|---:|---:|
| G1 | 20 | 20 | 0 |
| G2 | 10 | 9 | 1 |
| Y1 | 20 | 20 | 0 |
| Y2 | 10 | 9 | 1 |
四张证本次预占均变0。实际少于第一张占用,如18吨,则第一张用18、第二张用0,分别释放未用2和10。实际超过30吨时,多出部分必须补分配并重新校验容量与匹配;不足则记录真实差异进入异常处理,保留原账与处理依据,不能伪造实际量或无条件放行。
归档后改量按差额调整并保留历史流水;重复归档幂等。异单位归档必须重新确认实际折算量,不沿用计划比例。同一物理运输的装送两侧不能在同证上相加;来源唯一标识与另一侧追溯关联要保留。采购和销售独立合同统计不改变此去重要求。
未执行取消释放占用;已有执行证据不能直接释放当作未用。改派/改产品/改合同/改数量/改车辆应整体重算新旧证,成功一起替换,失败保留原占用。不得全删全增重建使用明细。
## 6. 彻底退出“证书齐备”
移除确认证书齐备、取消齐备、批量齐备、人工强制齐备、上传完整自动齐备。停止读写hazard_cert_ready/by/time作为任何业务门槛,旧值仅可在历史审计保留。不要把开关改名为“额度已核验”后继续手动放行。
前端展示动态结果:无需本次两证控制、待绑定证件、待人工折算、额度不足(注明证种/需求/可用/缺口/单位)、条件不匹配、可安排;已安排显示逐证已预占及用量明细,归档显示已核销。结果由后端返回,不能客户端直接编辑。查看时结果仅供参考,提交仍重校验。已安排计划复核时应计入自身已持有占用,不能把自己预占导致的余额减少误报为不足。
筛选、菜单角标、待办通知以“需要处理用证问题”的动态结果为依据,已完成预占的计划不误计缺口;可缓存展示但安排不能信任缓存。移除旧导出列、按钮权限和API调用。新旧客户端切换期间旧hazard-cert-ready写接口明确返回410迁移提示,不静默成功;旧筛选参数拒绝或提示更新,不能继续作为真实齐备查询。
当前代码关联点:
| 范围 | 已核实入口 |
|---|---|
| 齐备判断与自动标记 | backend/app/services/pl_plan_service.py:clear_hazard_cert_ready、maybe_auto_set_hazard_cert_ready、validate_hazard_cert_ready_for_transport、set_hazard_cert_ready |
| 安排与归档调用 | backend/app/api/pl/transport.py、backend/app/api/pl/plan.py;以及plan_service内直接创建运输入口 |
| 列表与角标 | backend/app/services/pl/plan_list_filters.py、backend/app/services/pl_menu_badge_service.py |
| 模型/schema | backend/app/models/pl_models.py、backend/app/schemas/pl/plan.py |
| Web检查与上传弹窗 | web-admin/src/composables/usePlToxicProductCertCheck.ts、src/components/business/pl-plan-cert-upload-dialog/index.vue |
| Web界面 | web-admin/src/views/pl/plan-cert/index.vue、columnFilterDefs.ts、src/views/pl/plan-archive/index.vue |
| H5界面 | web-admin/src/views/m/pl/plan-cert/index.vue、detail.vue、CertDetail.vue、PlanCard.vue |
| API类型/展示 | web-admin/src/api/pl/index.ts、src/utils/pl-display.ts |
| 小程序回归 | miniprogram/scripts/mp_api_smoke.py;实施时继续追踪原生/嵌入H5调用及通知入口 |
以上是本次只读定位,不代表已修改代码。
## 7. SQL、API与权限
DDL保留8表:pl_purchase_cert、pl_transport_cert、pl_transport_cert_purchase_ref、pl_contract_cert_link、pl_contract_cert_product、pl_plan_cert_usage、pl_plan_cert_usage_item、pl_cert_qty_log。
主档:证号、完整证面字段、entry_mode、可空attachment_urls、total_qty/quantity_unit、reserved_qty/used_qty及版本。绑定表支持两类证多对多。usage按计划+证种+证ID唯一;item保留来源完整量快照、来源分配量、本证单位计划/实际量、合同范围版本、allocation_seq及折算留痕。跨证原始完整量快照不能求和。
allocation_seq在同计划、同合同来源、同证种范围内确定结转顺序,事务内检查正数及不重复;与公共order_num分开,后者不作业务结算顺序。两种证的来源分配独立覆盖完整业务量。运输计划车辆在confirmation_snapshot/source_snapshot保存本次快照。
计划用证接口返回purchaseAllocations[]与transportAllocations[],每行包含usageItemId(已有时)、certId、contractLinkId、scopeProductId、allocationSeq、allocatedSourceQty、certQty、单位及版本、转换说明。车辆由当前安排上下文读取,单位由后端证件取得。预览返回逐证缺口、原因和人工输入项;安排接口内完成提交,无需前端先占证再创建运输。归档接口同事务提交实际量和异单位确认信息。
租户与权限使用当前用户上下文,数据权限多角色并集;增量子数据保存遵守专题规则。所有金额外数量用Decimal,禁止float;MySQL5.7不依赖CHECK约束,服务层验证非负、总额度和历史引用。
## 8. 迁移与上线
先建档、确认历史已用与在途预占,再切换安排门槛;旧图片/齐备标记不能直接推定核定量或余额。旧附件可作为建档来源,不能自动生成无限额度。历史已归档不自动回算重复扣,明确期初截止点;在途计划逐条关联有效证和占用并核对未包含在期初已用内。
准备期新能力不参与正式放行,切换后所有入口统一使用新规则,不双扣、不允许旧齐备备用放行。未完成历史映射的受影响计划进入明确的数据补齐流程,不虚构分配。旧字段暂留用于兼容审计,不物理删除业务记录;客户端切换完成后再单独评估列清理。
启用新账后回滚不得恢复旧齐备绕过;暂停相关新安排、保留新账、修复后继续,必要的业务纠错走可追溯调整。
## 9. 易制爆合法使用证明(用户已确认)
2026-11-01用户明确:合法使用证明针对易制爆产品,独立提供界面,用户后续上传,不影响运输安排。此决定替代此前“保留合法用途证明独立阻断校验”的候选建议,不再等待确认。
业务展示名称统一为“合法使用证明”;现有技术字段`legal_use_cert_url`可继续复用,保留历史附件,不能仅为改名清空或迁移丢失数据。
- 仅含易制爆、无需两证控制的产品:未上传合法使用证明也可安排运输,其他正常运输业务校验照常执行。不得因易制爆标志本身强制要求购买证和运输证额度。
- 同时涉及易制毒/易制爆的计划或产品:购买证、运输证按实际需证产品范围检查条件并预占;合法使用证明未上传不构成阻断。不能因允许后补证明而放宽两证额度校验。
- 合法使用证明不预占、不扣量、不影响购买证与运输证余额;其附件状态不得重新包装为“证书齐备”。
- 单独提供“合法使用证明”界面,按计划及易制爆产品明细列示计划号、合同、产品、实际相关客户、已有附件和上传情况。允许筛选待上传/已上传,上传、预览、下载及按权限维护附件;状态由附件派生,仅供补资料跟进,不能回写计划放行开关。
- 允许运输安排之后继续补传;附件保存使用独立资料维护入口,不能复用会因计划已安排而禁止全部编辑的通用计划保存,也不能触发运输重建、额度重算或库存变化。若计划已归档,补充资料仍保留原业务明细ID和结算数据,不通过重开归档实现补图。
- 沿用现有计划产品`legal_use_cert_url`保存关系,同字段多附件按MinIO URL逗号分隔,不新增证件额度表。服务端校验当前租户、数据权限、目标产品明细归属和附件访问;更新只涉及本次提交附件,遗漏不变、显式清空按权限及引用规则处理,保留操作审计。
- Web提供独立菜单/页面;移动H5及小程序提供对应可达入口。实施前按当前规范确认页面选型、菜单归属和权限。原危化品上传页的历史合法使用证明继续可见,不与购买证/运输证档案混在齐备操作中。
- 待上传资料计数与运输额度缺口计数分开,前者不阻断安排,也不混入“不可安排”的数量。旧公共齐备判断必须拆除对合法使用证明的运输前置校验,不能仅删除按钮而保留后端拒绝。
这是本系统已确认的业务设计,验收依据为用户本次说明;本次仅更新方案,未实施界面或接口。
## 10. 工单 #4 实施前核对与候选补充(2026-11-01,待方案确认)
来源:[工单 #4](https://gitea.aichengyan.com/cykj/shanxia2.0/issues/4),远端更新时间2026-11-01 10:09:14(北京时间)。正文及全部评论已读取,评论0条,无图片附件。以下为当前代码核对及候选落地方案,不修改前述已确认业务规则,不代表业务实现、数据库验证或用户验收完成。
### 10.1 当前实现缺口
| 位置 | 核实结果 | 实施要求 |
| --- | --- | --- |
| `backend/app/services/pl_plan_service.py` 的 `validate_hazard_cert_ready_for_transport` | ready为1或附件完整即返回;纯易制爆也进入公共校验 | 所有安排入口改接额度服务;合法使用证明独立于需证判断 |
| 同文件 `update_plan_product_certs` | 已归档拒绝修改;三个附件字段均赋值,遗漏可能清空;末尾自动标记齐备并commit | 独立后补接口按显式字段更新,预校验整批明细后写入,不复用现有自动齐备流程 |
| `backend/app/api/pl/transport.py`、`api/pl/plan.py`、`pl_plan_service.py` | 均存在旧放行校验调用 | 分别覆盖已有计划安排、直接创建运输及对应业务入口,不能只改某一路由 |
| `web-admin/src/views/m/pl/plan-cert/model.ts`及其测试、`src/utils/mp-pl-plan-card-fields.ts`及其测试 | 仍依赖hazardCertReady筛选、卡片字段或批量操作 | 同步替换客户端模型及旧测试断言,不能仅隐藏按钮 |
| `miniprogram/scripts/mp_api_smoke.py` | 仍调用旧齐备写接口并恢复旧值 | 改为旧接口拒绝且业务状态不变的断言,不能保留旧成功期望 |
| 8表SQL草案 | 已有operation_id/request_hash及逐证唯一键;无独立请求结果记录;用证次数未有明确结构字段 | 在正式DDL前落实请求级幂等及次数模型,不把逐证唯一键等同于完整操作幂等 |
本次仅核实仓库模型与SQL草案,未连接数据库;不能据此认定运行数据库已具备或缺少任何表。
### 10.2 推荐实施顺序与替代方案
推荐在同一工单内分阶段开发、统一切换:A档案/绑定/迁移 → B分配/预占/核销核心及隔离数据库回归 → C全部放行入口与各端界面替换 → D历史对账及切换演练。合法使用证明独立接口可以在核心开发期间完成,但最终验收仍覆盖所有端。阶段完成不等于整单交付,准备期不提前停用旧入口或启用半套新账。
备选为全部模块一次实现再集中验证,优点是中间状态少,缺点是定位事务与跨端问题困难。仅隐藏齐备按钮无法达到工单要求,不作为可交付方案。
### 10.3 请求级幂等与次数(候选技术方案)
保留8张领域表;推荐另增请求操作记录,用`tenant_no + operation_id`唯一约束记录动作、plan_id、规范化request_hash及结果引用。在同一事务内创建操作记录、完成全部安排/调整/核销及流水;同号同载荷返回原结果,同号不同动作/计划/载荷拒绝。请求记录不能提前commit,失败整体回滚;数据库死锁或超时只允许有界重试整个事务。
原因:现有`uk_cert_operation(tenant_no, operation_id, cert_type, cert_id)`只能阻止同号同证重复流水,不能阻止同号改选另一组证、跨计划复用,也不能记录无需两证的成功安排。新表是对8表草案的候选补充,正式迁移前需确认,不在本次执行DDL。
证面有效次数保留原文;服务端派生一次/多次/待确认使用策略,不猜测无法识别的文字。一次有效证在证件行锁内检查有效占用和已执行事件,同次安排的多个产品共享一次事件。期初须独立记录是否已使用一次,不能仅凭used_qty是否为零推断。零实运量但有执行证据时不得自动恢复一次使用资格。最终字段与期初流水结构列为正式DDL前置任务。
### 10.4 联合分配、去重与异常边界
分配器输入为经过权限过滤的来源行、证件容量、合同适用边、车辆条件、购买证与运输证引用边及人工折算记录。先固定经确认的异单位分配,再对同单位剩余需求进行有容量约束的联合可行性求解;购买证分配结果不能先独立固定而忽略运输证引用限制。排序只是可行解偏好,搜索达到资源限额时返回明确的计算未完成状态,不能误称业务额度不足。
需增加反例:产品A可用G1/G2,产品B只能G1;以及购买证有余量但可用运输证仅引用G2的情形。都应找到完整可行解,而非因先使用G1误拒绝。
`PlPlanLoadProduct`和`PlPlanDeliveryProduct`都有合同/合同产品关联。现有usage item唯一键只覆盖同usage同来源侧行,不能单独证明装送去重;实施前需明确物理货物对应关系与唯一计量来源。推荐保留来源配对映射,不以产品名、SKU相同或两侧数量相同猜配。无法唯一对应时阻断受影响分配并要求补齐来源关系,采购/销售合同统计仍各按原口径计算。具体缺省计量侧属于待确认业务口径。
超量实际发生且补分配失败时,候选方案为保留实际回传及异常原因,原证账与预占不变,正式归档结转不成功;后续补证或调整后重试。异常证据与业务实际量必须持久化,不能在抛错回滚时一同丢失。需要区分“保存事实/异常”与“成功归档结转”两个结果,禁止假报归档成功。
### 10.5 当前阶段与下一步
当前阶段:工单已拉取,方案差距已记录;A—D均未开发。开始业务实现前确认第10.3节请求记录方案、第10.4节唯一计量来源及异常归档口径,随后在从V3.0建立的独立任务worktree落实实施清单。保留当前目录已有修改,不复制Agent凭据到任务分支。
验证缺口:未执行应用测试、隔离MySQL5.7事务验证、外部图片解析或UI验证;未执行生产迁移、push、合并、部署或远端工单修改。
## 11. 开发接入记录(2026-11-01)
用户在本会话回复“好的”确认第10节候选方案,进入开发。任务分支`codex/gitea-issue-4`;原工作目录已有修改保留。
- 模块命名修正:现有`pl_cert_service.py`已服务车辆/人员证件;新模块统一使用`pl_quota_*`,不覆盖原服务。
- 新发现的旁路:`api/pl/transport.py:create_transport`接受plan_ids并关联计划,却未调用旧hazard校验;纳入原子用证接入。`archive_plan`的无payload早提交分支也须覆盖。
- `create_transport_for_plan`当前仅有定义未找到调用;不能把计划车辆预填当正式安排预占。
- Figma流程原型v1:[根节点4:2](https://www.figma.com/design/ImDcikQnCX5GiJQLwUHwDC/shanxia2.0?node-id=4-2)。档案4:5、购买证4:43、运输证4:111、范围4:168、预览4:197、资料后补4:240、H5资料卡4:271。已检查渲染并修正横向容器行高;282个可编辑子节点,无完整界面位图,Inter字体,无横向溢出。当前为流程/字段布局稿,待用户确认,不能视为最终视觉验收。
- 视觉依据:档案P01参考`web-admin/src/views/demo/unit/index.vue`;多状态用证P02参考`views/demo/order/index.vue`;建档P12沿用顶部标签与分区表单;资料后补P13复用`components/business/attachment-upload-field/index.vue`。Web/H5沿用Fresh Mint,小程序按三墙规范;原型不是新建公共设计系统的授权。
- 新环境缺口:仅发现阿里云人员证件OCR,无购买证/运输证大模型解析配置。已询问服务选择,等待期间不上传真实图片。Docker可访问且有MySQL5.7镜像,因工程记录未授权服务启停,已请求独立测试容器授权;尚未创建容器。
### 11.1 本轮用户反馈与环境确认
- 用户明确“暂不启动容器,保留事务验证待办”:不创建MySQL测试容器,SQLite/纯逻辑测试继续,真实MySQL并发及事务验收保留未完成。
- 用户指定DeepSeek:使用官方视觉接口`deepseek-flash`候选,官方说明https://api-docs.deepseek.com/guides/vision/。运行密钥仅保存任务worktree被忽略的backend/.env(0600),不写入文档、Git、Agent凭据文件或日志。GET /models认证成功,返回支持的模型名称;尚未执行真实证件图片解析。
- 用户指出原型缺少如何关联合同及合同产品的操作过程;v1不视为获批。补充v2关联流程节点[11:2](https://www.figma.com/design/ImDcikQnCX5GiJQLwUHwDC/shanxia2.0?node-id=11-2):选择山峡合同 → 勾选合同产品行 → 分别配置购买证/运输证及各自适用行 → 保存后矩阵维护;另加证件详情反向查看关联及关联另一合同。等待修订稿确认,不先实施依赖界面。
# 实施确认补记(2026-11-01)
用户已确认合同关联 v2:“符合,按 v2 实现(推荐)”。原型节点为 `ImDcikQnCX5GiJQLwUHwDC / 11:2`:选择山峡自身合同 → 勾选合同产品行 → 分别选择购买证、运输证及各自适用产品 → 保存;合同与证件两侧均可查看维护。绑定不扣量,产品和车辆共享证件余额。沿用 Fresh Mint 和现有组件实现。
用户明确暂不启动 MySQL 测试容器,实际 InnoDB 事务/并发锁验证保留待办。图片候选解析选择 DeepSeek,凭据仅保存在忽略的本地配置,不进入代码或文档。
@@ -0,0 +1,25 @@
# 购买证、运输证与合同额度控制改造
日期:2026-11-01。状态:方案整理,未开发、未执行DDL、未验收。
## Why
原运输计划以“证书齐备”人工标记或附件完整作为放行条件,不能控制证件剩余数量,也不能防止多产品、多车辆重复使用同一额度。用户要求取消此概念,统一通过合同关联的购买证、运输证和本次数量控制。
## What Changes
- 两类证件均可手工无图建档或图片解析后编辑确认,保存全部9组证面字段及子字段。
- 合同与证件绑定,再维护适用合同产品;不同浓度产品可共用多张证。
- 两种证均支持自动跨证分配、提交时事务预占、归档按原分配顺序结转;运输证多车共享总额度。
- 移除“证书齐备”按钮、人工开关、批量操作和上传完整自动放行。改为动态计算用证需求、缺口及当前占用。
- 替换后端所有放行入口,以及Web、移动H5、小程序相关入口、筛选、权限、角标和通知依据。
- 易制爆产品的“合法使用证明”提供独立界面,允许后续上传,不影响运输安排、不参与两证额度计算;混合产品仍按适用范围控制购买证/运输证额度。
## Capabilities
### New Capabilities
- `contract-cert-quota`:证件档案、合同适用范围、自动分配与预占、实际核销及旧齐备流程退出。
## Impact
后端pl计划/运输/归档/合同服务,Web与H5用证界面,小程序入口,8张设计表及旧字段兼容退出。已关联Gitea工单[#4](https://gitea.aichengyan.com/cykj/shanxia2.0/issues/4);2026-11-01已读取最新正文及全部评论(0条),正文无图片附件。本次完善本地方案,不代表已实施或已回写远端。本变更以design为完整方案、tasks为实施清单,原建档补充仅保留历史链接。
@@ -0,0 +1,78 @@
# contract-cert-quota
## ADDED Requirements
### Requirement: 两种可编辑建档方式
系统 SHALL 支持无图片手工录入,以及图片解析后人工编辑确认;两方式共用档案与额度。
#### Scenario: 图片误识别
- WHEN 100吨被识别为1000千克
- THEN 用户可修改数量为100、单位为吨,保存使用确认值;识别本身不创建占用。
#### Scenario: 补传图片
- WHEN 已有使用记录的手工档案补图
- THEN 保留原档案及子明细ID、合同关联、余额与历史,不自动覆盖关键字段。
### Requirement: 合同产品和两种证多对多
系统 SHALL 允许多个合同产品共用多张购买证、运输证;每张证仅有一个共享额度。
#### Scenario: 不同浓度共享
- WHEN 合同50%和98%硫酸各运输10、20吨且均在同证适用范围
- THEN 同单位证需求为30吨,不折纯、不复制额度、不为未选产品扣减。
### Requirement: 自动跨证分配与原子预占
系统 SHALL 在安排提交时校验全部匹配条件并逐证原子预占,预览不占用;两类证均支持跨证。
#### Scenario: 单证不足
- WHEN 本次30吨且匹配的第一张证仅余20吨、第二张可覆盖10吨
- THEN 依次预占20和10;购买证及运输证均遵守此规则。
#### Scenario: 并发或任一证不足
- WHEN 并发计划竞争同一份余额或一张证校验失败
- THEN 不超占,失败请求不产生部分预占或运输安排,重复请求不重复扣减。
#### Scenario: 关联条件约束
- WHEN 可选证余额总和足够但产品范围或运输引用关系无法覆盖全部需求
- THEN 返回具体不匹配原因,不以总余额直接放行;存在可行重新分配时采用可行组合。
### Requirement: 运输证多车共享
系统 SHALL 允许证面列出的多辆车共享同证总量。
#### Scenario: 三辆车共同使用
- WHEN 总量100吨,A已用20、B预占30、C预占10
- THEN 全证余40,所有车共用40;未列车辆不能使用,不能按车复制额度。
### Requirement: 实际量按原顺序核销
系统 SHALL 保存原分配顺序,同单位按来源产品实际数量逐证结转并释放未用量。
#### Scenario: 三十预占二十九实运
- WHEN 第一证预占20、第二证预占10,实际29
- THEN 第一证已用增加20,第二证增加9,分别清除本次预占20和10,第二证释放未用1;两类证均适用。
#### Scenario: 异单位或超预占
- WHEN 单位不同或实际量超过预占
- THEN 异单位重新人工确认,超额部分重新校验补分配;不足保留真实差异并进入异常处理,不篡改实运量。
### Requirement: 退出证书齐备开关
系统 SHALL 移除人工齐备及附件完整放行逻辑,额度与条件校验作为本次两证控制的唯一依据。
#### Scenario: 旧标记不可旁路
- WHEN 旧hazard_cert_ready为1或两张图片均已上传但可用额度不足
- THEN 安排失败并返回逐证缺口;新客户端没有齐备按钮,旧写接口不改变任何状态。
#### Scenario: 动态结果与自身占用
- WHEN 已安排计划查询用证情况
- THEN 展示已持有占用,不能把其自身占用误判为额度缺口;归档按实际用量核销。
### Requirement: 历史、权限与身份保持
系统 SHALL 保持租户/数据权限、幂等及子数据身份,迁移时核实期初与在途记录。
#### Scenario: 历史齐备无量
- WHEN 历史记录只有附件和齐备标记
- THEN 不自动创建全额余额或虚构已用量,需补齐档案和有依据的期初。
#### Scenario: 子集合遗漏
- WHEN 补图请求没有提交合同产品或引用证号集合
- THEN 原集合和ID保持不变;显式清空仍先执行引用保护。
### Requirement: 合法使用证明独立后补且不阻断运输
系统 SHALL 为易制爆产品提供独立合法使用证明资料界面,允许后续上传;证明缺失 SHALL NOT 阻断运输安排或影响购买证、运输证额度。
#### Scenario: 纯易制爆缺少证明
- WHEN 计划仅含无需购买证/运输证控制的易制爆产品且合法使用证明尚未上传
- THEN 其他正常运输条件满足即可安排,不要求点齐备或虚构两证额度,独立资料页面显示待上传。
#### Scenario: 混合计划额度控制
- WHEN 混合计划合法使用证明未上传
- THEN 需证产品的购买证/运输证额度不足仍拒绝安排;额度与匹配条件满足则不因合法使用证明缺失拒绝。
#### Scenario: 安排后补资料
- WHEN 用户在安排或归档后通过独立页面补传合法使用证明
- THEN 按租户和数据权限更新对应原计划产品附件,保留原明细ID和用量/结算数据,不重新安排、核销或标记齐备。
#### Scenario: 资料待办与额度待办分离
- WHEN 计划已成功预占但合法使用证明仍待上传
- THEN 可在待补资料列表跟进,不能将其作为运输额度不足或不可安排计划。
@@ -0,0 +1,165 @@
# 实施与验收清单
状态:本地实现与独立业务审查已完成;MySQL5.7事务实机验证由用户明确延期,未部署或关闭工单。第1–6节保留初始验收清单,第10节记录本次交付边界。实施目标集成分支沿用项目V3.0配置。易制爆合法使用证明后补且不影响安排已由用户确认,见design第9节。
## 1. 档案与SQL
- [ ] 根据docs/sql/designs/2026-10-25-purchase-transport-cert-draft.sql新增正式迁移;在隔离MySQL5.7验证8表、UUID与公共字段,不直接执行设计草案到业务库。
- [ ] 新增backend/app/models/pl_cert_models.py、app/schemas/pl/cert.py、app/services/pl_cert_service.py及app/api/pl/cert.py;注册两个路由入口。核心档案字段、可空附件、entry_mode、allocation_seq在读写schema与前端一致。
- [ ] 新增backend/tests/test_pl_cert_archive.py:覆盖两种建档、全部子字段、重复证号、跨租户拒绝、补图不改余额和原ID。
- [ ] 接入既有图片解析能力,先确认可用服务;只返回白名单候选字段,数量单位可编辑,不自动启用。验证失败手填、重新解析不覆盖、多个车牌和引用号。
## 2. 合同绑定与候选
- [ ] 新增app/services/pl_contract_cert_service.py及test_pl_contract_cert_scope.py,验证多对多、同合同产品归属、范围版本和引用保护,遗漏/空集合、无变更ID保留和非法ID全回滚。
- [ ] 合同选择校验与实际装送客户分开,保持租户/权限/合同状态及业务方向约束。针对A签约B收货及供应商直送添加回归,不放宽产品归属。
## 3. 分配、预占与核销
- [ ] 新增app/services/pl_cert_allocation_service.py、pl_cert_usage_service.py;前者计算候选和可行分配,后者在调用方事务内执行,不能自行commit。
- [ ] 新增test_pl_cert_allocation.py:30拆20+10、两规格共享、稀缺证优先、重分配可行、运输引用不匹配、不同单位人工确认、车牌不匹配。
- [ ] 新增test_pl_cert_usage_transactions.py,在隔离InnoDB实际验证跨车并发锁、两证整体回滚、同operation_id重试、修改请求冲突、改派失败保留原占用。
- [ ] 新增test_pl_cert_settlement.py:29按20+9、18按18+0、超过30补分配/不足异常、多产品逐项实际量、异单位不按比例、重复归档、调整差额与取消释放。核对明细/汇总/流水/主档余额一致。
- [ ] 将预占接入plan_service.py、api/pl/transport.py、api/pl/plan.py的安排、直接创建运输和确认归档入口;覆盖全部旁路,临时归档保存不冒充正式结转。
## 4. 齐备逻辑退出与界面
- [ ] 移除design第6节列出的四个齐备服务函数的业务调用,替换所有放行判断。已上传附件与ready=1仍须通过额度校验。
- [ ] 旧hazard-cert-ready接口改为410并撤销写权限入口;旧字段留历史审计但不参与业务。更新schema、列表筛选、导出、角标、待办通知及小程序接口检查。
- [ ] 更新Web/H5计划用证页面和共享composable:删除确认/取消/批量齐备按钮;返回动态缺口与原因,展示两类分配列表及已预占/已核销。移除“先齐备再补图”的提示。
- [ ] 两种建档方式共用表单,按当前Web视觉规范/参考页选型;选择P01-P27具体模式并记录后再开始UI实现,小程序遵循自身规范。
- [ ] 增加前端与API回归:旧齐备不存在、无图手工证可按额度使用、解析值可改、异单位需要填量、余额变化需重校验、旧客户端不旁路。
## 4A. 合法使用证明独立资料界面
- [ ] 新建独立Web/H5资料维护界面并提供小程序入口,列出计划与易制爆产品明细、附件、待上传/已上传;统一业务名称“合法使用证明”,无齐备按钮、无额度分配。
- [ ] 独立附件维护接口复用既有`legal_use_cert_url`,保存原明细ID及历史附件,服务端按租户/权限/计划产品归属校验,允许安排后补传,不通过重建计划或子行实现;补图不改占用、实际量、归档及库存。
- [ ] 上传情况筛选和待补资料角标独立于运输用证缺口,图片缺失不进入安排失败原因;移除后端所有合法使用证明运输前置检查。
- [ ] 新增`backend/tests/test_pl_legal_use_document.py`:纯易制爆未上传可安排、混合产品两证不足仍拒绝、两证充足且未上传可安排、安排/归档后补图保持ID及额度不变、跨租户/错误产品归属拒绝、遗漏附件不变、显式清空授权校验。
- [ ] 前端回归独立入口可达、待上传筛选、补传/预览/下载、权限按钮;旧附件可见,资料补充不回写已废弃齐备状态。
## 5. 数据切换与验证
- [ ] 按design第8节清点历史档案、期初及在途占用;有数据缺口不虚构额度,冻结受影响新安排直至补齐。已关联工单#4,远端回写仍按会话授权执行。
- [ ] 在受控测试环境运行新增专项pytest;命令在测试文件创建后执行:`cd backend && venv/bin/python -m pytest tests/test_pl_cert_archive.py tests/test_pl_contract_cert_scope.py tests/test_pl_cert_allocation.py tests/test_pl_cert_usage_transactions.py tests/test_pl_cert_settlement.py -q`。
- [ ] 执行受影响既有计划/运输/归档测试;`cd web-admin && pnpm build:typecheck`,Web/H5人工验证两证20+10到20+9、多车共享、无齐备按钮;小程序验证实际入口而非占位测试。
- [ ] 验证纯易制爆缺合法使用证明仍可安排,混合产品按需满足两证额度且不受该证明缺失阻断,完成后切换公共门槛。不执行graphify,不默认部署/启停服务、不自动关单验收。
## 初始方案检查记录(实施前历史记录)
只读核对旧函数、调用入口、前端按钮及列表/角标;DDL和规格执行静态一致性检查。没有运行应用测试、数据库迁移或外部识别服务。方案尚未实施。
## 6. 工单 #4 核对后补充的实施前置项(初始清单;最新证据见第8–9节)
- [ ] 确认design第10节候选技术方案:在8张领域表之外增加请求级幂等记录,或提供满足同等约束的持久化方案;正式DDL前确定。
- [ ] 覆盖同operation_id跨计划、改选不同证件、不同动作、同号不同载荷及无需两证安排的重试;成功结果必须可恢复,失败无部分结果。
- [ ] 明确有效次数的可执行策略、次数事件身份与期初一次已用标记;覆盖零实际量但已有执行证据、多产品共用一次、取消后恢复与已执行不得恢复。
- [ ] 落实装送来源配对及唯一计量侧;覆盖一装多送、多装一送、同SKU多合同及来源无法配对,不能仅靠usage item唯一键宣称已去重。
- [ ] 确认超量异常处理:保存真实发生及异常、保留原占用,额度不足不能成功结转;覆盖回滚后事实仍可追溯与补证后重试。
- [ ] 对联合分配增加购买证与运输证引用反例、稀缺产品反例及计算资源限额处理;限额返回与业务额度不足区分。
- [ ] 更新H5 `model.test.ts`、小程序卡片字段测试及`mp_api_smoke.py`的旧齐备成功期望,补充所有安排入口拒绝旁路的回归。
- [ ] 合法使用证明独立接口覆盖同批次重复ID、非法ID全回滚、附件遗漏保持、归档后补传、无库存/用证副作用。
2026-11-01补充记录:工单正文及全部评论已读(0评论、无图片);代码与草案静态核对完成,未连接数据库。本节记录待开发事项,不勾选功能完成。
## 7. 已确认实施顺序(2026-11-01)
用户已确认第10节方案并同意进入开发。任务分支`codex/gitea-issue-4`,worktree为`/Users/zlwu/.codex/worktrees/gitea-issue-4/shanxia2.0`;默认Agent测试。原工作目录未提交改动保留。以下执行步骤补充上述验收清单,不另复制需求。
### A. 持久化与档案基础
- [x] 先新增`backend/tests/test_pl_quota_cert_archive.py`,使用内存SQLite独立建表,覆盖无图建档、Decimal、字段遗漏/显式清空、跨租户/越权、历史用量保护与子行差量保存。
- [x] 从草案实现`backend/app/models/pl_quota_models.py`及正式迁移`docs/sql/2026-11-01-pl-contract-cert-quota.sql`,包含8张领域表与请求操作表;保留公共字段顺序,增加期初一次有效已使用标记。
- [x] 实现`backend/app/schemas/pl/quota_cert.py`和`backend/app/services/pl_quota_cert_service.py`,避免覆盖已有`pl_cert_service.py`。服务由调用方提交事务。
- [x] 测试命令:在backend执行项目venv的`python -m pytest tests/test_pl_quota_cert_archive.py -q`;先确认缺失实现导致失败,再实现并验证通过。
### B. 纯计算分配与结转
- [x] 在`test_pl_quota_allocation.py`先写20+10、稀缺产品、双证引用反例、单位不一致、29/18实际量、非法Decimal与计算限额测试。
- [x] `pl_quota_allocation.py`以不可变输入表示来源、候选证和引用关系,联合求解可行分配;不得访问数据库或修改余额。
- [x] 每一来源按allocation_seq结转,分别输出reserved释放与used新增;不足返回明确缺口,异单位要求显式确认。
### C. 原子账本与业务接入
- [ ] `pl_quota_usage_service.py`统一处理预占/释放/调整/归档,证件、来源与范围锁顺序一致;request操作记录和逐证日志在同事务完成。
- [ ] 在`test_pl_quota_usage.py`覆盖同号同载荷、同号异载荷、跨计划重用、改派失败保持原账、余额对账及无两证需求。
- [ ] 在隔离MySQL5.7中验证并发及失败回滚,SQLite测试不可替代锁语义验证。
- [ ] 修改plan/transport各安排入口及归档入口,明确来源配对;旧齐备写接口410,旧字段不作为放行依据。
### D. API与资料后补
- [ ] 新建`backend/app/api/pl/quota_cert.py`并在两个注册入口接入,复用认证、租户与数据范围过滤;API暴露档案、合同绑定、预览及已有占用查询。
- [ ] 独立合法使用证明接口允许安排/归档后按原产品ID更新,先验证整批身份再写,遗漏保持,无库存/运输副作用。
- [ ] 复用图片解析基础设施返回白名单候选,解析不保存、不启用;失败允许手填。
### E. 界面与旧入口退出
- [ ] 按UI规范建立Figma原型并确认,随后实现档案/合同范围/动态分配与合法使用证明界面。
- [ ] 替换Web、H5、小程序入口及类型、菜单、筛选、角标、导出和通知,更新旧测试期望。
### F. 审查与交付
- [ ] 每阶段先规格审查,再代码质量审查;修复发现后复测。
- [ ] 新增专项与受影响既有测试、Web类型构建、各端视觉检查及隔离数据库验证全部完成后记录可交付结果。
- [ ] 保留工单开启状态;未经授权不push、合并、执行生产迁移或部署。
基线:backend内`test_pl_plan_product_certs.py`及`test_pl_scan_cert_expiry.py`共8项通过(现有依赖弃用警告10条);初次从仓库根目录运行因测试相对路径错误未执行,已纠正目录重跑。
### 接入审查追加(初始清单;已接线并通过专项回归)
- [ ] `api/pl/transport.py:create_transport`整批plan_ids需租户和权限预校验,draft与正式安排明确区分;正式安排必须走统一用证事务。
- [ ] 阻止通用`PlanUpdate.transport_status`及旧`create_plan`的transport_status/archive_status客户端字段绕过安排或归档,状态转换只接受对应业务接口。
- [ ] `force_void_plan`区别未执行释放与已有执行证据,不恢复已消费的一次有效次数。
- [ ] `archive_plan(payload=None)`从明确计量来源读取已保存事实,实际量缺失拒绝结转;不得读取按计划量回退的合同统计值。
- [ ] 零实运量不能读可能残留旧值的`PlPlanProduct.actual_qty`;优先明确来源段行实际数量,包括真实0。
## 8. 当前开发证据(2026-11-01,持续更新)
- 用户已确认Figma合同关联v2(11:2),按该流程开发;不再等待原型批准。MySQL容器明确暂不启动;事务并发实机验证保持待办。
- 档案基础、纯分配器、DeepSeek候选解析、合同差量绑定、账本核心与合法使用证明独立服务已完成阶段规格和质量审查。账本128项通过;随后档案锁顺序/current-read收口仍在复测与后续整合审查范围。
- 正式安排/改派、审批、取消/强制作废、归档/实际纠错接线已实现。整业务操作号重放、MySQL1213整事务有限重试;归档额度失败保留真实数量及占用、返回quotaSettlementError,库存仅在成功结转后更新。规格审查发现审批autoflush、强制作废资格、普通写并发旁路3项,修复后相关组合216 passed(仍非MySQL锁验证)。等待复审与质量审查。
- 新Web档案、合同关联v2、合法使用证明页面及CRM合同入口已编码并阶段审查通过。合成浏览器验证合同保存保留link1/scope1,详情响应乱序和旧图片解析不能污染新表单;附件按编辑会话隔离,保存时禁止改动与关闭。
- Web/H5计划用证配置含唯一计量侧、装送配对、选证、逐证参与方/路线确认、异单位安排换算及预览;目标车辆只影响预览快照,不写DB。合成browser检查通过,390px截图已人工检查。计划列表按真实预占、结转、异常及配置状态筛选;原齐备UI入口被替换。
- Web/H5合法使用证明支持安排/归档后补传,显示授权可见合同与实际装送单位,H5支持上传状态筛选,小程序入口已接线。新增加关系上下文和动态列表回归;planning/sources/legal/api组合34 passed。限定规格复审PASS,质量审查中。
- 新增总量更正API/流水查看与异单位实际用量核对弹窗;总量API测试先404失败,补实现后4 passed。实际量纠错必须理由及依据。此新增范围仍须独立审查及界面验证。
- 最新Web构建曾通过39.70秒;后续修改需最终重跑。全量vue-tsc既有大量错误(/tmp/shanxia-issue4-typecheck.log);新模块未出现报错,不能称全库类型检查通过。Frontend模型/卡片字段测试7 passed。
- 尚未完成:超原预占补量与对应缺口诊断、最终全链路回归/审查、全部新界面视觉验收及SQL人工核对。旧字段最终检索与通知/导出核对仍需收口;不能宣称整单交付。
- 临时Vite任务worktree预览127.0.0.1:5176,仅合成接口;未启动后端、MySQL或业务数据库。主目录node_modules软链接复用,无依赖安装。收尾停止本次预览进程。
- DeepSeek仅以合成测试图片验证成功,未上传真实业务证件。密钥未进入Git。
- SQL迁移未执行,新菜单不自动授予新写权限。远端工单写入、push/合并、部署均未执行。
## 9. 补分配及收口证据(2026-11-01)
- 业务接入质量复审PASS:阻止终态计划被旧审批重新占用;审批使用当前租户有效车辆主数据并校验指定审批人;单计划调整共享运输须先拆分,不能只重算其中一单。独立业务回归66 passed;两处产品查询补齐租户与计划条件。
- 档案当前读/锁顺序复审PASS,35项通过;确认/复核重放读取当前证件及期初流水,重复操作失败整体回滚。未运行MySQL并发。
- 补分配已编码:显式quotaAllowSupplement,候选及人工条件随归档同一请求提交;保留原分配容量、顺序、ID,同证/新证补量、异单位证面补差、明确人工拆分换新证,实际量不改写。当前source_snapshot记录本次补量,逐证日志保存原段/补段和人工依据;失败保留已保存事实与原账。待独立规格、质量复审。
- 预览返回按证种和单位的需求、余额上界和缺口下界,共享池只计一次。异单位不直接相加;余额足但产品/引用约束不可行时提示核对条件,不能当作可安排。
- Web/H5实际量核对界面已接补候选选择,原来源及装送配对锁定,原段与补段人工量分开。合成浏览器校验返回补量意图、两证条件及理由/依据,未调用业务后端。H5合法使用证明Vant筛选循环更新已修复,合成保存保留原产品ID;总量更正浏览器回归通过。
- 用证弹窗保存/预览旧回包跨会话问题已按独立规格反馈修复;2项真实生产handler回归先失败再通过,限定复审PASS。新增实际量补充候选回包和关闭意图测试3 passed。
- 最新后端组合449 passed、14既有警告(全部quota模块、独立合法证明、库存差量归档、作废、计划筛选、角标、旧产品附件和证件到期扫描)。日志/tmp/shanxia-issue4-final-backend.log。
- 新前端模型/卡片/移动状态/归档/配置/补量提交回归37 passed。首次使用Node原生strip-types跑含扩展名省略import的模型测试出现模块解析失败,改为项目已有tsx后37项全部通过。日志/tmp/shanxia-issue4-final-ui.log。
- 迁移后旧移动组合85项中81 passed、4 failed;4项均为原主目录同样存在的voidForce测试桩错误,主目录基线120项中116 passed、4 failed。本次未修复无关基线。
- SQL静态核对:9表字段及顺序逐一与SQLAlchemy模型一致;utf8mb4索引上界均不超过3072字节,DDL使用InnoDB/DYNAMIC。菜单DML已合并为一个事务。此为静态检查,不替代MySQL5.7实际执行。
- 最近Web构建通过38.17秒;之后补分配UI待最终重跑。vue-tsc全库仍有既有错误,新quota/legal模块无报错;不能宣称类型检查通过。
- 未执行迁移、真实数据库连接、容器、生产服务动作、远端工单写入、提交、push或合并。当前仍为开发/审查中,整单未验收关闭。
## 10. 本地实现收口(2026-11-01)
- [x] 用户批准的合同关联v2:合同→合同产品行→购买证/运输证各自适用产品,合同与档案两侧维护;绑定不扣额度,同证共享余额。
- [x] 无图手工建档、图片候选解析后确认、期初与复核、总量更正及流水;差量保留档案引用与合同产品范围ID。
- [x] 动态来源配对与逐证条件确认、双证联合分配、原子安排/改派/审批/取消、实际量归档与纠错、超量补分配;旧齐备状态不放行,旧写入口410。
- [x] 易制爆合法使用证明独立Web/H5及小程序入口,允许安排/归档后补图;独立资料待补角标,不参与运输额度判断。
- [x] 规格与质量审查完成;最终质量独立运行271 passed。计算未完成保留真实数量;历史异单位零原容量不能影响同单位原顺序,覆盖补量开关两种路径。
- [x] 最终受影响后端459 passed(14条现有警告)。前端专项37 passed、补充共享/模型11 passed、端到端元数据持久化20 passed;浏览器全部合成API,合同ID往返/乱序、计划配置、H5合法资料、总量更正、补分配提交检查通过。
- [x] 最新生产构建通过52.18秒。主目录vue-tsc基线505条错误,本worktree499条;按错误内容归一化行号及工作目录后,本次新增错误为0。全库类型检查仍未通过。
- [x] 9表SQL与模型字段/顺序及索引长度静态核对,菜单DML同事务;SQL未执行。
- [ ] MySQL5.7 InnoDB并发、锁顺序/死锁重试及真实事务回滚验证:用户明确“暂不启动容器,保留事务验证待办”。SQLite不替代该项。
- [ ] 历史真实数据期初/在途对账、数据库迁移、真实小程序WebView联调及部署验收未执行;不得从旧齐备或附件推算额度。
- [ ] 全库既有TypeScript与移动测试基线问题未纳入本工单修复,扩展移动回归的最终对比见下方更新。
保留分支`codex/gitea-issue-4`与本地worktree供审阅,未提交、推送、合并、回写或关闭工单。DeepSeek只做过合成图验证,未上传业务证件;本地密钥不进入Git。
最终移动基线对比:排除在主目录和worktree均挂起的`mobile-pl-plan-load-state.test.ts`后,主目录391项(361通过、30失败),worktree341项(311通过、30失败),失败用例名称集合一致,无本次新增失败。退休齐备父页面22项测试已移除,保留普通计划及旧子组件独立回归,单文件60/60通过;新quota/legal真实组件会话验证在专用测试中覆盖。日志`/tmp/shanxia-issue4-mobile-final-baseline.log`与`/tmp/shanxia-issue4-mobile-final.log`。先前worktree缺少venv导致的3项元数据用例已通过临时复用主目录venv重新验证(20/20),未安装依赖,临时symlink已清理。
本次127.0.0.1:5176合成预览已停止;原有应用服务未操作。最后`git diff --check`通过。以上测试不包含真实DB/小程序运行环境,工单保持开放。
## 11. 本地主分支转测(2026-11-01)
- 用户要求“请把代码合并到主分支,我来测试下”,本轮范围为本地提交并合入项目集成分支 `V3.0`;测试责任转为用户,不推送远端、不关闭工单、不启停服务、不执行数据库迁移。
- 合并前已 fetch,远端及本地主分支均为 `428a09b82`。任务基线之后两项改动为派车日历车辆配色、三方车辆承运商必填;与本工单文件无代码重叠。合并结果做 Git 核对,上一节为此前实际测试证据,本次集成运行验收待用户测试。
- 主目录已有个人开发流程升级等未提交改动须完整保留;两份重叠草案内容与任务分支一致,OpenSpec 初始方案由本次实现记录接续,合并前单独备份。保留任务 worktree 供测试反馈修复。
- 测试前需在目标测试数据库按顺序应用 `docs/sql/2026-11-01-pl-contract-cert-quota.sql`、`docs/sql/migrations/2026-11-01-pl-quota-plan-configuration.sql`、`docs/sql/migrations/2026-11-01-pl-quota-cert-menus.sql`,并按测试账号分配新增菜单权限;本次未执行。DeepSeek 配置仅在任务 worktree 的忽略文件中,未随 Git 合并复制到主目录。