Files
onboard/tests/Feature/ReportPatientsServicesTest.php
2026-04-24 16:46:10 +09:00

1023 lines
37 KiB
PHP

<?php
use App\Models\Department;
use App\Models\User;
use App\Services\DateRange;
use App\Services\DateRangeService;
use App\Services\PatientService;
use App\Services\ReportService;
use App\Services\SnapshotService;
use App\Services\UnifiedPatientService;
use Carbon\Carbon;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
beforeEach(function () {
Carbon::setTestNow(Carbon::parse('2026-04-09 08:00:00', 'Asia/Yakutsk'));
foreach ([
'stt_stationarbranch',
'reports',
'medical_history_snapshots',
'department_patients',
'observation_patients',
'stt_medicalhistory',
'stt_migrationpatient',
'stt_surgicaloperation',
'stt_operationpurpose',
'stt_diagnos',
'oms_mkb',
'oms_servicemedical',
] as $table) {
Schema::dropIfExists($table);
}
Schema::create('stt_stationarbranch', function (Blueprint $table) {
$table->integer('StationarBranchID')->primary();
$table->integer('rf_DepartmentID');
});
Schema::create('reports', function (Blueprint $table) {
$table->integer('report_id')->primary();
$table->date('created_at');
$table->dateTime('sent_at')->nullable();
$table->integer('rf_department_id');
$table->integer('rf_user_id')->nullable();
$table->integer('rf_lpudoctor_id')->nullable();
});
Schema::create('medical_history_snapshots', function (Blueprint $table) {
$table->integer('medical_history_snapshot_id')->primary();
$table->integer('rf_report_id');
$table->integer('rf_medicalhistory_id')->nullable();
$table->integer('rf_department_patient_id')->nullable();
$table->string('patient_type');
$table->string('patient_uid')->nullable();
$table->string('patient_source_type')->nullable();
$table->string('patient_kind')->nullable();
$table->string('full_name')->nullable();
$table->date('birth_date')->nullable();
$table->string('diagnosis_code')->nullable();
$table->string('diagnosis_name')->nullable();
$table->dateTime('admitted_at')->nullable();
$table->string('outcome_type')->nullable();
$table->dateTime('outcome_at')->nullable();
$table->boolean('is_manual')->default(false);
$table->timestamps();
});
Schema::create('department_patients', function (Blueprint $table) {
$table->integer('department_patient_id')->primary();
$table->integer('rf_department_id');
$table->string('source_type')->default('manual');
$table->integer('rf_medicalhistory_id')->nullable();
$table->string('full_name');
$table->date('birth_date')->nullable();
$table->string('patient_kind')->nullable();
$table->string('diagnosis_code')->nullable();
$table->string('diagnosis_name')->nullable();
$table->dateTime('admitted_at')->nullable();
$table->boolean('is_current')->default(true);
$table->string('outcome_type')->nullable();
$table->dateTime('outcome_at')->nullable();
$table->integer('created_by')->nullable();
$table->dateTime('linked_to_mis_at')->nullable();
$table->timestamps();
});
Schema::create('observation_patients', function (Blueprint $table) {
$table->integer('observation_patient_id')->primary();
$table->integer('rf_report_id')->nullable();
$table->integer('rf_department_id')->nullable();
$table->integer('rf_medicalhistory_id')->nullable();
$table->integer('rf_department_patient_id')->nullable();
$table->text('comment')->nullable();
});
Schema::create('stt_medicalhistory', function (Blueprint $table) {
$table->integer('MedicalHistoryID')->primary();
$table->integer('rf_EmerSignID')->nullable();
$table->integer('rf_kl_VisitResultID')->default(0);
$table->dateTime('DateRecipient')->nullable();
$table->dateTime('DateExtract')->nullable();
});
Schema::create('stt_migrationpatient', function (Blueprint $table) {
$table->integer('MigrationPatientID')->primary();
$table->integer('rf_MedicalHistoryID');
$table->integer('rf_StationarBranchID');
$table->integer('rf_kl_VisitResultID')->default(0);
$table->integer('rf_kl_StatCureResultID')->default(0);
$table->dateTime('DateIngoing')->nullable();
$table->dateTime('DateOut')->nullable();
});
Schema::create('stt_surgicaloperation', function (Blueprint $table) {
$table->integer('SurgicalOperationID')->primary();
$table->integer('rf_MedicalHistoryID')->nullable();
$table->integer('rf_StationarBranchID')->nullable();
$table->integer('rf_kl_ServiceMedicalID')->nullable();
$table->dateTime('Date')->nullable();
});
Schema::create('stt_operationpurpose', function (Blueprint $table) {
$table->integer('OperationPurposeID')->primary();
$table->integer('rf_SurgicalOperationID');
$table->integer('rf_OperationStatusID');
});
Schema::create('stt_diagnos', function (Blueprint $table) {
$table->integer('DiagnosID')->primary();
$table->integer('rf_MigrationPatientID')->nullable();
$table->integer('rf_DiagnosTypeID')->nullable();
$table->integer('rf_MKBID')->nullable();
});
Schema::create('oms_mkb', function (Blueprint $table) {
$table->integer('MKBID')->primary();
$table->string('DS')->nullable();
$table->string('NAME')->nullable();
});
Schema::create('oms_servicemedical', function (Blueprint $table) {
$table->integer('ServiceMedicalID')->primary();
});
});
afterEach(function () {
Carbon::setTestNow();
\Mockery::close();
});
function reportDateRange(string $start, string $end): DateRange
{
return new DateRange(
startDate: Carbon::parse($start, 'Asia/Yakutsk'),
endDate: Carbon::parse($end, 'Asia/Yakutsk'),
startDateRaw: $start,
endDateRaw: $end,
isOneDay: true,
);
}
function makeUser(bool $isHead = false, bool $isAdmin = false): User
{
$user = new class extends User
{
public bool $head = false;
public bool $admin = false;
public function isHeadOfDepartment()
{
return $this->head;
}
public function isAdmin()
{
return $this->admin;
}
};
$user->head = $isHead;
$user->admin = $isAdmin;
return $user;
}
function makeUnifiedPatientService(?PatientService $patientService = null): UnifiedPatientService
{
return new UnifiedPatientService($patientService ?? app(PatientService::class));
}
it('returns only today recipients and current in-department patients for plan and emergency', function () {
$service = app(PatientService::class);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
DB::table('stt_medicalhistory')->insert([
[
'MedicalHistoryID' => 1,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 2,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-07 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 3,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 1,
'DateRecipient' => '2026-04-08 09:00:00',
'DateExtract' => '2026-04-08 22:00:00',
],
[
'MedicalHistoryID' => 4,
'rf_EmerSignID' => 2,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 10:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 5,
'rf_EmerSignID' => 2,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-06 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 6,
'rf_EmerSignID' => 2,
'rf_kl_VisitResultID' => 1,
'DateRecipient' => '2026-04-08 11:00:00',
'DateExtract' => '2026-04-08 23:00:00',
],
[
'MedicalHistoryID' => 7,
'rf_EmerSignID' => 4,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 12:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
]);
DB::table('stt_migrationpatient')->insert([
[
'MigrationPatientID' => 1,
'rf_MedicalHistoryID' => 1,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
[
'MigrationPatientID' => 2,
'rf_MedicalHistoryID' => 2,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-07 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
[
'MigrationPatientID' => 3,
'rf_MedicalHistoryID' => 3,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 1,
'rf_kl_StatCureResultID' => 1,
'DateIngoing' => '2026-04-08 09:00:00',
'DateOut' => '2026-04-08 22:00:00',
],
[
'MigrationPatientID' => 4,
'rf_MedicalHistoryID' => 4,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 10:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
[
'MigrationPatientID' => 5,
'rf_MedicalHistoryID' => 5,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-06 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
[
'MigrationPatientID' => 6,
'rf_MedicalHistoryID' => 6,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 1,
'rf_kl_StatCureResultID' => 1,
'DateIngoing' => '2026-04-08 11:00:00',
'DateOut' => '2026-04-08 23:00:00',
],
[
'MigrationPatientID' => 7,
'rf_MedicalHistoryID' => 7,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 12:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
]);
$planPatients = $service->getPlanOrEmergencyPatients('plan', false, 10, $dateRange, false, false, true);
$emergencyPatients = $service->getPlanOrEmergencyPatients('emergency', false, 10, $dateRange, false, false, true);
expect($planPatients->pluck('MedicalHistoryID')->all())->toBe([3, 1, 2])
->and($planPatients->where('MedicalHistoryID', 1)->first()->is_recipient_today)->toBeTrue()
->and($planPatients->where('MedicalHistoryID', 2)->first()->is_recipient_today)->toBeFalse()
->and($planPatients->where('MedicalHistoryID', 3)->first()->is_recipient_today)->toBeTrue()
->and($service->getPatientsCountWithCurrent('plan', false, 10, $dateRange))->toBe(3)
->and($emergencyPatients->pluck('MedicalHistoryID')->all())->toBe([7, 6, 4, 5])
->and($emergencyPatients->where('MedicalHistoryID', 6)->first()->is_recipient_today)->toBeTrue()
->and($service->getPatientsCountWithCurrent('emergency', false, 10, $dateRange))->toBe(4);
});
it('treats 2222-01-01 as current hospitalization sentinel', function () {
$service = app(PatientService::class);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
DB::table('stt_medicalhistory')->insert([
[
'MedicalHistoryID' => 31,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '2222-01-01 00:00:00',
],
]);
DB::table('stt_migrationpatient')->insert([
[
'MigrationPatientID' => 31,
'rf_MedicalHistoryID' => 31,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
]);
$patients = $service->getPlanOrEmergencyPatients('plan', false, 10, $dateRange, false, false, true);
expect($patients->pluck('MedicalHistoryID')->all())->toBe([31])
->and($service->getPatientsCountWithCurrent('plan', false, 10, $dateRange))->toBe(1);
});
it('uses snapshots for head on current-day plan requests', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser(isHead: true);
$expected = collect([(object) ['MedicalHistoryID' => 1]]);
$patientService = \Mockery::mock(PatientService::class);
$snapshotService = \Mockery::mock(SnapshotService::class);
$snapshotService
->shouldReceive('getPatientsFromOneDayCurrentSnapshots')
->once()
->with('plan', [], false, [])
->andReturn($expected);
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService($patientService),
$patientService,
$snapshotService,
\Mockery::mock(\App\Services\StatisticsService::class)
);
expect($service->getPatientsByStatus($department, $user, 'plan', $dateRange))->toBe($expected);
});
it('uses snapshots for historical head plan requests and counts unique snapshot patients', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('reports')->insert([
'report_id' => 77,
'created_at' => '2026-04-08',
'sent_at' => '2026-04-08 06:00:00',
'rf_department_id' => 1,
'rf_user_id' => 1,
'rf_lpudoctor_id' => 1,
]);
DB::table('medical_history_snapshots')->insert([
[
'medical_history_snapshot_id' => 1,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 10,
'patient_type' => 'plan',
'patient_uid' => 'mis:10',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 10',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 2,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 10,
'patient_type' => 'plan',
'patient_uid' => 'mis:10',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 10',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 3,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 11,
'patient_type' => 'plan',
'patient_uid' => 'mis:11',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 11',
'created_at' => now(),
'updated_at' => now(),
],
]);
$dateRange = new DateRange(
startDate: Carbon::parse('2026-04-07 06:00:00', 'Asia/Yakutsk'),
endDate: Carbon::parse('2026-04-08 06:00:00', 'Asia/Yakutsk'),
startDateRaw: '2026-04-07 06:00:00',
endDateRaw: '2026-04-08 06:00:00',
isOneDay: false,
);
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser(isHead: true);
$expected = collect([(object) ['MedicalHistoryID' => 10]]);
$patientService = \Mockery::mock(PatientService::class);
$snapshotService = \Mockery::mock(SnapshotService::class);
$snapshotService
->shouldReceive('getPatientsFromSnapshots')
->once()
->with('plan', [77], 10, false, true, [77])
->andReturn($expected);
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService($patientService),
$patientService,
$snapshotService,
\Mockery::mock(\App\Services\StatisticsService::class)
);
expect($service->getPatientsByStatus($department, $user, 'plan', $dateRange))->toBe($expected)
->and($service->getPatientsCountByStatus($department, $user, 'plan', $dateRange))->toBe(2);
});
it('filters historical head plan snapshots by latest report and marks only latest recipients', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('reports')->insert([
[
'report_id' => 76,
'created_at' => '2026-04-07',
'sent_at' => '2026-04-07 06:00:00',
'rf_department_id' => 1,
'rf_user_id' => 1,
'rf_lpudoctor_id' => 1,
],
[
'report_id' => 77,
'created_at' => '2026-04-08',
'sent_at' => '2026-04-08 06:00:00',
'rf_department_id' => 1,
'rf_user_id' => 1,
'rf_lpudoctor_id' => 1,
],
]);
DB::table('stt_medicalhistory')->insert([
[
'MedicalHistoryID' => 10,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 1,
'DateRecipient' => '2026-04-07 08:00:00',
'DateExtract' => '2026-04-08 12:00:00',
],
[
'MedicalHistoryID' => 11,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-07 10:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 12,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
]);
DB::table('medical_history_snapshots')->insert([
[
'medical_history_snapshot_id' => 1,
'rf_report_id' => 76,
'rf_medicalhistory_id' => 10,
'patient_type' => 'plan',
'patient_uid' => 'mis:10',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 10',
'admitted_at' => '2026-04-07 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 2,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 11,
'patient_type' => 'plan',
'patient_uid' => 'mis:11',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 11',
'admitted_at' => '2026-04-07 10:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 3,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 12,
'patient_type' => 'plan',
'patient_uid' => 'mis:12',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 12',
'admitted_at' => '2026-04-08 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 4,
'rf_report_id' => 77,
'rf_medicalhistory_id' => 12,
'patient_type' => 'recipient',
'patient_uid' => 'mis:12',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 12',
'admitted_at' => '2026-04-08 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
]);
$dateRange = new DateRange(
startDate: Carbon::parse('2026-04-07 06:00:00', 'Asia/Yakutsk'),
endDate: Carbon::parse('2026-04-08 06:00:00', 'Asia/Yakutsk'),
startDateRaw: '2026-04-07 06:00:00',
endDateRaw: '2026-04-08 06:00:00',
isOneDay: false,
);
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser(isHead: true);
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class)),
\Mockery::mock(\App\Services\StatisticsService::class)
);
$patients = $service->getPatientsByStatus($department, $user, 'plan', $dateRange);
expect($patients->pluck('medicalHistoryId')->all())->toBe([12, 11])
->and($patients->firstWhere('medicalHistoryId', 12)->isRecipientToday)->toBeTrue()
->and($patients->firstWhere('medicalHistoryId', 11)->isRecipientToday)->toBeFalse()
->and($service->getPatientsCountByStatus($department, $user, 'plan', $dateRange))->toBe(2);
});
it('uses current snapshots for head one-day plan list and marks recipients separately', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('reports')->insert([
'report_id' => 88,
'created_at' => '2026-04-09',
'sent_at' => '2026-04-09 06:00:00',
'rf_department_id' => 1,
'rf_user_id' => 1,
'rf_lpudoctor_id' => 1,
]);
DB::table('stt_medicalhistory')->insert([
[
'MedicalHistoryID' => 21,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 22,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-07 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
[
'MedicalHistoryID' => 23,
'rf_EmerSignID' => 2,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 09:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
]);
DB::table('medical_history_snapshots')->insert([
[
'medical_history_snapshot_id' => 10,
'rf_report_id' => 88,
'rf_medicalhistory_id' => 21,
'patient_type' => 'current',
'patient_uid' => 'mis:21',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 21',
'admitted_at' => '2026-04-08 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 11,
'rf_report_id' => 88,
'rf_medicalhistory_id' => 22,
'patient_type' => 'current',
'patient_uid' => 'mis:22',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 22',
'admitted_at' => '2026-04-07 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 12,
'rf_report_id' => 88,
'rf_medicalhistory_id' => 23,
'patient_type' => 'current',
'patient_uid' => 'mis:23',
'patient_source_type' => 'mis',
'patient_kind' => 'emergency',
'full_name' => 'Patient 23',
'admitted_at' => '2026-04-08 09:00:00',
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 13,
'rf_report_id' => 88,
'rf_medicalhistory_id' => 21,
'patient_type' => 'recipient',
'patient_uid' => 'mis:21',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Patient 21',
'admitted_at' => '2026-04-08 08:00:00',
'created_at' => now(),
'updated_at' => now(),
],
]);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$service = new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class));
$patients = $service->getPatientsFromOneDayCurrentSnapshots('plan', [88], false, [88]);
expect($patients->pluck('medicalHistoryId')->all())->toBe([21, 22])
->and($patients->firstWhere('medicalHistoryId', 21)->isRecipientToday)->toBeTrue()
->and($patients->firstWhere('medicalHistoryId', 22)->isRecipientToday)->toBeFalse()
->and($service->getPatientsFromOneDayCurrentSnapshots('plan', [88], false, [88])->count())->toBe(2);
});
it('separates special contingent from mis lists while keeping it in aggregate live counters', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('department_patients')->insert([
[
'department_patient_id' => 501,
'rf_department_id' => 1,
'source_type' => 'special',
'full_name' => 'Special Plan Patient',
'birth_date' => '1990-01-01',
'patient_kind' => 'plan',
'admitted_at' => '2026-04-08 08:00:00',
'is_current' => true,
'created_at' => now(),
'updated_at' => now(),
],
]);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser();
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class)),
\Mockery::mock(\App\Services\StatisticsService::class)
);
expect($service->getPatientsByStatus($department, $user, 'mis-plan', $dateRange)->pluck('id')->all())->toBe([])
->and($service->getPatientsCountByStatus($department, $user, 'mis-plan', $dateRange))->toBe(0)
->and($service->getPatientsByStatus($department, $user, 'special-plan', $dateRange)->pluck('id')->all())->toBe(['manual:501'])
->and($service->getPatientsCountByStatus($department, $user, 'special-plan', $dateRange))->toBe(1)
->and($service->getPatientsByStatus($department, $user, 'plan', $dateRange)->pluck('id')->all())->toBe(['manual:501'])
->and($service->getPatientsCountByStatus($department, $user, 'plan', $dateRange))->toBe(1);
});
it('separates special contingent from mis lists in snapshot mode', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('reports')->insert([
'report_id' => 91,
'created_at' => '2026-04-08',
'sent_at' => '2026-04-08 06:00:00',
'rf_department_id' => 1,
'rf_user_id' => 1,
'rf_lpudoctor_id' => 1,
]);
DB::table('medical_history_snapshots')->insert([
[
'medical_history_snapshot_id' => 201,
'rf_report_id' => 91,
'rf_medicalhistory_id' => 10,
'patient_type' => 'plan',
'patient_uid' => 'mis:10',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Mis Patient',
'admitted_at' => '2026-04-08 08:00:00',
'is_manual' => false,
'created_at' => now(),
'updated_at' => now(),
],
[
'medical_history_snapshot_id' => 202,
'rf_report_id' => 91,
'rf_department_patient_id' => 601,
'patient_type' => 'plan',
'patient_uid' => 'manual:601',
'patient_source_type' => 'special',
'patient_kind' => 'plan',
'full_name' => 'Special Patient',
'admitted_at' => '2026-04-08 09:00:00',
'is_manual' => true,
'created_at' => now(),
'updated_at' => now(),
],
]);
$dateRange = new DateRange(
startDate: Carbon::parse('2026-04-07 06:00:00', 'Asia/Yakutsk'),
endDate: Carbon::parse('2026-04-08 06:00:00', 'Asia/Yakutsk'),
startDateRaw: '2026-04-07 06:00:00',
endDateRaw: '2026-04-08 06:00:00',
isOneDay: false,
);
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser(isHead: true);
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class)),
\Mockery::mock(\App\Services\StatisticsService::class)
);
expect($service->getPatientsByStatus($department, $user, 'mis-plan', $dateRange)->pluck('id')->all())->toBe(['mis:10'])
->and($service->getPatientsCountByStatus($department, $user, 'mis-plan', $dateRange))->toBe(1)
->and($service->getPatientsByStatus($department, $user, 'special-plan', $dateRange)->pluck('id')->all())->toBe(['manual:601'])
->and($service->getPatientsCountByStatus($department, $user, 'special-plan', $dateRange))->toBe(1)
->and($service->getPatientsByStatus($department, $user, 'plan', $dateRange)->pluck('id')->all())->toBe(['manual:601', 'mis:10'])
->and($service->getPatientsCountByStatus($department, $user, 'plan', $dateRange))->toBe(2);
});
it('keeps operations for snapshot patients with medical history ids', function () {
DB::table('medical_history_snapshots')->insert([
[
'medical_history_snapshot_id' => 401,
'rf_report_id' => 91,
'rf_medicalhistory_id' => 10,
'patient_type' => 'plan',
'patient_uid' => 'mis:10',
'patient_source_type' => 'mis',
'patient_kind' => 'plan',
'full_name' => 'Mis Patient',
'admitted_at' => '2026-04-08 08:00:00',
'is_manual' => false,
'created_at' => now(),
'updated_at' => now(),
],
]);
DB::table('stt_medicalhistory')->insert([
'MedicalHistoryID' => 10,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
]);
DB::table('stt_surgicaloperation')->insert([
'SurgicalOperationID' => 501,
'rf_MedicalHistoryID' => 10,
'rf_StationarBranchID' => 10,
'rf_kl_ServiceMedicalID' => 77,
'Date' => '2026-04-08 10:00:00',
]);
DB::table('stt_operationpurpose')->insert([
'OperationPurposeID' => 501,
'rf_SurgicalOperationID' => 501,
'rf_OperationStatusID' => 3,
]);
DB::table('oms_servicemedical')->insert([
'ServiceMedicalID' => 77,
]);
$service = new SnapshotService(
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
app(DateRangeService::class)
);
$patients = $service->getPatientsFromSnapshots('plan', [91]);
expect($patients)->toHaveCount(1)
->and($patients->first()->operations)->toHaveCount(1);
});
it('keeps operations for replica patients on live report requests', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('stt_medicalhistory')->insert([
[
'MedicalHistoryID' => 41,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
],
]);
DB::table('stt_migrationpatient')->insert([
[
'MigrationPatientID' => 41,
'rf_MedicalHistoryID' => 41,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
],
]);
DB::table('stt_surgicaloperation')->insert([
'SurgicalOperationID' => 601,
'rf_MedicalHistoryID' => 41,
'rf_StationarBranchID' => 10,
'rf_kl_ServiceMedicalID' => 88,
'Date' => '2026-04-08 11:00:00',
]);
DB::table('stt_operationpurpose')->insert([
'OperationPurposeID' => 601,
'rf_SurgicalOperationID' => 601,
'rf_OperationStatusID' => 3,
]);
DB::table('oms_servicemedical')->insert([
'ServiceMedicalID' => 88,
]);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser();
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class)),
\Mockery::mock(\App\Services\StatisticsService::class)
);
$patients = $service->getPatientsByStatus($department, $user, 'mis-plan', $dateRange);
expect($patients)->toHaveCount(1)
->and($patients->first()->medicalHistoryId)->toBe(41)
->and($patients->first()->operations)->toHaveCount(1);
});
it('keeps completed operations in patient rows even if operation date is outside report range', function () {
DB::table('stt_stationarbranch')->insert([
'StationarBranchID' => 10,
'rf_DepartmentID' => 100,
]);
DB::table('stt_medicalhistory')->insert([
'MedicalHistoryID' => 42,
'rf_EmerSignID' => 1,
'rf_kl_VisitResultID' => 0,
'DateRecipient' => '2026-04-08 08:00:00',
'DateExtract' => '1900-01-01 00:00:00',
]);
DB::table('stt_migrationpatient')->insert([
'MigrationPatientID' => 42,
'rf_MedicalHistoryID' => 42,
'rf_StationarBranchID' => 10,
'rf_kl_VisitResultID' => 0,
'rf_kl_StatCureResultID' => 0,
'DateIngoing' => '2026-04-08 08:00:00',
'DateOut' => '1900-01-01 00:00:00',
]);
DB::table('stt_surgicaloperation')->insert([
'SurgicalOperationID' => 602,
'rf_MedicalHistoryID' => 42,
'rf_StationarBranchID' => 10,
'rf_kl_ServiceMedicalID' => 89,
'Date' => '2026-04-07 12:00:00',
]);
DB::table('stt_operationpurpose')->insert([
'OperationPurposeID' => 602,
'rf_SurgicalOperationID' => 602,
'rf_OperationStatusID' => 3,
]);
DB::table('oms_servicemedical')->insert([
'ServiceMedicalID' => 89,
]);
$dateRange = reportDateRange('2026-04-08 06:00:00', '2026-04-09 06:00:00');
$department = new Department;
$department->department_id = 1;
$department->rf_mis_department_id = 100;
$user = makeUser();
$service = new ReportService(
app(DateRangeService::class),
makeUnifiedPatientService(app(PatientService::class)),
app(PatientService::class),
new SnapshotService(makeUnifiedPatientService(app(PatientService::class)), app(PatientService::class), app(DateRangeService::class)),
\Mockery::mock(\App\Services\StatisticsService::class)
);
$patients = $service->getPatientsByStatus($department, $user, 'mis-plan', $dateRange);
expect($patients)->toHaveCount(1)
->and($patients->first()->medicalHistoryId)->toBe(42)
->and($patients->first()->operations)->toHaveCount(1);
});