validate([ 'entry_no' => 'required|exists:entries,entry_no', 'description' => 'required|string|max:255', 'order_quantity' => 'required|numeric|min:0', 'region' => 'required|string|max:50', 'amount' => 'required|numeric|min:0', //'payment_status' => 'required|string|max:50', ]); $entry = Entry::where('entry_no', $data['entry_no'])->first(); if (!$entry) { return response()->json([ 'success' => false, 'message' => 'Entry not found.', ], 404); } $entry->description = $data['description']; $entry->order_quantity = $data['order_quantity']; $entry->region = $data['region']; $entry->amount = $data['amount']; //$entry->payment_status = $data['payment_status']; $entry->save(); return response()->json([ 'success' => true, 'message' => 'Entry updated successfully.', 'entry' => $entry, ]); } catch (\Throwable $e) { return response()->json([ 'success' => false, 'message' => 'Server error: '.$e->getMessage(), ], 500); } } /** * ๐Ÿš€ 1. Get dashboard entries */ public function getDashboardData() { $entries = Entry::withCount('installments') ->orderBy('id', 'desc') ->get(); return response()->json([ 'success' => true, 'entries' => $entries ]); } /** * ๐Ÿš€ 2. Get available consolidated orders */ public function getAvailableOrders() { $orders = Order::whereDoesntHave('entries') ->orderBy('id', 'desc') ->get(); return response()->json([ 'success' => true, 'orders' => $orders, ]); } /** * ๐Ÿš€ 3. Create new entry */ public function accountCreateOrder(Request $request) { $data = $request->validate([ 'description' => 'required|string|max:255', 'region' => 'required|string|max:50', 'amount' => 'required|numeric|min:1', 'entry_date' => 'nullable|date', 'selected_orders' => 'nullable|array', 'selected_orders.*'=> 'integer|exists:orders,id', ]); return DB::transaction(function () use ($data) { $entryDate = $data['entry_date'] ?? now()->toDateString(); // Count selected consolidated orders $orderQuantity = !empty($data['selected_orders']) ? count($data['selected_orders']) : 0; // Generate entry No: PAY-2025-001 $prefix = 'PAY-' . date('Y') . '-'; $last = Entry::where('entry_no', 'like', $prefix . '%') ->orderBy('id', 'desc') ->first(); $next = $last ? intval(substr($last->entry_no, strrpos($last->entry_no, '-') + 1)) + 1 : 1; $entryNo = $prefix . str_pad($next, 7, '0', STR_PAD_LEFT); // Create entry $entry = Entry::create([ 'entry_no' => $entryNo, 'description' => $data['description'], 'region' => $data['region'], 'order_quantity' => $orderQuantity, 'amount' => $data['amount'], 'pending_amount' => $data['amount'], 'entry_date' => $entryDate, 'payment_status' => 'unpaid', 'toggle_pos' => 0, 'dispatch_status' => 'pending', ]); // Attach consolidated orders if (!empty($data['selected_orders'])) { $entry->orders()->attach($data['selected_orders']); } $entry->load('orders'); return response()->json([ 'success' => true, 'message' => 'Entry Created Successfully', 'entry' => $entry ], 201); }); } /** * ๐Ÿš€ 4. Toggle payment switch */ public function togglePayment(Request $request) { $request->validate([ 'entry_no' => 'required|string|exists:entries,entry_no', 'toggle_pos' => 'required|integer|in:0,1,2', ]); $entry = Entry::where('entry_no', $request->entry_no)->firstOrFail(); $map = [ 0 => 'unpaid', 1 => 'pending', 2 => 'paid' ]; $entry->update([ 'toggle_pos' => $request->toggle_pos, 'payment_status' => $map[$request->toggle_pos], ]); return response()->json([ 'success' => true, 'entry' => $entry ]); } /** * ๐Ÿš€ 5. Add Installment */ public function addInstallment(Request $request) { $data = $request->validate([ 'entry_no' => 'required|exists:entries,entry_no', 'proc_date' => 'nullable|date', 'amount' => 'required|numeric|min:1', 'status' => 'required|string' ]); return DB::transaction(function () use ($data) { $entry = Entry::where('entry_no', $data['entry_no']) ->lockForUpdate() ->firstOrFail(); $amount = floatval($data['amount']); if ($amount > $entry->pending_amount) { return response()->json([ 'success' => false, 'message' => 'Installment cannot exceed pending amount.' ], 422); } $installment = Installment::create([ 'entry_id' => $entry->id, 'proc_date' => $data['proc_date'] ?? now()->toDateString(), 'amount' => $amount, 'description'=> $entry->description, 'region' => $entry->region, 'status' => $data['status'] ]); $entry->pending_amount -= $amount; if ($entry->pending_amount <= 0.001) { $entry->pending_amount = 0; $entry->dispatch_status = 'dispatched'; } $entry->save(); return response()->json([ 'success' => true, 'entry' => $entry, 'installment' => $installment ]); }); } /** * ๐Ÿš€ 6. Update Installment Status */ public function updateInstallmentStatus(Request $request) { $data = $request->validate([ 'installment_id' => 'required|exists:installments,id', 'status' => 'required|string|max:50' ]); return DB::transaction(function () use ($data) { $installment = Installment::lockForUpdate()->findOrFail($data['installment_id']); $installment->status = $data['status']; $installment->save(); $entry = Entry::lockForUpdate()->find($installment->entry_id); // If ANY installment is not delivered โ€” entry is NOT delivered if ($entry->installments()->where('status', '!=', 'Delivered')->exists()) { // entry still in progress $entry->dispatch_status = 'pending'; } else { // all installments delivered $entry->dispatch_status = 'delivered'; } $entry->save(); return response()->json([ 'success' => true, 'message' => 'Installment updated successfully', 'installment' => $installment, 'entry' => $entry ]); }); } /** * ๐Ÿš€ 6. Entry Details (installment history) */ public function getEntryDetails($entry_no) { $entry = Entry::with('installments') ->where('entry_no', $entry_no) ->firstOrFail(); $totalProcessed = $entry->amount - $entry->pending_amount; return response()->json([ 'success' => true, 'entry' => $entry, 'total_processed' => $totalProcessed, 'pending' => $entry->pending_amount, ]); } //-------------------------- //add order Entry //-------------------------- public function addOrdersToEntry(Request $request) { $data = $request->validate([ 'entry_no' => 'required|exists:entries,entry_no', 'order_ids' => 'required|array', 'order_ids.*' => 'integer|exists:orders,id', ]); return DB::transaction(function () use ($data) { $entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail(); $entry->orders()->syncWithoutDetaching($data['order_ids']); $entry->order_quantity = $entry->orders()->count(); $entry->save(); $entry->load('orders'); return response()->json([ 'success' => true, 'message' => 'Orders added successfully.', 'entry' => $entry, ]); }); } public function getEntryOrders($entry_no) { $entry = Entry::where('entry_no', $entry_no) ->with('orders') ->first(); if (!$entry) { return response()->json([ 'success' => false, 'message' => 'Entry not found.', ], 404); } return response()->json([ 'success' => true, 'orders' => $entry->orders, ]); } public function removeOrderFromEntry(Request $request) { $data = $request->validate([ 'entry_no' => 'required|exists:entries,entry_no', 'order_id' => 'required|integer|exists:orders,id', ]); return DB::transaction(function () use ($data) { $entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail(); // order detach เค•เคฐเคพ $entry->orders()->detach($data['order_id']); // เค‡เคฅเฅ‡ quantity auto update $entry->order_quantity = $entry->orders()->count(); $entry->save(); return response()->json([ 'success' => true, 'message' => 'Order removed successfully.', 'entry' => $entry, ]); }); } public function deleteEntry(Request $request) { try { $data = $request->validate([ 'entry_no' => 'required|exists:entries,entry_no', ]); $entry = Entry::where('entry_no', $data['entry_no'])->first(); if (!$entry) { return response()->json([ 'success' => false, 'message' => 'Entry not found.', ], 404); } $entry->delete(); return response()->json([ 'success' => true, 'message' => 'Entry deleted successfully.', ]); } catch (\Throwable $e) { return response()->json([ 'success' => false, 'message' => 'Server error: '.$e->getMessage(), ], 500); } } }