user() ?? Auth::guard('receptionist')->user(); if (!$user) return response()->json(['message' => 'Unauthenticated'], 401); $query = Expense::with(['branch', 'category']); $branchId = $user->isReceptionist() ? $user->branch_id : $request->query('branch_id'); $startDate = $request->query('start_date'); $endDate = $request->query('end_date'); if ($branchId) { $query->where('branch_id', $branchId); } if ($startDate) { $query->where('date', '>=', $startDate); } if ($endDate) { $query->where('date', '<=', $endDate); } return response()->json($query->orderBy('date', 'desc')->get()); } public function store(Request $request) { $user = Auth::guard('web')->user() ?? Auth::guard('receptionist')->user(); if (!$user) return response()->json(['message' => 'Unauthenticated'], 401); $data = $request->all(); if ($user->isReceptionist()) { $data['branch_id'] = $user->branch_id; } $validated = \Illuminate\Support\Facades\Validator::make($data, [ 'date' => 'required|date', 'branch_id' => 'required|exists:branches,id', 'expense_category_id' => 'required|exists:expense_categories,id', 'expense_type' => 'required|string|in:Account,Petty Cash', 'amount' => 'required|numeric|min:0', 'remarks' => 'nullable|string' ])->validate(); // Security check for branch_id if receptionist if ($user->isReceptionist() && $validated['branch_id'] != $user->branch_id) { return response()->json(['message' => 'Unauthorized branch assignment'], 403); } $expense = Expense::create($validated); // Auto-ledgering: Debit from Accounts Account::create([ 'date' => $expense->date, 'time' => Carbon::now()->toTimeString(), 'credit' => 0, 'debit' => $expense->amount, 'type' => 'expense', 'branch_id' => $expense->branch_id, 'accountable_id' => $expense->id, 'accountable_type' => Expense::class, 'description' => "Expense: {$expense->category->name} - {$expense->remarks}" ]); return response()->json($expense->load(['branch', 'category']), 201); } public function getCategories() { return response()->json(ExpenseCategory::where('status', 'Active')->get()); } public function getBranches() { $user = Auth::guard('web')->user() ?? Auth::guard('receptionist')->user(); $query = Branch::where('status', 'Active'); if ($user && $user->isReceptionist()) { $query->where('id', $user->branch_id); } return response()->json($query->get()); } public function getSalaryHistory(Request $request) { $user = Auth::guard('web')->user() ?? Auth::guard('receptionist')->user(); if (!$user) return response()->json(['message' => 'Unauthenticated'], 401); $salaryCategory = ExpenseCategory::where('name', 'Salary')->first(); if (!$salaryCategory) return response()->json([]); $query = Expense::with(['branch']) ->where('expense_category_id', $salaryCategory->id); if ($user->isReceptionist()) { $query->where('branch_id', $user->branch_id); } $expenses = $query->orderBy('date', 'desc')->get(); // Group by batch_id $grouped = $expenses->groupBy(function ($item) { return $item->batch_id ?? 'INDIVIDUAL-' . $item->id; })->map(function ($items, $batchId) { $first = $items->first(); $isBulk = strpos($batchId, 'BATCH-') === 0; return [ 'batch_id' => $isBulk ? $batchId : null, 'is_bulk' => $isBulk, 'date' => $first->date, 'branch' => $first->branch?->name ?? 'Mixed', 'amount' => $items->sum('amount'), 'remarks' => $isBulk ? "Bulk Salary Release" : $first->remarks, 'count' => $items->count(), 'items' => $items // Optional: for detail view ]; })->values(); return response()->json($grouped); } }