Files
zyt/server/tests/AssistantServiceReminderRecipientTest.php
T
2026-11-12 09:07:07 +08:00

88 lines
6.6 KiB
PHP

<?php
declare(strict_types=1);
// 真实 ORM/Access 与合成授权记录;不初始化应用、不联网、不发送企微消息。
require dirname(__DIR__) . '/vendor/autoload.php';
require dirname(__DIR__) . '/vendor/topthink/framework/src/helper.php';
use app\common\service\assistantservice\AssistantServiceReminderRecipient as Recipient;
use think\Container;
use think\facade\Db;
new think\App();
set_exception_handler(static function (Throwable $e): void { fwrite(STDERR, $e->getMessage() . PHP_EOL . $e->getTraceAsString()); exit(1); });
$manager = new think\DbManager();
$manager->setConfig(['default' => 'isolated', 'connections' => ['isolated' => [
'type' => 'sqlite', 'database' => ':memory:', 'prefix' => 'test_', 'fields_strict' => true,
]]]);
Container::getInstance()->instance('think\DbManager', $manager);
think\Model::setDb($manager);
Container::getInstance()->instance('config', new think\Config());
$checks = 0;
$expect = static function (bool $ok, string $why) use (&$checks): void { if (!$ok) { throw new RuntimeException($why); } $checks++; };
$deny = static function (callable $action, string $why) use ($expect): void {
try { $action(); } catch (DomainException $e) { $expect(true, $why); return; }
throw new RuntimeException('Expected rejection: ' . $why);
};
$todo = ['id' => 1, 'diagnosis_id' => 101, 'patient_id' => 201, 'creator_id' => 13];
$expect(Recipient::resolve($todo) === 13, 'legacy reminder works before module migration');
$schemas = [
'admin' => 'id INTEGER PRIMARY KEY,name TEXT,root INTEGER DEFAULT 0,disable INTEGER DEFAULT 0,delete_time INTEGER NULL',
'admin_role' => 'admin_id INTEGER,role_id INTEGER',
'admin_dept' => 'admin_id INTEGER,dept_id INTEGER',
'system_role' => 'id INTEGER PRIMARY KEY,name TEXT,data_scope INTEGER,delete_time INTEGER NULL',
'system_role_menu' => 'role_id INTEGER,menu_id INTEGER',
'system_menu' => 'id INTEGER PRIMARY KEY,perms TEXT,is_disable INTEGER DEFAULT 0',
'tcm_diagnosis' => 'id INTEGER PRIMARY KEY,patient_id INTEGER,assistant_id INTEGER,status INTEGER DEFAULT 1,delete_time INTEGER NULL',
'assistant_service_action' => 'id INTEGER PRIMARY KEY,todo_id INTEGER,diagnosis_id INTEGER,job_id INTEGER,assignee_id INTEGER,business_state TEXT',
'assistant_service_job' => 'id INTEGER PRIMARY KEY,diagnosis_id INTEGER,patient_id INTEGER,payload_json TEXT',
];
foreach ($schemas as $table => $schema) { Db::execute('CREATE TABLE test_' . $table . ' (' . $schema . ')'); }
Db::name('admin')->insertAll([['id' => 11, 'name' => '合成医助'], ['id' => 13, 'name' => '合成主管']]);
Db::name('system_role')->insert(['id' => 2, 'name' => '医助', 'data_scope' => 4]);
Db::name('admin_role')->insert(['admin_id' => 11, 'role_id' => 2]);
Db::name('system_menu')->insert(['id' => 1, 'perms' => 'tcm.assistantService/view']);
Db::name('system_role_menu')->insert(['role_id' => 2, 'menu_id' => 1]);
Db::name('tcm_diagnosis')->insert(['id' => 101, 'patient_id' => 201, 'assistant_id' => 11]);
$expect(Recipient::resolve($todo) === 13, 'ordinary reminder keeps creator after module installed');
Db::name('assistant_service_job')->insert(['id' => 5, 'diagnosis_id' => 101, 'patient_id' => 201]);
Db::name('assistant_service_action')->insert(['id' => 7, 'todo_id' => 1, 'diagnosis_id' => 101, 'job_id' => 5, 'assignee_id' => 11, 'business_state' => 'pending']);
$expect(Recipient::resolve($todo) === 11, 'module reminder goes to assignee rather than manager creator');
$expect(Recipient::resolve($todo + ['assignee_id' => 99]) === 11, 'caller cannot override stored responsibility');
Db::name('admin')->where('id', 11)->update(['disable' => 1]);
$deny(fn () => Recipient::resolve($todo), 'disabled assignee not notified');
Db::name('admin')->where('id', 11)->update(['disable' => 0]);
Db::name('system_menu')->where('id', 1)->update(['is_disable' => 1]);
$deny(fn () => Recipient::resolve($todo), 'revoked module permission not notified');
Db::name('system_menu')->where('id', 1)->update(['is_disable' => 0]);
Db::name('tcm_diagnosis')->where('id', 101)->update(['assistant_id' => 12]);
$deny(fn () => Recipient::resolve($todo), 'transferred patient not disclosed to prior assignee');
Db::name('tcm_diagnosis')->where('id', 101)->update(['assistant_id' => 11, 'patient_id' => 202]);
$deny(fn () => Recipient::resolve($todo), 'rebound patient not disclosed through old reminder');
Db::name('tcm_diagnosis')->where('id', 101)->update(['patient_id' => 201]);
Db::name('assistant_service_action')->where('id', 7)->update(['business_state' => 'completed']);
$deny(fn () => Recipient::resolve($todo), 'finished action does not send stale reminder');
Db::name('assistant_service_action')->where('id', 7)->update(['business_state' => 'in_progress']);
$expect(Recipient::resolve($todo) === 11, 'in-progress action remains deliverable');
$deny(fn () => Recipient::resolve(array_replace($todo, ['diagnosis_id' => 102])), 'mismatched reminder link rejected');
Db::name('assistant_service_job')->where('id', 5)->delete();
$deny(fn () => Recipient::resolve($todo), 'orphaned module task does not fall back to manager');
Db::name('assistant_service_job')->insert(['id' => 5, 'diagnosis_id' => 101, 'patient_id' => 201,
'payload_json' => json_encode(['context' => ['subject_admin_id' => 11]])]);
Db::name('system_role_menu')->where('role_id', 2)->delete();
$expect(Recipient::resolve($todo) === 11, 'valid target without module menu receives supervisor-assigned reminder');
Db::name('assistant_service_job')->where('id', 5)->update(['payload_json' => json_encode(['context' => ['subject_admin_id' => 12]])]);
$deny(fn () => Recipient::resolve($todo), 'stored subject must match assigned target');
Db::name('assistant_service_job')->where('id', 5)->update(['payload_json' => json_encode(['context' => ['subject_admin_id' => 11]])]);
Db::name('system_role')->insert(['id' => 1, 'name' => '医生', 'data_scope' => 1]);
Db::name('admin_role')->where('admin_id', 11)->update(['role_id' => 1]);
$deny(fn () => Recipient::resolve($todo), 'former assistant with doctor role is not a valid target recipient');
Db::name('admin_role')->where('admin_id', 11)->update(['role_id' => 2]);
Db::name('tcm_diagnosis')->where('id', 101)->update(['assistant_id' => 12]);
$deny(fn () => Recipient::resolve($todo), 'target reminder rechecks direct patient responsibility');
Db::name('tcm_diagnosis')->where('id', 101)->update(['assistant_id' => 11]);
Db::name('system_role')->where('id', 2)->update(['delete_time' => 1]);
$deny(fn () => Recipient::resolve($todo), 'deleted assistant role cannot receive target reminder');
echo 'ASSISTANT_SERVICE_REMINDER_RECIPIENT assertions=' . $checks . ' PASS real_access_orm=1 sends=0' . PHP_EOL;