quoteModel = new MotorQuoteModel(); $this->executor = new DigitExecutorService(); } // ===================== LIST ===================== public function list() { if (strtolower($this->request->getMethod()) === 'post') { $filters = [ 'status' => $this->request->getPost('status'), 'enquiry_id' => $this->request->getPost('enquiry_id'), 'quote_number' => $this->request->getPost('quote_number'), 'license_plate' => $this->request->getPost('license_plate'), ]; $data['quotes'] = $this->quoteModel->getListWithVehicle($filters); return view('digit_motor/list_table', $data); } $data['quotes'] = $this->quoteModel->getListWithVehicle(); $data['statuses'] = [ 'DRAFT' => 'Draft', 'QUOTED' => 'Quoted', 'CREATED' => 'Created', 'KYC_DONE' => 'KYC Done', 'PAID' => 'Paid', 'EFFECTIVE' => 'Effective', 'FAILED' => 'Failed', ]; $data['title'] = 'Digit Motor Quotes'; return $this->loadLayout('digit_motor/list', $data); } // ===================== JOURNEY UI ===================== public function journey($quoteId = null) { $data['title'] = 'Digit Motor Journey'; $data['quote'] = null; $data['quote_id'] = null; if ($quoteId) { $data['quote'] = $this->quoteModel->getDetail((int) $quoteId); $data['quote_id'] = (int) $quoteId; if (!$data['quote']) { return redirect()->to(base_url('digit-motor/list'))->with('error', 'Quote not found.'); } } return $this->loadLayout('digit_motor/journey', $data); } public function detail($quoteId) { $detail = $this->quoteModel->getDetail((int) $quoteId); if (!$detail) { return $this->respond(['status' => false, 'message' => 'Quote not found.'], 404); } return $this->respond(['status' => true, 'data' => $detail]); } // ===================== API ACTIONS ===================== public function quickQuote() { return $this->runAction(function () { $input = $this->request->getJSON(true) ?: $this->request->getPost(); $rules = [ 'license_plate_number' => 'required|min_length[4]', 'vehicle_maincode' => 'required', 'registration_date' => 'required', 'manufacture_date' => 'required', 'pincode' => 'required|exact_length[6]', ]; if (!$this->validateDigitInput($input, $rules)) { return $this->respond([ 'status' => false, 'message' => 'Validation failed.', 'errors' => $this->validator->getErrors(), ], 422); } $result = $this->executor->quickQuote($input); return $this->respond([ 'status' => true, 'message' => 'Quick quote generated.', 'data' => $result, ]); }); } public function createQuote($quoteId = null) { return $this->runAction(function () use ($quoteId) { $input = $this->request->getJSON(true) ?: $this->request->getPost(); $quoteId = (int) ($quoteId ?: ($input['quote_id'] ?? 0)); if ($quoteId <= 0) { return $this->respond(['status' => false, 'message' => 'quote_id is required.'], 422); } $result = $this->executor->createQuote($quoteId, $input); return $this->respond([ 'status' => true, 'message' => 'Quote created.', 'data' => $result, ]); }); } public function kycStatus($quoteId) { return $this->runAction(function () use ($quoteId) { $result = $this->executor->kycStatus((int) $quoteId); return $this->respond([ 'status' => true, 'message' => 'KYC status fetched.', 'data' => $result, ]); }); } public function paymentLink($quoteId) { return $this->runAction(function () use ($quoteId) { $input = $this->request->getJSON(true) ?: $this->request->getPost(); $result = $this->executor->paymentLink((int) $quoteId, $input ?: []); return $this->respond([ 'status' => true, 'message' => 'Payment link generated.', 'data' => $result, ]); }); } public function policyStatus($quoteId) { return $this->runAction(function () use ($quoteId) { $result = $this->executor->policyStatus((int) $quoteId); return $this->respond([ 'status' => true, 'message' => 'Policy status fetched.', 'data' => $result, ]); }); } public function policyPdf($quoteId) { return $this->runAction(function () use ($quoteId) { $result = $this->executor->policyPdf((int) $quoteId); return $this->respond([ 'status' => true, 'message' => 'Policy PDF fetched.', 'data' => $result, ]); }); } public function paymentCallback($outcome, $quoteId) { $quoteId = (int) $quoteId; if ($outcome === 'success' && $quoteId > 0) { try { $this->executor->policyStatus($quoteId); } catch (\Throwable $e) { log_message('error', 'DigitMotor payment callback policyStatus: ' . $e->getMessage()); } } return redirect()->to(base_url('digit-motor/journey/' . $quoteId)) ->with($outcome === 'success' ? 'success' : 'error', $outcome === 'success' ? 'Payment return received. Refreshing policy status.' : 'Payment was cancelled or failed.'); } protected function runAction(callable $fn) { try { return $fn(); } catch (DigitApiException $e) { log_message('error', 'DigitMotor API error: ' . $e->getMessage() . ' code=' . $e->getDigitCode()); $http = $e->getHttpStatus() >= 400 ? $e->getHttpStatus() : 502; if ($e->isInfraError()) { $http = 502; } return $this->respond([ 'status' => false, 'message' => $e->getMessage(), 'digit_code' => $e->getDigitCode(), 'infra' => $e->isInfraError(), ], min($http, 599)); } catch (\Throwable $e) { log_message('error', 'DigitMotor unexpected error: ' . $e->getMessage()); return $this->respond([ 'status' => false, 'message' => 'Something went wrong. Please try again.', ], 500); } } protected function validateDigitInput(array $data, array $rules): bool { $this->validator = \Config\Services::validation(); $this->validator->setRules($rules); return $this->validator->run($data); } }