feat(service): huỷ dịch vụ, SSL, đổi mật khẩu hosting, lịch sử thanh toán theo hình thức

- Lịch sử thanh toán hoá đơn trả thêm `method` (tự động gia hạn / số dư / admin / chuyển khoản / hoàn tiền), bỏ đuôi `(method)` khỏi ghi chú
- `DnsServer::panelUrl()` = https://<domain>/ dùng cho email cấp hosting và nút Plesk của khách
- Order item trả thêm `uuid`/`type` của dịch vụ để FE dẫn tới trang quản lý
- Yêu cầu huỷ dịch vụ, chứng chỉ SSL, lịch sử gia hạn, đổi mật khẩu hosting cho khách

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
baodev0
2026-10-28 16:40:24 +07:00
co-authored by Claude Sonnet 5.5
parent a6b641015e
commit b44a88bb52
72 changed files with 1701 additions and 231 deletions
+14
View File
@@ -15,6 +15,7 @@ use App\Services\AutoRenewFailureNotifier;
use App\Services\InvoicePaymentService;
use App\Services\RenewalInvoiceNotifier;
use App\Support\RenewalPricing;
use App\Support\ServiceCancellation;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
@@ -33,6 +34,7 @@ class ServiceExpiry extends Command
->with(['orderItem.product', 'customer'])
->whereNotNull('expires_at')
->whereBetween('expires_at', [now(), now()->addDays($renewalWindowDays)])
->where('cancel_at_expiry', false)
->whereNotIn('status', ['terminated', 'cancelled'])
->get();
@@ -63,6 +65,17 @@ class ServiceExpiry extends Command
foreach ($expired as $service) {
try {
if ($service->cancel_at_expiry) {
if ($dryRun) {
$this->line(" [dry-run:cancel] Service #{$service->id}");
} else {
ServiceCancellation::finalize($service);
Log::info('Service cancelled at expiry', ['service_id' => $service->id]);
$this->line(" [cancelled] Service #{$service->id}");
}
continue;
}
// Hướng tính tường minh (mốc quá khứ → now), absolute: true để không phụ thuộc
// việc Carbon 2 trả trị tuyệt đối — Carbon 3 trả số âm, điều kiện >= 30 sẽ
// không bao giờ đúng và không dịch vụ nào bị terminate nữa, hoàn toàn im lặng.
@@ -132,6 +145,7 @@ class ServiceExpiry extends Command
$services = Service::query()
->with('customer')
->where('auto_renew', true)
->where('cancel_at_expiry', false)
->whereNotNull('invoice_id')
->whereNotNull('expires_at')
->where('expires_at', '<=', now()->addDays($windowDays))