feat: history and calculate needs for user
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\PacePreference;
|
||||
use App\Enums\WeeklyReviewStatus;
|
||||
use App\Enums\WeightGoal;
|
||||
use App\Models\MealPosts;
|
||||
use App\Models\NutritionPlan;
|
||||
use App\Models\User;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
CarbonImmutable::setTestNow('2026-08-17 10:00:00');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
CarbonImmutable::setTestNow();
|
||||
});
|
||||
|
||||
it('returns an insufficient data review without changing the plan', function () {
|
||||
$user = User::factory()->create();
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$this->getJson('/api/weekly-reviews/current')
|
||||
->assertOk()
|
||||
->assertJsonPath('data.periodStart', '2026-08-10')
|
||||
->assertJsonPath('data.periodEnd', '2026-08-16')
|
||||
->assertJsonPath('data.status', WeeklyReviewStatus::INSUFFICIENT_DATA->value)
|
||||
->assertJsonPath('data.recommendedCalorieAdjustment', 0);
|
||||
|
||||
$this->assertDatabaseCount('nutrition_plans', 1);
|
||||
});
|
||||
|
||||
it('proposes and applies a small confirmed adjustment', function () {
|
||||
$user = User::factory()->create([
|
||||
'weight_goal' => WeightGoal::LOSE_WEIGHT,
|
||||
'pace_preference' => PacePreference::NORMAL,
|
||||
]);
|
||||
$user->weightEntries()->delete();
|
||||
|
||||
foreach ([
|
||||
['2026-08-03 07:00:00', 70.0],
|
||||
['2026-08-07 07:00:00', 69.98],
|
||||
['2026-08-12 07:00:00', 69.95],
|
||||
['2026-08-16 07:00:00', 69.90],
|
||||
] as [$measuredAt, $weightKg]) {
|
||||
$user->weightEntries()->create([
|
||||
'weight_kg' => $weightKg,
|
||||
'measured_at' => $measuredAt,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (range(10, 14) as $day) {
|
||||
MealPosts::factory()->for($user, 'user')->create([
|
||||
'calories' => 2200,
|
||||
'proteins' => 112,
|
||||
'carbs' => 286,
|
||||
'fats' => 61,
|
||||
'eaten_at' => "2026-08-{$day} 12:00:00",
|
||||
]);
|
||||
}
|
||||
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$reviewResponse = $this->getJson('/api/weekly-reviews/current')
|
||||
->assertOk()
|
||||
->assertJsonPath('data.status', WeeklyReviewStatus::ADJUSTMENT_RECOMMENDED->value)
|
||||
->assertJsonPath('data.recommendedCalorieAdjustment', -100);
|
||||
|
||||
$reviewId = $reviewResponse->json('data.id');
|
||||
|
||||
$this->postJson("/api/weekly-reviews/{$reviewId}/accept")
|
||||
->assertCreated()
|
||||
->assertJsonPath('data.source', 'weekly_adjustment');
|
||||
|
||||
$this->assertDatabaseCount('nutrition_plans', 2);
|
||||
$this->assertDatabaseHas('weekly_reviews', [
|
||||
'id' => $reviewId,
|
||||
'recommended_calorie_adjustment' => -100,
|
||||
]);
|
||||
|
||||
expect($user->weeklyReviews()->findOrFail($reviewId)->accepted_at)->not->toBeNull();
|
||||
});
|
||||
|
||||
it('does not allow accepting another users review', function () {
|
||||
$user = User::factory()->create();
|
||||
$otherUser = User::factory()->create();
|
||||
$review = $otherUser->weeklyReviews()->create([
|
||||
'period_start' => '2026-08-10',
|
||||
'period_end' => '2026-08-16',
|
||||
'status' => WeeklyReviewStatus::ADJUSTMENT_RECOMMENDED,
|
||||
'recommended_calorie_adjustment' => -100,
|
||||
'message_code' => 'WEEKLY_REVIEW_ADJUSTMENT',
|
||||
'metrics' => [],
|
||||
'generated_at' => now(),
|
||||
]);
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$this->postJson("/api/weekly-reviews/{$review->id}/accept")->assertNotFound();
|
||||
});
|
||||
|
||||
it('rejects an adjustment generated for a plan that is no longer active', function () {
|
||||
$user = User::factory()->create();
|
||||
$previousPlan = $user->nutritionPlans()->where('is_active', true)->firstOrFail();
|
||||
$review = $user->weeklyReviews()->create([
|
||||
'nutrition_plan_id' => $previousPlan->getKey(),
|
||||
'period_start' => '2026-08-10',
|
||||
'period_end' => '2026-08-16',
|
||||
'status' => WeeklyReviewStatus::ADJUSTMENT_RECOMMENDED,
|
||||
'recommended_calorie_adjustment' => -100,
|
||||
'message_code' => 'WEEKLY_REVIEW_ADJUSTMENT',
|
||||
'metrics' => [],
|
||||
'generated_at' => now(),
|
||||
]);
|
||||
$previousPlan->update([
|
||||
'is_active' => false,
|
||||
'effective_until' => now(),
|
||||
]);
|
||||
NutritionPlan::factory()->for($user)->create([
|
||||
'is_active' => true,
|
||||
'effective_from' => now()->addMinute(),
|
||||
]);
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$this->postJson("/api/weekly-reviews/{$review->id}/accept")
|
||||
->assertStatus(409);
|
||||
|
||||
expect($review->fresh()->accepted_at)->toBeNull();
|
||||
});
|
||||
Reference in New Issue
Block a user