['required', Rule::exists('outlets', 'id')], 'channel' => ['required', Rule::in(OrderChannel::values())], 'status' => ['required', Rule::in(OrderStatus::values())], 'payment_method' => ['required', Rule::in(PaymentMethod::values())], 'discount' => ['nullable', new UnsignedInteger], 'member_id' => ['nullable', Rule::exists('customers', 'id')], ]; } public function validationAttributes(): array { return [ 'payment_method' => 'metode pembayaran', 'discount' => 'diskon', 'member_id' => 'member', ]; } public function store() { $this->validate(); $orderItems = $this->loadOrderItems(); // Generate a unique invoice number based on today's paid order count $todayCount = Order::whereDate('created_at', now())->paid()->count() + 1; $invoiceNumber = 'INV'.now()->format('Ymd').str_pad($todayCount, 4, '0', STR_PAD_LEFT); // Calculate total cost of goods sold (COGS) — internal purchase cost $cogs = $orderItems->sum(fn ($item) => $item->cogs * $item->quantity); // Calculate subtotal before any global discount $subtotal = $orderItems->sum(fn ($item) => $item->unit_price * $item->quantity); $discount = replaceCurrency($this->discount); // Apply global discount to get final total $total = $subtotal - $discount; // Wrap the entire operation in a database transaction // Ensures atomicity — if any step fails, all changes are rolled back DB::transaction(function () use ($invoiceNumber, $cogs, $subtotal, $discount, $total, $orderItems) { $order = Order::create([ 'outlet_id' => $this->outlet_id, 'user_id' => auth()->id(), 'customer_id' => $this->member_id == '' ? null : $this->member_id, 'invoice_number' => $invoiceNumber, 'cogs' => $cogs, 'subtotal' => $subtotal, 'discount' => $discount, 'total' => $total, 'channel' => $this->channel, 'status' => $this->status, 'payment_method' => $this->payment_method, ]); // Attach all order items to the newly created order $orderItems->each(function ($item) use ($order) { $item->order_id = $order->id; $item->save(); // Deduct item stock from the outlet inventory $this->decreaseOutletStock($order->outlet, $item); }); // Automatically record payment for the order Payment::create([ 'order_id' => $order->id, 'user_id' => auth()->id(), 'method' => $this->payment_method, 'amount' => $total, 'status' => PaymentStatus::PAID->value, ]); }); } }