feat: Add IT Support catalog and related migrations, seeders, and email templates

- Created migration to add 'group_label' to 'product_type_fields' table.
- Implemented ItSupportCatalogSeeder to populate IT Support features and tiers.
- Added ProductCategorySeeder for initial product categories.
- Developed ProductMockupSeeder for mockup products in various categories.
- Introduced ProductTypeFieldSeeder to define fields for different product types.
- Created email templates for VPS service information and service renewal reminders.
This commit is contained in:
baodev0
2026-08-26 16:19:38 +07:00
parent 382b7c0ef8
commit c917e3bf5e
47 changed files with 2992 additions and 1759 deletions
+36
View File
@@ -94,4 +94,40 @@ class ModuleVmware extends Model
default => '<span class="badge bg-danger">Pending</span>',
};
}
/**
* `virtual_machine_id`/`cpu`/`ram_mb` are only written when a service is
* created directly against a known vCenter inventory row (admin "create
* service" flow) or after a manual config change (UpdateVmConfigJob) —
* the normal auto-provisioning pipeline never sets them, since the VM
* isn't synced into `virtual_machines` yet at creation time. Backfill
* them here from the live `vmware_id` ↔ `virtual_machines.vm_id` match
* so API responses always expose the real link/spec (needed by the
* admin UI to show CPU/RAM and enable power on/off/restart/console).
*
* `disk_gb` has no source anywhere in the app (vCenter sync doesn't
* track disk size) — it stays null until captured some other way.
*/
public static function resolveVirtualMachineIds(iterable $vmwares): void
{
$candidates = collect($vmwares)->filter(fn ($vm) => $vm && $vm->vmware_id
&& (!$vm->virtual_machine_id || !$vm->cpu || !$vm->ram_mb));
if ($candidates->isEmpty()) {
return;
}
$inventory = \App\Models\VirtualMachines::whereIn('vm_id', $candidates->pluck('vmware_id')->unique())
->get(['id', 'vm_id', 'cpu', 'ram_mb'])
->keyBy('vm_id');
foreach ($candidates as $vm) {
$match = $inventory->get($vm->vmware_id);
if (!$match) {
continue;
}
$vm->virtual_machine_id ??= $match->id;
$vm->cpu ??= $match->cpu;
$vm->ram_mb ??= $match->ram_mb;
}
}
}
+3
View File
@@ -29,6 +29,7 @@ class Product extends Model
'gpu',
'disk',
'bandwidth',
'domain_count',
'stock',
'is_unlimited',
'is_active',
@@ -39,6 +40,7 @@ class Product extends Model
'module_host_id',
'module_datastore_id',
'published_at',
'features',
];
protected $casts = [
@@ -47,6 +49,7 @@ class Product extends Model
'published_at' => 'date',
'gallery' => 'array',
'product_type' => 'string',
'features' => 'array',
];
protected static function boot()
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProductTypeField extends Model
{
protected $fillable = [
'product_type',
'group_label',
'key',
'label',
'field_type',
'sort_order',
'is_required',
];
protected $casts = [
'is_required' => 'boolean',
'sort_order' => 'integer',
];
}