修复 QCDistributionRegisterInfo 重复登记问题
问题:qcDistId=41 下 QC269 出现两条 (QCDistributionId, LabId, ProjectId)
完全相同的登记记录,ConfigrmFee 的 FirstOrDefault 静默命中其中一条导致
IsCharged 状态不同步,在 OutputUnderTakenLabs 导出时暴露。已手工清理 5
组历史脏数据(Id=2944/7508/7509/7664/7666)。
代码修改(不动 DDL,全部在业务层):
- QCService.SaveQcDistributionRegister:Id==0 时按业务唯一键查重,命中
既有行则按 MergeRegisterInfo 合并后 UPDATE,并写 [WARN] 日志。作为
所有 Insert 路径的最后一道防线,覆盖未来任何新调用方。
- MergeRegisterInfo:刻意不对称的合并规则——string/DateTime? 仅非 null
才覆盖,bool 只能 false→true 不能反向,防止一次脏 Save 把 IsCharged=1
意外清零。
- QCDistributionInfoViewModel.ToEntity:SaveLabList 路径的第一道防线,
新行插入前按 (QCDist, LabId, ProjectId) 查重,存在则复用走 Update。
- QCDistributionRegisterInfoViewModel.ToEntityByLabCode:查询条件补上
ProjectId 过滤,让 ConfigrmFee/ConfigrmEMS/switchNextOne 在"一个实
验室多项目"场景下能精准命中目标登记行,不再静默合并。
- BackstageController.ImportLabs:加 oriDistId==TargetDistId 和目标为
null 的前置守卫;源读取后按 GroupBy(LabId, ProjectId) 去重,阻止脏
数据跨分发传染。
- BackstageController.OutputUnderTakenLabs:清理 headers/cellKes 中重
复的"是否收费"/isCharged 列(残留自上次 15e82c0 提交)。
CLAUDE.md 新增"QCDistributionRegisterInfo 保存契约"章节,记录上述约定
及已知残余风险(多管理员并发编辑同一分发的理论窗口)。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>