Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f95d9182e |
@@ -39,6 +39,7 @@ use think\facade\Log;
|
||||
*
|
||||
* 日志:无论分配与否,每条待指派诊单都会写入 tcm_diagnosis_auto_assign_log,记录原因(为什么分配 / 为什么不分配)。
|
||||
* 成功分配同时写 tcm_diagnosis_assign_log(is_inherit=0,计入次月接诊率分母),与手动指派同口径。
|
||||
* 写入时 from_assistant_id 尽量带上「一中心」原医助(指派日志中最近的一中心身份,否则回退业务单创建人若属一中心),避免原医助恒为空。
|
||||
*/
|
||||
class AutoAssignPendingDiagnosis extends Command
|
||||
{
|
||||
@@ -499,9 +500,12 @@ class AutoAssignPendingDiagnosis extends Command
|
||||
$relatedPoCreatorId = 0;
|
||||
}
|
||||
|
||||
// 自动分给二中心时,原医助带上一中心身份(列表「原医助」不再恒为空)
|
||||
$fromAssistantId = $this->resolveYiCenterPreviousAssistantId($diagnosisId, $relatedPoCreatorId);
|
||||
|
||||
Db::name('tcm_diagnosis_assign_log')->insert([
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
'from_assistant_id' => 0,
|
||||
'from_assistant_id' => $fromAssistantId,
|
||||
'to_assistant_id' => $toAssistantId,
|
||||
'operator_admin_id' => 0,
|
||||
'operator_name' => '系统自动分配',
|
||||
@@ -524,6 +528,88 @@ class AutoAssignPendingDiagnosis extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析诊单对应的「一中心」原医助 id,供自动指派写入 from_assistant_id。
|
||||
* 优先:指派日志由新到旧,取最近出现的一中心身份(先 to 后 from);
|
||||
* 回退:最新业务单创建人若属一中心则用之。跳过二中心身份,避免原医助写成上一任二中心。
|
||||
*/
|
||||
private function resolveYiCenterPreviousAssistantId(int $diagnosisId, int $relatedPoCreatorId): int
|
||||
{
|
||||
if ($diagnosisId <= 0) {
|
||||
return 0;
|
||||
}
|
||||
$yiDeptSet = DeptLogic::getYiCenterSubtreeDeptIdSet();
|
||||
if ($yiDeptSet === []) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$logs = Db::name('tcm_diagnosis_assign_log')
|
||||
->where('diagnosis_id', $diagnosisId)
|
||||
->order('id', 'desc')
|
||||
->field(['from_assistant_id', 'to_assistant_id'])
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$candidateIds = [];
|
||||
foreach ($logs as $log) {
|
||||
$to = (int) ($log['to_assistant_id'] ?? 0);
|
||||
$from = (int) ($log['from_assistant_id'] ?? 0);
|
||||
if ($to > 0) {
|
||||
$candidateIds[] = $to;
|
||||
}
|
||||
if ($from > 0) {
|
||||
$candidateIds[] = $from;
|
||||
}
|
||||
}
|
||||
if ($relatedPoCreatorId > 0) {
|
||||
$candidateIds[] = $relatedPoCreatorId;
|
||||
}
|
||||
$candidateIds = array_values(array_unique(array_filter($candidateIds)));
|
||||
if ($candidateIds === []) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$yiAdminSet = $this->filterAdminIdsInDeptSet($candidateIds, $yiDeptSet);
|
||||
if ($yiAdminSet === []) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$to = (int) ($log['to_assistant_id'] ?? 0);
|
||||
if ($to > 0 && isset($yiAdminSet[$to])) {
|
||||
return $to;
|
||||
}
|
||||
$from = (int) ($log['from_assistant_id'] ?? 0);
|
||||
if ($from > 0 && isset($yiAdminSet[$from])) {
|
||||
return $from;
|
||||
}
|
||||
}
|
||||
if ($relatedPoCreatorId > 0 && isset($yiAdminSet[$relatedPoCreatorId])) {
|
||||
return $relatedPoCreatorId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<int> $adminIds
|
||||
* @param array<int, true> $deptIdSet
|
||||
*
|
||||
* @return array<int, true> admin_id => true
|
||||
*/
|
||||
private function filterAdminIdsInDeptSet(array $adminIds, array $deptIdSet): array
|
||||
{
|
||||
if ($adminIds === [] || $deptIdSet === []) {
|
||||
return [];
|
||||
}
|
||||
$rows = Db::name('admin_dept')
|
||||
->whereIn('admin_id', $adminIds)
|
||||
->whereIn('dept_id', array_keys($deptIdSet))
|
||||
->column('admin_id');
|
||||
|
||||
return array_fill_keys(array_map('intval', $rows), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $diag 诊单行(含 id/patient_name/phone)
|
||||
* @param array<string,mixed> $extra action/assistant_id/assistant_name/tier/visit2_rate/round_no/reason
|
||||
|
||||
@@ -18,7 +18,7 @@ use think\console\Output;
|
||||
* 配置 crontab(每 10 分钟):拉快递 100 + 按履约「已发货」核对释放诊单医助(跳过已完成/已签收业务单,与是否甘草单无关)
|
||||
* 0,10,20,30,40,50 * * * * cd /path/to/server && php think express:auto-update >> /dev/null 2>&1
|
||||
*
|
||||
* 已对「业务订单创建人非二中心」(或创建人为开方医生时按待释放身份判定)执行发货/签收自动释放的诊单会写入 tcm_diagnosis.shipped_non_er_assistant_cleared_at,
|
||||
* 已对「待释放医助非二中心」执行发货/签收自动释放的诊单会写入 tcm_diagnosis.shipped_non_er_assistant_cleared_at,
|
||||
* 后续履约核对不再重复扫描(需先执行 sql/1.9.20260507/add_diagnosis_shipped_non_er_assistant_cleared_at.sql)。
|
||||
*/
|
||||
class ExpressAutoUpdate extends Command
|
||||
|
||||
@@ -34,7 +34,7 @@ use think\console\Output;
|
||||
* 0,30 * * * * cd /path/to/server && php think gancao:sync-logistics >> runtime/log/gancao_sync.log 2>&1
|
||||
*
|
||||
* 跳过履约状态为已完成(3)、已签收(6) 的业务订单,不再拉取甘草路由。
|
||||
* 已对「业务订单创建人非二中心」(发货/签收自动释放规则见 ExpressTrackingService)的诊单会写入 tcm_diagnosis.shipped_non_er_assistant_cleared_at,
|
||||
* 已对「待释放医助非二中心」(发货/签收自动释放规则见 ExpressTrackingService)的诊单会写入 tcm_diagnosis.shipped_non_er_assistant_cleared_at,
|
||||
* 后续履约核对不再重复扫描(需先执行 sql/1.9.20260507/add_diagnosis_shipped_non_er_assistant_cleared_at.sql)。
|
||||
*/
|
||||
class GancaoSyncLogisticsRoute extends Command
|
||||
|
||||
@@ -588,7 +588,7 @@ class ExpressTrackingService
|
||||
/**
|
||||
* 处方业务订单履约「已发货(5) / 已签收(6)」时:清空关联诊单(患者)医助,并写入 tcm_diagnosis_assign_log(含关联业务订单 creator_id / create_time 快照,便于核对医助创建订单时间)。
|
||||
* 快递 100 定时拉轨迹、甘草路由、甘草回调与履约核对共用同一规则。
|
||||
* 不自动清空的情形:(1)按业务订单 creator_id(代建场景)或回退身份判断是否在「二中心」部门子树;(2)诊单已有 shipped_non_er_assistant_cleared_at 且 assistant_id 已为 0(视为已处理);(3)指派日志存在后台人工指派:`operator_admin_id>0` 且 `to_assistant_id>0`(系统任务为 operator_admin_id=0);或 related_po_creator_id=from_assistant_id 且 to>0 的旧数据兼容。避免「系统·已发货履约核对」覆盖人工指派链。
|
||||
* 不自动清空的情形:(1)待释放医助(诊单 assistant_id,或代建回退身份)归属「二中心」部门子树;(2)诊单当前已指派、或指派日志曾 to 给「二中心」医助(含系统自动分配);(3)诊单已有 shipped_non_er_assistant_cleared_at 且 assistant_id 已为 0(视为已处理);(4)指派日志存在后台人工指派:`operator_admin_id>0` 且 `to_assistant_id>0`;或 related_po_creator_id=from_assistant_id 且 to>0 的旧数据兼容。避免「系统·已发货履约核对」覆盖人工指派链。
|
||||
*
|
||||
* @param array{tracking_id?:int,tracking_number?:string,source?:string} $meta
|
||||
* @return array{
|
||||
@@ -663,19 +663,18 @@ class ExpressTrackingService
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 是否因「二中心」跳过释放:优先看业务订单创建人 creator_id(代建场景);创建人即开方医生时用 fromAssistantId */
|
||||
$erZhongxinCheckAdminId = ($poCreatorId > 0 && ($rxId <= 0 || $poCreatorId !== $rxCreator))
|
||||
? $poCreatorId
|
||||
: $fromAssistantId;
|
||||
|
||||
if ($erZhongxinCheckAdminId > 0 && self::currentAssistantBelongsToErzhongxinDeptTree($erZhongxinCheckAdminId)) {
|
||||
Log::info('Skipped auto assistant release (shipped/signed): order creator (or fallback from-id) under 二中心 dept tree', [
|
||||
// 二中心不释放:(a)待释放医助属二中心;(b)诊单当前医助属二中心;(c)指派日志曾指派给二中心医助
|
||||
$skipErzhongxin = self::currentAssistantBelongsToErzhongxinDeptTree($fromAssistantId)
|
||||
|| ($diagAssistantIdNow > 0 && self::currentAssistantBelongsToErzhongxinDeptTree($diagAssistantIdNow))
|
||||
|| self::diagnosisHasBeenAssignedToErzhongxinAssistant($diagnosisId);
|
||||
if ($skipErzhongxin) {
|
||||
Log::info('Skipped auto assistant release (shipped/signed): 二中心 assistant assigned or targeted', [
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
'prescription_order_id' => $orderId,
|
||||
'source' => $source,
|
||||
'er_zhongxin_check_admin_id' => $erZhongxinCheckAdminId,
|
||||
'prescription_order_creator_id' => $poCreatorId,
|
||||
'from_assistant_id_for_log' => $fromAssistantId,
|
||||
'from_assistant_id' => $fromAssistantId,
|
||||
'diagnosis_assistant_id' => $diagAssistantIdNow,
|
||||
'prescription_order_creator_id' => $poCreatorId,
|
||||
]);
|
||||
|
||||
return null;
|
||||
@@ -798,6 +797,36 @@ class ExpressTrackingService
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 诊单指派日志是否曾指派给「二中心」医助(to_assistant_id>0,含人工指派与系统自动分配)。
|
||||
*/
|
||||
private static function diagnosisHasBeenAssignedToErzhongxinAssistant(int $diagnosisId): bool
|
||||
{
|
||||
if ($diagnosisId <= 0) {
|
||||
return false;
|
||||
}
|
||||
$toIds = Db::name('tcm_diagnosis_assign_log')
|
||||
->where('diagnosis_id', $diagnosisId)
|
||||
->where('to_assistant_id', '>', 0)
|
||||
->column('to_assistant_id');
|
||||
if ($toIds === [] || $toIds === null) {
|
||||
return false;
|
||||
}
|
||||
$seen = [];
|
||||
foreach ($toIds as $aid) {
|
||||
$aid = (int) $aid;
|
||||
if ($aid <= 0 || isset($seen[$aid])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$aid] = true;
|
||||
if (self::currentAssistantBelongsToErzhongxinDeptTree($aid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 若诊单曾被后台人工指派到具体医助,则不再执行发运/签收自动清空(避免「系统·已发货履约核对」覆盖人工链)。
|
||||
* 判定:operator_admin_id>0 且 to_assistant_id>0(人工);系统写入的释放/同步为 operator_admin_id=0。
|
||||
@@ -1031,7 +1060,7 @@ class ExpressTrackingService
|
||||
|
||||
/**
|
||||
* 按处方订单履约核对:仅已发货(5) 时符合条件的订单调用 applyAssistantReleaseForShippedPrescriptionOrder(已完成/已签收不再扫描)。
|
||||
* 与快递 100 / 甘草来自哪个物流渠道无关;是否清空医助以该方法为准(**二中心豁免看业务单创建人**参见 apply;已 shipped 释放且 assistant_id=0 视为已处理)。
|
||||
* 与快递 100 / 甘草来自哪个物流渠道无关;是否清空医助以该方法为准(**二中心豁免看待释放医助**参见 apply;已 shipped 释放且 assistant_id=0 视为已处理)。
|
||||
*
|
||||
* @return array{scanned: int, cleared: int, lines: list<string>}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user