diff --git a/app/Console/Commands/GenerateBudgetPeriods.php b/app/Console/Commands/GenerateBudgetPeriods.php index 69912369..e94a8594 100644 --- a/app/Console/Commands/GenerateBudgetPeriods.php +++ b/app/Console/Commands/GenerateBudgetPeriods.php @@ -36,18 +36,18 @@ class GenerateBudgetPeriods extends Command } $completedPeriods = BudgetPeriod::where('budget_id', $budget->id) - ->where('end_date', '<', now()->subDay()) + ->where('end_date', '<', today()) ->get(); foreach ($completedPeriods as $period) { - if ($period->end_date < now()->subDay()) { + if ($period->end_date < today()) { $this->budgetPeriodService->closePeriod($period); $closedCount++; } } $futurePeriods = $budget->periods() - ->where('start_date', '>', now()) + ->where('start_date', '>', today()) ->count(); if ($futurePeriods < 2) { diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index 0b82f35f..e1996418 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -25,8 +25,8 @@ class BudgetController extends Controller $budgets = $user ->budgets() ->with(['category', 'label', 'periods' => function ($query) { - $query->where('start_date', '<=', now()) - ->where('end_date', '>=', now()) + $query->where('start_date', '<=', today()) + ->where('end_date', '>=', today()) ->with(['budgetTransactions']); }]) ->get(); diff --git a/app/Models/Budget.php b/app/Models/Budget.php index 0a023cf6..66569b95 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -59,8 +59,8 @@ class Budget extends Model public function getCurrentPeriod(): ?BudgetPeriod { return $this->periods() - ->where('start_date', '<=', now()) - ->where('end_date', '>=', now()) + ->where('start_date', '<=', today()) + ->where('end_date', '>=', today()) ->first(); } } diff --git a/tests/Feature/BudgetPeriodDateTest.php b/tests/Feature/BudgetPeriodDateTest.php new file mode 100644 index 00000000..dbd274ac --- /dev/null +++ b/tests/Feature/BudgetPeriodDateTest.php @@ -0,0 +1,121 @@ +create(['onboarded_at' => now()]); + $budget = Budget::factory()->create([ + 'user_id' => $user->id, + 'period_type' => BudgetPeriodType::Monthly, + 'period_start_day' => 1, + ]); + + BudgetPeriod::factory()->create([ + 'budget_id' => $budget->id, + 'start_date' => '2026-01-01', + 'end_date' => '2026-01-31', + 'allocated_amount' => 100000, + ]); + + $currentPeriod = $budget->getCurrentPeriod(); + + expect($currentPeriod)->not->toBeNull(); + expect($currentPeriod->start_date->toDateString())->toBe('2026-01-01'); + expect($currentPeriod->end_date->toDateString())->toBe('2026-01-31'); + + Carbon::setTestNow(); +}); + +test('getCurrentPeriod finds period on its first day regardless of time', function () { + Carbon::setTestNow(Carbon::parse('2026-01-01 23:59:59')); + + $user = User::factory()->create(['onboarded_at' => now()]); + $budget = Budget::factory()->create([ + 'user_id' => $user->id, + 'period_type' => BudgetPeriodType::Monthly, + 'period_start_day' => 1, + ]); + + BudgetPeriod::factory()->create([ + 'budget_id' => $budget->id, + 'start_date' => '2026-01-01', + 'end_date' => '2026-01-31', + 'allocated_amount' => 100000, + ]); + + $currentPeriod = $budget->getCurrentPeriod(); + + expect($currentPeriod)->not->toBeNull(); + expect($currentPeriod->start_date->toDateString())->toBe('2026-01-01'); + + Carbon::setTestNow(); +}); + +test('budget index loads current period on last day of period', function () { + Carbon::setTestNow(Carbon::parse('2026-01-31 18:00:00')); + + $user = User::factory()->create(['onboarded_at' => now()]); + Feature::for($user)->activate('budgets'); + + $budget = Budget::factory()->create([ + 'user_id' => $user->id, + 'period_type' => BudgetPeriodType::Monthly, + 'period_start_day' => 1, + ]); + + BudgetPeriod::factory()->create([ + 'budget_id' => $budget->id, + 'start_date' => '2026-01-01', + 'end_date' => '2026-01-31', + 'allocated_amount' => 100000, + ]); + + $response = $this->actingAs($user)->get('/budgets'); + + $response->assertOk(); + $response->assertInertia(fn ($page) => $page + ->component('budgets/index') + ->has('budgets', 1) + ->where('budgets.0.periods', fn ($periods) => count($periods) === 1) + ); + + Carbon::setTestNow(); +}); + +test('budget show finds current period on last day of period', function () { + Carbon::setTestNow(Carbon::parse('2026-01-31 20:00:00')); + + $user = User::factory()->create(['onboarded_at' => now()]); + Feature::for($user)->activate('budgets'); + + $budget = Budget::factory()->create([ + 'user_id' => $user->id, + 'period_type' => BudgetPeriodType::Monthly, + 'period_start_day' => 1, + ]); + + BudgetPeriod::factory()->create([ + 'budget_id' => $budget->id, + 'start_date' => '2026-01-01', + 'end_date' => '2026-01-31', + 'allocated_amount' => 100000, + ]); + + $response = $this->actingAs($user)->get("/budgets/{$budget->id}"); + + $response->assertOk(); + $response->assertInertia(fn ($page) => $page + ->component('budgets/show') + ->has('currentPeriod') + ->where('currentPeriod.start_date', '2026-01-01T00:00:00.000000Z') + ); + + Carbon::setTestNow(); +});