Files
zyt/artifacts/revisit-cohort-assignment-research.md
T
2026-10-17 16:08:24 +08:00

8.0 KiB
Raw Blame History

复诊接诊率:指派 / 继承写入与兼容性研究

2026-10-16。只读检查产品源码;未读取 .env 或凭据;未连接数据库。项目存在 AGENTS.md,但 .trellis/workflow.md 不存在,无法读取 Trellis 流程与分层规范。

关键结论

  • 现有报表是“当月指派分母 + 当月成交分子”,不是“指派日期区间内患者的后续接诊队列”。仅把 month 换成起止日期会继续产生区间外患者进入分子的错误。
  • 新指派、继承已有可用事件字段,无需为重新起算修改患者全局诊次。应在统计层根据入组指派事件重新计算后续订单;RevisitVisitSlotService 同时服务诊单节点、到期快照,改变它会影响其他业务。
  • 自动指派和个人业绩都直接依赖当前统计实现。页面改队列口径时要明确兼容入口;尤其不要悄悄改变自动指派档位。

写入侧与数据字段

入口 现有行为 注意点
DiagnosisLogic::assign(约 673 行) 诊单行 FOR UPDATE;更新 assistant_id、assign_read_at;同事务插入指派日志。is_inherit=1 仅在目标医助大于 0 时成立。 from==to 允许写入;当前 slot 统计忽略该行,旧 exclude 仍计入新指派。新队列避免把自指派当成新承接事件。
同上,继承 同事务用 slotAtTime($id,$now) 写 inherit_visit_slot 和 inherit_visit_slot_calc_time。 快照只用于展示 / 对账。现有统计通过有效订单实时重算 k,所以事后退款、取消、offset 修改会联动。不能把快照当唯一订单数依据;历史回退没有快照。
AutoAssignPendingDiagnosis::applyAssignment(约 567 行) is_inherit=0、操作人 0、名称“系统自动分配”;同事务改医助并写日志;from 可推断为一中心原医助。 自动指派属于新指派,不能以 from>0 判定继承。
AutoAssignLogLogic::rollbackOne(约 72 行) 锁自动指派日志和诊单;仅当前医助仍为自动分配目标时允许回退;回到前任 / 0。写指派日志 is_inherit=0,并写自动分配日志 rollback 字段。 保留写入规则;新口径需把历史回退识别为继承,目标 0 的释放行不入组。
ExpressTrackingService(约 702 行) 发货释放写 to_assistant_id=0,未显式写 is_inherit(列默认 0)。 释放不是新指派,但会终止原医助持有时间段。

主要表 / 模型:

  • DiagnosisAssignLog 只设置表名 tcm_diagnosis_assign_log,关闭自动时间戳,无字段白名单。指派核心数据:id, diagnosis_id, from_assistant_id, to_assistant_id, operator_admin_id, create_time, is_inherit, inherit_visit_slot, inherit_visit_slot_calc_time;还含最新订单创建人 / 时间快照与操作人信息。
  • tcm_diagnosis:assistant_id 是当前归属,不应代替历史持有时间线;revisit_slot_start_offset 为全局诊次偏移(钳制 0~20)。
  • tcm_prescription_order:有效业务单剔除软删、履约状态 4/9/10;统一调用 YejiStatsLogic::applyPrescriptionOrderNotCancelledForPerformanceQuery;序列稳定排序 (diagnosis_id, create_time, id)。
  • 迁移:server/sql/1.9.20260601/add_diagnosis_assign_log_is_inherit.sql;server/sql/1.9.20261012/06_add_diagnosis_assign_log_inherit_visit_slot.sql。继承标记引入前的数据无法可靠恢复继承类型,不应按 from>0 猜测。
  • 现有订单复合索引迁移:server/sql/1.9.20261012/01_add_prescription_order_diag_ct_index.sql,(diagnosis_id, delete_time, fulfillment_status, create_time)。源码内未找到指派日志建表 DDL,不能据此断言线上索引情况。

rollback 与重新起算

  • RevisitRateLogic::fetchRollbackKeySet 使用 diagnosis_id | rollback_time | rollback_admin_id 关联到指派日志 diagnosis_id | create_time | operator_admin_id;同一事务同一 $now 保证当前写入可匹配。需要继承独立页时复用这一兼容规则,不能只筛 is_inherit=1。
  • 现有 RevisitRateCalculator::compute 在 slot 模式将命中回退的日志当继承;exclude 模式完全保留其 is_inherit=0 的旧语义。回退无继承快照,订单实时计算仍可用。
  • 新继承“重新起算”应按继承事件时间切开序列,继承前历史单不进入继承后的接诊次数。保留同一秒约定:日志时间 t <= order.create_time 时归新医助,继承前完成单计数用严格 < t。
  • 转派 / 释放 / 再次继承会形成多个持有段;要先明确入组去重,再把订单归属到有效段,避免同一订单被多个队列事件重复领取。当前实现按同一医助 × 诊单去重,继承取区间内最早,且同区间新指派优先覆盖继承;这一合并规则不适合直接复用到“新指派和继承分别统计”。
  • 当前拒收 / 退款处理是“该诊单存在任意时间状态 9/10 有效订单,则整诊单从分母剔除”,分子只是剔除对应无效单。若沿用需在两个独立页面和明细保持一致;不要无意中改变这一业务规则。

当前统计调用方

  1. AutoAssignPendingDiagnosis::execute 调 RevisitRateLogic::overview(['month'=>上个自然月,'inherit_mode'=>'slot']),再从部门 children 中取医助率。配置实际值为 project.revisit_rate.auto_assign_tier_field='visit2_rate_new_assign',页面默认实际是 default_inherit_mode='exclude'(部分注释仍写默认 slot)。
    • 分档字段白名单仅 visit2_rate_new_assign / visit2_rate,对应 rate_version=v1/v2。无分母必须继续返回 null,否则可能改变谁参与自动指派。
    • 自动日志同时记录两套率。历史 v1 行无 visit2_rate_new_assign 时,前端回落 visit2_rate。不要重解释历史日志字段;如变更分档口径要单独版本化。
  2. AssistantPerformanceController::revisitRate 只收 month,Logic 从配置取 mode,再调 RevisitRateLogic::assistantOverview,只返回本人行。
    • 本人统计有 600 秒缓存,key 为 month + assistantId + mode。改统计口径需更新缓存 key 版本;加日期范围 / 队列类型需纳入 key。
    • 前端个人业绩卡片仍按月,响应类型依赖 month, inherit_mode, slots, in_scope, row。保持 month 兼容可避免页面破坏,但卡片文案和规则应同步说明指派队列口径。
  3. RevisitRateLogic::overview 目前不处理 assistant_id;只有两个下钻方法调用 applyRowScope。新增医助筛选需同时约束 overview 的医助行、部门汇总、总计以及下钻集合。部门归属取当前 admin_dept 中最小有效 dept_id,默认限二中心子树。
  4. YejiStatsLogic 的“被指派数”仍独立按 is_inherit=0、区间指派、医助×诊单去重;避免此次顺带修改整个业绩看板。

新独立页还需菜单 / 权限迁移与 MCP review 文案。AuthMiddleware 对未登记接口默认放行,因此新增接口须登记权限。现有 deptOptions 还被复诊到期页复用,不应改成仅某一队列的选项。

测试运行方式与已验证基线

无根级 PHPUnit 配置,server/composer.json 无 test script / PHPUnit;相关测试是独立 PHP CLI 脚本,仅加载 server/vendor/autoload.php,不启动应用、不连库。当前 PATH PHP:D:/phpstudy_pro/Extensions/php/php8.2.9nts/php.exe。

已从项目根目录运行并通过:

php server/tests/RevisitRateContractTest.php       # 45 checks
php server/tests/RevisitRateInheritSlotTest.php    # 57 checks
php server/tests/RevisitVisitSlotServiceTest.php   # 20 checks

RevisitRateContractTest 是源码字符串 / Reflection 契约,明确锁住“分子按当月下单”“继承从 k+1 列入分母”等旧实现,新队列实现需要合理更新这些断言,不能仅为通过保留过时语义。建议纯函数覆盖:区间指派后跨月成交、区间外患者同月成交不计入、自指派、转派终止归属、多次继承与重置、回退继承、同秒排序、医助筛选汇总和两类明细对账;保留全局诊次服务现有测试。