isGoldCreditEnabled()) { abort(403, 'اعتبار طلایی برای این نسخه فعال نیست'); } } public function store(Request $request) { $this->ensureEnabled(); $data = $request->validate([ 'customer_id' => 'required|integer|exists:customers,id', 'gold_amount' => 'required|numeric|min:0.001', 'months' => 'required|integer|min:1|max:120', 'interest_type' => 'nullable|in:none,percent,fixed_gram', 'interest_value' => 'nullable|numeric|min:0', 'delivery_method' => 'nullable|in:auto,manual,in_person', 'notes' => 'nullable|string', 'has_check' => 'nullable|boolean', 'has_contract' => 'nullable|boolean', 'check_note' => 'nullable|string|max:255', 'contract_note' => 'nullable|string|max:255', 'penalty_type' => 'nullable|in:rial,gold', 'penalty_amount' => 'nullable|numeric|min:0', 'grace_hours' => 'nullable|integer|min:0|max:720', ]); $credit = $this->service->createCredit($data, auth()->id(), 'admin_direct'); return response()->json($credit); } public function update(Request $request, int $id) { $this->ensureEnabled(); $data = $request->validate([ 'gold_amount' => 'nullable|numeric|min:0.001', 'months' => 'nullable|integer|min:1|max:120', 'interest_type' => 'nullable|in:none,percent,fixed_gram', 'interest_value' => 'nullable|numeric|min:0', 'notes' => 'nullable|string', 'status' => 'nullable|in:cancelled', 'has_check' => 'nullable|boolean', 'has_contract' => 'nullable|boolean', 'check_note' => 'nullable|string|max:255', 'contract_note' => 'nullable|string|max:255', 'penalty_type' => 'nullable|in:rial,gold', 'penalty_amount' => 'nullable|numeric|min:0', 'grace_hours' => 'nullable|integer|min:0|max:720', ]); $credit = $this->service->updateCredit($id, $data); return response()->json($credit); } public function table(Request $request) { $this->ensureEnabled(); $data = $request->all(); if (isset($data['select']) && is_null($data['select'])) { $data['select'] = []; } $query = GoldCredit::with(['customer:id,name,mobile', 'creator:id,name']) ->whereIn('status', ['pending', 'active', 'completed']); TableEngine::create($query, $data) ->initSearch(['notes', 'customer.name', 'customer.mobile']) ->select(['*']) ->export($query); return $query; } public function requestsTable(Request $request) { $this->ensureEnabled(); $data = $request->all(); if (isset($data['select']) && is_null($data['select'])) { $data['select'] = []; } $query = GoldCreditRequest::with(['customer:id,name,mobile']); TableEngine::create($query, $data) ->initSearch(['note', 'admin_note', 'customer.name', 'customer.mobile']) ->select(['*']) ->export($query); return $query; } public function customerInstallments(Request $request, int $customerId) { $this->ensureEnabled(); $credit = GoldCredit::with('installments') ->where('customer_id', $customerId) ->whereIn('status', ['pending', 'active', 'completed']) ->orderByDesc('id') ->first(); if (!$credit) { return response()->json(['rows' => [], 'total' => 0, 'credit' => null]); } $this->service->refreshOverdueStatuses($credit); return response()->json([ 'rows' => $credit->installments, 'total' => $credit->installments->count(), 'credit' => $credit, ]); } public function approveRequest(Request $request, int $id) { $this->ensureEnabled(); $data = $request->validate([ 'gold_amount' => 'nullable|numeric|min:0.001', 'months' => 'required|integer|min:1|max:120', 'interest_type' => 'nullable|in:none,percent,fixed_gram', 'interest_value' => 'nullable|numeric|min:0', 'delivery_method' => 'nullable|in:auto,manual,in_person', 'admin_note' => 'nullable|string', 'notes' => 'nullable|string', 'has_check' => 'nullable|boolean', 'has_contract' => 'nullable|boolean', 'check_note' => 'nullable|string|max:255', 'contract_note' => 'nullable|string|max:255', 'penalty_type' => 'nullable|in:rial,gold', 'penalty_amount' => 'nullable|numeric|min:0', 'grace_hours' => 'nullable|integer|min:0|max:720', ]); $credit = $this->service->approveRequest($id, $data, auth()->id()); return response()->json($credit); } public function rejectRequest(Request $request, int $id) { $this->ensureEnabled(); $data = $request->validate([ 'admin_note' => 'nullable|string', ]); $result = $this->service->rejectRequest($id, $data['admin_note'] ?? null); return response()->json($result); } public function payInstallments(Request $request) { $this->ensureEnabled(); $data = $request->validate([ 'gold_credit_id' => 'required|integer|exists:gold_credits,id', 'installment_ids' => 'required|array|min:1', 'installment_ids.*' => 'integer|exists:gold_credit_installments,id', 'pay_method' => 'required|in:gold,rial,mixed', 'gold_amount' => 'nullable|numeric|min:0', 'rial_amount' => 'nullable|integer|min:0', ]); $credit = GoldCredit::findOrFail($data['gold_credit_id']); $result = $this->service->payInstallments( $credit, $data['installment_ids'], $data['pay_method'], $data['gold_amount'] ?? null, $data['rial_amount'] ?? null, auth()->id() ); return response()->json($result); } public function preview(Request $request) { $this->ensureEnabled(); $data = $request->validate([ 'gold_amount' => 'required|numeric|min:0.001', 'months' => 'required|integer|min:1|max:120', 'interest_type' => 'nullable|in:none,percent,fixed_gram', 'interest_value' => 'nullable|numeric|min:0', ]); $plan = $this->service->buildInstallmentPlan( (float) $data['gold_amount'], (int) $data['months'], $data['interest_type'] ?? 'none', (float) ($data['interest_value'] ?? 0) ); return response()->json($plan); } }