diff --git a/app/Libraries/NaverApiClient.php b/app/Libraries/NaverApiClient.php index e6530ad..6bfd12b 100644 --- a/app/Libraries/NaverApiClient.php +++ b/app/Libraries/NaverApiClient.php @@ -31,6 +31,13 @@ class NaverApiClient return $this->request('PUT', $url, $updateData); } + public function submitSyncResult(string $reserveNoList): ?array + { + $url = "{$this->baseUrl}/site/submitSyncResult.nhn"; + $url .= '?reserveNoList=' . $reserveNoList; + return $this->request('GET', $url); + } + /** * CURL 공통 실행 함수 */ diff --git a/app/Services/NaverService.php b/app/Services/NaverService.php index 87e9982..a4819d5 100644 --- a/app/Services/NaverService.php +++ b/app/Services/NaverService.php @@ -103,104 +103,156 @@ class NaverService * [Type S] 현장확인 응답 처리 (A01 등) */ private function processTypeS($articleNumber, $rawData, $payload) -{ - $now = date('Y-m-d H:i:s'); - - // 시작 전 트랜잭션 - $this->db->transStart(); + { + $now = db_now(); + + // 시작 전 트랜잭션 + $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())); + + switch ( trim($rawData['tradeType']) ) { + case '매매': $trade_type = 'A1'; break; + case '전세': $trade_type = 'B1'; break; + case '월세': $trade_type = 'B2'; break; + case '단기임대': $trade_type = 'B3'; break; } - $rcpt_sq = $this->receiptModel->getInsertID(); + /* 좌표와 전용면적을 기준으로 */ + if( in_array($rawData['realEstateTypeCode'], array('C01', 'C02'))){ + $ground_plan = 'N'; + } else { + $ground_plan = 'Y'; + } - if ( $receiptData['isVrVerification'] == "Y") { - $dept_sq = '29'; - $usr_sq = '1993'; + try { + // 1. receipt 데이터 준비 + $receiptData = [ + 'comp_sq' => '2', + 'rcpt_rating' => '3', + 'rcpt_key' => $articleNumber, + 'rcpt_atclno' => $articleNumber, + '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_info4'=> $rawData['price']['preSaleAmount'] ?? '0', + 'rcpt_product_info5'=> $rawData['price']['premiumAmount'] ?? '0', + 'rcpt_living_yn' => ($rawData['site']['isRegistration'] ?? false) ? 'Y' : 'N', + '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_ptp_nm' => null, + 'rcpt_ptp_no' => $rawData['address']['pyeongTypeNumber'] ?? 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_exps_type' => '', + 'rcpt_exp_photo_yn' => 'Y', + 'rcpt_deal_type' => $rawData['tradeTypeCode'] ?? null, + 'rcpt_product_nm' => $rawData['tradeType'] ?? null, + 'trade_type' => $trade_type ?? null, + 'ground_plan' => $ground_plan, + 'excls_spce' => $rawData['space']['exclusiveSpace'] ?? null, + 'sply_spc' => $rawData['space']['supplySpace'] ?? null, + 'tot_spc' => $rawData['space']['totalSpace'] ?? null, + 'grnd_spc' => $rawData['space']['groundSpace'] ?? null, + 'bldg_spc' => $rawData['space']['buildingSpace'] ?? null, + 'share_spc' => $rawData['space']['supplySpace']-$rawData['space']['exclusiveSpace'] ?? null, + 'room_cnt' => $rawData['facilities']['roomCount'] ?? null, + 'cupnNo' => $rawData['couponNumber'] ?? null, + 'roomSiteAtclRgstCnt' => $rawData['site']['monthlyRegisterCount'] ?? null, + 'roomSiteAtclExpsCnt' => $rawData['site']['monthlyExposureCount'] ?? null, + 'direct_trad_yn' => ($rawData['seller']['isDirectTrade'] ?? false) ? 'Y' : 'N', + 'sellr_nm' => $rawData['seller']['sellerName'] ?? null, + 'sellr_tel_no' => $rawData['seller']['sellerTelephoneNumber'] ?? null, + 'rcpt_ref_addr' => $rawData['address']['etcAddress'] ?? null, + 'rcpt_tm' => $now, + 'rcpt_stat' => '100000', + 'rcpt_x' => $rawData['address']['longitude'] ?? null, + 'rcpt_y' => $rawData['address']['latitude'] ?? null, + 'agent_id' => '', + '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', + 'isPromotionApply' => ($rawData['site']['isVrRepresentativeApply'] ?? 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['site']['isRegistration'] ?? false) ? 'Y' : 'N', + ]; + + if (!$this->resultModel->insert($resultData)) { + throw new \Exception("Result Insert 실패"); + } + + $this->db->transComplete(); + // 성공 로그 생성 쿼리 포함 + write_custom_log("Type S 처리 성공 | Atcl: $articleNumber | Rcpt_sq: $rcpt_sq", 'INFO', 'service'); + write_custom_log("Receipt Insert SQL: " . (string)$this->receiptModel->getLastQuery(), 'INFO', 'service'); + write_custom_log("Result Insert SQL: " . (string)$this->resultModel->getLastQuery(), 'INFO', 'service'); + + // 예약 정보 동기화 전송 + $return = $this->naverClient->submitSyncResult($rawData['reserveNo']); + write_custom_log("Naver Sync Result Response: " . json_encode($return), 'INFO', 'service'); + + // transComplete 이후에 transStatus를 확인하는 것이 CI4의 표준입니다. + if ($this->db->transStatus() === false) { + // transComplete가 실패하면 자동으로 롤백되지만, 명시적 예외 처리가 안전합니다. + // 로그 남기기 + write_custom_log("Type S DB 트랜잭션 최종 실패", 'ERROR', 'service'); + throw new \Exception("Type S DB 트랜잭션 최종 실패"); + } + + return $rcpt_sq; + + } catch (\Exception $e) { + // 이미 transComplete 내부에서 실패 시 롤백되지만, 예외 발생 시 수동 롤백 보장 + // if ($this->db->transEnabled()) { + $this->db->transRollback(); + // } + throw $e; } - - // 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; } -} + public function processTypeV2($articleNumber, $rawData, $payload){ + + } + + /** * [REG] 신규 등록