491 lines
18 KiB
PHP
491 lines
18 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Admin\Order;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Helpers\Helper;
|
|
use App\Http\Requests\OrderRequest;
|
|
use App\Http\Requests\UpdateOrderRequest;
|
|
use App\Http\Resources\Api\Admin\OrderResource;
|
|
use App\Jobs\Hosting\CreateHostingJobs;
|
|
use App\Jobs\VirtualMachine\Create\CreateVMJobs;
|
|
use App\Jobs\VirtualMachine\Upgrade\UpgradeVirtualMachine;
|
|
use App\Models\Order;
|
|
use App\Repositories\Addon\AddonRepositoryInterface;
|
|
use App\Repositories\Hosting\HostingRepositoryInterface;
|
|
use App\Repositories\Invoice\InvoiceRepositoryInterface;
|
|
use App\Repositories\InvoiceItem\InvoiceItemRepositoryInterface;
|
|
use App\Repositories\Module\Hosting\HostingRepositoryInterface as ModuleHostingRepositoryInterface;
|
|
use App\Repositories\Module\HostingServer\HostingServerRepositoryInterface;
|
|
use App\Repositories\Module\IpAddress\IpAddressRepositoryInterface;
|
|
use App\Repositories\Module\Vmware\VmwareRepositoryInterface;
|
|
use App\Repositories\Order\OrderRepositoryInterface;
|
|
use App\Repositories\Os\OsRepositoryInterface;
|
|
use App\Repositories\VPS\VPSRepositoryInterface;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Yajra\DataTables\Facades\DataTables;
|
|
|
|
class OrderController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly OrderRepositoryInterface $orderRepository,
|
|
private readonly HostingRepositoryInterface $hostingRepository,
|
|
private readonly VPSRepositoryInterface $vPSRepository,
|
|
private readonly InvoiceRepositoryInterface $invoiceRepository,
|
|
private readonly InvoiceItemRepositoryInterface $invoiceItemRepository,
|
|
private readonly ModuleHostingRepositoryInterface $moduleHostingRepository,
|
|
private readonly VmwareRepositoryInterface $moduleVmwareRepository,
|
|
private readonly HostingServerRepositoryInterface $moduleHostingServerRepository,
|
|
private readonly OsRepositoryInterface $osRepository,
|
|
private readonly IpAddressRepositoryInterface $ipAddressRepository,
|
|
private readonly AddonRepositoryInterface $addonRepository,
|
|
) {}
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$perPage = min((int) $request->get('per_page', 15), 100);
|
|
|
|
$query = $this->orderRepository->filter(
|
|
$request->all(),
|
|
['payment', 'customer', 'invoice'],
|
|
[],
|
|
['*'],
|
|
true
|
|
);
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'data' => [
|
|
'items' => OrderResource::collection($query->get())->resolve(),
|
|
'total' => $query->count(),
|
|
'per_page' => $perPage,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function datatable(Request $request): JsonResponse
|
|
{
|
|
$query = $this->orderRepository->filter(
|
|
$request->all(),
|
|
['payment', 'customer', 'invoice'],
|
|
[],
|
|
['*'],
|
|
true
|
|
);
|
|
|
|
return DataTables::eloquent($query)
|
|
->addColumn('order_num', fn($d) => $d->order_num)
|
|
->addColumn('date', fn($d) => $d->date)
|
|
->addColumn('customer', fn($d) => $d->customer?->fullname)
|
|
->addColumn('payment', fn($d) => $d->payment?->name)
|
|
->addColumn('amount', fn($d) => $d->amount)
|
|
->addColumn('invoice_status', fn($d) => $d->invoice?->status)
|
|
->addColumn('status', fn($d) => $d->status)
|
|
->addColumn('action', fn($d) => $d->id)
|
|
->rawColumns(['order_num', 'date', 'customer', 'payment', 'amount', 'invoice_status', 'status', 'action'])
|
|
->make(true);
|
|
}
|
|
|
|
public function store(OrderRequest $request): JsonResponse
|
|
{
|
|
$request->validated();
|
|
|
|
$total = 0;
|
|
$product_item = [];
|
|
$relid_data = [];
|
|
|
|
foreach ($request->product as $key => $item) {
|
|
$product = null;
|
|
$relid_data[$key]['type'] = $item['type'];
|
|
|
|
$product = match ((int) $item['type']) {
|
|
3 => $this->hostingRepository->find($item['product_id']),
|
|
4 => $this->vPSRepository->find($item['product_id']),
|
|
default => null
|
|
};
|
|
|
|
if (!$product) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Invalid product."
|
|
], 422);
|
|
}
|
|
|
|
$message = $product->name;
|
|
$relid_data[$key]['data'] = [
|
|
'customer_id' => $request->customer_id,
|
|
'status' => 0,
|
|
'name' => $item['domain']
|
|
];
|
|
|
|
$billingDetails = $this->calculateBillingDetails($item['billing']);
|
|
$relid_data[$key]['data'] = array_merge($relid_data[$key]['data'], $billingDetails);
|
|
|
|
$price_select = $item['price_custom'] ?? $product->price_sale ?? $product->price;
|
|
$relid_data[$key]['data']['first_payment'] = $price_select * $billingDetails['billing'];
|
|
$relid_data[$key]['data']['next_payment'] = ($item['price_custom'] ?? $product->price) * $billingDetails['billing'];
|
|
|
|
$generalCode = Helper::generateUniqueCode();
|
|
|
|
$product_item[$key] = [
|
|
'customer_id' => $request->customer_id,
|
|
'type_id' => $item['type'],
|
|
'product_id' => $item['product_id'],
|
|
'description' => $message,
|
|
'amount' => $price_select,
|
|
'billing' => $item['billing'],
|
|
'tax' => 1,
|
|
'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp,
|
|
'code' => $generalCode
|
|
];
|
|
|
|
$relid_data[$key]['code'] = $generalCode;
|
|
|
|
if ($item['quantity'] > 1) {
|
|
for ($i = 1; $i < $item['quantity']; $i++) {
|
|
$newCode = Helper::generateUniqueCode();
|
|
$product_item[] = array_merge($product_item[$key], ['code' => $newCode]);
|
|
$relid_data[] = array_merge($relid_data[$key], ['code' => $newCode]);
|
|
}
|
|
}
|
|
|
|
$total += $item['quantity'] * ($item['price_custom'] ?? ($product->price_sale ?? $product->price)) * $billingDetails['billing'];
|
|
}
|
|
|
|
$order_item = [
|
|
'order_num' => Helper::generateUniqueCode(),
|
|
'customer_id' => $request->customer_id,
|
|
'date' => Carbon::today()->timestamp,
|
|
'invoice_id' => 0,
|
|
'discount_id' => $request->discount_id ?? 0,
|
|
'amount' => $total + ($total * (10 / 100)),
|
|
'payment_id' => $request->payment_id,
|
|
'user_id' => Auth::guard('admins-api')->id(),
|
|
'status' => $request->status,
|
|
'client_ip' => $request->getClientIp()
|
|
];
|
|
|
|
$invoice_data = [
|
|
'date' => Carbon::today()->timestamp,
|
|
'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp,
|
|
'date_paid' => (int)$request->status === 1 ? Carbon::today()->timestamp : null,
|
|
'sub_total' => $total,
|
|
'tax' => $total * (10 / 100),
|
|
'total' => $total + ($total * (10 / 100)),
|
|
'payment_id' => $request->payment_id,
|
|
'customer_id' => $request->create_invoice ? $request->customer_id : 0,
|
|
'status' => $request->status
|
|
];
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
$invoice = $this->invoiceRepository->create($invoice_data);
|
|
|
|
$product_item = array_map(function ($array) use ($invoice) {
|
|
$array['invoice_id'] = $invoice->id;
|
|
return $array;
|
|
}, $product_item);
|
|
|
|
if ($request->create_invoice) {
|
|
$order_item['invoice_id'] = $invoice->id;
|
|
}
|
|
|
|
$order = $this->orderRepository->create($order_item);
|
|
|
|
$relid_data = array_map(function ($array) use ($order) {
|
|
$array['data']['order_id'] = $order->id;
|
|
return $array;
|
|
}, $relid_data);
|
|
|
|
$relid = [];
|
|
|
|
foreach ($relid_data as $item) {
|
|
$code = $item['code'];
|
|
|
|
switch ($item['type']) {
|
|
case 3:
|
|
$relid_id = $this->moduleHostingRepository->create($item['data']);
|
|
$relid[$code] = $relid_id->id;
|
|
break;
|
|
case 4:
|
|
$item['data']['status'] = 2;
|
|
$relid_id = $this->moduleVmwareRepository->create($item['data']);
|
|
$relid[$code] = $relid_id->id;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$product_item = array_filter(array_map(function ($array) use ($relid) {
|
|
if (isset($relid[$array['code']])) {
|
|
$array['relid'] = $relid[$array['code']];
|
|
unset($array['code']);
|
|
return $array;
|
|
}
|
|
return null;
|
|
}, $product_item));
|
|
|
|
$this->invoiceItemRepository->insert($product_item);
|
|
|
|
$last_id = $this->invoiceItemRepository->filter(['limit' => count($product_item)], [], [], ['id'])->pluck('id')->toArray();
|
|
|
|
$order->orderItem()->sync($last_id);
|
|
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Order created successfully',
|
|
'data' => new OrderResource($order)
|
|
], 201);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function show(int $id): JsonResponse
|
|
{
|
|
$order = $this->orderRepository->findWithRelationships(
|
|
$id,
|
|
['orderItem', 'user', 'customer.invoiceItem.type', 'payment', 'discount', 'invoice.invoiceItem']
|
|
);
|
|
|
|
if (!$order) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Can't find order by ID #" . $id
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'data' => new OrderResource($order)
|
|
]);
|
|
}
|
|
|
|
public function update(int $id, UpdateOrderRequest $request): JsonResponse
|
|
{
|
|
$order = $this->orderRepository->findWithRelationships($id, ['invoice', 'orderItem']);
|
|
|
|
if (!$order) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Can't find order by ID #" . $id
|
|
], 404);
|
|
}
|
|
|
|
$status = match ($request->action) {
|
|
"accept" => 1,
|
|
"cancel" => 2,
|
|
default => 0
|
|
};
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$this->orderRepository->update($id, ['status' => $status]);
|
|
|
|
if ($status === 1 && $request->module == 1) {
|
|
$jobs = [];
|
|
$addon = [];
|
|
$product = 0;
|
|
|
|
foreach ($order->orderItem as $key => $item) {
|
|
switch ((int) $item->type_id) {
|
|
case 1:
|
|
$itemData = $this->addonRepository->find($item->relid);
|
|
if ($itemData) {
|
|
$price = match ((int) $item->billing) {
|
|
2 => $item->amount / 1,
|
|
3 => $item->amount / 3,
|
|
4 => $item->amount / 6,
|
|
5 => $item->amount / 12,
|
|
default => 0
|
|
};
|
|
$addon[strtolower($itemData->name)] = (int) $price / $itemData->price;
|
|
$product = $item->parent_id;
|
|
}
|
|
break;
|
|
case 3:
|
|
$hostingServer = $this->moduleHostingServerRepository->get_active();
|
|
if ($hostingServer) {
|
|
$this->moduleHostingRepository->update($item->relid, ['module_server_id' => $hostingServer->first()->id]);
|
|
$jobs[] = new CreateHostingJobs($item->relid);
|
|
}
|
|
break;
|
|
case 4:
|
|
$product = $this->moduleVmwareRepository->find($item->relid);
|
|
|
|
if ($product && $product->os_id) {
|
|
$os = $this->osRepository->findWithRelationships($product->os_id, ['osGroup']);
|
|
if (!$os || !$os->osGroup->isNotEmpty()) break;
|
|
|
|
$ip_address = $this->ipAddressRepository->filter([
|
|
'module_host_id' => $os->osGroup->module_host_id,
|
|
'status' => 0
|
|
]);
|
|
|
|
if (count($ip_address) > 0) {
|
|
$this->moduleVmwareRepository->update($item->relid, [
|
|
'module_ipaddress_id' => $ip_address->first()->id,
|
|
]);
|
|
$this->ipAddressRepository->update($ip_address->first()->id, [
|
|
'status' => 1
|
|
]);
|
|
$jobs[] = new CreateVMJobs($product->id);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (count($order->orderItem) === count($addon)) {
|
|
dispatch(new UpgradeVirtualMachine($product, $addon, $order->id))->delay(now()->addSeconds(10));
|
|
}
|
|
|
|
foreach ($jobs as $item) {
|
|
dispatch($item)->delay(now()->addSeconds(10));
|
|
}
|
|
}
|
|
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Order updated successfully'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function destroy(int $id): JsonResponse
|
|
{
|
|
$order = Order::with('Invoice', 'Invoice.InvoiceItem')->find($id);
|
|
|
|
if (!$order) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Can't find order by ID #" . $id
|
|
], 404);
|
|
}
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
if ($order->Invoice) {
|
|
$order->Invoice->delete();
|
|
|
|
if ($order->Invoice->InvoiceItem->count()) {
|
|
foreach ($order->Invoice->InvoiceItem->all() as $item) {
|
|
$item->delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
$order->delete();
|
|
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Order deleted successfully'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function accept(int $id): JsonResponse
|
|
{
|
|
$order = $this->orderRepository->findWithRelationships($id, ['invoice', 'orderItem']);
|
|
|
|
if (!$order) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Can't find order by ID #" . $id
|
|
], 404);
|
|
}
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
$this->orderRepository->update($id, ['status' => 1]);
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Order accepted successfully'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function cancel(int $id): JsonResponse
|
|
{
|
|
$order = $this->orderRepository->find($id);
|
|
|
|
if (!$order) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => "Can't find order by ID #" . $id
|
|
], 404);
|
|
}
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
$this->orderRepository->update($id, ['status' => 2]);
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Order cancelled successfully'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
private function calculateBillingDetails($billing): array
|
|
{
|
|
$months = match ($billing) {
|
|
2 => 1,
|
|
3 => 3,
|
|
4 => 6,
|
|
5 => 12,
|
|
default => 0
|
|
};
|
|
|
|
return [
|
|
'next_due_date' => $months ? Carbon::today()->addMonths($months)->timestamp : null,
|
|
'next_invoice' => $months ? Carbon::today()->addMonths($months)->timestamp : null,
|
|
'billing' => $months ?: 1
|
|
];
|
|
}
|
|
}
|