'required|integer', 'INFLUENCER_SEQ' => 'required|integer', 'REQUEST_TYPE' => 'required|in_list[INFLUENCER_REQUEST,VENDOR_INVITE,INFLUENCER_REAPPLY,VENDOR_PROPOSAL]', 'REQUESTED_BY' => 'required|integer', 'IS_ACT' => 'required|in_list[Y,N]' ]; protected $validationMessages = [ 'VENDOR_SEQ' => [ 'required' => '벤더사 SEQ는 필수입니다.', 'integer' => '벤더사 SEQ는 정수여야 합니다.' ], 'INFLUENCER_SEQ' => [ 'required' => '인플루언서 SEQ는 필수입니다.', 'integer' => '인플루언서 SEQ는 정수여야 합니다.' ], 'REQUEST_TYPE' => [ 'required' => '요청 타입은 필수입니다.', 'in_list' => '유효하지 않은 요청 타입입니다.' ], 'REQUESTED_BY' => [ 'required' => '요청자는 필수입니다.', 'integer' => '요청자 SEQ는 정수여야 합니다.' ] ]; protected $skipValidation = false; protected $cleanValidationRules = true; // Callbacks protected $allowCallbacks = true; protected $beforeInsert = ['beforeInsert']; protected $afterInsert = ['afterInsert']; protected $beforeUpdate = ['beforeUpdate']; protected $afterUpdate = []; protected $beforeFind = []; protected $afterFind = []; protected $beforeDelete = []; protected $afterDelete = []; // 히스토리 모델 protected $statusHistoryModel; public function __construct() { parent::__construct(); $this->statusHistoryModel = new VendorInfluencerStatusHistoryModel(); } /** * 삽입 전 처리 */ protected function beforeInsert(array $data) { if (!isset($data['data']['REG_DATE'])) { $data['data']['REG_DATE'] = date('Y-m-d H:i:s'); } if (!isset($data['data']['MOD_DATE'])) { $data['data']['MOD_DATE'] = date('Y-m-d H:i:s'); } if (!isset($data['data']['IS_ACT'])) { $data['data']['IS_ACT'] = 'Y'; } return $data; } /** * 삽입 후 처리 - 초기 상태 히스토리 생성 */ protected function afterInsert(array $data) { $mappingSeq = $data['id']; $insertData = $data['data']; // 초기 상태를 PENDING으로 설정 $this->statusHistoryModel->changeStatus( $mappingSeq, 'PENDING', $insertData['REQUEST_MESSAGE'] ?? '', $insertData['REQUESTED_BY'] ); return $data; } /** * 업데이트 전 처리 */ protected function beforeUpdate(array $data) { $data['data']['MOD_DATE'] = date('Y-m-d H:i:s'); return $data; } /** * 현재 상태와 함께 매핑 정보 조회 */ public function getWithCurrentStatus($mappingSeq) { $builder = $this->builder(); return $builder->select('VENDOR_INFLUENCER_MAPPING.*, VENDOR_INFLUENCER_STATUS_HISTORY.STATUS as CURRENT_STATUS, VENDOR_INFLUENCER_STATUS_HISTORY.STATUS_MESSAGE as CURRENT_STATUS_MESSAGE, VENDOR_INFLUENCER_STATUS_HISTORY.CHANGED_DATE as STATUS_CHANGED_DATE') ->join('VENDOR_INFLUENCER_STATUS_HISTORY', 'VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ = VENDOR_INFLUENCER_MAPPING.SEQ AND VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT = "Y"') ->where('VENDOR_INFLUENCER_MAPPING.SEQ', $mappingSeq) ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y') ->get() ->getRowArray(); } /** * 상태 변경 (히스토리 모델 위임) */ public function changePartnershipStatus($mappingSeq, $newStatus, $statusMessage = '', $changedBy = null) { return $this->statusHistoryModel->changeStatus($mappingSeq, $newStatus, $statusMessage, $changedBy); } /** * 특정 상태의 파트너십 조회 */ public function getPartnershipsByStatus($status) { return $this->statusHistoryModel->getMappingsByStatus($status); } /** * 중복 요청 확인 (특정 벤더사-인플루언서 조합에서 PENDING 상태 확인) */ public function checkExistingPendingRequest($vendorSeq, $influencerSeq) { $builder = $this->builder(); return $builder->select('VENDOR_INFLUENCER_MAPPING.SEQ') ->join('VENDOR_INFLUENCER_STATUS_HISTORY', 'VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ = VENDOR_INFLUENCER_MAPPING.SEQ AND VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT = "Y"') ->where('VENDOR_INFLUENCER_MAPPING.VENDOR_SEQ', $vendorSeq) ->where('VENDOR_INFLUENCER_MAPPING.INFLUENCER_SEQ', $influencerSeq) ->where('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS', 'PENDING') ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y') ->get() ->getRowArray(); } /** * 재승인 가능한 파트너십 확인 (TERMINATED 또는 REJECTED 상태) */ public function checkReapplyEligiblePartnership($vendorSeq, $influencerSeq) { $builder = $this->builder(); return $builder->select('VENDOR_INFLUENCER_MAPPING.*, VENDOR_INFLUENCER_STATUS_HISTORY.STATUS as CURRENT_STATUS') ->join('VENDOR_INFLUENCER_STATUS_HISTORY', 'VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ = VENDOR_INFLUENCER_MAPPING.SEQ AND VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT = "Y"') ->where('VENDOR_INFLUENCER_MAPPING.VENDOR_SEQ', $vendorSeq) ->where('VENDOR_INFLUENCER_MAPPING.INFLUENCER_SEQ', $influencerSeq) ->whereIn('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS', ['TERMINATED', 'REJECTED']) ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y') ->orderBy('VENDOR_INFLUENCER_MAPPING.REG_DATE', 'DESC') ->get() ->getRowArray(); } /** * 기본 매핑 정보 조회 (조인 없이) */ public function getBasicMapping($mappingSeq) { return $this->where('SEQ', $mappingSeq) ->where('IS_ACT', 'Y') ->first(); } /** * 벤더사-인플루언서 조합의 기존 매핑 조회 */ public function getExistingMapping($vendorSeq, $influencerSeq, $excludeStatuses = []) { $builder = $this->builder(); $query = $builder->select('VENDOR_INFLUENCER_MAPPING.*, VENDOR_INFLUENCER_STATUS_HISTORY.STATUS as CURRENT_STATUS') ->join('VENDOR_INFLUENCER_STATUS_HISTORY', 'VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ = VENDOR_INFLUENCER_MAPPING.SEQ AND VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT = "Y"') ->where('VENDOR_INFLUENCER_MAPPING.VENDOR_SEQ', $vendorSeq) ->where('VENDOR_INFLUENCER_MAPPING.INFLUENCER_SEQ', $influencerSeq) ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y'); if (!empty($excludeStatuses)) { $query->whereNotIn('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS', $excludeStatuses); } return $query->orderBy('VENDOR_INFLUENCER_MAPPING.REG_DATE', 'DESC') ->get() ->getResultArray(); } /** * 매핑 비활성화 */ public function deactivateMapping($mappingSeq, $reason = '') { return $this->update($mappingSeq, [ 'IS_ACT' => 'N', 'ADD_INFO3' => $reason, 'MOD_DATE' => date('Y-m-d H:i:s') ]); } /** * 만료일 설정 */ public function setExpiredDate($mappingSeq, $expiredDate) { return $this->update($mappingSeq, [ 'EXPIRED_DATE' => $expiredDate, 'MOD_DATE' => date('Y-m-d H:i:s') ]); } }