feat(admin): improve payments and server settings
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Jobs\Mail\Admin\AdminPaymentReceivedJob;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Notification;
|
||||
|
||||
class AdminPaymentNotifier
|
||||
{
|
||||
public function notify(Invoice $invoice, int $amount, string $paymentType): void
|
||||
{
|
||||
$invoice->loadMissing(['customer', 'order']);
|
||||
$outstanding = InvoicePaymentService::outstanding($invoice);
|
||||
$reference = $invoice->order?->order_num ?? $invoice->invoice_number;
|
||||
$label = $paymentType === 'order' ? 'đơn hàng' : 'hóa đơn';
|
||||
$amountFormatted = number_format($amount, 0, ',', '.') . ' VNĐ';
|
||||
|
||||
Notification::notifyAdmins([
|
||||
'type' => 'payment_received',
|
||||
'title' => 'Khách hàng thanh toán ' . $label,
|
||||
'body' => "{$invoice->customer->fullname} đã thanh toán {$amountFormatted} cho {$label} #{$reference}.",
|
||||
'link' => '/order-invoice',
|
||||
'data' => [
|
||||
'invoice_id' => $invoice->id,
|
||||
'order_id' => $invoice->order_id,
|
||||
'amount' => $amount,
|
||||
'outstanding' => $outstanding,
|
||||
],
|
||||
]);
|
||||
|
||||
AdminPaymentReceivedJob::dispatch([
|
||||
'payment_type' => $paymentType === 'order' ? 'Đơn hàng' : 'Hóa đơn',
|
||||
'reference' => $reference,
|
||||
'invoice_number' => $invoice->invoice_number,
|
||||
'customer_name' => (string) $invoice->customer->fullname,
|
||||
'customer_email' => (string) $invoice->customer->email,
|
||||
'amount' => $amount,
|
||||
'outstanding' => $outstanding,
|
||||
'created_at' => now()->format('d/m/Y H:i:s'),
|
||||
])->afterCommit();
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,18 @@
|
||||
|
||||
namespace App\Services\Api\Order;
|
||||
|
||||
use App\Enums\Invoice\InvoiceStatus;
|
||||
use App\Enums\Order\OrderStatus;
|
||||
use App\Helpers\OrderHelper;
|
||||
use App\Jobs\Mail\Admin\AdminOrderNotificationJob;
|
||||
use App\Models\Order;
|
||||
use App\Models\Product;
|
||||
use App\Repositories\Api\Invoice\InvoiceRepositoryInterface;
|
||||
use App\Repositories\Api\Order\OrderRepositoryInterface;
|
||||
use App\Repositories\Api\Service\ServiceRepository;
|
||||
use App\Services\InvoicePaymentService;
|
||||
use App\Services\AdminPaymentNotifier;
|
||||
use App\Support\AddonQuantityValidator;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class OrderService
|
||||
{
|
||||
@@ -23,6 +22,7 @@ class OrderService
|
||||
protected ServiceRepository $productRepo,
|
||||
protected InvoiceRepositoryInterface $invoiceRepo,
|
||||
protected InvoicePaymentService $invoicePaymentService,
|
||||
protected AdminPaymentNotifier $adminPaymentNotifier,
|
||||
) {}
|
||||
|
||||
// =========================================================================
|
||||
@@ -110,7 +110,7 @@ class OrderService
|
||||
throw new \InvalidArgumentException('Đơn hàng đã được thanh toán hoặc đang xử lý.');
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($order, $method) {
|
||||
$processedOrder = DB::transaction(function () use ($order, $method) {
|
||||
$customer = $order->customer;
|
||||
|
||||
if ($customer->total < $order->total) {
|
||||
@@ -121,22 +121,28 @@ class OrderService
|
||||
));
|
||||
}
|
||||
|
||||
// Allow re-paying a cancelled order
|
||||
$invoice = $order->invoice;
|
||||
if (! $invoice) {
|
||||
throw new \InvalidArgumentException('Không tìm thấy hóa đơn của đơn hàng.');
|
||||
}
|
||||
|
||||
if ((int) $invoice->status === InvoiceStatus::PAID->value) {
|
||||
throw new \InvalidArgumentException('Đơn hàng đã được thanh toán hoặc đang xử lý.');
|
||||
}
|
||||
|
||||
if ($order->status === OrderStatus::CANCELLED->value) {
|
||||
$order->update(['status' => OrderStatus::PENDING->value]);
|
||||
}
|
||||
|
||||
if (! $order->invoice) {
|
||||
throw new \InvalidArgumentException('Không tìm thấy hóa đơn của đơn hàng.');
|
||||
}
|
||||
|
||||
$this->invoicePaymentService->payWithBalance($order->invoice, $customer, $method);
|
||||
$paidInvoice = $this->invoicePaymentService->payWithBalance($invoice, $customer, $method);
|
||||
$processedOrder = $order->fresh(['orderItems', 'invoice', 'customer']);
|
||||
|
||||
$this->dispatchAdminNotification($processedOrder, $customer);
|
||||
|
||||
return $processedOrder;
|
||||
});
|
||||
|
||||
$this->adminPaymentNotifier->notify($processedOrder->invoice, (int) $processedOrder->total, 'order');
|
||||
|
||||
return $processedOrder;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,32 +151,6 @@ class OrderService
|
||||
// =========================================================================
|
||||
|
||||
|
||||
private function dispatchAdminNotification(Order $order, $customer): void
|
||||
{
|
||||
try {
|
||||
$item = $order->orderItems->first();
|
||||
$product = $item?->product;
|
||||
$productType = $product?->category?->name ?? $product?->type ?? 'N/A';
|
||||
|
||||
AdminOrderNotificationJob::dispatch([
|
||||
'order_num' => $order->order_num,
|
||||
'customer_name' => (string) $customer->fullname,
|
||||
'customer_email' => $customer->email,
|
||||
'client_ip' => $order->client_ip ?? request()?->ip(),
|
||||
'product_name' => $product?->name ?? 'N/A',
|
||||
'product_type' => $productType,
|
||||
'billing_cycle' => $item?->billing_cycle ?? 'N/A',
|
||||
'total' => $order->total,
|
||||
'created_at' => now()->format('d/m/Y H:i:s'),
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Log::error('OrderService: failed to dispatch admin notification', [
|
||||
'order_id' => $order->id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrich raw addon entries with resolved price & subtotal.
|
||||
*
|
||||
|
||||
@@ -137,12 +137,12 @@ class PleskHostingService
|
||||
'plesk_login' => $pleskLogin,
|
||||
'plesk_password' => $pleskPassword,
|
||||
// Plesk's actual login page — not the :8443 REST API entry point.
|
||||
'plesk_panel_url' => 'https://' . $server->ip_address . '/login_up.php',
|
||||
'plesk_panel_url' => 'https://' . $server->publicHost() . '/login_up.php',
|
||||
'created_at' => now()->format('d/m/Y H:i:s'),
|
||||
];
|
||||
|
||||
dispatch(new HostingAccountCreatedJob(array_merge($shared, [
|
||||
'server_host' => $server->ip_address,
|
||||
'server_host' => $server->publicHost(),
|
||||
])));
|
||||
|
||||
dispatch(new HostingAccountCreatedAdminNotificationJob(array_merge($shared, [
|
||||
|
||||
Reference in New Issue
Block a user