feat: implement upgrade validation to prevent downgrades and enhance service upgrade process with improved error handling
This commit is contained in:
@@ -118,6 +118,15 @@ class Upgrade extends Component
|
||||
->first();
|
||||
if (!$plan) {
|
||||
$fail(__('Invalid upgrade.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent downgrades - only allow upgrades where new price >= current price
|
||||
$currentPrice = $this->service->plan->price()->price;
|
||||
$newPrice = $plan->price()->price;
|
||||
|
||||
if ($newPrice < $currentPrice) {
|
||||
$fail(__('Downgrades are not allowed. You may only upgrade to a higher-priced plan.'));
|
||||
}
|
||||
},
|
||||
],
|
||||
@@ -146,6 +155,12 @@ class Upgrade extends Component
|
||||
$this->validate();
|
||||
|
||||
$upgradePlan = $this->upgradeProduct->availablePlans()->where('billing_period', $this->service->plan->billing_period)->where('billing_unit', $this->service->plan->billing_unit)->first();
|
||||
|
||||
// Additional check to prevent downgrades
|
||||
if ($upgradePlan && $upgradePlan->price()->price < $this->service->plan->price()->price) {
|
||||
$this->notify('Downgrades are not allowed. You may only upgrade to a higher-priced plan.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// The old config options must be in upgradableConfigOptions
|
||||
$serviceConfigOptions = $this->service->configs->pluck('config_value_id', 'config_option_id')->toArray();
|
||||
@@ -177,7 +192,9 @@ class Upgrade extends Component
|
||||
}
|
||||
$price = $upgrade->calculatePrice();
|
||||
|
||||
if ($price->price <= 0) {
|
||||
// Only process free upgrades immediately (price == 0)
|
||||
// Negative prices (downgrades) are blocked by validation
|
||||
if ($price->price == 0) {
|
||||
$upgrade->status = ServiceUpgrade::STATUS_COMPLETED;
|
||||
$upgrade->save();
|
||||
|
||||
@@ -203,26 +220,7 @@ class Upgrade extends Component
|
||||
UpgradeJob::dispatch($this->service);
|
||||
}
|
||||
|
||||
// Check if user has credits in this currency
|
||||
/** @var \App\Models\User */
|
||||
$user = Auth::user();
|
||||
$credit = $user->credits()->where('currency_code', $price->currency->code)->first();
|
||||
|
||||
if ($credit) {
|
||||
// Increment the credits, `abs()` ensures the amount to add is positive
|
||||
$credit->increment('amount', abs($price->price));
|
||||
} else {
|
||||
$user->credits()->create([
|
||||
'currency_code' => $price->currency->code,
|
||||
'amount' => $price->price,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($price->price < 0) {
|
||||
$this->notify('The upgrade has been completed. We\'ve added the remaining amount to your account balance.', 'success');
|
||||
} else {
|
||||
$this->notify('The upgrade has been completed.', 'success');
|
||||
}
|
||||
$this->notify('The upgrade has been completed.', 'success');
|
||||
|
||||
return $this->redirect(route('services.show', $this->service), true);
|
||||
}
|
||||
|
||||
@@ -191,8 +191,14 @@ class Service extends Model
|
||||
// Only get the upgrades that have the exact same billing cycle as the service
|
||||
if ($plan->count() > 0) {
|
||||
$product->plan = $plan->first();
|
||||
|
||||
return $product;
|
||||
|
||||
// Only allow upgrades (not downgrades) - check if new price is greater than or equal to current price
|
||||
$currentPrice = $this->plan->price()->price;
|
||||
$newPrice = $product->plan->price()->price;
|
||||
|
||||
if ($newPrice >= $currentPrice) {
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user