feat(admin): improve payments and server settings
This commit is contained in:
@@ -12,6 +12,8 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
private const DOMAIN_PATTERN = '/^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i';
|
||||
|
||||
public function __construct(
|
||||
private readonly DnsServerRepositoryInterface $serverRepository,
|
||||
private readonly ServerService $serverService,
|
||||
@@ -30,6 +32,7 @@ class ServerController extends Controller
|
||||
$query->where(function ($subQuery) use ($filter) {
|
||||
$subQuery->where('name', 'like', "%{$filter}%")
|
||||
->orWhere('ip_address', 'like', "%{$filter}%")
|
||||
->orWhere('domain', 'like', "%{$filter}%")
|
||||
->orWhere('username', 'like', "%{$filter}%");
|
||||
});
|
||||
}
|
||||
@@ -79,6 +82,7 @@ class ServerController extends Controller
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'ip_address' => 'required|string|max:255',
|
||||
'domain' => ['nullable', 'string', 'max:255', 'regex:' . self::DOMAIN_PATTERN],
|
||||
'panel_port' => 'nullable|integer|min:1|max:65535',
|
||||
'username' => 'required|string|max:255',
|
||||
'password' => 'required|string|max:255',
|
||||
@@ -93,6 +97,7 @@ class ServerController extends Controller
|
||||
$server = $this->serverRepository->create([
|
||||
'name' => $validated['name'],
|
||||
'ip_address' => $validated['ip_address'],
|
||||
'domain' => $validated['domain'] ?? null,
|
||||
'panel_port' => $validated['panel_port'] ?? 8880,
|
||||
'username' => $validated['username'],
|
||||
'password' => Crypt::encryptString($validated['password']),
|
||||
@@ -125,6 +130,7 @@ class ServerController extends Controller
|
||||
$validated = $request->validate([
|
||||
'name' => 'sometimes|required|string|max:255',
|
||||
'ip_address' => 'sometimes|required|string|max:255',
|
||||
'domain' => ['nullable', 'string', 'max:255', 'regex:' . self::DOMAIN_PATTERN],
|
||||
'panel_port' => 'nullable|integer|min:1|max:65535',
|
||||
'username' => 'sometimes|required|string|max:255',
|
||||
'password' => 'nullable|string|max:255',
|
||||
@@ -194,6 +200,7 @@ class ServerController extends Controller
|
||||
'id' => $server->id,
|
||||
'name' => $server->name,
|
||||
'ip_address' => $server->ip_address,
|
||||
'domain' => $server->domain,
|
||||
'panel_port' => $server->panel_port,
|
||||
'username' => $server->username,
|
||||
'api_key' => $server->api_key,
|
||||
|
||||
@@ -101,6 +101,10 @@ class SettingController extends Controller
|
||||
'smtp.encryption' => 'sometimes|in:ssl,tls,starttls,',
|
||||
'smtp.from_name' => 'sometimes|string|nullable',
|
||||
'smtp.from_address' => 'sometimes|email|nullable',
|
||||
'smtp.cc' => 'sometimes|array',
|
||||
'smtp.cc.*' => 'email|max:255|distinct',
|
||||
'smtp.bcc' => 'sometimes|array',
|
||||
'smtp.bcc.*' => 'email|max:255|distinct',
|
||||
'turnstile' => 'sometimes|array',
|
||||
'turnstile.enabled' => 'sometimes|boolean',
|
||||
'turnstile.site_key' => 'sometimes|string|nullable|max:255',
|
||||
|
||||
@@ -20,6 +20,7 @@ use App\Services\Api\Order\OrderQueryService;
|
||||
use App\Services\Api\Order\OrderService;
|
||||
use App\Services\InvoicePaymentService;
|
||||
use App\Services\InvoicePdfService;
|
||||
use App\Services\AdminPaymentNotifier;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -32,6 +33,7 @@ class OrderControllerRefactor extends Controller
|
||||
private readonly OrderQueryService $orderQueryService,
|
||||
private readonly ActivityLogger $activityLogger,
|
||||
private readonly InvoicePaymentService $invoicePaymentService,
|
||||
private readonly AdminPaymentNotifier $adminPaymentNotifier,
|
||||
) {}
|
||||
|
||||
public function getList(Request $request): JsonResponse
|
||||
@@ -234,6 +236,7 @@ class OrderControllerRefactor extends Controller
|
||||
]);
|
||||
|
||||
try {
|
||||
$amountPaidBefore = (int) $invoice->amount_paid;
|
||||
$paidInvoice = $this->invoicePaymentService->payWithBalance(
|
||||
$invoice,
|
||||
$request->user(),
|
||||
@@ -250,6 +253,11 @@ class OrderControllerRefactor extends Controller
|
||||
);
|
||||
|
||||
$outstanding = \App\Services\InvoicePaymentService::outstanding($paidInvoice);
|
||||
$this->adminPaymentNotifier->notify(
|
||||
$paidInvoice,
|
||||
(int) $paidInvoice->amount_paid - $amountPaidBefore,
|
||||
'invoice',
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Http\Services\Telegram;
|
||||
use App\Mail\Admin\ManualDepositPendingNotification;
|
||||
use App\Mail\Customer\ManualDepositStatus;
|
||||
use App\Models\Log;
|
||||
use App\Models\Notification;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Transaction;
|
||||
use App\Services\ActivityLogger;
|
||||
@@ -229,13 +230,34 @@ class ManualDepositController extends Controller
|
||||
], 422);
|
||||
}
|
||||
|
||||
Notification::notifyAdmins([
|
||||
'type' => 'manual_deposit_pending',
|
||||
'title' => 'Có yêu cầu nạp tiền chờ duyệt',
|
||||
'body' => sprintf(
|
||||
'%s vừa gửi chứng từ nạp %s VNĐ (%s).',
|
||||
$user->fullname,
|
||||
number_format((float) $transaction->amount, 0, ',', '.'),
|
||||
$transaction->public_code,
|
||||
),
|
||||
'link' => '/transactions',
|
||||
'data' => [
|
||||
'transaction_uuid' => $transaction->uuid,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'customer_id' => $user->id,
|
||||
'amount' => (int) $transaction->amount,
|
||||
],
|
||||
]);
|
||||
|
||||
try {
|
||||
(new Telegram())->SendManualDepositPendingApproval($user, $transaction);
|
||||
$this->sendManualDepositAdminEmail($user, $transaction, $request);
|
||||
} catch (\Exception) {
|
||||
// Không để lỗi Telegram ảnh hưởng response
|
||||
} catch (\Throwable $e) {
|
||||
\Log::error('Không thể gửi Telegram thông báo nạp tiền chờ duyệt: ' . $e->getMessage(), [
|
||||
'transaction_code' => $transaction->public_code,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->sendManualDepositAdminEmail($user, $transaction, $request);
|
||||
|
||||
Log::create([
|
||||
'agent' => 'api',
|
||||
'client_ip' => $request->ip(),
|
||||
|
||||
@@ -267,6 +267,7 @@ class TransactionController extends Controller
|
||||
'public_code' => $t->public_code,
|
||||
'trans' => $t->trans,
|
||||
'description' => $t->typeLabel(),
|
||||
'direction' => $t->direction,
|
||||
'amount' => (float) $t->amount,
|
||||
'status' => $t->status,
|
||||
'status_label' => TransactionStatus::from((int) $t->status)->label(),
|
||||
@@ -283,6 +284,7 @@ class TransactionController extends Controller
|
||||
'public_code' => $inv->invoice_number,
|
||||
'trans' => null,
|
||||
'description' => 'Thanh toán đơn hàng: ' . ($inv->order?->orderItems->first()?->product?->name ?? $inv->order?->order_num),
|
||||
'direction' => 'debit',
|
||||
'amount' => (float) $inv->total,
|
||||
'status' => $inv->status,
|
||||
'status_label' => \App\Enums\Invoice\InvoiceStatus::tryFrom((int) $inv->status)?->label() ?? '-',
|
||||
@@ -368,4 +370,4 @@ class TransactionController extends Controller
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user