user()->business_id; $banks = PaymentType::where('business_id', $business_id)->latest()->get(); $cash = Transaction::with('user:id,name') ->where('business_id', auth()->user()->business_id) ->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']); // Default to today $startDate = Carbon::today()->format('Y-m-d'); $endDate = Carbon::today()->format('Y-m-d'); if ($request->custom_days === 'yesterday') { $startDate = Carbon::yesterday()->format('Y-m-d'); $endDate = Carbon::yesterday()->format('Y-m-d'); } elseif ($request->custom_days === 'last_seven_days') { $startDate = Carbon::today()->subDays(6)->format('Y-m-d'); } elseif ($request->custom_days === 'last_thirty_days') { $startDate = Carbon::today()->subDays(29)->format('Y-m-d'); } elseif ($request->custom_days === 'current_month') { $startDate = Carbon::now()->startOfMonth()->format('Y-m-d'); $endDate = Carbon::now()->endOfMonth()->format('Y-m-d'); } elseif ($request->custom_days === 'last_month') { $startDate = Carbon::now()->subMonth()->startOfMonth()->format('Y-m-d'); $endDate = Carbon::now()->subMonth()->endOfMonth()->format('Y-m-d'); } elseif ($request->custom_days === 'current_year') { $startDate = Carbon::now()->startOfYear()->format('Y-m-d'); $endDate = Carbon::now()->endOfYear()->format('Y-m-d'); } elseif ($request->custom_days === 'custom_date' && $request->from_date && $request->to_date) { $startDate = Carbon::parse($request->from_date)->format('Y-m-d'); $endDate = Carbon::parse($request->to_date)->format('Y-m-d'); } $cash->whereDate('date', '>=', $startDate) ->whereDate('date', '<=', $endDate); $cashes = $cash->when(request('search'), function ($q) use ($request) { $q->where(function ($q) use ($request) { $q->where('date', 'like', '%' . $request->search . '%') ->orWhere('transaction_type', 'like', '%' . $request->search . '%') ->orWhere('amount', 'like', '%' . $request->search . '%') ->orWhereHas('user', function ($q) use ($request) { $q->where('name', 'like', '%' . $request->search . '%'); }); }); }) ->latest() ->paginate($request->per_page ?? 20)->appends($request->query()); if ($request->ajax()) { return response()->json([ 'data' => view('business::cashes.datas', compact('cashes'))->render() ]); } return view('business::cashes.index', compact('cashes', 'banks')); } public function store(Request $request) { $request->validate([ 'to' => 'nullable|exists:payment_types,id', 'type' => 'nullable|in:credit,debit', 'transaction_type' => 'required|in:cash_to_bank,adjust_cash', 'amount' => 'required|numeric|min:0.01', 'date' => 'nullable|date', 'image' => 'nullable|image|mimes:jpg,png,jpeg,svg', 'note' => 'nullable|string', ]); $business_id = auth()->user()->business_id; $amount = $request->amount ?? 0; $type = 'transfer'; DB::beginTransaction(); try { // Cash to Bank if ($request->transaction_type === 'cash_to_bank') { $toBank = PaymentType::findOrFail($request->to); // increase target bank balance $toBank->increment('balance', $amount); // Adjust Cash } elseif ($request->transaction_type === 'adjust_cash') { $type = $request->type; } // Store transaction record Transaction::create([ 'business_id' => $business_id, 'user_id' => auth()->id(), 'type' => $type, 'platform' => 'cash', 'transaction_type' => $request->transaction_type, 'amount' => $amount, 'from_bank' => null, 'to_bank' => ($request->transaction_type === 'cash_to_bank') ? $request->to : null, 'date' => $request->date ?? now(), 'image' => $request->image ? $this->upload($request, 'image') : NULL, 'note' => $request->note, ]); DB::commit(); return response()->json([ 'message' => __('Transaction completed successfully.'), 'redirect' => route('business.cashes.index'), ]); } catch (\Exception $e) { DB::rollBack(); return response()->json([ 'message' => 'Error: ' . $e->getMessage(), ], 500); } } public function update(Request $request, string $id) { $request->validate([ 'to' => 'nullable|exists:payment_types,id', 'type' => 'nullable|in:credit,debit', 'transaction_type' => 'required|in:cash_to_bank,adjust_cash', 'amount' => 'required|numeric|min:0.01', 'date' => 'nullable|date', 'image' => 'nullable|image|mimes:jpg,png,jpeg,svg', 'note' => 'nullable|string', ]); $transaction = Transaction::findOrFail($id); $newAmount = $request->amount ?? 0; $newTransactionType = $request->transaction_type; $type = 'transfer'; DB::beginTransaction(); try { // Transaction type is the same if ($transaction->transaction_type === $newTransactionType) { if ($newTransactionType === 'cash_to_bank') { $toBank = PaymentType::findOrFail($request->to); // Adjust balance difference $diff = $newAmount - $transaction->amount; // Prevent negative balance if ($toBank->balance + $diff < 0) { return response()->json([ 'message' => 'Cannot update: updated bank balance would be negative.' ], 400); } $toBank->increment('balance', $diff); } elseif ($newTransactionType === 'adjust_cash') { $type = $request->type; } } // Transaction type changed else { // Reverse old transaction effect if ($transaction->transaction_type === 'cash_to_bank' && $transaction->to_bank) { $prevBank = PaymentType::find($transaction->to_bank); if ($prevBank) { if ($prevBank->balance < $transaction->amount) { return response()->json([ 'message' => 'Cannot update: insufficient balance in ' . $prevBank->name . ' to reverse previous transaction.' ], 400); } $prevBank->decrement('balance', $transaction->amount); } } // Apply new transaction effect if ($newTransactionType === 'cash_to_bank') { $toBank = PaymentType::findOrFail($request->to); $toBank->increment('balance', $newAmount); $type = 'transfer'; } elseif ($newTransactionType === 'adjust_cash') { $type = $request->type; } } // Update transaction record $transaction->update([ 'type' => $type, 'transaction_type' => $newTransactionType, 'amount' => $newAmount, 'to_bank' => ($newTransactionType === 'cash_to_bank') ? $request->to : null, 'date' => $request->date ?? now(), 'image' => $request->image ? $this->upload($request, 'image') : $transaction->image, 'note' => $request->note, ]); DB::commit(); return response()->json([ 'message' => __('Transaction updated successfully.'), 'redirect' => route('business.cashes.index'), ]); } catch (\Exception $e) { DB::rollBack(); return response()->json([ 'message' => 'Error: ' . $e->getMessage(), ], 500); } } public function destroy(string $id) { $transaction = Transaction::findOrFail($id); DB::beginTransaction(); try { // Allow only "cash" platform transactions to be deleted if ($transaction->platform !== 'cash') { return response()->json([ 'message' => 'Cannot delete here, please delete from ' . ucfirst($transaction->platform) . ' section.', ], 400); } $amount = $transaction->amount; $toBank = $transaction->to_bank ? PaymentType::find($transaction->to_bank) : null; // Reverse balance changes based on transaction type switch ($transaction->transaction_type) { case 'cash_to_bank': if ($toBank) { // Ensure bank has enough balance to reverse if ($toBank->balance < $amount) { return response()->json([ 'message' => 'Cannot delete: bank balance would go negative.', ], 400); } $toBank->decrement('balance', $amount); } break; case 'adjust_cash': // Cash is static, so no bank adjustments needed break; } if (file_exists($transaction->image)) { Storage::delete($transaction->image); } $transaction->delete(); DB::commit(); return response()->json([ 'message' => __('Cash transaction reversed and deleted successfully.'), 'redirect' => route('business.cashes.index'), ]); } catch (\Exception $e) { DB::rollBack(); return response()->json([ 'message' => 'Error: ' . $e->getMessage(), ], 500); } } }