80 lines
3.1 KiB
PHP
80 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Actions;
|
|
|
|
use App\Enums\NutritionPlanSource;
|
|
use App\Enums\WeeklyReviewStatus;
|
|
use App\Models\NutritionPlan;
|
|
use App\Models\WeeklyReview;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class AcceptWeeklyReviewAdjustment
|
|
{
|
|
public function execute(WeeklyReview $weeklyReview): NutritionPlan
|
|
{
|
|
return DB::transaction(function () use ($weeklyReview): NutritionPlan {
|
|
$lockedReview = WeeklyReview::query()->lockForUpdate()->findOrFail($weeklyReview->getKey());
|
|
|
|
abort_if($lockedReview->accepted_at !== null, 409, 'WEEKLY_ADJUSTMENT_ALREADY_ACCEPTED');
|
|
abort_unless(
|
|
$lockedReview->status === WeeklyReviewStatus::ADJUSTMENT_RECOMMENDED
|
|
&& $lockedReview->recommended_calorie_adjustment !== 0,
|
|
409,
|
|
'WEEKLY_ADJUSTMENT_UNAVAILABLE',
|
|
);
|
|
|
|
$user = $lockedReview->user()->lockForUpdate()->firstOrFail();
|
|
$currentPlan = $user->nutritionPlans()->where('is_active', true)->latest('effective_from')->firstOrFail();
|
|
|
|
abort_unless(
|
|
$lockedReview->nutrition_plan_id === $currentPlan->getKey(),
|
|
409,
|
|
'WEEKLY_ADJUSTMENT_STALE',
|
|
);
|
|
|
|
$now = now();
|
|
$targetCalories = max(1200, $currentPlan->calories + $lockedReview->recommended_calorie_adjustment);
|
|
$proteins = (int) round($currentPlan->proteins);
|
|
$fats = (int) round($currentPlan->fats);
|
|
$carbs = max(0, (int) round(($targetCalories - ($proteins * 4) - ($fats * 9)) / 4));
|
|
$calories = ($proteins * 4) + ($carbs * 4) + ($fats * 9);
|
|
|
|
abort_if(
|
|
$calories === $currentPlan->calories,
|
|
409,
|
|
'WEEKLY_ADJUSTMENT_UNAVAILABLE',
|
|
);
|
|
|
|
$currentPlan->update([
|
|
'is_active' => false,
|
|
'effective_until' => $now,
|
|
]);
|
|
|
|
$nextPlan = $user->nutritionPlans()->create([
|
|
'source' => NutritionPlanSource::WEEKLY_ADJUSTMENT,
|
|
'formula_version' => $currentPlan->formula_version,
|
|
'calories' => $calories,
|
|
'proteins' => $proteins,
|
|
'carbs' => $carbs,
|
|
'fats' => $fats,
|
|
'resting_metabolism' => $currentPlan->resting_metabolism,
|
|
'maintenance_calories' => $currentPlan->maintenance_calories,
|
|
'calorie_adjustment_percent' => ($calories - $currentPlan->maintenance_calories) / max(1, $currentPlan->maintenance_calories),
|
|
'calculation_details' => [
|
|
...$currentPlan->calculation_details,
|
|
'weeklyReviewId' => $lockedReview->getKey(),
|
|
'weeklyAdjustmentCalories' => $lockedReview->recommended_calorie_adjustment,
|
|
],
|
|
'effective_from' => $now,
|
|
]);
|
|
|
|
$lockedReview->update([
|
|
'accepted_at' => $now,
|
|
'accepted_nutrition_plan_id' => $nextPlan->getKey(),
|
|
]);
|
|
|
|
return $nextPlan;
|
|
}, attempts: 3);
|
|
}
|
|
}
|