更新
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\service\tcm;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 复诊到期快照业务钩子(订单 / 挂号 / 指派 / 诊单变更 / 过号 cron)。
|
||||
*
|
||||
* 所有方法整体 try/catch 并 Log::warning,绝不向调用方抛异常、不改变主流程返回值;
|
||||
* 任一钩子漏接由 30 分钟增量 cron(tcm:revisit-due-scan --mode=incremental)与列表自愈兜底。
|
||||
*
|
||||
* 接入点(由其它代理在业务 Logic 的事务提交之后调用):
|
||||
* - PrescriptionOrderLogic create/editTime/withdraw/complete(9,10)/refund、GancaoCallbackController case 91/92 → onOrderChanged
|
||||
* - AppointmentLogic create/cancel/complete/adminEdit → onAppointmentChanged
|
||||
* - DiagnosisLogic::assign、AutoAssignPendingDiagnosis、AutoAssignLogLogic 回退 → onAssistantChanged
|
||||
* - DiagnosisLogic::setRevisitSlotStartOffset 等诊单字段变更 → onDiagnosisChanged
|
||||
* - UpdateAppointmentStatus 两条 Db::execute 之后 → onAppointmentStatusCronDone
|
||||
*/
|
||||
final class RevisitDueHook
|
||||
{
|
||||
/**
|
||||
* 业务订单变化(新建 / 改下单时间 / 撤回 / 完成为 9,10 / 退款 / 甘草回调置 4)。
|
||||
* diagnosisId 为 0 时按 orderId 反查诊单。
|
||||
*/
|
||||
public static function onOrderChanged(int $diagnosisId, int $orderId = 0, string $reason = ''): void
|
||||
{
|
||||
try {
|
||||
if ($diagnosisId <= 0 && $orderId > 0) {
|
||||
$diagnosisId = (int) Db::name('tcm_prescription_order')->where('id', $orderId)->value('diagnosis_id');
|
||||
}
|
||||
if ($diagnosisId <= 0) {
|
||||
return;
|
||||
}
|
||||
RevisitDueService::refreshDiagnoses([$diagnosisId], [
|
||||
'reason' => self::reasonTag('order', $reason),
|
||||
'operator_id' => self::currentAdminId(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning(sprintf('复诊到期钩子 onOrderChanged 失败 diagnosis_id=%d order_id=%d: %s', $diagnosisId, $orderId, $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂号变化(创建 / 取消 / 完成 / 后台编辑)。diagnosisId 为 0 时按 appointmentId 反查(patient_id 存诊单 id)。
|
||||
*/
|
||||
public static function onAppointmentChanged(int $diagnosisId, int $appointmentId = 0, string $reason = ''): void
|
||||
{
|
||||
try {
|
||||
if ($diagnosisId <= 0 && $appointmentId > 0) {
|
||||
$diagnosisId = (int) Db::name('doctor_appointment')->where('id', $appointmentId)->value('patient_id');
|
||||
}
|
||||
if ($diagnosisId <= 0) {
|
||||
return;
|
||||
}
|
||||
RevisitDueService::refreshDiagnoses([$diagnosisId], [
|
||||
'reason' => self::reasonTag('appointment', $reason),
|
||||
'operator_id' => self::currentAdminId(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning(sprintf('复诊到期钩子 onAppointmentChanged 失败 diagnosis_id=%d appointment_id=%d: %s', $diagnosisId, $appointmentId, $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 医助变更(指派 / 继承 / 释放 to=0 / 自动分配 / 回退)。toAssistantId 仅用于流水 payload,实际以库内 tcm_diagnosis.assistant_id 为准。
|
||||
*/
|
||||
public static function onAssistantChanged(int $diagnosisId, int $toAssistantId, string $reason = ''): void
|
||||
{
|
||||
try {
|
||||
if ($diagnosisId <= 0) {
|
||||
return;
|
||||
}
|
||||
$tag = self::reasonTag('assign', $reason);
|
||||
if ($toAssistantId >= 0) {
|
||||
$tag .= ':to=' . $toAssistantId;
|
||||
}
|
||||
RevisitDueService::refreshDiagnoses([$diagnosisId], [
|
||||
'reason' => $tag,
|
||||
'operator_id' => self::currentAdminId(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning(sprintf('复诊到期钩子 onAssistantChanged 失败 diagnosis_id=%d to=%d: %s', $diagnosisId, $toAssistantId, $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 诊单其它字段变更(如 revisit_slot_start_offset、status 禁用/启用、软删)。
|
||||
*/
|
||||
public static function onDiagnosisChanged(int $diagnosisId, string $reason = ''): void
|
||||
{
|
||||
try {
|
||||
if ($diagnosisId <= 0) {
|
||||
return;
|
||||
}
|
||||
RevisitDueService::refreshDiagnoses([$diagnosisId], [
|
||||
'reason' => self::reasonTag('diagnosis', $reason),
|
||||
'operator_id' => self::currentAdminId(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning(sprintf('复诊到期钩子 onDiagnosisChanged 失败 diagnosis_id=%d: %s', $diagnosisId, $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过号 cron(update_appointment_status)执行之后:重评 closed_state=2 / appointment_state=1 的行,使当天过号即进标红/弹窗。
|
||||
*/
|
||||
public static function onAppointmentStatusCronDone(): void
|
||||
{
|
||||
try {
|
||||
RevisitDueService::reevaluateBookedRows();
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('复诊到期钩子 onAppointmentStatusCronDone 失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** 流水 payload 的 reason 标签:<来源>[:<说明>],限 64 字符 */
|
||||
private static function reasonTag(string $source, string $reason): string
|
||||
{
|
||||
$reason = trim($reason);
|
||||
|
||||
return mb_substr($reason !== '' ? $source . ':' . $reason : $source, 0, 64);
|
||||
}
|
||||
|
||||
/** 当前登录管理员 id(CLI / 回调无登录态时为 0),任何异常均视为 0 */
|
||||
private static function currentAdminId(): int
|
||||
{
|
||||
try {
|
||||
$req = request();
|
||||
$admin = $req->adminInfo ?? null;
|
||||
if (is_array($admin)) {
|
||||
return (int) ($admin['admin_id'] ?? 0);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// CLI 场景无请求上下文,忽略
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user