api
This commit is contained in:
@@ -81,139 +81,5 @@ class NaverWorker extends BaseCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function insertVrfc($payload)
|
|
||||||
{
|
|
||||||
// 1. 필수 데이터 검증
|
|
||||||
if (empty($payload['articleNumber']) || empty($payload['requestType'])) {
|
|
||||||
throw new \Exception("필수 파라미터 누락");
|
|
||||||
}
|
|
||||||
|
|
||||||
$articleNumber = $payload['articleNumber'];
|
|
||||||
$requestType = $payload['requestType'];
|
|
||||||
$requestDatetime = date('Y-m-d H:i:s', strtotime($payload['requestDatetime']));
|
|
||||||
|
|
||||||
$vrfcModel = model(\App\Models\VrfcReqModel::class);
|
|
||||||
// 중복 요청 체크
|
|
||||||
$existing = $vrfcModel->where('atcl_no', $articleNumber)
|
|
||||||
->where('req_type', $requestType)
|
|
||||||
->first();
|
|
||||||
if ($existing) {
|
|
||||||
throw new \Exception("중복 요청: " . $articleNumber . " / " . $requestType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 네이버 API 클라이언트 초기화
|
|
||||||
$naverClient = new \App\Libraries\NaverApiClient();
|
|
||||||
// 매물 정보 조회
|
|
||||||
$articleInfojson = $naverClient->getArticleInfo($articleNumber);
|
|
||||||
// if (!$articleInfojson || !isset($articleInfojson['data']) || empty($articleInfojson['code'] !== 'success')) {
|
|
||||||
// throw new \Exception("매물 정보 조회 실패: $articleNumber ::: message : " . ($articleInfojson['message'] ?? 'No response'));
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!$articleInfojson || !isset($articleInfojson['data']) || $articleInfojson['code'] !== 'success') {
|
|
||||||
$msg = $articleInfojson['message'] ?? 'No message';
|
|
||||||
throw new \Exception("네이버 API 응답 에러: $articleNumber | 메시지: $msg");
|
|
||||||
}
|
|
||||||
|
|
||||||
$articleInfo = $articleInfojson['data'];
|
|
||||||
|
|
||||||
// 받아온 정보 로그 기록
|
|
||||||
CLI::write("DEBUG: write_custom_log 호출 직전");
|
|
||||||
write_custom_log("ARTICLE_INFO | ArticleNumber: $articleNumber | Info: " . json_encode($articleInfo , JSON_UNESCAPED_UNICODE), 'INFO', 'service');
|
|
||||||
CLI::write("DEBUG: write_custom_log 호출 완료");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* $articleInfo['verificationTypeCode']
|
|
||||||
* S : 현장확인매물
|
|
||||||
* D : 홍보확인서
|
|
||||||
* N : 신홍보확인서
|
|
||||||
* M : 모바일
|
|
||||||
* T : 전화
|
|
||||||
* O : 모바일확인V2
|
|
||||||
*
|
|
||||||
* S - reciept , result 테이블 사용
|
|
||||||
* D,N,M,T,O - v2_vrfc_req , v2_article_info , v2_article_info_etc , v2_article_fail 테이블 사용
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {"code":"success","message":"","data":{"articleNumber":"2500000001","realEstateType":"빌라/연립","realEstateTypeCode":"C02","cpId":"toad","cpArticleNumber":"15882606","tradeType":"전세","tradeTypeCode":"B1","statusTypeCode":"E12","verificationTypeCode":"M","isUnregisteredVerificationRequested":false,"isBuildingRegisterAreaCheckRequested":false,"isAutoVerificationRequested":false,"exposureStartDateTime":"2025-01-02 09:12:02","facilities":{"roomCount":2,"bathroomCount":1},"address":{"legalDivision":{"cityNumber":"1100000000","divisionNumber":"1168000000","sectorNumber":"1168010700","legalDivisionAddress":"서울특별시 강남구 신사동"},"isVirtualAddress":false,"correspondenceFloorCount":2,"longitude":0.0,"latitude":0.0},"space":{"totalSpace":34.5,"groundSpace":34.5,"buildingSpace":34.5,"supplySpace":34.5,"exclusiveSpace":34.5},"price":{"dealAmount":777777777,"warrantyAmount":2999999999,"leaseAmount":7777777},"floor":{"correspondenceFloorCount":2,"totalFloorCount":3,"undergroundFloorCount":null}}}
|
|
||||||
$comp_sq = '2';
|
|
||||||
$rcpt_rating = '3';
|
|
||||||
|
|
||||||
$files = $articleInfo['files'] ?? [];
|
|
||||||
$certRegister = [];
|
|
||||||
$confirm_doc_img_url = [];
|
|
||||||
$referenceFileUrl = [];
|
|
||||||
foreach ($files as $file) {
|
|
||||||
// 파일 처리 로직
|
|
||||||
$fileTypeCode = $file['fileTypeCode'];
|
|
||||||
if ( $fileTypeCode == 'RCDOC' ) {
|
|
||||||
$certRegister[] = $file['fileUrl'];
|
|
||||||
} elseif ( $fileTypeCode == 'ADDOC' ) {
|
|
||||||
$confirm_doc_img_url[] = $file['fileUrl'];
|
|
||||||
} elseif ( $fileTypeCode == 'REFER') {
|
|
||||||
$referenceFileUrl[] = $file['fileUrl'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$vrfc_params = [
|
|
||||||
'reqSeq' => '',
|
|
||||||
'atcl_no' => $articleInfo['articleNumber'],
|
|
||||||
'step' => '',
|
|
||||||
'cpid' => $articleInfo['cpId'],
|
|
||||||
'cp_atcl_id' => $articleInfo['cpArticleNumber'],
|
|
||||||
'trade_type' => $articleInfo['tradeTypeCode'],
|
|
||||||
'realtor_nm' => $articleInfo['realtor']['realtorName'],
|
|
||||||
'realtor_tel_no' => $articleInfo['realtor']['representativeCellphoneNumber'],
|
|
||||||
'seller_tel_no' => $articleInfo['seller']['sellerTelephoneNumber'],
|
|
||||||
'vrfc_type' => $articleInfo['verificationTypeCode'],
|
|
||||||
'rgbk_confirm' => $articleInfo['isUnregisteredVerificationRequested'] ? 'Y' : 'N',
|
|
||||||
'req_type' => '',
|
|
||||||
'rdate' => $requestDatetime ?? db_now('Y-m-d H:i:s'),
|
|
||||||
'cpTelNo' => $articleInfo['seller']['sellerTelephoneNumber'],
|
|
||||||
'stat_cd' => '10',
|
|
||||||
'try_cnt' => '0',
|
|
||||||
'insert_user' => 'admin',
|
|
||||||
'insert_tm' => db_now(),
|
|
||||||
'memo' => '',
|
|
||||||
'contact_fail_cnt' => '0',
|
|
||||||
'sync_yn' => 'N',
|
|
||||||
'reg_try_cnt' => '0',
|
|
||||||
'tel_fail_cause' => null,
|
|
||||||
'rgbk_confirm_owner_nm' => $articleInfo['seller']['ownerName'] ?? null,
|
|
||||||
'direct_trad_yn' => $articleInfo['seller']['isDirectTrade'] === true ? 'Y' : 'N',
|
|
||||||
'confirm_doc_img_url' => json_encode($confirm_doc_img_url, JSON_UNESCAPED_UNICODE),
|
|
||||||
'confirm_doc_owner_check_yn' => '',
|
|
||||||
'owner_verifiable' => null,
|
|
||||||
'vrfc_cmpl_type' => null,
|
|
||||||
'rgbk_doc_img_url' => null,
|
|
||||||
'certRegister' => json_encode($certRegister, JSON_UNESCAPED_UNICODE),
|
|
||||||
'referenceFileUrl' => json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE),
|
|
||||||
];
|
|
||||||
|
|
||||||
write_custom_log("VRFC_PARAMS | " . json_encode($vrfc_params , JSON_UNESCAPED_UNICODE), 'INFO', 'service');
|
|
||||||
|
|
||||||
|
|
||||||
// if ($articleInfo['verificationTypeCode'] == 'S') { // 현장확인매물
|
|
||||||
// // 현장확인매물 처리 로직
|
|
||||||
|
|
||||||
// } else { // 그외 일반매물
|
|
||||||
// // V2 매물 처리 로직
|
|
||||||
// $v2ArticleModel = model(\App\Models\V2ArticleModel::class);
|
|
||||||
// // 매물 번호로 중복 체크
|
|
||||||
// $existingV2 = $v2ArticleModel->where('atcl_no', $articleInfo['articleNumber'])->first();
|
|
||||||
// if ($existingV2) {
|
|
||||||
// throw new \Exception("중복 매물 번호: " . $articleInfo['articleNumber']);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// $v2ArticleModel->insert($vrfc_params);
|
|
||||||
// $vr_sq = $v2ArticleModel->getInsertID(); // 방금 삽입한 vr_sq 값 가져오기
|
|
||||||
// CLI::write("Inserted V2 Article with vr_sq: " . $vr_sq);
|
|
||||||
// // 오류 처리
|
|
||||||
// if ($v2ArticleModel->errors()) {
|
|
||||||
// $errorMessages = implode(', ', $v2ArticleModel->errors());
|
|
||||||
// throw new \Exception("V2 매물 삽입 오류: " . $errorMessages);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -11,12 +11,34 @@ if (! function_exists('write_custom_log')) {
|
|||||||
@mkdir($logDir, 0777, true);
|
@mkdir($logDir, 0777, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- 호출 위치 추적 로직 추가 ---
|
||||||
|
// debug_backtrace는 호출 스택을 가져옵니다.
|
||||||
|
// [0]은 현재 함수(write_custom_log), [1]은 이 함수를 호출한 곳입니다.
|
||||||
|
$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||||
|
$caller = $bt[1] ?? null;
|
||||||
|
$fileInfo = $bt[0] ?? null; // 파일명과 라인수는 호출 시점인 0번 인덱스에 들어있음
|
||||||
|
|
||||||
|
$location = 'unknown';
|
||||||
|
if ($caller) {
|
||||||
|
$class = $caller['class'] ?? '';
|
||||||
|
$func = $caller['function'] ?? '';
|
||||||
|
$line = $fileInfo['line'] ?? '0';
|
||||||
|
|
||||||
|
// 클래스명에서 Namespace 제외하고 클래스명만 짧게 가져오기 (선택 사항)
|
||||||
|
$classShort = substr(strrchr($class, "\\"), 1) ?: $class;
|
||||||
|
|
||||||
|
$location = "{$classShort}::{$func}:{$line}";
|
||||||
|
}
|
||||||
|
// ----------------------------
|
||||||
|
|
||||||
$suffix = ($type === 'failed') ? '_failed' : '';
|
$suffix = ($type === 'failed') ? '_failed' : '';
|
||||||
$logFile = $logDir . '/' . date('Y-m-d') . $suffix . '.log';
|
$logFile = $logDir . '/' . date('Y-m-d') . $suffix . '.log';
|
||||||
|
|
||||||
$timestamp = date('Y-m-d H:i:s');
|
$timestamp = date('Y-m-d H:i:s');
|
||||||
$singleLine = str_replace(["\r", "\n", "\t"], " ", $message);
|
$singleLine = str_replace(["\r", "\n", "\t"], " ", $message);
|
||||||
$formatted = "[$timestamp] [$level] $singleLine" . PHP_EOL;
|
|
||||||
|
// 포맷에 [$location] 추가
|
||||||
|
$formatted = "[$timestamp] [$level] [$location] $singleLine" . PHP_EOL;
|
||||||
|
|
||||||
@file_put_contents($logFile, $formatted, FILE_APPEND);
|
@file_put_contents($logFile, $formatted, FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|||||||
59
app/Models/Entities/V2chghistoryModel.php
Normal file
59
app/Models/Entities/V2chghistoryModel.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
CREATE TABLE `v2_chg_history` (
|
||||||
|
`seq` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '순번',
|
||||||
|
`vr_sq` BIGINT(20) UNSIGNED NOT NULL COMMENT '검증요청순번',
|
||||||
|
`stat_cd` VARCHAR(6) NOT NULL COMMENT '상태코드' COLLATE 'utf8mb3_uca1400_ai_ci',
|
||||||
|
`chg_type` VARCHAR(10) NOT NULL COMMENT '변경유형' COLLATE 'utf8mb3_uca1400_ai_ci',
|
||||||
|
`memo` TEXT NULL DEFAULT NULL COMMENT '메모' COLLATE 'utf8mb3_uca1400_ai_ci',
|
||||||
|
`insert_id` VARCHAR(60) NOT NULL COMMENT '등록자ID' COLLATE 'utf8mb3_uca1400_ai_ci',
|
||||||
|
`insert_tm` DATETIME NOT NULL COMMENT '등록시간',
|
||||||
|
PRIMARY KEY (`seq`) USING BTREE,
|
||||||
|
INDEX `vr_sq` (`vr_sq`) USING BTREE
|
||||||
|
)
|
||||||
|
COMMENT='변경이력'
|
||||||
|
COLLATE='utf8mb3_uca1400_ai_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
AUTO_INCREMENT=81103559
|
||||||
|
;
|
||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use CodeIgniter\Model;
|
||||||
|
|
||||||
|
class V2chgstatModel extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_chg_history';
|
||||||
|
protected $primaryKey = 'seq'; // 실제 PK 컬럼명으로 수정하세요 (st_date, cpid, gbn_cd가 복합키인 경우도 있음)
|
||||||
|
protected $allowedFields = ['vr_sq', 'stat_cd', 'chg_type', 'memo', 'insert_id', 'insert_tm'];
|
||||||
|
|
||||||
|
protected $useTimestamps = false; // insert_tm을 직접 넣으시므로 false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 상태 변경 이력 저장 (CI4 통합 버전)
|
||||||
|
* @param array $data ['vr_sq' => 값, 'stat_cd' => 값, ...]
|
||||||
|
* @param string $saveType 'I'(Upsert), 'U'(Update)
|
||||||
|
*/
|
||||||
|
public function v2_savehistory(array $data )
|
||||||
|
{
|
||||||
|
$payload = [
|
||||||
|
'vr_sq' => $data['vr_sq'],
|
||||||
|
'stat_cd' => $data['stat_cd'],
|
||||||
|
'chg_type' => $data['chg_type'],
|
||||||
|
'memo' => $data['memo'] ?? '',
|
||||||
|
'insert_id' => $data['insert_id'] ?? '0',
|
||||||
|
'insert_tm' => $data['insert_tm'] ?? db_now(),
|
||||||
|
];
|
||||||
|
|
||||||
|
// insert 수행
|
||||||
|
if (!$this->insert($payload)) {
|
||||||
|
return [
|
||||||
|
'error' => [
|
||||||
|
'code' => $this->db->error()['code'],
|
||||||
|
'message' => $this->db->error()['message'],
|
||||||
|
],
|
||||||
|
'query' => (string)$this->getLastQuery()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['error' => ['code' => 0, 'message' => ''], 'id' => $this->getInsertID()];
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/Models/Entities/V2chgstatModel.php
Normal file
50
app/Models/Entities/V2chgstatModel.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use CodeIgniter\Model;
|
||||||
|
|
||||||
|
class V2chgstatModel extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_chg_stat';
|
||||||
|
protected $primaryKey = 'seq'; // 실제 PK 컬럼명으로 수정하세요 (st_date, cpid, gbn_cd가 복합키인 경우도 있음)
|
||||||
|
protected $allowedFields = ['vr_sq', 'stat_cd', 'insert_user', 'insert_tm'];
|
||||||
|
|
||||||
|
protected $useTimestamps = false; // insert_tm을 직접 넣으시므로 false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 상태 변경 이력 저장 (CI4 통합 버전)
|
||||||
|
* @param array $data ['vr_sq' => 값, 'stat_cd' => 값, ...]
|
||||||
|
* @param string $saveType 'I'(Upsert), 'U'(Update)
|
||||||
|
*/
|
||||||
|
public function saveChgstat(array $data, string $saveType)
|
||||||
|
{
|
||||||
|
// 1. 기본값 세팅 (데이터 유연성 확보)
|
||||||
|
$payload = [
|
||||||
|
'vr_sq' => $data['vr_sq'] ?? null,
|
||||||
|
'stat_cd' => $data['stat_cd'] ?? '10', // 기본값 30
|
||||||
|
'insert_user' => $data['insert_user'] ?? 0,
|
||||||
|
'insert_tm' => $data['insert_tm'] ?? date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($payload['vr_sq'])) {
|
||||||
|
throw new \Exception("V2chgstatModel Error: vr_sq is required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($saveType === 'I') {
|
||||||
|
// CI2 방식의 ON DUPLICATE KEY UPDATE 유지 (seq 번호 보존을 위해)
|
||||||
|
$sql = "INSERT INTO v2_chg_stat (vr_sq, stat_cd, insert_user, insert_tm)
|
||||||
|
VALUES (:vr_sq:, :stat_cd:, :insert_user:, :insert_tm:)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
insert_user = VALUES(insert_user),
|
||||||
|
insert_tm = VALUES(insert_tm)";
|
||||||
|
|
||||||
|
return $this->db->query($sql, $payload);
|
||||||
|
} else {
|
||||||
|
// Update 방식
|
||||||
|
return $this->where('vr_sq', $payload['vr_sq'])
|
||||||
|
->where('stat_cd', $payload['stat_cd'])
|
||||||
|
->set($payload)
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/Models/Entities/V2stdailyModel.php
Normal file
50
app/Models/Entities/V2stdailyModel.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use CodeIgniter\Model;
|
||||||
|
|
||||||
|
class V2stdailyModel extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_st_daily';
|
||||||
|
protected $primaryKey = 'id'; // 실제 PK 컬럼명으로 수정하세요 (st_date, cpid, gbn_cd가 복합키인 경우도 있음)
|
||||||
|
protected $allowedFields = ['st_date', 'cpid', 'gbn_cd', 'cnt'];
|
||||||
|
|
||||||
|
public function set_v2_st_daily($st_date, $cpid, $gbn_cd, $cnt, $cnt_type = 'add')
|
||||||
|
{
|
||||||
|
if (empty($cnt)) $cnt = 0;
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
// 1. 날짜 처리
|
||||||
|
$date_field = empty($st_date) ? "NOW()" : "?";
|
||||||
|
if (!empty($st_date)) $data[] = $st_date;
|
||||||
|
|
||||||
|
// 2. 나머지 필드 바인딩 데이터 준비
|
||||||
|
$data[] = $cpid;
|
||||||
|
$data[] = $gbn_cd;
|
||||||
|
$data[] = $cnt;
|
||||||
|
|
||||||
|
// 3. 중복 처리 로직 분기
|
||||||
|
if (strtolower($cnt_type) === 'add') {
|
||||||
|
// MariaDB에서 가장 안전한 바인딩 방식
|
||||||
|
$sql = "INSERT INTO v2_st_daily (st_date, cpid, gbn_cd, cnt)
|
||||||
|
VALUES ($date_field, ?, ?, ?)
|
||||||
|
ON DUPLICATE KEY UPDATE cnt = cnt + ?";
|
||||||
|
$data[] = $cnt; // UPDATE 절의 더하기 값을 위해 한 번 더 추가
|
||||||
|
} else {
|
||||||
|
// 중복 시 값을 덮어씌움 (VALUES 함수 사용)
|
||||||
|
$sql = "INSERT INTO v2_st_daily (st_date, cpid, gbn_cd, cnt)
|
||||||
|
VALUES ($date_field, ?, ?, ?)
|
||||||
|
ON DUPLICATE KEY UPDATE cnt = VALUES(cnt)";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 쿼리 실행
|
||||||
|
$result = $this->db->query($sql, $data);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status' => $result ? true : false,
|
||||||
|
'error' => $this->db->error(), // ['code', 'message']
|
||||||
|
'last_query' => (string)$this->db->getLastQuery() // 디버깅용
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,89 +3,180 @@
|
|||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Libraries\NaverApiClient;
|
use App\Libraries\NaverApiClient;
|
||||||
use App\Models\Entities\V2ArticleModel;
|
|
||||||
use App\Models\Entities\VrfcReqModel;
|
use App\Models\Entities\VrfcReqModel;
|
||||||
use App\Models\Entities\NaverWorkerLogModel; // 새로 만든 테이블용 모델
|
use App\Models\Entities\V2stdailyModel;
|
||||||
|
use App\Models\Entities\V2chgstatModel;
|
||||||
|
use App\Models\Entities\V2chghistoryModel;
|
||||||
|
|
||||||
class NaverService
|
class NaverService
|
||||||
{
|
{
|
||||||
protected $naverClient;
|
protected $naverClient, $VrfcReqModel, $V2stdailyModel, $V2chgstatModel, $V2chghistoryModel;
|
||||||
protected $VrfcReqModel;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->naverClient = new NaverApiClient();
|
$this->naverClient = new NaverApiClient();
|
||||||
$this->VrfcReqModel = model(VrfcReqModel::class);
|
$this->VrfcReqModel = model(VrfcReqModel::class);
|
||||||
helper('log'); // 헬퍼 로드
|
$this->V2stdailyModel = model(V2stdailyModel::class);
|
||||||
|
$this->V2chgstatModel = model(V2chgstatModel::class);
|
||||||
|
$this->V2chghistoryModel = model(V2chghistoryModel::class);
|
||||||
|
helper('log');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 매물 정보를 처리하고 DB에 저장하는 메인 함수
|
* 메인 프로세스: 요청 타입에 따른 분기 처리
|
||||||
* @param array $payload 큐에서 꺼낸 원본 데이터
|
|
||||||
* requestType
|
|
||||||
* REG:수동검증요청
|
|
||||||
* MOD:매물정보수정-매물제공업체의 매물정보수정으로 재검증요청1차실패 후재검증요청
|
|
||||||
* CNC:사용자취소
|
|
||||||
* FIN 서비스-서비스 노출/대기검수완료상태,필요한상태인지확인필요
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function processArticle(array $payload)
|
public function processArticle(array $payload)
|
||||||
{
|
{
|
||||||
$articleNumber = $payload['articleNumber'];
|
$articleNumber = $payload['articleNumber'];
|
||||||
$requestDatetime = date('Y-m-d H:i:s', strtotime($payload['requestDatetime'] ?? 'now'));
|
$requestType = $payload['requestType'] ?? '';
|
||||||
$requestType = $payload['requestType'] ?? ''; // REG:등록 ,
|
|
||||||
|
|
||||||
// 1. 네이버 API 호출
|
// 1. 네이버 API 호출
|
||||||
$response = $this->naverClient->getArticleInfo($articleNumber);
|
$response = $this->naverClient->getArticleInfo($articleNumber);
|
||||||
|
if (!$response || $response['code'] !== 'success') {
|
||||||
if (!$response || !isset($response['data']) || $response['code'] !== 'success') {
|
throw new \Exception("네이버 API 응답 에러: $articleNumber");
|
||||||
$msg = $response['message'] ?? 'No message';
|
|
||||||
throw new \Exception("네이버 API 응답 에러: $articleNumber | 메시지: $msg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$articleInfo = $response['data'];
|
$vrfcParams = $this->mapToDatabaseParams($response['data'], $payload);
|
||||||
// 로그 기록
|
write_custom_log("PROCESS_START | Type: $requestType | Atcl: $articleNumber", 'INFO', 'service');
|
||||||
write_custom_log("ARTICLE_INFO | ArticleNumber: $articleNumber", 'INFO', 'service');
|
|
||||||
// 2. 가공 로직 (insertVrfc에 있던 긴 배열 생성 로직)
|
|
||||||
$vrfcParams = $this->mapToDatabaseParams($articleInfo, $payload);
|
|
||||||
write_custom_log("VRFC_PARAMS | " . json_encode($vrfcParams, JSON_UNESCAPED_UNICODE), 'INFO', 'service');
|
|
||||||
|
|
||||||
switch ($requestType) {
|
switch ($requestType) {
|
||||||
case 'REG':
|
case 'REG': // 신규 등록
|
||||||
$vrfcParams['req_type'] = '10';
|
$vr_sq = $this->insertVrfcReq($articleNumber, $vrfcParams);
|
||||||
return $this->handleRegistration($articleNumber, $vrfcParams);
|
if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], $vrfcParams['vrfc_type'] . '0103', '1', 'add');
|
||||||
break;
|
break;
|
||||||
case 'MOD':
|
|
||||||
$vrfcParams['req_type'] = '20';
|
case 'MOD': // 수정
|
||||||
return $this->handleModification($articleNumber, $vrfcParams);
|
$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;
|
break;
|
||||||
case 'CNC':
|
|
||||||
$vrfcParams['req_type'] = '30';
|
case 'CNC': // 취소
|
||||||
return $this->handleStatusChange($articleNumber, $vrfcParams);
|
$vr_sq = $this->deleteVrfcReq($articleNumber, $vrfcParams);
|
||||||
|
if ($vr_sq) $this->V2stdailyModel->set_v2_st_daily(null, $vrfcParams['cpid'], 'A0101', '1', 'add');
|
||||||
break;
|
break;
|
||||||
case 'FIN':
|
|
||||||
$vrfcParams['req_type'] = '40';
|
case 'FIN': // 완료
|
||||||
return $this->handleStatusChange($articleNumber, $vrfcParams);
|
$vr_sq = $this->finVrfcReq($articleNumber, $vrfcParams);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new \Exception("알 수 없는 requestType: " . $requestType);
|
throw new \Exception("알 수 없는 requestType: $requestType");
|
||||||
}
|
|
||||||
|
|
||||||
// 중복 체크
|
|
||||||
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)
|
|
||||||
|
|
||||||
->first();
|
|
||||||
if ($existing) {
|
|
||||||
throw new \Exception("중복 요청: " . $articleNumber . " / " . $vrfcParams['req_type']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. DB 저장
|
return ['vr_sq' => $vr_sq, 'articleNumber' => $articleNumber];
|
||||||
if (!$this->VrfcReqModel->insert($vrfcParams)) {
|
}
|
||||||
$errorMessages = implode(', ', $this->VrfcReqModel->errors());
|
|
||||||
throw new \Exception("V2 매물 삽입 오류: " . $errorMessages);
|
/**
|
||||||
|
* [REG] 신규 등록
|
||||||
|
*/
|
||||||
|
private function insertVrfcReq($articleNumber, $params)
|
||||||
|
{
|
||||||
|
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first();
|
||||||
|
if ($existing) throw new \Exception("중복 등록 시도: $articleNumber");
|
||||||
|
|
||||||
|
$params['stat_cd'] = '10';
|
||||||
|
$params['insert_user'] = '0';
|
||||||
|
$params['req_type'] = 'C';
|
||||||
|
|
||||||
|
if (!$this->VrfcReqModel->insert($params)) {
|
||||||
|
$sql = (string)$this->VrfcReqModel->getLastQuery();
|
||||||
|
write_custom_log("INSERT_FAILED | Atcl: $articleNumber | SQL: $sql", 'ERROR', 'failed');
|
||||||
|
throw new \Exception("신규 등록 실패");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->VrfcReqModel->getInsertID();
|
$vr_sq = $this->VrfcReqModel->getInsertID();
|
||||||
|
$this->recordStatusAndHistory($vr_sq, '10', 'C9', "신규접수 : 10");
|
||||||
|
|
||||||
|
return $vr_sq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MOD] 수정 처리
|
||||||
|
*/
|
||||||
|
private function updateVrfcReq($articleNumber, $params)
|
||||||
|
{
|
||||||
|
$existing = $this->findExisting($articleNumber);
|
||||||
|
if (!$existing) return $this->insertVrfcReq($articleNumber, $params);
|
||||||
|
|
||||||
|
$params['stat_cd'] = '30';
|
||||||
|
$params['req_type'] = 'U';
|
||||||
|
$params['insert_tm'] = db_now();
|
||||||
|
|
||||||
|
return $this->updateProcess($existing, $params, 'MOD', "재접수 상태변경: {$existing['stat_cd']} => 30");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [CNC] 취소 처리
|
||||||
|
*/
|
||||||
|
private function deleteVrfcReq($articleNumber, $params)
|
||||||
|
{
|
||||||
|
$existing = $this->findExisting($articleNumber);
|
||||||
|
$params['stat_cd'] = '19';
|
||||||
|
$params['req_type'] = 'D';
|
||||||
|
|
||||||
|
return $this->updateProcess($existing, $params, 'CNC', "취소 처리: {$existing['stat_cd']} => 19");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [FIN] 완료 처리
|
||||||
|
*/
|
||||||
|
private function finVrfcReq($articleNumber, $params)
|
||||||
|
{
|
||||||
|
$existing = $this->findExisting($articleNumber);
|
||||||
|
$params['stat_cd'] = '60';
|
||||||
|
$params['req_type'] = 'F';
|
||||||
|
|
||||||
|
return $this->updateProcess($existing, $params, 'FIN', "완료 처리: {$existing['stat_cd']} => 60");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 내부 공통 유틸리티 함수 ---
|
||||||
|
|
||||||
|
private function findExisting($articleNumber) {
|
||||||
|
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first();
|
||||||
|
if (!$existing) throw new \Exception("해당 매물 없음: $articleNumber");
|
||||||
|
return $existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 공통 업데이트 및 이력 기록 로직 (Lock 최소화)
|
||||||
|
*/
|
||||||
|
private function updateProcess($existing, $params, $type, $memo)
|
||||||
|
{
|
||||||
|
$vr_sq = $existing['vr_sq'];
|
||||||
|
|
||||||
|
if (!$this->VrfcReqModel->update($vr_sq, $params)) {
|
||||||
|
$sql = (string)$this->VrfcReqModel->getLastQuery();
|
||||||
|
write_custom_log("UPDATE_FAILED | Type: $type | vr_sq: $vr_sq | SQL: $sql", 'ERROR', 'failed');
|
||||||
|
throw new \Exception("[$type] 업데이트 실패");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->recordStatusAndHistory($vr_sq, $params['stat_cd'], 'C9', $memo);
|
||||||
|
return $vr_sq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 상태 및 이력 테이블 기록 (독립적 에러 처리)
|
||||||
|
*/
|
||||||
|
private function recordStatusAndHistory($vr_sq, $stat_cd, $chg_type, $memo)
|
||||||
|
{
|
||||||
|
// 1. 상태(stat) 저장
|
||||||
|
try {
|
||||||
|
$this->V2chgstatModel->saveChgstat([
|
||||||
|
'vr_sq' => $vr_sq, 'stat_cd' => $stat_cd, 'insert_user' => '0', 'insert_tm' => db_now()
|
||||||
|
], 'I');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
write_custom_log("STAT_SAVE_ERR | vr_sq: $vr_sq | Msg: " . $e->getMessage(), 'ERROR', 'failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 이력(history) 저장
|
||||||
|
try {
|
||||||
|
$this->V2chghistoryModel->v2_savehistory([
|
||||||
|
'vr_sq' => $vr_sq, 'stat_cd' => $stat_cd, 'chg_type' => $chg_type,
|
||||||
|
'memo' => $memo, 'insert_id' => 'SYSTEM', 'insert_tm' => db_now()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
write_custom_log("HIST_SAVE_ERR | vr_sq: $vr_sq | Msg: " . $e->getMessage(), 'ERROR', 'failed');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,6 +188,7 @@ class NaverService
|
|||||||
$certRegister = [];
|
$certRegister = [];
|
||||||
$confirm_doc_img_url = [];
|
$confirm_doc_img_url = [];
|
||||||
$referenceFileUrl = [];
|
$referenceFileUrl = [];
|
||||||
|
$requestDatetime = date('YmdHis', strtotime($payload['requestDatetime'] ?? 'now'));
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$fileTypeCode = $file['fileTypeCode'];
|
$fileTypeCode = $file['fileTypeCode'];
|
||||||
@@ -124,13 +216,13 @@ class NaverService
|
|||||||
'req_type' => '',
|
'req_type' => '',
|
||||||
'rdate' => $requestDatetime ?? db_now('Y-m-d H:i:s'),
|
'rdate' => $requestDatetime ?? db_now('Y-m-d H:i:s'),
|
||||||
'cpTelNo' => $articleInfo['seller']['sellerTelephoneNumber'],
|
'cpTelNo' => $articleInfo['seller']['sellerTelephoneNumber'],
|
||||||
'stat_cd' => '10',
|
'stat_cd' => '',
|
||||||
'try_cnt' => '0',
|
'try_cnt' => '0',
|
||||||
'insert_user' => 'admin',
|
'insert_user' => '',
|
||||||
'insert_tm' => db_now(),
|
'insert_tm' => db_now(),
|
||||||
'memo' => '',
|
'memo' => '',
|
||||||
'contact_fail_cnt' => '0',
|
'contact_fail_cnt' => '0',
|
||||||
'sync_yn' => 'N',
|
'sync_yn' => 'Y',
|
||||||
'reg_try_cnt' => '0',
|
'reg_try_cnt' => '0',
|
||||||
'tel_fail_cause' => null,
|
'tel_fail_cause' => null,
|
||||||
'rgbk_confirm_owner_nm' => $articleInfo['seller']['ownerName'] ?? null,
|
'rgbk_confirm_owner_nm' => $articleInfo['seller']['ownerName'] ?? null,
|
||||||
@@ -144,65 +236,11 @@ class NaverService
|
|||||||
'referenceFileUrl' => empty($referenceFileUrl) ? null : json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE),
|
'referenceFileUrl' => empty($referenceFileUrl) ? null : json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
return $vrfc_params;
|
return $vrfc_params;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* [REG] 신규 등록 처리
|
|
||||||
*/
|
|
||||||
private function handleRegistration($articleNumber, $params)
|
|
||||||
{
|
|
||||||
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first();
|
|
||||||
if ($existing) {
|
|
||||||
// 이미 존재한다면 업데이트로 돌리거나 예외 처리
|
|
||||||
return $this->handleModification($articleNumber, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->VrfcReqModel->insert($params)) {
|
|
||||||
throw new \Exception("등록 실패: " . implode(', ', $this->VrfcReqModel->errors()));
|
|
||||||
}
|
|
||||||
return $this->VrfcReqModel->getInsertID();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [MOD] 수정 처리
|
|
||||||
*/
|
|
||||||
private function handleModification($articleNumber, $params)
|
|
||||||
{
|
|
||||||
// 기존 기록이 있는지 확인
|
|
||||||
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first();
|
|
||||||
|
|
||||||
if (!$existing) {
|
|
||||||
// 수정 요청인데 데이터가 없으면 새로 등록
|
|
||||||
return $this->handleRegistration($articleNumber, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 기존 데이터 업데이트 (PK인 reqSeq 기준으로 업데이트)
|
|
||||||
if (!$this->VrfcReqModel->update($existing['reqSeq'], $params)) {
|
|
||||||
throw new \Exception("수정 실패: " . implode(', ', $this->VrfcReqModel->errors()));
|
|
||||||
}
|
|
||||||
return $existing['reqSeq'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [CNC / FIN] 상태값 변경 처리
|
|
||||||
*/
|
|
||||||
private function handleStatusChange($articleNumber, $statusCode, $memo)
|
|
||||||
{
|
|
||||||
$existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first();
|
|
||||||
if (!$existing) {
|
|
||||||
throw new \Exception("상태 변경 실패: 해당 매물 없음 ($articleNumber)");
|
|
||||||
}
|
|
||||||
|
|
||||||
$updateData = [
|
|
||||||
'stat_cd' => $statusCode,
|
|
||||||
'memo' => $existing['memo'] . " | " . $memo . "(" . date('Y-m-d H:i:s') . ")"
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!$this->VrfcReqModel->update($existing['reqSeq'], $updateData)) {
|
|
||||||
throw new \Exception("상태 업데이트 실패: " . $articleNumber);
|
|
||||||
}
|
|
||||||
return $existing['reqSeq'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user