diff --git a/app/Models/Entities/NaverRawStagingModel.php b/app/Models/Entities/NaverRawStagingModel.php new file mode 100644 index 0000000..364ed73 --- /dev/null +++ b/app/Models/Entities/NaverRawStagingModel.php @@ -0,0 +1,19 @@ +db->table('receipt a'); diff --git a/app/Models/Entities/ResultModel.php b/app/Models/Entities/ResultModel.php new file mode 100644 index 0000000..61fc563 --- /dev/null +++ b/app/Models/Entities/ResultModel.php @@ -0,0 +1,43 @@ +select('result.*, receipt.rcpt_atclno, receipt.rcpt_product_nm') + ->join('receipt', 'receipt.rcpt_sq = result.rcpt_sq') + ->where('result.rcpt_sq', $rcpt_sq) + ->first(); + } +} \ No newline at end of file diff --git a/app/Services/NaverService.php b/app/Services/NaverService.php index b51b25b..87e9982 100644 --- a/app/Services/NaverService.php +++ b/app/Services/NaverService.php @@ -6,19 +6,30 @@ use CodeIgniter\CLI\CLI; use App\Libraries\NaverApiClient; use App\Models\Entities\VrfcReqModel; use App\Models\Entities\V2stdailyModel; +use App\Models\Entities\NaverRawStagingModel; +use App\Models\Entities\ReceiptModel; +use App\Models\Entities\ResultModel; use App\Services\StatusService; // 추가 use Exception; class NaverService { - protected $naverClient, $VrfcReqModel, $V2stdailyModel, $statusService; + protected $db; + protected $naverClient, $VrfcReqModel, $V2stdailyModel, $statusService, $rawStagingModel, $receiptModel, $resultModel; public function __construct() { + $this->db = \Config\Database::connect(); + $this->naverClient = new NaverApiClient(); $this->VrfcReqModel = model(VrfcReqModel::class); $this->V2stdailyModel = model(V2stdailyModel::class); + $this->rawStagingModel = model(NaverRawStagingModel::class); + + $this->receiptModel = model(ReceiptModel::class); + $this->resultModel = model(ResultModel::class); $this->statusService = new StatusService(); // 인스턴스 생성 + helper('log'); } @@ -36,37 +47,161 @@ class NaverService throw new \Exception("네이버 API 응답 에러: $articleNumber"); } - $vrfcParams = $this->mapToDatabaseParams($response['data'], $payload); - write_custom_log("PROCESS_START | Type: $requestType | Atcl: $articleNumber", 'INFO', 'service'); + $rawData = $response['data']; + $vType = $rawData['verificationTypeCode'] ?? ''; - switch ($requestType) { - case 'REG': // 신규 등록 - $vr_sq = $this->insertVrfcReq($articleNumber, $vrfcParams); - if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], $vrfcParams['vrfc_type'] . '0103', '1', 'add'); - break; + // 2. [Staging] 원본 DB 저장 (JSON 타입 컬럼 활용) + $this->rawStagingModel->insert([ + 'atcl_no' => $articleNumber, + 'verification_type' => $vType, + 'request_type' => $requestType, + 'raw_json' => $rawData // 모델에서 json_encode 처리됨 + ]); - case 'MOD': // 수정 - $vr_sq = $this->updateVrfcReq($articleNumber, $vrfcParams); - if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], $vrfcParams['vrfc_type'] . '0102', '1', 'add'); - break; - - case 'CNC': // 취소 - $vr_sq = $this->deleteVrfcReq($articleNumber, $vrfcParams); - if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], 'A0101', '1', 'add'); - break; - - // case 'FIN': // 완료 - // $vr_sq = $this->finVrfcReq($articleNumber, $vrfcParams); - // if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], 'A0101', '1', 'add'); - // break; - - default: - throw new \Exception("알 수 없는 requestType: $requestType"); + // 3. 타입별 분기 처리 + if ($vType === 'S') { + // [Type S] 현장확인 응답 처리 (A01 등) + return $this->processTypeS($articleNumber, $rawData, $payload); + } else { + // [Type D/기타] 서류확인/비공동 처리 (D04, F01 등) + return $this->processTypeV2($articleNumber, $rawData, $payload); } - return ['vr_sq' => $vr_sq, 'articleNumber' => $articleNumber]; + // $vrfcParams = $this->mapToDatabaseParams($response['data'], $payload); + // write_custom_log("PROCESS_START | Type: $requestType | Atcl: $articleNumber", 'INFO', 'service'); + + // switch ($requestType) { + // case 'REG': // 신규 등록 + // $vr_sq = $this->insertVrfcReq($articleNumber, $vrfcParams); + // if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], $vrfcParams['vrfc_type'] . '0103', '1', 'add'); + // break; + + // case 'MOD': // 수정 + // $vr_sq = $this->updateVrfcReq($articleNumber, $vrfcParams); + // if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], $vrfcParams['vrfc_type'] . '0102', '1', 'add'); + // break; + + // case 'CNC': // 취소 + // $vr_sq = $this->deleteVrfcReq($articleNumber, $vrfcParams); + // if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], 'A0101', '1', 'add'); + // break; + + // // case 'FIN': // 완료 + // // $vr_sq = $this->finVrfcReq($articleNumber, $vrfcParams); + // // if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], 'A0101', '1', 'add'); + // // break; + + // default: + // throw new \Exception("알 수 없는 requestType: $requestType"); + // } + + // return ['vr_sq' => $vr_sq, 'articleNumber' => $articleNumber]; } + + /** + * [Type S] 현장확인 응답 처리 (A01 등) + */ + private function processTypeS($articleNumber, $rawData, $payload) +{ + $now = date('Y-m-d H:i:s'); + + // 시작 전 트랜잭션 + $this->db->transStart(); + + try { + // 1. receipt 데이터 준비 + $receiptData = [ + 'comp_sq' => '2', + 'rcpt_rating' => '3', + 'rcpt_key' => $rawData['cpArticleNumber'] ?? '', + 'rcpt_atclno' => $articleNumber, + 'rcpt_type' => 'C', + 'rcpt_product' => $rawData['realEstateTypeCode'] ?? null, + 'rcpt_product_nm' => $rawData['realEstateType'] ?? null, + 'rcpt_product_info1'=> $rawData['tradeType'] ?? null, + 'rcpt_product_info2'=> $rawData['price']['dealAmount'] ?? '0', + 'rcpt_product_info3'=> $rawData['price']['leaseAmount'] ?? '0', + 'rcpt_living_yn' => ($rawData['site']['isRegistration'] ?? false) ? 'Y' : 'N', + 'rcpt_office' => $rawData['realtor']['realtorName'] ?? null, + 'rcpt_agent' => $rawData['realtor']['realtorName'] ?? null, + 'rcpt_sido' => mb_substr($rawData['address']['legalDivision']['cityNumber'] ?? '', 0, 5), + 'rcpt_gugun' => mb_substr($rawData['address']['legalDivision']['divisionNumber'] ?? '', 0, 10), + 'rcpt_dong' => $rawData['address']['legalDivision']['sectorNumber'] ?? null, + 'rcpt_hscp_nm' => $rawData['address']['complexName'] ?? null, + 'rcpt_hscp_no' => $rawData['address']['complexNumber'] ?? null, + 'rcpt_dtl_addr' => trim(($rawData['address']['legalDivision']['legalDivisionAddress'] ?? '') . $rawData['address']['buildingName'] . '동 ' . ($rawData['address']['hoName'] ?? '') . '호'), + 'rcpt_etc_addr' => $rawData['address']['hoName'] ?? null, + 'rcpt_floor' => $rawData['floor']['correspondenceFloorCount'] ?? null, + 'rcpt_floor2' => $rawData['floor']['totalFloorCount'] ?? null, + 'rcpt_tm' => $now, + 'rcpt_stat' => '100000', + 'rcpt_x' => $rawData['address']['longitude'] ?? null, + 'rcpt_y' => $rawData['address']['latitude'] ?? null, + 'agent_id' => $rawData['realtor']['realtorName'] ?? null, + 'agent_nm' => $rawData['realtor']['realtorName'] ?? null, + 'agent_head_tel' => $rawData['realtor']['representativeCellphoneNumber'] ?? null, + 'rsrv_date' => $rawData['site']['visitReserveDate'] ?? null, + 'rsrv_tm_ap' => '00', // 컬럼명이 rsrv_tm_ap 인지 확인 필요 (제공해주신 스키마 기준) + 'insert_tm' => $now, + 'rcpt_cpid' => $rawData['cpId'] ?? 'naver', + 'room_cnt' => $rawData['facilities']['roomCount'] ?? null, + 'isSiteVRVerification' => ($rawData['site']['isVrVerification'] ?? false) ? 'Y' : 'N' + ]; + + if (!$this->receiptModel->insert($receiptData)) { + throw new \Exception("Receipt Insert 실패: " . json_encode($this->receiptModel->errors())); + } + + $rcpt_sq = $this->receiptModel->getInsertID(); + + if ( $receiptData['isVrVerification'] == "Y") { + $dept_sq = '29'; + $usr_sq = '1993'; + } + + // 2. result 데이터 준비 + $resultData = [ + 'rcpt_sq' => $rcpt_sq, + 'use_yn' => 'Y', + 'cust_nm' => '', + 'rsrv_date' => $rawData['site']['visitReserveDate'] ?? null, + 'rsrv_tm_ap' => '00', // 컬럼명이 rsrv_tm_ap 인지 확인 필요 (제공해주신 스키마 기준) + 'result_cd1' => '10', + 'result_cd2' => '1000', + 'result_cd3' => '100000', + 'insert_tm' => $now, + 'insert_usr' => 0, + 'update_tm' => $now, + 'update_usr' => 0, + 'dept_sq' => $dept_sq, // 필요 시 매핑 로직 추가 + 'usr_sq' => $usr_sq, // 필요 시 매핑 로직 추가 + 'resYn' => ($rawData['verificationResult']['isSuccessful'] ?? false) ? 'Y' : 'N', + ]; + + if (!$this->resultModel->insert($resultData)) { + throw new \Exception("Result Insert 실패"); + } + + $this->db->transComplete(); + + // transComplete 이후에 transStatus를 확인하는 것이 CI4의 표준입니다. + if ($this->db->transStatus() === false) { + // transComplete가 실패하면 자동으로 롤백되지만, 명시적 예외 처리가 안전합니다. + throw new \Exception("Type S DB 트랜잭션 최종 실패"); + } + + return $rcpt_sq; + + } catch (\Exception $e) { + // 이미 transComplete 내부에서 실패 시 롤백되지만, 예외 발생 시 수동 롤백 보장 + if ($this->db->transEnabled()) { + $this->db->transRollback(); + } + throw $e; + } +} + /** * [REG] 신규 등록 */