228 lines
8.6 KiB
PHP
228 lines
8.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin\Manage;
|
|
|
|
use App\Enums\OrderChannel;
|
|
use App\Enums\OrderStatus;
|
|
use App\Enums\PaymentMethod;
|
|
use App\Enums\PriceType;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Admin\Manage\Order\OrderRequest;
|
|
use App\Models\Order;
|
|
use App\Models\OrderItem;
|
|
use App\Models\Product;
|
|
use App\Support\LogHelper;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class OrderController extends Controller
|
|
{
|
|
public function index(): Response
|
|
{
|
|
return Inertia::render('admin/manage/order/index', [
|
|
'orders' => Order::with(['items.product', 'user'])->latest()->paginate(10),
|
|
]);
|
|
}
|
|
|
|
public function create(): Response
|
|
{
|
|
return Inertia::render('admin/manage/order/create', [
|
|
'products' => Product::with(['prices', 'categories'])->active()->get(),
|
|
'cartItems' => OrderItem::with(['product.prices', 'product.categories'])
|
|
->where('user_id', auth()->id())
|
|
->whereNull('order_id')
|
|
->latest()
|
|
->get(),
|
|
'orderStatus' => OrderStatus::options(),
|
|
'orderChannels' => OrderChannel::options(),
|
|
'paymentMethods' => PaymentMethod::options(),
|
|
'priceTypes' => PriceType::options(),
|
|
]);
|
|
}
|
|
|
|
public function store(OrderRequest $request): RedirectResponse
|
|
{
|
|
$validated = $request->validated();
|
|
|
|
try {
|
|
DB::transaction(function () use ($validated) {
|
|
$totalItemsPrice = collect($validated['items'])->sum('total');
|
|
$cogs = collect($validated['items'])->sum(function ($item) {
|
|
$product = Product::find($item['product_id']);
|
|
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
|
|
|
return $purchasePrice * $item['qty'];
|
|
});
|
|
|
|
$order = Order::create([
|
|
'customer_name' => $validated['customer_name'],
|
|
'cogs' => $cogs,
|
|
'subtotal' => $totalItemsPrice,
|
|
'discount' => $validated['discount'],
|
|
'payment' => $validated['payment'],
|
|
'payment_method' => $validated['payment_method'],
|
|
'order_status' => $validated['order_status'],
|
|
'order_channel' => $validated['order_channel'],
|
|
]);
|
|
|
|
foreach ($validated['items'] as $item) {
|
|
OrderItem::create([
|
|
'user_id' => auth()->id(),
|
|
'order_id' => $order->id,
|
|
'product_id' => $item['product_id'],
|
|
'price' => $item['price'],
|
|
'qty' => $item['qty'],
|
|
'total' => $item['total'],
|
|
'price_type' => $item['price_type'],
|
|
]);
|
|
|
|
$product = Product::find($item['product_id']);
|
|
if ($product->stock < $item['qty']) {
|
|
throw new \InvalidArgumentException("Stok produk {$product->name} tidak mencukupi. Sisa stok: {$product->stock}");
|
|
}
|
|
$product->decrement('stock', $item['qty']);
|
|
}
|
|
|
|
OrderItem::where('user_id', auth()->id())
|
|
->whereNull('order_id')
|
|
->delete();
|
|
});
|
|
|
|
return redirect()->route('order.index')->with('success', 'Pesanan berhasil disimpan');
|
|
} catch (\InvalidArgumentException $e) {
|
|
return redirect()->back()->withInput()->with('error', $e->getMessage());
|
|
} catch (\Throwable $e) {
|
|
LogHelper::logException($e, 'Failed to store order', [
|
|
'customer_name' => $validated['customer_name'],
|
|
'items_count' => count($validated['items'] ?? []),
|
|
]);
|
|
|
|
return redirect()
|
|
->back()
|
|
->withInput()
|
|
->with('error', 'Terjadi kesalahan, silakan hubungi pengembang');
|
|
}
|
|
}
|
|
|
|
public function edit(Order $order): Response
|
|
{
|
|
$order->load(['items.product']);
|
|
|
|
return Inertia::render('admin/manage/order/edit', [
|
|
'order' => $order,
|
|
'products' => Product::with(['prices', 'categories'])->active()->get(),
|
|
'orderStatus' => OrderStatus::options(),
|
|
'orderChannels' => OrderChannel::options(),
|
|
'paymentMethods' => PaymentMethod::options(),
|
|
'priceTypes' => PriceType::options(),
|
|
]);
|
|
}
|
|
|
|
public function show(Order $order): Response
|
|
{
|
|
$order->load(['items.product', 'user']);
|
|
|
|
return Inertia::render('admin/manage/order/show', [
|
|
'order' => $order,
|
|
]);
|
|
}
|
|
|
|
public function update(OrderRequest $request, Order $order): RedirectResponse
|
|
{
|
|
$validated = $request->validated();
|
|
|
|
try {
|
|
DB::transaction(function () use ($validated, $order) {
|
|
$totalItemsPrice = collect($validated['items'])->sum(fn ($item) => $item['qty'] * $item['price']);
|
|
$cogs = collect($validated['items'])->sum(function ($item) {
|
|
$product = Product::find($item['product_id']);
|
|
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
|
|
|
return $purchasePrice * $item['qty'];
|
|
});
|
|
|
|
// Restore stock for old items
|
|
foreach ($order->items as $item) {
|
|
$item->product->increment('stock', $item->qty);
|
|
}
|
|
|
|
$order->items()->delete();
|
|
|
|
$order->update([
|
|
'customer_name' => $validated['customer_name'],
|
|
'cogs' => $cogs,
|
|
'subtotal' => $totalItemsPrice,
|
|
'discount' => $validated['discount'],
|
|
'payment' => $validated['payment'],
|
|
'payment_method' => $validated['payment_method'],
|
|
'order_status' => $validated['order_status'],
|
|
'order_channel' => $validated['order_channel'],
|
|
]);
|
|
|
|
foreach ($validated['items'] as $item) {
|
|
$order->items()->create([
|
|
'user_id' => auth()->id(),
|
|
'product_id' => $item['product_id'],
|
|
'price' => $item['price'],
|
|
'qty' => $item['qty'],
|
|
'total' => $item['total'],
|
|
'price_type' => $item['price_type'],
|
|
]);
|
|
|
|
$product = Product::find($item['product_id']);
|
|
if ($product->stock < $item['qty']) {
|
|
throw new \InvalidArgumentException("Stok produk {$product->name} tidak mencukupi. Sisa stok: {$product->stock}");
|
|
}
|
|
$product->decrement('stock', $item['qty']);
|
|
}
|
|
});
|
|
|
|
return redirect()->route('order.index')->with('success', 'Pesanan berhasil diperbarui');
|
|
} catch (\InvalidArgumentException $e) {
|
|
return redirect()->back()->withInput()->with('error', $e->getMessage());
|
|
} catch (\Throwable $e) {
|
|
LogHelper::logException($e, 'Failed to update order', [
|
|
'order_id' => $order->id,
|
|
'customer_name' => $validated['customer_name'],
|
|
]);
|
|
|
|
return redirect()
|
|
->back()
|
|
->withInput()
|
|
->with('error', 'Terjadi kesalahan, silakan hubungi pengembang');
|
|
}
|
|
}
|
|
|
|
public function destroy(Order $order): RedirectResponse
|
|
{
|
|
$order->delete();
|
|
|
|
return redirect()->back()->with('success', 'Pesanan berhasil dihapus');
|
|
}
|
|
|
|
public function bulkDestroy(Request $request): RedirectResponse
|
|
{
|
|
$ids = $request->input('ids');
|
|
|
|
try {
|
|
DB::transaction(function () use ($ids) {
|
|
$orders = Order::whereIn('id', $ids)->get();
|
|
foreach ($orders as $order) {
|
|
$order->delete();
|
|
}
|
|
});
|
|
|
|
return redirect()->back()->with('success', 'Pesanan terpilih berhasil dihapus');
|
|
} catch (\Throwable $e) {
|
|
LogHelper::logException($e, 'Failed to bulk delete orders', [
|
|
'ids' => $ids,
|
|
]);
|
|
|
|
return redirect()->back()->with('error', 'Terjadi kesalahan, silakan hubungi pengembang');
|
|
}
|
|
}
|
|
}
|