feat(billing): renewals, coupons, VAT numbering, billing cycles and invoice payment tracking
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
ea9a53f742
commit
25f23d541e
@@ -30,6 +30,24 @@ final class AdminTemplates
|
||||
'Thời gian' => '{{created_at}}',
|
||||
]),
|
||||
],
|
||||
[
|
||||
'scenario' => 'admin_service_renewed',
|
||||
'name' => '[Admin] Dịch vụ được gia hạn',
|
||||
'subject' => '[ADMIN] {{admin_name}} gia hạn dịch vụ {{product_name}} — {{customer_email}}',
|
||||
'body' => T::title('Dịch vụ vừa được gia hạn')
|
||||
. T::paragraph('Nhân viên <strong>{{admin_name}}</strong> vừa gia hạn dịch vụ cho khách hàng.')
|
||||
. T::infoTable([
|
||||
'Khách hàng' => '{{customer_name}}',
|
||||
'Email' => '{{customer_email}}',
|
||||
'Dịch vụ' => '{{product_name}}{{server_name_suffix}}',
|
||||
'Thời gian gia hạn' => '{{months_label}}',
|
||||
'Hạn sử dụng trước' => '{{old_expires_at}}',
|
||||
'Hạn sử dụng mới' => '{{expires_at}}',
|
||||
'Hoá đơn' => '{{invoice_number}}',
|
||||
'Số tiền' => '{{amount_formatted}}',
|
||||
'Thanh toán' => '{{payment_method_label}}',
|
||||
]),
|
||||
],
|
||||
[
|
||||
'scenario' => 'admin_order_notification',
|
||||
'name' => '[Admin] Đơn hàng mới',
|
||||
|
||||
@@ -25,8 +25,9 @@ final class BillingTemplates
|
||||
'Hạn thanh toán' => '{{due_date}}',
|
||||
'Tổng tiền' => '{{total}} VNĐ',
|
||||
'Trạng thái' => '{{status_label}}',
|
||||
], '{{outstanding_row}}')
|
||||
], '{{outstanding_row}}{{lookup_row}}')
|
||||
. T::paragraph('{{intro_note}}')
|
||||
. '{{lookup_note}}'
|
||||
. '{{pay_button}}{{attachments_block}}{{note_block}}'
|
||||
. T::supportLine(),
|
||||
],
|
||||
@@ -41,7 +42,8 @@ final class BillingTemplates
|
||||
'Số hoá đơn' => '{{invoice_number}}',
|
||||
'Hạn thanh toán' => '{{due_date}}',
|
||||
'Tổng tiền' => '{{total}} VNĐ',
|
||||
], '{{paid_row}}' . T::row('Còn phải thanh toán', '<span style="color: #dc2626;">{{outstanding}} VNĐ</span>'))
|
||||
], '{{paid_row}}' . T::row('Còn phải thanh toán', '<span style="color: #dc2626;">{{outstanding}} VNĐ</span>') . '{{lookup_row}}')
|
||||
. '{{lookup_note}}'
|
||||
. T::button('{{login_url}}', 'THANH TOÁN NGAY')
|
||||
. T::paragraph('Nếu Quý khách đã thanh toán, vui lòng bỏ qua email này.')
|
||||
. T::supportLine(),
|
||||
|
||||
@@ -66,7 +66,7 @@ final class ServiceTemplates
|
||||
[
|
||||
'scenario' => 'hosting_account_created',
|
||||
'name' => 'Hosting đã khởi tạo',
|
||||
'subject' => 'Hosting của bạn đã sẵn sàng — {{domain_name}}',
|
||||
'subject' => 'V/v: {{app_name}} gửi thông tin truy cập - {{server_name}} - {{recipient_label}}',
|
||||
'body' => T::title('Hosting đã sẵn sàng')
|
||||
. T::greeting('{{full_name}}')
|
||||
. T::paragraph('Gói hosting cho tên miền <strong>{{domain_name}}</strong> tại <strong>{{app_name}}</strong> đã được khởi tạo thành công. Dưới đây là thông tin truy cập:')
|
||||
@@ -125,6 +125,39 @@ final class ServiceTemplates
|
||||
. T::button('{{login_url}}', 'GIA HẠN NGAY')
|
||||
. T::supportLine(),
|
||||
],
|
||||
[
|
||||
'scenario' => 'service_renewed',
|
||||
'name' => 'Dịch vụ đã được gia hạn',
|
||||
'subject' => 'Dịch vụ {{product_name}} đã được gia hạn',
|
||||
'body' => T::title('Gia hạn dịch vụ thành công')
|
||||
. T::greeting('{{client_name}}')
|
||||
. T::paragraph('Dịch vụ <strong>{{product_name}}</strong>{{server_name_suffix}} của Quý khách vừa được gia hạn thêm <strong>{{months_label}}</strong>.')
|
||||
. T::infoTable([
|
||||
'Dịch vụ' => '{{product_name}}',
|
||||
'Hạn sử dụng trước' => '{{old_expires_at}}',
|
||||
'Hạn sử dụng mới' => '<span style="color: #16a34a;">{{expires_at}}</span>',
|
||||
'Hoá đơn' => '{{invoice_number}}',
|
||||
], '{{price_row}}')
|
||||
. T::button('{{login_url}}', 'XEM DỊCH VỤ')
|
||||
. T::supportLine(),
|
||||
],
|
||||
[
|
||||
'scenario' => 'auto_renew_failed',
|
||||
'name' => 'Tự động gia hạn thất bại (thiếu số dư)',
|
||||
'subject' => 'Chưa thể tự động gia hạn dịch vụ {{product_name}}',
|
||||
'body' => T::title('Tự động gia hạn chưa thành công')
|
||||
. T::greeting('{{client_name}}')
|
||||
. T::paragraph('Dịch vụ <strong>{{product_name}}</strong>{{server_name_suffix}} đã bật tự động gia hạn nhưng số dư tài khoản hiện chưa đủ để thanh toán hoá đơn gia hạn.')
|
||||
. T::infoTable([
|
||||
'Hoá đơn' => '{{invoice_number}}',
|
||||
'Ngày hết hạn' => '<span style="color: #dc2626;">{{expires_at}}</span>',
|
||||
'Cần thanh toán' => '{{outstanding}} VNĐ',
|
||||
'Số dư hiện có' => '{{balance_formatted}} VNĐ',
|
||||
])
|
||||
. T::paragraph('Quý khách vui lòng nạp thêm tiền, hệ thống sẽ tự trừ ở lần kiểm tra kế tiếp. Nếu không, dịch vụ có thể bị tạm ngưng khi quá hạn.')
|
||||
. T::button('{{topup_url}}', 'NẠP TIỀN NGAY')
|
||||
. T::supportLine(),
|
||||
],
|
||||
[
|
||||
'scenario' => 'vm_creation_failed',
|
||||
'name' => 'Khởi tạo VPS thất bại',
|
||||
|
||||
@@ -46,8 +46,14 @@ final class TemplateVariables
|
||||
'suspended_at' => ['Thời gian tạm ngưng', 'string', '08/10/2026 09:00'],
|
||||
'server_name_suffix' => ['[Tự động] Tên máy chủ kèm theo', 'html', ''],
|
||||
'expires_at' => ['Ngày hết hạn', 'string', '31/12/2026'],
|
||||
'months_label' => ['Thời gian gia hạn', 'string', '12 tháng'],
|
||||
'old_expires_at' => ['Ngày hết hạn trước khi gia hạn', 'string', '31/12/2026'],
|
||||
'payment_method_label' => ['Hình thức thanh toán', 'string', 'Đã thu ngoài hệ thống'],
|
||||
'admin_name' => ['Nhân viên thực hiện', 'string', 'Nguyễn Văn B'],
|
||||
'price_row' => ['[Tự động] Dòng số tiền gia hạn', 'html', ''],
|
||||
'invoice_url' => ['Link đơn hàng', 'url', 'https://tgs.com.vn/don-hang'],
|
||||
'balance_formatted' => ['Số dư hiện có', 'string', '200.000'],
|
||||
'topup_url' => ['Link nạp tiền', 'url', 'https://tgs.com.vn/nap-tien'],
|
||||
'ip' => ['Địa chỉ IP', 'string', '103.0.0.10'],
|
||||
'ip_count' => ['Số địa chỉ IP', 'string', '2'],
|
||||
'ip_rows' => ['[Tự động] Danh sách địa chỉ IP', 'html', ''],
|
||||
@@ -70,6 +76,8 @@ final class TemplateVariables
|
||||
'name_server_1' => ['Name server 1', 'string', 'ns9.tgs.com.vn'],
|
||||
'name_server_2' => ['Name server 2', 'string', 'ns10.tgs.com.vn'],
|
||||
'kyc_block' => ['[Tự động] Khối xác thực eKYC', 'html', ''],
|
||||
'server_name' => ['Máy chủ hosting', 'string', 'Hosting-01'],
|
||||
'recipient_label' => ['[Tự động] Họ tên khách (trống thì tên công ty, rồi "Công ty")', 'string', 'Nguyễn Văn A'],
|
||||
'hosting_plan' => ['Gói hosting', 'string', 'Premium Hosting 1'],
|
||||
'server_host_row' => ['[Tự động] Dòng máy chủ / FTP host', 'html', ''],
|
||||
'ftp_username_row' => ['[Tự động] Dòng tài khoản FTP', 'html', ''],
|
||||
@@ -95,6 +103,8 @@ final class TemplateVariables
|
||||
'status_label' => ['[Tự động] Trạng thái hoá đơn', 'html', ''],
|
||||
'outstanding_row' => ['[Tự động] Dòng đã trả / còn thiếu', 'html', ''],
|
||||
'intro_note' => ['Ghi chú đính kèm', 'string', 'File PDF hóa đơn đã được đính kèm trong email này.'],
|
||||
'lookup_row' => ['[Tự động] Dòng mã tra cứu hoá đơn', 'html', ''],
|
||||
'lookup_note' => ['[Tự động] Hướng dẫn tra cứu hoá đơn', 'html', ''],
|
||||
'pay_button' => ['[Tự động] Nút thanh toán', 'html', ''],
|
||||
'attachments_block' => ['[Tự động] Danh sách file đính kèm', 'html', ''],
|
||||
'note_block' => ['[Tự động] Ghi chú hoá đơn', 'html', ''],
|
||||
|
||||
Reference in New Issue
Block a user