228 lines
7.7 KiB
PHP
228 lines
7.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\adminapi\logic\stats;
|
||
|
||
use app\common\logic\BaseLogic;
|
||
use think\facade\Db;
|
||
use think\facade\Log;
|
||
|
||
/**
|
||
* 待分配诊单自动指派日志:回退已自动分配的医助
|
||
*/
|
||
class AutoAssignLogLogic extends BaseLogic
|
||
{
|
||
/**
|
||
* 批量回退:将诊单医助撤回到自动分配前的原医助(指派日志 from_assistant_id),并标记自动分配日志已回退。
|
||
*
|
||
* @param list<int|string> $ids 自动分配日志 id
|
||
* @return array{success:int,failed:int,messages:list<string>}|false
|
||
*/
|
||
public static function rollback(array $ids, int $adminId, array $adminInfo = []): array|false
|
||
{
|
||
$idList = array_values(array_unique(array_filter(array_map('intval', $ids), static fn (int $id) => $id > 0)));
|
||
if ($idList === []) {
|
||
self::setError('请选择要回退的记录');
|
||
|
||
return false;
|
||
}
|
||
|
||
$adminName = (string) ($adminInfo['name'] ?? '');
|
||
$adminAccount = (string) ($adminInfo['account'] ?? '');
|
||
$req = request();
|
||
$ip = (string) ($req->ip() ?? '');
|
||
$now = time();
|
||
|
||
$success = 0;
|
||
$failed = 0;
|
||
$messages = [];
|
||
|
||
foreach ($idList as $logId) {
|
||
try {
|
||
$ret = self::rollbackOne($logId, $adminId, $adminName, $adminAccount, $ip, $now);
|
||
if ($ret === true) {
|
||
$success++;
|
||
} else {
|
||
$failed++;
|
||
$messages[] = (string) $ret;
|
||
}
|
||
} catch (\Throwable $e) {
|
||
$failed++;
|
||
$messages[] = sprintf('日志#%d:%s', $logId, $e->getMessage());
|
||
Log::warning('auto assign rollback failed: ' . $e->getMessage(), ['log_id' => $logId]);
|
||
}
|
||
}
|
||
|
||
if ($success === 0 && $failed > 0) {
|
||
self::setError($messages[0] ?? '回退失败');
|
||
|
||
return false;
|
||
}
|
||
|
||
return [
|
||
'success' => $success,
|
||
'failed' => $failed,
|
||
'messages' => $messages,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @return true|string true=成功,string=失败原因
|
||
*/
|
||
private static function rollbackOne(
|
||
int $logId,
|
||
int $adminId,
|
||
string $adminName,
|
||
string $adminAccount,
|
||
string $ip,
|
||
int $now
|
||
): bool|string {
|
||
Db::startTrans();
|
||
try {
|
||
$log = Db::name('tcm_diagnosis_auto_assign_log')
|
||
->where('id', $logId)
|
||
->lock(true)
|
||
->find();
|
||
if ($log === null || $log === []) {
|
||
Db::rollback();
|
||
|
||
return sprintf('日志#%d:记录不存在', $logId);
|
||
}
|
||
|
||
if ((int) ($log['action'] ?? 0) !== 1) {
|
||
Db::rollback();
|
||
|
||
return sprintf('日志#%d:仅「已分配」记录可回退', $logId);
|
||
}
|
||
if ((int) ($log['rollback_time'] ?? 0) > 0) {
|
||
Db::rollback();
|
||
|
||
return sprintf('日志#%d:已回退,勿重复操作', $logId);
|
||
}
|
||
|
||
$diagnosisId = (int) ($log['diagnosis_id'] ?? 0);
|
||
$assignedAssistantId = (int) ($log['assistant_id'] ?? 0);
|
||
if ($diagnosisId <= 0 || $assignedAssistantId <= 0) {
|
||
Db::rollback();
|
||
|
||
return sprintf('日志#%d:数据不完整,无法回退', $logId);
|
||
}
|
||
|
||
$diag = Db::name('tcm_diagnosis')
|
||
->where('id', $diagnosisId)
|
||
->whereNull('delete_time')
|
||
->lock(true)
|
||
->field(['id', 'assistant_id'])
|
||
->find();
|
||
if ($diag === null || $diag === []) {
|
||
Db::rollback();
|
||
|
||
return sprintf('日志#%d:诊单#%d 不存在', $logId, $diagnosisId);
|
||
}
|
||
|
||
$currentAssistantId = (int) ($diag['assistant_id'] ?? 0);
|
||
if ($currentAssistantId !== $assignedAssistantId) {
|
||
Db::rollback();
|
||
|
||
return sprintf(
|
||
'日志#%d:诊单#%d 当前医助已变更(非自动分配的医助),跳过回退',
|
||
$logId,
|
||
$diagnosisId
|
||
);
|
||
}
|
||
|
||
$prevAssistantId = self::resolvePreviousAssistantIdFromAutoAssign(
|
||
$diagnosisId,
|
||
$assignedAssistantId,
|
||
(int) ($log['create_time'] ?? 0)
|
||
);
|
||
|
||
$poSnap = Db::name('tcm_prescription_order')
|
||
->where('diagnosis_id', $diagnosisId)
|
||
->whereNull('delete_time')
|
||
->order(['create_time' => 'desc', 'id' => 'desc'])
|
||
->field(['creator_id', 'create_time'])
|
||
->find();
|
||
$relatedPoCreatorId = (int) ($poSnap['creator_id'] ?? 0);
|
||
$relatedPoCreateTime = (int) ($poSnap['create_time'] ?? 0);
|
||
if ($relatedPoCreateTime <= 0) {
|
||
$relatedPoCreateTime = $now;
|
||
$relatedPoCreatorId = 0;
|
||
}
|
||
|
||
Db::name('tcm_diagnosis')
|
||
->where('id', $diagnosisId)
|
||
->whereNull('delete_time')
|
||
->update([
|
||
'assistant_id' => $prevAssistantId,
|
||
'assign_read_at' => $prevAssistantId > 0 ? null : 0,
|
||
]);
|
||
|
||
Db::name('tcm_diagnosis_assign_log')->insert([
|
||
'diagnosis_id' => $diagnosisId,
|
||
'from_assistant_id' => $currentAssistantId,
|
||
'to_assistant_id' => $prevAssistantId,
|
||
'operator_admin_id' => $adminId,
|
||
'operator_name' => $adminName !== '' ? $adminName : '回退自动分配',
|
||
'operator_account' => $adminAccount,
|
||
'ip' => $ip,
|
||
'related_po_creator_id' => $relatedPoCreatorId,
|
||
'related_po_create_time' => $relatedPoCreateTime,
|
||
'is_inherit' => 0,
|
||
'create_time' => $now,
|
||
]);
|
||
|
||
Db::name('tcm_diagnosis_auto_assign_log')
|
||
->where('id', $logId)
|
||
->update([
|
||
'rollback_time' => $now,
|
||
'rollback_admin_id' => $adminId,
|
||
'rollback_admin_name' => $adminName,
|
||
]);
|
||
|
||
Db::commit();
|
||
|
||
return true;
|
||
} catch (\Throwable $e) {
|
||
Db::rollback();
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 从「系统自动分配」指派日志取 from_assistant_id 作为回退目标。
|
||
*/
|
||
private static function resolvePreviousAssistantIdFromAutoAssign(
|
||
int $diagnosisId,
|
||
int $assignedAssistantId,
|
||
int $autoLogCreateTime
|
||
): int {
|
||
$query = Db::name('tcm_diagnosis_assign_log')
|
||
->where('diagnosis_id', $diagnosisId)
|
||
->where('to_assistant_id', $assignedAssistantId)
|
||
->where('operator_name', '系统自动分配');
|
||
|
||
if ($autoLogCreateTime > 0) {
|
||
$query->where('create_time', '>=', $autoLogCreateTime - 30)
|
||
->where('create_time', '<=', $autoLogCreateTime + 30);
|
||
}
|
||
|
||
$row = $query->order('id', 'desc')->field(['from_assistant_id'])->find();
|
||
if ($row !== null && $row !== []) {
|
||
return (int) ($row['from_assistant_id'] ?? 0);
|
||
}
|
||
|
||
// 兜底:不限时间窗再查最近一条系统自动分配
|
||
$fallback = Db::name('tcm_diagnosis_assign_log')
|
||
->where('diagnosis_id', $diagnosisId)
|
||
->where('to_assistant_id', $assignedAssistantId)
|
||
->where('operator_name', '系统自动分配')
|
||
->order('id', 'desc')
|
||
->field(['from_assistant_id'])
|
||
->find();
|
||
|
||
return (int) ($fallback['from_assistant_id'] ?? 0);
|
||
}
|
||
}
|