feat: add reviewed follow-up audio patient enrichment
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\service\followupaudio;
|
||||
|
||||
use app\adminapi\logic\firstvisit\MyPatientLogic;
|
||||
use DomainException;
|
||||
use think\facade\Db;
|
||||
|
||||
/** Every entry point (including the background worker) uses current actor and row scope. */
|
||||
final class FollowupAudioAccess
|
||||
{
|
||||
public static function actor(int $actor): array
|
||||
{
|
||||
$row = Db::name('admin')->where('id', $actor)->whereNull('delete_time')->where('disable', 0)->lock(true)->find();
|
||||
if (!$row) {
|
||||
throw new DomainException('账号已停用或无权访问');
|
||||
}
|
||||
return [
|
||||
'admin_id' => $actor, 'id' => $actor, 'root' => (int) $row['root'], 'name' => (string) $row['name'],
|
||||
'role_id' => Db::name('admin_role')->where('admin_id', $actor)->lock(true)->column('role_id'),
|
||||
'dept_id' => Db::name('admin_dept')->where('admin_id', $actor)->lock(true)->column('dept_id'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function allowed(int $actor, array $info, string $permission): bool
|
||||
{
|
||||
if ($actor <= 0) {
|
||||
return false;
|
||||
}
|
||||
if ((int) ($info['root'] ?? 0) === 1) {
|
||||
return true;
|
||||
}
|
||||
// Explicit current reads also avoid permission-cache and MVCC snapshot staleness.
|
||||
$roles = Db::name('admin_role')->where('admin_id', $actor)->lock(true)->column('role_id');
|
||||
$menus = $roles ? Db::name('system_role_menu')->whereIn('role_id', $roles)->lock(true)->column('menu_id') : [];
|
||||
$permissions = $menus ? Db::name('system_menu')->whereIn('id', array_unique($menus))
|
||||
->where('is_disable', 0)->lock(true)->column('perms') : [];
|
||||
return in_array(strtolower($permission), array_map('strtolower', $permissions), true);
|
||||
}
|
||||
|
||||
public static function diagnosis(int $diagnosisId, int $actor, array $info, bool $daily = false): array
|
||||
{
|
||||
if ($diagnosisId <= 0) {
|
||||
throw new DomainException('诊单不存在或无权操作');
|
||||
}
|
||||
// Acquire the target row before rebuilding current actor/scope after any lock wait.
|
||||
$row = Db::name('tcm_diagnosis')->where('id', $diagnosisId)->whereNull('delete_time')->lock(true)->find();
|
||||
$info = self::actor($actor);
|
||||
if (!$row || !self::allowed($actor, $info, 'tcm.diagnosis/edit')
|
||||
|| ($daily && !self::allowed($actor, $info, 'tcm.diagnosis/dailyRecord'))) {
|
||||
throw new DomainException('诊单不存在或无权操作');
|
||||
}
|
||||
$query = Db::name('tcm_diagnosis')->alias('d')->where('d.id', $diagnosisId)
|
||||
->whereNull('d.delete_time')->where('d.status', 1);
|
||||
MyPatientLogic::applyScope($query, $actor, $info);
|
||||
if (!$query->lock(true)->find()) {
|
||||
throw new DomainException('诊单不存在或无权操作');
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
public static function task(int $taskId, int $actor, array $info, bool $daily = false): array
|
||||
{
|
||||
$task = FollowupAudioStore::task($taskId);
|
||||
$diagnosis = self::diagnosis((int) $task['diagnosis_id'], $actor, $info, $daily);
|
||||
if (array_key_exists('patient_id', $task)
|
||||
&& (int) $task['patient_id'] !== (int) ($diagnosis['patient_id'] ?? 0)) {
|
||||
throw new DomainException('诊单患者归属已变化,不能访问原回访录音');
|
||||
}
|
||||
return $task;
|
||||
}
|
||||
|
||||
public static function canDaily(int $actor, array $info): bool
|
||||
{
|
||||
$info = self::actor($actor);
|
||||
return self::allowed($actor, $info, 'tcm.diagnosis/dailyRecord');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user