| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- <?php
- namespace App\Models;
- use CodeIgniter\Model;
- class VendorInfluencerStatusHistoryModel extends Model
- {
- protected $table = 'VENDOR_INFLUENCER_STATUS_HISTORY';
- protected $primaryKey = 'SEQ';
- protected $useAutoIncrement = true;
- protected $returnType = 'array';
- protected $useSoftDeletes = false;
- protected $protectFields = true;
- protected $allowedFields = [
- 'MAPPING_SEQ',
- 'STATUS',
- 'PREVIOUS_STATUS',
- 'STATUS_MESSAGE',
- 'CHANGED_BY',
- 'CHANGED_DATE',
- 'IS_CURRENT',
- 'REG_DATE'
- ];
- // Dates
- protected $useTimestamps = false;
- protected $dateFormat = 'datetime';
- protected $createdField = 'REG_DATE';
- protected $updatedField = '';
- protected $deletedField = '';
- // Validation
- protected $validationRules = [
- 'MAPPING_SEQ' => 'required|integer',
- 'STATUS' => 'required|in_list[PENDING,APPROVED,REJECTED,CANCELLED,EXPIRED,TERMINATED]',
- 'CHANGED_BY' => 'permit_empty|integer', // required 제거, permit_empty로 변경
- 'IS_CURRENT' => 'required|in_list[Y,N]'
- ];
- protected $validationMessages = [
- 'MAPPING_SEQ' => [
- 'required' => '매핑 SEQ는 필수입니다.',
- 'integer' => '매핑 SEQ는 정수여야 합니다.'
- ],
- 'STATUS' => [
- 'required' => '상태는 필수입니다.',
- 'in_list' => '유효하지 않은 상태입니다.'
- ],
- 'CHANGED_BY' => [
- 'integer' => '변경자 SEQ는 정수여야 합니다.'
- ],
- 'IS_CURRENT' => [
- 'required' => 'IS_CURRENT는 필수입니다.',
- 'in_list' => 'IS_CURRENT는 Y 또는 N이어야 합니다.'
- ]
- ];
- protected $skipValidation = false;
- protected $cleanValidationRules = true;
- // Callbacks
- protected $allowCallbacks = true;
- protected $beforeInsert = ['beforeInsert'];
- protected $afterInsert = [];
- protected $beforeUpdate = [];
- protected $afterUpdate = [];
- protected $beforeFind = [];
- protected $afterFind = [];
- protected $beforeDelete = [];
- protected $afterDelete = [];
- /**
- * 상태 변경 전 처리
- */
- protected function beforeInsert(array $data)
- {
- // REG_DATE 자동 설정
- if (!isset($data['data']['REG_DATE'])) {
- $data['data']['REG_DATE'] = date('Y-m-d H:i:s');
- }
-
- // CHANGED_DATE 자동 설정
- if (!isset($data['data']['CHANGED_DATE'])) {
- $data['data']['CHANGED_DATE'] = date('Y-m-d H:i:s');
- }
- return $data;
- }
- /**
- * 특정 매핑의 현재 상태 조회
- */
- public function getCurrentStatus($mappingSeq)
- {
- return $this->where('MAPPING_SEQ', $mappingSeq)
- ->where('IS_CURRENT', 'Y')
- ->first();
- }
- /**
- * 특정 매핑의 상태 히스토리 조회
- */
- public function getStatusHistory($mappingSeq, $limit = 10)
- {
- return $this->where('MAPPING_SEQ', $mappingSeq)
- ->orderBy('CHANGED_DATE', 'DESC')
- ->limit($limit)
- ->findAll();
- }
- /**
- * 상태 변경 (트랜잭션 포함) - Fallback 방식 우선 적용
- */
- public function changeStatus($mappingSeq, $newStatus, $statusMessage = '', $changedBy = null)
- {
- $db = \Config\Database::connect();
- $db->transStart();
- try {
- log_message('info', "상태 변경 시작: mappingSeq={$mappingSeq}, newStatus={$newStatus}");
- // CHANGED_BY 기본값 처리
- if ($changedBy === null) {
- $changedBy = 1;
- log_message('warning', 'CHANGED_BY가 null이므로 기본값 1로 설정');
- }
- // 1. 현재 상태 조회
- $currentStatus = $this->getCurrentStatus($mappingSeq);
- $previousStatus = $currentStatus ? $currentStatus['STATUS'] : null;
- log_message('info', "이전 상태: " . ($previousStatus ?: 'NULL') . " → 새 상태: {$newStatus}");
- // 2. 히스토리 테이블 방식 시도
- $historySuccess = false;
-
- try {
- // 기존 상태 비활성화
- if ($currentStatus) {
- $updateSql = "UPDATE VENDOR_INFLUENCER_STATUS_HISTORY
- SET IS_CURRENT = 'N'
- WHERE MAPPING_SEQ = ? AND IS_CURRENT = 'Y'";
- $db->query($updateSql, [$mappingSeq]);
- log_message('info', "기존 상태 비활성화 완료");
- }
- // 새 히스토리 레코드 추가
- $historyData = [
- 'MAPPING_SEQ' => (int)$mappingSeq,
- 'STATUS' => $newStatus,
- 'PREVIOUS_STATUS' => $previousStatus,
- 'STATUS_MESSAGE' => $statusMessage ?: '',
- 'CHANGED_BY' => (int)$changedBy,
- 'IS_CURRENT' => 'Y',
- 'CHANGED_DATE' => date('Y-m-d H:i:s'),
- 'REG_DATE' => date('Y-m-d H:i:s')
- ];
- if ($this->validate($historyData)) {
- $insertResult = $this->insert($historyData, false);
- if ($insertResult) {
- $historySuccess = true;
- log_message('info', "히스토리 테이블 업데이트 성공: ID={$insertResult}");
- }
- }
- } catch (\Exception $historyError) {
- log_message('warning', '히스토리 테이블 방식 실패: ' . $historyError->getMessage());
- }
- // 3. 히스토리 테이블 실패 시 메인 테이블 직접 업데이트 (Fallback)
- if (!$historySuccess) {
- log_message('info', '히스토리 테이블 실패 - 메인 테이블 직접 업데이트로 fallback');
-
- $mappingModel = new VendorInfluencerMappingModel();
- $mainUpdateData = [
- 'STATUS' => $newStatus,
- 'RESPONSE_MESSAGE' => $statusMessage,
- 'RESPONSE_DATE' => date('Y-m-d H:i:s'),
- 'APPROVED_BY' => $changedBy,
- 'MOD_DATE' => date('Y-m-d H:i:s')
- ];
- // TERMINATED 상태인 경우 종료일 추가
- if ($newStatus === 'TERMINATED') {
- $mainUpdateData['PARTNERSHIP_END_DATE'] = date('Y-m-d H:i:s');
- }
- $mainUpdateResult = $mappingModel->update($mappingSeq, $mainUpdateData);
-
- if (!$mainUpdateResult) {
- throw new \Exception('메인 테이블 업데이트도 실패');
- }
- log_message('info', '메인 테이블 직접 업데이트 성공 (Fallback)');
-
- // 트랜잭션 완료
- $db->transComplete();
-
- if ($db->transStatus() === false) {
- throw new \Exception('트랜잭션 실패');
- }
- return 'main_table_update'; // 성공 표시
- }
- // 4. 히스토리 테이블 성공 시 메인 테이블 MOD_DATE도 업데이트
- try {
- $mappingModel = new VendorInfluencerMappingModel();
- $mappingModel->update($mappingSeq, ['MOD_DATE' => date('Y-m-d H:i:s')]);
- } catch (\Exception $mainUpdateError) {
- log_message('warning', '메인 테이블 MOD_DATE 업데이트 실패 (계속 진행): ' . $mainUpdateError->getMessage());
- }
- // 트랜잭션 완료
- $db->transComplete();
- if ($db->transStatus() === false) {
- throw new \Exception('상태 변경 트랜잭션 실패');
- }
- log_message('info', "상태 변경 완료: mappingSeq={$mappingSeq}");
- return $insertResult ?? 'fallback_success';
- } catch (\Exception $e) {
- $db->transRollback();
- log_message('error', '상태 변경 실패: ' . $e->getMessage());
- log_message('error', '실패한 파라미터: ' . json_encode([
- 'mappingSeq' => $mappingSeq,
- 'newStatus' => $newStatus,
- 'statusMessage' => $statusMessage,
- 'changedBy' => $changedBy
- ]));
- throw $e;
- }
- }
- /**
- * 특정 상태의 매핑 목록 조회
- */
- public function getMappingsByStatus($status, $isActive = true)
- {
- $builder = $this->builder();
- $builder->select('VENDOR_INFLUENCER_STATUS_HISTORY.*, VENDOR_INFLUENCER_MAPPING.*')
- ->join('VENDOR_INFLUENCER_MAPPING',
- 'VENDOR_INFLUENCER_MAPPING.SEQ = VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ')
- ->where('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS', $status)
- ->where('VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT', 'Y');
-
- if ($isActive) {
- $builder->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y');
- }
- return $builder->get()->getResultArray();
- }
- /**
- * 벤더사별 상태 통계
- */
- public function getStatusStatsByVendor($vendorSeq)
- {
- $builder = $this->builder();
- return $builder->select('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS, COUNT(*) as count')
- ->join('VENDOR_INFLUENCER_MAPPING',
- 'VENDOR_INFLUENCER_MAPPING.SEQ = VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ')
- ->where('VENDOR_INFLUENCER_MAPPING.VENDOR_SEQ', $vendorSeq)
- ->where('VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT', 'Y')
- ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y')
- ->groupBy('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS')
- ->get()
- ->getResultArray();
- }
- /**
- * 인플루언서별 상태 통계
- */
- public function getStatusStatsByInfluencer($influencerSeq)
- {
- $builder = $this->builder();
- return $builder->select('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS, COUNT(*) as count')
- ->join('VENDOR_INFLUENCER_MAPPING',
- 'VENDOR_INFLUENCER_MAPPING.SEQ = VENDOR_INFLUENCER_STATUS_HISTORY.MAPPING_SEQ')
- ->where('VENDOR_INFLUENCER_MAPPING.INFLUENCER_SEQ', $influencerSeq)
- ->where('VENDOR_INFLUENCER_STATUS_HISTORY.IS_CURRENT', 'Y')
- ->where('VENDOR_INFLUENCER_MAPPING.IS_ACT', 'Y')
- ->groupBy('VENDOR_INFLUENCER_STATUS_HISTORY.STATUS')
- ->get()
- ->getResultArray();
- }
- }
|