62 lines
5.6 KiB
PHP
62 lines
5.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/** 仅显式授权的15339隔离MySQL及已核实目录;不加载框架/.env,不连接业务库。 */
|
|
$port = (int) getenv('ASSISTANT_SERVICE_TEST_PORT');
|
|
$expectedDirectory = str_replace('\\', '/', (string) getenv('ASSISTANT_SERVICE_TEST_DATADIR'));
|
|
if (getenv('ASSISTANT_SERVICE_TEST_ALLOW_DISPOSABLE') !== '1' || $port !== 15339
|
|
|| $expectedDirectory === '' || !str_contains(strtolower($expectedDirectory), '/.spool/assistant-service-mysql')) {
|
|
throw new RuntimeException('必须显式提供15339隔离测试库端口和项目临时数据目录指纹');
|
|
}
|
|
$pdo = new PDO("mysql:host=127.0.0.1;port={$port};charset=utf8mb4", 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
$actual = str_replace('\\', '/', (string) $pdo->query('SELECT @@datadir')->fetchColumn());
|
|
if (strtolower(rtrim($actual, '/')) !== strtolower(rtrim($expectedDirectory, '/'))) { throw new RuntimeException('数据目录不匹配,拒绝创建测试数据库'); }
|
|
$database = 'daily_contact_test_' . bin2hex(random_bytes(6)); $checks = 0;
|
|
$ok = static function (bool $condition, string $message) use (&$checks): void { if (!$condition) { throw new RuntimeException($message); } $checks++; };
|
|
$sql = preg_replace('/^--.*$/m', '', (string) file_get_contents(dirname(__DIR__) . '/sql/1.9.20261110/01_assistant_service_daily_contact.sql'));
|
|
$migrate = static function () use ($pdo, $sql): void {
|
|
foreach (explode(';', (string) $sql) as $statement) { if (trim($statement) !== '') { $query = $pdo->query($statement); $query->closeCursor(); } }
|
|
};
|
|
$pdo->exec("CREATE DATABASE `{$database}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
|
try {
|
|
$pdo->exec("USE `{$database}`");
|
|
$pdo->exec('CREATE TABLE zyt_assistant_service_action(id BIGINT UNSIGNED PRIMARY KEY,diagnosis_id INT,assignee_id INT,business_state VARCHAR(20),completed_at INT,completion_note VARCHAR(200)) ENGINE=InnoDB');
|
|
$pdo->exec("INSERT INTO zyt_assistant_service_action VALUES(1,101,11,'completed',1234,'历史哨兵')");
|
|
$pdo->exec('CREATE TABLE zyt_tcm_diagnosis_todo(id INT PRIMARY KEY,status INT,notified_at INT) ENGINE=InnoDB');
|
|
$pdo->exec('INSERT INTO zyt_tcm_diagnosis_todo VALUES(1,1,1234)');
|
|
$before = $pdo->query('SELECT * FROM zyt_assistant_service_action')->fetchAll(PDO::FETCH_ASSOC);
|
|
$todos = $pdo->query('SELECT * FROM zyt_tcm_diagnosis_todo')->fetchAll(PDO::FETCH_ASSOC);
|
|
$migrate();
|
|
$columns = $pdo->query('SHOW COLUMNS FROM zyt_assistant_service_action')->fetchAll(PDO::FETCH_ASSOC);
|
|
$columns = array_column($columns, null, 'Field');
|
|
$ok(isset($columns['contact_required'], $columns['completed_by']), '缺少明确联系标记或真实完成操作者字段');
|
|
$ok((string) $columns['contact_required']['Default'] === '0' && (string) $columns['completed_by']['Default'] === '0', '旧动作不应自动推断联系属性或操作者');
|
|
$row = $pdo->query('SELECT * FROM zyt_assistant_service_action WHERE id=1')->fetch(PDO::FETCH_ASSOC);
|
|
$ok((int) $row['contact_required'] === 0 && (int) $row['completed_by'] === 0, '历史动作必须保留未知属性');
|
|
unset($row['contact_required'], $row['completed_by']);
|
|
$ok($row === $before[0], '迁移不应改写历史执行记录');
|
|
$pdo->exec('UPDATE zyt_assistant_service_action SET contact_required=1,completed_by=13 WHERE id=1');
|
|
$insert = $pdo->prepare('INSERT INTO zyt_assistant_service_daily_contact(business_date,assistant_id,diagnosis_id,patient_id,source_type,source_id,source_order_id,reason,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?)');
|
|
$insert->execute(['2026-11-10',11,101,201,'revisit',1,100,'合成到期',1000,1000]);
|
|
$plan = $pdo->query('SELECT * FROM zyt_assistant_service_daily_contact')->fetchAll(PDO::FETCH_ASSOC);
|
|
$migrate(); $migrate();
|
|
$ok($plan === $pdo->query('SELECT * FROM zyt_assistant_service_daily_contact')->fetchAll(PDO::FETCH_ASSOC), '重复迁移不应改写计划');
|
|
$row = $pdo->query('SELECT contact_required,completed_by FROM zyt_assistant_service_action WHERE id=1')->fetch(PDO::FETCH_ASSOC);
|
|
$ok((int) $row['contact_required'] === 1 && (int) $row['completed_by'] === 13, '重复迁移不应覆盖新增字段真实值');
|
|
$ok($todos === $pdo->query('SELECT * FROM zyt_tcm_diagnosis_todo')->fetchAll(PDO::FETCH_ASSOC), '迁移不应改变提醒status或notified_at');
|
|
$duplicate = false;
|
|
try { $insert->execute(['2026-11-10',11,101,201,'revisit',1,100,'重复',1001,1001]); }
|
|
catch (PDOException $e) { $duplicate = $e->getCode() === '23000'; }
|
|
$ok($duplicate, '数据库未保护当日来源幂等');
|
|
foreach ([['2026-11-10',11,101,201,'revisit',1,101], ['2026-11-11',11,101,201,'revisit',1,100], ['2026-11-10',15,101,201,'revisit',1,100], ['2026-11-10',11,101,201,'action',1,0]] as $values) {
|
|
$insert->execute(array_merge($values, ['独立责任/周期',1001,1001]));
|
|
}
|
|
$ok((int) $pdo->query('SELECT COUNT(*) FROM zyt_assistant_service_daily_contact')->fetchColumn() === 5, '新周期、新自然日、新责任医助、另一来源须可独立入计划');
|
|
$indexes = $pdo->query('SHOW INDEX FROM zyt_assistant_service_daily_contact')->fetchAll(PDO::FETCH_ASSOC);
|
|
$ok(in_array('idx_day_cursor', array_column($indexes, 'Key_name'), true) && in_array('idx_day_staff_patient', array_column($indexes, 'Key_name'), true), '缺少日游标或医助患者聚合索引');
|
|
echo 'ASSISTANT_SERVICE_DAILY_CONTACT_MIGRATION assertions=' . $checks . ' PASS mysql=' . $pdo->query('SELECT VERSION()')->fetchColumn() . ' disposable=1 migration_runs=3' . PHP_EOL;
|
|
} finally {
|
|
if (preg_match('/^daily_contact_test_[a-f0-9]{12}$/D', $database)) { $pdo->exec("DROP DATABASE `{$database}`"); }
|
|
}
|