Files
portal-api/app/Http/Controllers/Api/Service/OrderControllerRefactor.php
T
2026-07-14 17:03:38 +07:00

313 lines
13 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Service;
use App\DTOs\Order\ClientOrderFilters;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Order\CheckServerNameRequest;
use App\Http\Requests\Api\Order\PayOrderRequest;
use App\Http\Requests\Api\Order\RenewServiceRequest;
use App\Http\Requests\Api\Order\StoreOrderRequest;
use App\Http\Resources\Api\Service\Order\InvoiceDetailResource;
use App\Http\Resources\Api\Service\Order\InvoiceSummaryResource;
use App\Http\Resources\Api\Service\Order\OrderDetailResource;
use App\Http\Resources\Api\Service\Order\OrderItemResource;
use App\Http\Resources\Api\Service\Order\OrderSummaryResource;
use App\Http\Resources\Api\Service\Order\ServiceDetailResource;
use App\Http\Resources\Api\Service\Order\ServiceSummaryResource;
use App\Repositories\Api\Order\OrderRepository;
use App\Services\ActivityLogger;
use App\Services\Api\Order\OrderQueryService;
use App\Services\Api\Order\OrderService;
use App\Services\InvoicePaymentService;
use App\Services\InvoicePdfService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class OrderControllerRefactor extends Controller
{
public function __construct(
private readonly OrderService $orderService,
private readonly OrderRepository $orderRepository,
private readonly OrderQueryService $orderQueryService,
private readonly ActivityLogger $activityLogger,
private readonly InvoicePaymentService $invoicePaymentService,
) {
}
public function getList(Request $request): JsonResponse
{
$orders = $this->orderQueryService->getOrdersForCustomer(
(int) $request->user()->id,
ClientOrderFilters::fromArray($request->only(['total_price', 'pending']))
);
return response()->json(['success' => true, 'data' => $orders]);
}
public function checkServerName(CheckServerNameRequest $request): JsonResponse
{
$result = $this->orderQueryService->checkServerName($request->string('name')->toString());
return response()->json($result['available'] ? ['available' => true] : $result);
}
public function getClientOrders(Request $request): JsonResponse
{
$orders = $this->orderRepository->getOrders((int) $request->user()->id, []);
return response()->json([
'success' => true,
'data' => OrderSummaryResource::collection($orders->getCollection()->load('invoice')),
]);
}
public function getClientOrderDetail(Request $request, int $id): JsonResponse
{
$order = $this->orderQueryService->findCustomerOrder((int) $request->user()->id, $id);
if (! $order) {
return response()->json(['success' => false, 'message' => 'Đơn hàng không tồn tại.'], 404);
}
return response()->json(['success' => true, 'data' => new OrderDetailResource($order)]);
}
public function storeOrder(StoreOrderRequest $request): JsonResponse
{
try {
$customer = $request->user();
$data = $request->validated();
$product = \App\Models\Product::where('uuid', $data['product_id'])->first();
if (! $product) {
return response()->json(['success' => false, 'message' => 'Sản phẩm không tìm thấy hoặc đã bị xóa.'], 404);
}
$data['product_id'] = $product->id;
$result = $this->orderService->create($data, $customer);
$order = $result['order']->load(['orderItems.product', 'invoice', 'customer']);
return response()->json([
'success' => true,
'message' => 'Tạo đơn hàng thành công.',
'notice' => 'Dịch vụ VPS sẽ được khởi tạo trong 5-10 phút sau khi thanh toán.',
'data' => [
'order' => new OrderDetailResource($order),
'invoice' => new InvoiceDetailResource($result['invoice']->load(['customer', 'order'])),
'items' => OrderItemResource::collection($order->orderItems),
],
], 201);
} catch (\Throwable $e) {
return response()->json(['success' => false, 'message' => $e->getMessage()], 400);
}
}
public function payOrder(int $id, PayOrderRequest $request): JsonResponse
{
$order = $this->orderRepository->find($id);
if (! $order) {
return response()->json(['success' => false, 'message' => 'Đơn hàng không tồn tại.'], 404);
}
if ($order->customer_id !== $request->user()->id) {
return response()->json(['success' => false, 'message' => 'Không có quyền truy cập.'], 403);
}
$this->orderService->pay($order, $request->payment_method);
$this->activityLogger->log(
event: 'payment',
logName: 'Order',
description: "Customer {$request->user()->email} thanh toán đơn hàng #{$order->order_num} qua {$request->payment_method}",
subject: $order,
newValues: ['payment_method' => $request->payment_method, 'total' => $order->total],
);
return response()->json(['success' => true, 'message' => 'Thanh toán thành công.']);
}
public function retryOrderProvisioning(Request $request, int $id): JsonResponse
{
$order = $this->orderRepository->find($id);
if (! $order) {
return response()->json(['success' => false, 'message' => 'Đơn hàng không tồn tại.'], 404);
}
$result = $this->orderQueryService->retryProvisioning($order, (int) $request->user()->id);
if (! $result['ok']) {
return response()->json(['success' => false, 'message' => $result['message']], $result['code']);
}
$this->activityLogger->log(
event: 'retry_provisioning',
logName: 'Order',
description: "Customer {$request->user()->email} yêu cầu khởi tạo lại dịch vụ cho đơn hàng #{$order->order_num}",
subject: $order,
);
return response()->json(['success' => true, 'message' => $result['message']]);
}
public function getClientInvoices(Request $request): JsonResponse
{
$invoices = $this->orderQueryService->getCustomerInvoices((int) $request->user()->id);
return response()->json(['success' => true, 'data' => InvoiceSummaryResource::collection($invoices)]);
}
public function getClientInvoiceDetail(Request $request, int $id): JsonResponse
{
$invoice = $this->orderQueryService->findCustomerInvoice((int) $request->user()->id, $id);
if (! $invoice) {
return response()->json(['success' => false, 'message' => 'Hóa đơn không tồn tại.'], 404);
}
return response()->json(['success' => true, 'data' => new InvoiceDetailResource($invoice)]);
}
public function getClientInvoiceDetailByOrderNum(Request $request, string $orderNumber): JsonResponse
{
$order = $this->orderQueryService->findCustomerInvoiceByOrderNum((int) $request->user()->id, $orderNumber);
if (! $order?->invoice) {
return response()->json(['success' => false, 'message' => 'Hóa đơn không tồn tại.'], 404);
}
return response()->json(['success' => true, 'data' => new InvoiceDetailResource($order->invoice->setRelation('order', $order))]);
}
public function getClientInvoiceDetailByNumber(Request $request, string $invoiceNumber): JsonResponse
{
$invoice = $this->orderQueryService->findCustomerInvoiceByNumber((int) $request->user()->id, $invoiceNumber);
if (! $invoice) {
return response()->json(['success' => false, 'message' => 'Hóa đơn không tồn tại.'], 404);
}
return response()->json([
'success' => true,
'data' => new InvoiceDetailResource($invoice),
'payment_url' => url('/client/invoices/' . $invoice->invoice_number . '/payment'),
]);
}
public function payClientInvoiceByNumber(Request $request, string $invoiceNumber): JsonResponse
{
$invoice = $this->orderQueryService->findCustomerInvoiceByNumber((int) $request->user()->id, $invoiceNumber);
if (! $invoice) {
return response()->json(['success' => false, 'message' => 'Hóa đơn không tồn tại.'], 404);
}
try {
$paidInvoice = $this->invoicePaymentService->payWithBalance($invoice, $request->user(), 'balance');
$this->activityLogger->log(
event: 'payment',
logName: 'Invoice',
description: "Customer {$request->user()->email} thanh toán hóa đơn #{$paidInvoice->invoice_number}",
subject: $paidInvoice,
newValues: ['invoice_number' => $paidInvoice->invoice_number, 'total' => $paidInvoice->total],
);
return response()->json([
'success' => true,
'message' => 'Thanh toán hóa đơn thành công.',
'data' => new InvoiceDetailResource($paidInvoice),
]);
} catch (\Throwable $e) {
return response()->json(['success' => false, 'message' => $e->getMessage()], 422);
}
}
public function getClientOrderDetailByOrderNum(Request $request, string $orderNum): JsonResponse
{
$order = $this->orderQueryService->findCustomerInvoiceByOrderNum((int) $request->user()->id, $orderNum);
if (! $order) {
return response()->json(['success' => false, 'message' => 'Đơn hàng không tồn tại.'], 404);
}
return response()->json(['success' => true, 'data' => new OrderDetailResource($order)]);
}
public function downloadInvoicePdfByOrderNum(Request $request, string $orderNum, InvoicePdfService $pdfService): Response
{
$order = $this->orderQueryService->findCustomerInvoiceByOrderNum((int) $request->user()->id, $orderNum);
if (! $order?->invoice) {
abort(404, 'Hóa đơn không tồn tại.');
}
$pdf = $pdfService->generate($order->invoice);
$filename = $pdfService->generateFileName($order->invoice);
return response($pdf, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
]);
}
public function getClientServices(Request $request): JsonResponse
{
$services = $this->orderQueryService->getCustomerServices((int) $request->user()->id);
return response()->json(['success' => true, 'data' => ServiceSummaryResource::collection($services)]);
}
public function getClientServiceDetail(Request $request, string $uuid): JsonResponse
{
$service = $this->orderQueryService->findCustomerService((int) $request->user()->id, $uuid);
if (! $service) {
return response()->json(['success' => false, 'message' => 'Không tìm thấy dịch vụ.'], 404);
}
return response()->json(['success' => true, 'data' => new ServiceDetailResource($service)]);
}
public function updateClientServiceAutoRenew(Request $request, int $id): JsonResponse
{
$validated = $request->validate(['auto_renew' => ['required', 'boolean']]);
$service = \App\Models\Service::query()
->where('id', $id)
->where('customer_id', $request->user()->id)
->first();
if (! $service) {
return response()->json(['success' => false, 'message' => 'Không tìm thấy dịch vụ.'], 404);
}
$service->update(['auto_renew' => (bool) $validated['auto_renew']]);
$this->activityLogger->log(
event: 'updated',
logName: 'Service',
description: "Customer {$request->user()->email} " . ($validated['auto_renew'] ? 'bật' : 'tắt') . " tự động gia hạn dịch vụ #{$service->id}",
subject: $service,
newValues: ['auto_renew' => (bool) $validated['auto_renew']],
);
return response()->json(['success' => true, 'message' => 'Cập nhật tự động gia hạn thành công.', 'data' => ['id' => $service->id, 'auto_renew' => (bool) $service->auto_renew]]);
}
public function renewService(RenewServiceRequest $request, int $id): JsonResponse
{
$result = $this->orderQueryService->renewService($id, (int) $request->user()->id, (int) $request->validated()['months']);
if (! $result['ok']) {
return response()->json(['success' => false, 'message' => $result['message']], $result['code']);
}
return response()->json(['success' => true, 'message' => $result['message'], 'data' => $result['data']]);
}
}