1022 lines
37 KiB
PHP
1022 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\Collection;
|
|
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);
|
|
});
|