feat: nhắc gia hạn QR theo dịch vụ, failover server hosting, CCCD admin, log cấp phát dịch vụ

- Mail campaign: mẫu nhắc gia hạn thanh toán QR, chọn dịch vụ + chu kỳ từng dòng (renewal_services)
- Hosting: nhiều server Plesk cho một gói (service_plan_servers), chuyển server khi server chết
- Admin xem/sửa giấy tờ định danh khách, tuỳ chọn gia hạn cho khách, nhật ký cấp phát dịch vụ
- Đánh dấu mẫu email dịch vụ là non-marketing

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
baodev0
2026-10-30 18:36:41 +07:00
co-authored by Claude Sonnet 5.5
parent 047c23beff
commit 55a834a2f8
53 changed files with 1463 additions and 119 deletions
+4
View File
@@ -2,6 +2,7 @@
use App\Http\Controllers\Api\Admin\Customer\CustomerBillingProfileController;
use App\Http\Controllers\Api\Admin\Customer\CustomerController;
use App\Http\Controllers\Api\Admin\Customer\CustomerIdentityController;
use App\Http\Controllers\Api\Admin\Service\ServiceCancellationRequestController;
use App\Http\Controllers\Api\Admin\Service\ServiceController;
use App\Http\Controllers\Api\Admin\Service\ServiceRenewalReminderController;
@@ -41,6 +42,7 @@ Route::prefix('customers')
Route::post('{uuid}/services/{serviceId}/change-port', 'changeServicePort')->middleware('perm:customer.edit');
Route::post('{uuid}/services/{serviceId}/notify-renew', 'notifyServiceRenewal')->middleware('perm:customer.edit');
Route::get('{uuid}/services/{serviceId}/renewals', 'serviceRenewals')->middleware('perm:customer.view');
Route::get('{uuid}/services/{serviceId}/provisioning-logs', 'serviceProvisioningLogs')->middleware('perm:customer.view');
Route::post('{uuid}/services/{serviceId}/renew', 'renewService')->middleware('perm:customer.edit');
Route::get('{uuid}/notes', 'getCustomerNotes')->middleware('perm:customer.view');
Route::post('{uuid}/notes', 'storeCustomerNote')->middleware('perm:customer.edit');
@@ -115,3 +117,5 @@ Route::prefix('customers/{uuid}/billing-profile')->controller(CustomerBillingPro
Route::get('/', 'show')->middleware('perm:customer.view');
Route::put('/', 'update')->middleware('perm:customer.edit');
});
Route::get('customers/{uuid}/identity', [CustomerIdentityController::class, 'show'])->middleware('perm:customer.view');