create(); ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, 'year' => 2026, 'month' => 2, ]); $response = $this ->actingAs($user) ->get(route('reports.periods.index', ['current_team' => $user->currentTeam])); $response ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('reports/periods/Index') ->where('periods.0.label', 'Февраль 2026')); }); test('authenticated users can create a report period scoped to their team', function () { $user = User::factory()->create(); $response = $this ->actingAs($user) ->post(route('reports.periods.store', ['current_team' => $user->currentTeam]), [ 'year' => 2026, 'month' => 2, ]); $response->assertRedirect(route('reports.periods.index', ['current_team' => $user->currentTeam])); $this->assertDatabaseHas('report_periods', [ 'team_id' => $user->currentTeam->id, 'year' => 2026, 'month' => 2, 'status' => 'draft', ]); }); test('report periods must be unique within a team', function () { $user = User::factory()->create(); ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, 'year' => 2026, 'month' => 2, ]); $response = $this ->actingAs($user) ->from(route('reports.periods.index', ['current_team' => $user->currentTeam])) ->post(route('reports.periods.store', ['current_team' => $user->currentTeam]), [ 'year' => 2026, 'month' => 2, ]); $response->assertSessionHasErrors('month'); }); test('authenticated users can approve a period', function () { $user = User::factory()->create(); $period = ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, ]); $response = $this ->actingAs($user) ->patch(route('reports.periods.approve', [ 'current_team' => $user->currentTeam, 'report_period' => $period, ])); $response->assertRedirect(route('reports.periods.index', ['current_team' => $user->currentTeam])); expect($period->fresh()->status->value)->toBe('approved'); }); test('approved periods can not be edited through services or medication forms', function () { $user = User::factory()->create(); $providerDepartment = Department::factory()->create(); $recipientDepartment = Department::factory()->create(); $serviceCatalog = ServiceCatalog::factory()->create(); $period = ReportPeriod::factory()->approved()->create([ 'team_id' => $user->currentTeam->id, ]); $this ->actingAs($user) ->post(route('reports.operations.store', ['current_team' => $user->currentTeam]), [ 'report_period_id' => $period->id, 'provider_department_id' => $providerDepartment->id, 'service_catalog_id' => $serviceCatalog->id, 'entries' => [ $recipientDepartment->id => [ 'quantity' => 100, 'unit_price' => 15.50, ], ], ]) ->assertStatus(422); $this ->actingAs($user) ->post(route('reports.medication-expenses.store', ['current_team' => $user->currentTeam]), [ 'report_period_id' => $period->id, 'department_id' => $providerDepartment->id, 'values' => [ 'oms' => [ 'alcohol' => 10, ], ], ]) ->assertStatus(422); }); test('authenticated users can store service entries', function () { $user = User::factory()->create(); $providerDepartment = Department::factory()->create(); $recipientDepartment = Department::factory()->create(); $period = ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, ]); $serviceCatalog = ServiceCatalog::factory()->create([ 'default_price' => 15.50, ]); $response = $this ->actingAs($user) ->post(route('reports.operations.store', ['current_team' => $user->currentTeam]), [ 'report_period_id' => $period->id, 'provider_department_id' => $providerDepartment->id, 'service_catalog_id' => $serviceCatalog->id, 'entries' => [ $recipientDepartment->id => [ 'quantity' => 2471, 'unit_price' => 15.50, ], ], ]); $response->assertRedirect(); $this->assertDatabaseHas('service_entries', [ 'report_period_id' => $period->id, 'service_catalog_id' => $serviceCatalog->id, 'provider_department_id' => $providerDepartment->id, 'recipient_department_id' => $recipientDepartment->id, 'quantity' => 2471.00, 'unit_price' => 15.50, ]); }); test('authenticated users can store medication expense values', function () { $user = User::factory()->create(); $department = Department::factory()->create(); $period = ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, ]); $response = $this ->actingAs($user) ->post(route('reports.medication-expenses.store', ['current_team' => $user->currentTeam]), [ 'report_period_id' => $period->id, 'department_id' => $department->id, 'values' => [ 'oms' => [ 'alcohol' => 120.5, 'dressing' => 30.75, ], 'budget' => [ 'medicines' => 80, ], ], ]); $response->assertRedirect(); $row = MedicationExpenseRow::query() ->where('report_period_id', $period->id) ->where('department_id', $department->id) ->first(); expect($row)->not->toBeNull(); $this->assertDatabaseHas('medication_expense_values', [ 'medication_expense_row_id' => $row->id, 'funding_source' => 'oms', 'expense_category' => 'alcohol', 'amount' => 120.50, ]); }); test('report pages are isolated per team', function () { $user = User::factory()->create(); $otherTeam = Team::factory()->create(); $user->teams()->attach($otherTeam, ['role' => TeamRole::Member->value]); ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, 'year' => 2026, 'month' => 2, ]); ReportPeriod::factory()->create([ 'team_id' => $otherTeam->id, 'year' => 2026, 'month' => 3, ]); $response = $this ->actingAs($user) ->get(route('reports.periods.index', ['current_team' => $user->currentTeam])); $response->assertInertia(fn (Assert $page) => $page ->where('periods', fn (array $periods) => count($periods) === 1 && $periods[0]['label'] === 'Февраль 2026')); }); test('non team members can not access report routes', function () { $user = User::factory()->create(); $foreignTeam = Team::factory()->create(); $this->actingAs($user) ->get(route('reports.periods.index', ['current_team' => $foreignTeam])) ->assertForbidden(); }); test('analysis page renders data from services and medication modules', function () { $user = User::factory()->create(); $profile = DepartmentProfile::factory()->create([ 'name' => 'Клинический профиль', ]); $department = Department::factory()->create([ 'name' => 'Гематологическое', 'department_profile_id' => $profile->id, ]); $period = ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, 'year' => 2026, 'month' => 2, ]); $serviceCatalog = ServiceCatalog::factory()->create([ 'code' => 'kdl_plan', 'name' => 'КДЛ плановая служба', 'sort_order' => 1, 'default_price' => 15.50, ]); $providerDepartment = Department::factory()->create([ 'name' => 'Яяя лаборатория', ]); ServiceEntry::factory()->create([ 'report_period_id' => $period->id, 'service_catalog_id' => $serviceCatalog->id, 'provider_department_id' => $providerDepartment->id, 'recipient_department_id' => $department->id, 'quantity' => 2471, 'unit_price' => 15.50, ]); $row = MedicationExpenseRow::factory()->create([ 'report_period_id' => $period->id, 'department_id' => $department->id, ]); MedicationExpenseValue::factory()->create([ 'medication_expense_row_id' => $row->id, 'funding_source' => 'oms', 'expense_category' => 'medicines', 'amount' => 1000, ]); MedicationExpenseValue::factory()->create([ 'medication_expense_row_id' => $row->id, 'funding_source' => 'budget', 'expense_category' => 'dressing', 'amount' => 150, ]); $response = $this ->actingAs($user) ->get(route('reports.analysis.index', [ 'current_team' => $user->currentTeam, 'period' => $period->id, ])); $response ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('reports/analysis/Index') ->where('period.label', 'Февраль 2026') ->where('rows.0.department.name', 'Гематологическое') ->where('rows.0.services.kdl_plan.quantity', 2471.0) ->where('rows.0.services.kdl_plan.amount', 38300.5) ->where('rows.0.serviceTotals.total_amount', 38300.5) ->where('rows.0.expense.total_expense', 1150.0) ->where('rows.0.expense.without_budget_total', 1000.0)); }); test('operations and medication entry pages render for authenticated team members', function () { $user = User::factory()->create(); $period = ReportPeriod::factory()->create([ 'team_id' => $user->currentTeam->id, ]); $department = Department::factory()->create(); ServiceCatalog::factory()->create(); $this->actingAs($user) ->get(route('reports.operations.index', [ 'current_team' => $user->currentTeam, 'period' => $period->id, 'provider_department' => $department->id, ])) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('reports/operations/Index')); $this->actingAs($user) ->get(route('reports.medication-expenses.index', [ 'current_team' => $user->currentTeam, 'period' => $period->id, 'department' => $department->id, ])) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('reports/medication-expenses/Index')); });