40 lines
2.0 KiB
PHP
40 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Enums\LicenseStatus;
|
|
use App\Models\BillingOrder;
|
|
use App\Models\DeploymentInstallation;
|
|
use App\Models\License;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class BillingService
|
|
{
|
|
public function activate(BillingOrder $order, ?int $issuerId = null): License
|
|
{
|
|
return DB::transaction(function () use ($order, $issuerId): License {
|
|
$order = BillingOrder::withoutGlobalScope('tenant')->lockForUpdate()->findOrFail($order->id);
|
|
if ($order->status === 'paid' && $order->license) {
|
|
return $order->license;
|
|
}
|
|
$plan = config("billing.plans.{$order->plan_code}");
|
|
abort_unless($plan, 422, 'Paket lisensi tidak tersedia.');
|
|
$installation = DeploymentInstallation::withoutGlobalScope('tenant')->where('tenant_id', $order->tenant_id)->firstOrFail();
|
|
$current = License::withoutGlobalScope('tenant')->where('tenant_id', $order->tenant_id)
|
|
->whereIn('status', [LicenseStatus::Active->value, LicenseStatus::Grace->value])->latest('created_at')->first();
|
|
$startsAt = $current && $current->plan !== 'cloud_free' && $current->expires_at->isFuture() ? $current->expires_at : now();
|
|
$current?->update(['status' => LicenseStatus::Revoked]);
|
|
$license = License::withoutGlobalScope('tenant')->create([
|
|
'tenant_id' => $order->tenant_id, 'deployment_installation_id' => $installation->id,
|
|
'license_key_hash' => hash('sha256', random_bytes(32)), 'plan' => $order->plan_code,
|
|
'status' => LicenseStatus::Active, 'max_devices' => $plan['max_devices'], 'max_users' => $plan['max_users'],
|
|
'features' => ['device_access_management'], 'starts_at' => $startsAt, 'expires_at' => $startsAt->addMonth(),
|
|
'grace_until' => $startsAt->addMonth()->addDays(7), 'issued_by' => $issuerId,
|
|
]);
|
|
$order->update(['license_id' => $license->id, 'status' => 'paid', 'paid_at' => now()]);
|
|
|
|
return $license;
|
|
});
|
|
}
|
|
}
|