更新
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use app\adminapi\logic\doctor\AppointmentLogic;
|
||||
use app\adminapi\lists\tcm\DiagnosisLists;
|
||||
use app\adminapi\validate\doctor\AppointmentValidate;
|
||||
use app\common\enum\AppointmentTypeEnum;
|
||||
use app\common\model\doctor\Appointment;
|
||||
|
||||
$testApp = new think\App();
|
||||
$testLang = new think\Lang($testApp);
|
||||
think\Validate::maker(static fn (think\Validate $validator) => $validator->setLang($testLang));
|
||||
|
||||
function appointmentTypeExpect(bool $condition, string $message): void
|
||||
{
|
||||
if (!$condition) {
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'id' => 1,
|
||||
'patient_id' => 101,
|
||||
'doctor_id' => 202,
|
||||
'appointment_date' => '2026-09-10',
|
||||
'appointment_time' => '09:30',
|
||||
'period' => 'morning',
|
||||
'channel_source' => 'test',
|
||||
'status' => 1,
|
||||
];
|
||||
|
||||
foreach (['video' => '视频问诊', 'text' => '图文问诊'] as $type => $label) {
|
||||
foreach (['create', 'adminEdit'] as $scene) {
|
||||
$validator = (new AppointmentValidate())->scene($scene);
|
||||
appointmentTypeExpect($validator->check($payload + ['appointment_type' => $type]), "$scene accepts $type");
|
||||
}
|
||||
appointmentTypeExpect(AppointmentTypeEnum::description($type) === $label, "$type label round trip");
|
||||
appointmentTypeExpect(AppointmentTypeEnum::withDefault(['appointment_type' => $type])['appointment_type'] === $type, 'default does not override an explicit choice');
|
||||
}
|
||||
|
||||
$invalidValues = ['', ' ', 'phone', 'Text', ' video ', 'unknown', 0, 1, true, false, null, [], ['text']];
|
||||
foreach ($invalidValues as $value) {
|
||||
foreach (['create', 'adminEdit'] as $scene) {
|
||||
appointmentTypeExpect(!(new AppointmentValidate())->scene($scene)->check($payload + ['appointment_type' => $value]), "$scene rejects " . json_encode($value));
|
||||
}
|
||||
// Invalid requests must be rejected before touching a database, even if called outside the controller.
|
||||
appointmentTypeExpect(AppointmentLogic::create(['appointment_type' => $value]) === false, 'create rejects invalid type before DB');
|
||||
appointmentTypeExpect(AppointmentLogic::adminEdit(['appointment_type' => $value], 0, []) === false, 'edit rejects invalid type before DB');
|
||||
}
|
||||
|
||||
appointmentTypeExpect((new AppointmentValidate())->scene('create')->check($payload), 'legacy create request may omit type');
|
||||
appointmentTypeExpect(AppointmentTypeEnum::withDefault([])['appointment_type'] === 'video', 'omitted create type persists as video');
|
||||
appointmentTypeExpect(!(new AppointmentValidate())->scene('adminEdit')->check($payload), 'edit cannot silently reset an existing text selection');
|
||||
appointmentTypeExpect(AppointmentLogic::adminEdit([], 0, []) === false, 'internal edit also requires explicit type');
|
||||
|
||||
$model = (new ReflectionClass(Appointment::class))->newInstanceWithoutConstructor();
|
||||
foreach ([null, '', ' '] as $legacyEmpty) {
|
||||
appointmentTypeExpect($model->getAppointmentTypeAttr($legacyEmpty) === 'video', 'legacy empty model value uses video');
|
||||
appointmentTypeExpect($model->getAppointmentTypeDescAttr(null, ['appointment_type' => $legacyEmpty]) === '视频问诊', 'legacy empty model label uses video');
|
||||
}
|
||||
appointmentTypeExpect(AppointmentTypeEnum::description('phone') === '电话问诊', 'historical phone records retain accurate labels');
|
||||
|
||||
$filter = (new ReflectionClass(AppointmentLogic::class))->getMethod('filterAppointmentRowByExistingColumns');
|
||||
appointmentTypeExpect($filter->invoke(null, ['appointment_type' => 'text'], ['appointment_type']) === ['appointment_type' => 'text'], 'text is retained in database write payload');
|
||||
try {
|
||||
$filter->invoke(null, ['appointment_type' => 'text'], ['id']);
|
||||
throw new RuntimeException('missing appointment_type column must not silently lose the selected type');
|
||||
} catch (RuntimeException $exception) {
|
||||
appointmentTypeExpect(str_contains($exception->getMessage(), '挂号表缺少 appointment_type'), 'missing schema yields an actionable error');
|
||||
}
|
||||
|
||||
$summary = (new ReflectionClass(DiagnosisLists::class))->getMethod('appendLatestAppointmentSummary');
|
||||
$lists = (new ReflectionClass(DiagnosisLists::class))->newInstanceWithoutConstructor();
|
||||
$row = [];
|
||||
$summary->invokeArgs($lists, [&$row, ['id' => 8, 'appointment_type' => 'text']]);
|
||||
appointmentTypeExpect($row['latest_appointment_id'] === 8 && $row['latest_appointment_type'] === 'text' && $row['latest_appointment_type_desc'] === '图文问诊', 'latest appointment summary keeps its own type');
|
||||
$summary->invokeArgs($lists, [&$row, ['id' => 9, 'appointment_type' => null]]);
|
||||
appointmentTypeExpect($row['latest_appointment_type'] === 'video', 'next legacy appointment does not inherit previous text type');
|
||||
|
||||
echo "Appointment type validation, defaults, legacy labels and summary: OK\n";
|
||||
Reference in New Issue
Block a user