- credit_inquiries 테이블 마이그레이션 추가 - CreditInquiry 모델 생성 (API 응답 저장, 이슈 카운트 등) - 조회 이력 리스트 화면으로 변경 (페이지네이션, 필터) - 원본 데이터 모달 조회 기능 추가 - 신용평가 리포트 모달 (TODO: 가공 형식 구현 예정) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
221 lines
6.6 KiB
PHP
221 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Credit;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Support\Str;
|
|
|
|
/**
|
|
* 신용평가 조회 이력 모델
|
|
*/
|
|
class CreditInquiry extends Model
|
|
{
|
|
protected $fillable = [
|
|
'inquiry_key',
|
|
'company_key',
|
|
'company_name',
|
|
'user_id',
|
|
'inquired_at',
|
|
'short_term_overdue_cnt',
|
|
'negative_info_kci_cnt',
|
|
'negative_info_pb_cnt',
|
|
'negative_info_cb_cnt',
|
|
'suspension_info_cnt',
|
|
'workout_cnt',
|
|
'raw_summary',
|
|
'raw_short_term_overdue',
|
|
'raw_negative_info_kci',
|
|
'raw_negative_info_cb',
|
|
'raw_suspension_info',
|
|
'raw_workout_info',
|
|
'status',
|
|
'error_message',
|
|
];
|
|
|
|
protected $casts = [
|
|
'inquired_at' => 'datetime',
|
|
'raw_summary' => 'array',
|
|
'raw_short_term_overdue' => 'array',
|
|
'raw_negative_info_kci' => 'array',
|
|
'raw_negative_info_cb' => 'array',
|
|
'raw_suspension_info' => 'array',
|
|
'raw_workout_info' => 'array',
|
|
'short_term_overdue_cnt' => 'integer',
|
|
'negative_info_kci_cnt' => 'integer',
|
|
'negative_info_pb_cnt' => 'integer',
|
|
'negative_info_cb_cnt' => 'integer',
|
|
'suspension_info_cnt' => 'integer',
|
|
'workout_cnt' => 'integer',
|
|
];
|
|
|
|
/**
|
|
* 모델 부팅 시 inquiry_key 자동 생성
|
|
*/
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
|
|
static::creating(function ($model) {
|
|
if (empty($model->inquiry_key)) {
|
|
$model->inquiry_key = self::generateInquiryKey();
|
|
}
|
|
if (empty($model->inquired_at)) {
|
|
$model->inquired_at = now();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 고유 조회 키 생성
|
|
*/
|
|
public static function generateInquiryKey(): string
|
|
{
|
|
return date('Ymd') . Str::upper(Str::random(24));
|
|
}
|
|
|
|
/**
|
|
* 조회자 관계
|
|
*/
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(\App\Models\User::class);
|
|
}
|
|
|
|
/**
|
|
* 총 이슈 건수 계산
|
|
*/
|
|
public function getTotalIssueCountAttribute(): int
|
|
{
|
|
return $this->short_term_overdue_cnt
|
|
+ $this->negative_info_kci_cnt
|
|
+ $this->negative_info_pb_cnt
|
|
+ $this->negative_info_cb_cnt
|
|
+ $this->suspension_info_cnt
|
|
+ $this->workout_cnt;
|
|
}
|
|
|
|
/**
|
|
* 이슈 여부 확인
|
|
*/
|
|
public function getHasIssueAttribute(): bool
|
|
{
|
|
return $this->total_issue_count > 0;
|
|
}
|
|
|
|
/**
|
|
* 포맷된 사업자번호
|
|
*/
|
|
public function getFormattedCompanyKeyAttribute(): string
|
|
{
|
|
$key = $this->company_key;
|
|
if (strlen($key) === 10) {
|
|
return substr($key, 0, 3) . '-' . substr($key, 3, 2) . '-' . substr($key, 5);
|
|
}
|
|
return $key;
|
|
}
|
|
|
|
/**
|
|
* 전체 원본 데이터 조합
|
|
*/
|
|
public function getAllRawData(): array
|
|
{
|
|
return [
|
|
'summary' => $this->raw_summary,
|
|
'shortTermOverdue' => $this->raw_short_term_overdue,
|
|
'negativeInfoKCI' => $this->raw_negative_info_kci,
|
|
'negativeInfoCB' => $this->raw_negative_info_cb,
|
|
'suspensionInfo' => $this->raw_suspension_info,
|
|
'workoutInfo' => $this->raw_workout_info,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* API 응답으로부터 모델 생성
|
|
*/
|
|
public static function createFromApiResponse(string $companyKey, array $apiResult, ?int $userId = null): self
|
|
{
|
|
// 요약 정보에서 건수 추출
|
|
$summaryData = $apiResult['summary']['data'] ?? [];
|
|
$creditSummaryList = $summaryData['data']['creditSummaryList'][0]
|
|
?? $summaryData['creditSummaryList'][0]
|
|
?? [];
|
|
|
|
// 성공/실패 상태 판단
|
|
$successCount = 0;
|
|
$totalCount = 6;
|
|
$errors = [];
|
|
|
|
foreach (['summary', 'shortTermOverdue', 'negativeInfoKCI', 'negativeInfoCB', 'suspensionInfo', 'workoutInfo'] as $key) {
|
|
if (isset($apiResult[$key]['success']) && $apiResult[$key]['success']) {
|
|
$successCount++;
|
|
} else {
|
|
$errors[] = $key . ': ' . ($apiResult[$key]['error'] ?? 'Unknown error');
|
|
}
|
|
}
|
|
|
|
$status = match (true) {
|
|
$successCount === $totalCount => 'success',
|
|
$successCount > 0 => 'partial',
|
|
default => 'failed',
|
|
};
|
|
|
|
return self::create([
|
|
'company_key' => $companyKey,
|
|
'user_id' => $userId,
|
|
'inquired_at' => now(),
|
|
|
|
// 요약 건수
|
|
'short_term_overdue_cnt' => $creditSummaryList['shorttermOverdueCnt'] ?? 0,
|
|
'negative_info_kci_cnt' => $creditSummaryList['negativeInfoBbCnt'] ?? 0,
|
|
'negative_info_pb_cnt' => $creditSummaryList['negativeInfoPbCnt'] ?? 0,
|
|
'negative_info_cb_cnt' => $creditSummaryList['negativeInfoCbCnt'] ?? 0,
|
|
'suspension_info_cnt' => $creditSummaryList['suspensionInfoCnt'] ?? 0,
|
|
'workout_cnt' => $creditSummaryList['workoutCnt'] ?? 0,
|
|
|
|
// 원본 데이터
|
|
'raw_summary' => $apiResult['summary'] ?? null,
|
|
'raw_short_term_overdue' => $apiResult['shortTermOverdue'] ?? null,
|
|
'raw_negative_info_kci' => $apiResult['negativeInfoKCI'] ?? null,
|
|
'raw_negative_info_cb' => $apiResult['negativeInfoCB'] ?? null,
|
|
'raw_suspension_info' => $apiResult['suspensionInfo'] ?? null,
|
|
'raw_workout_info' => $apiResult['workoutInfo'] ?? null,
|
|
|
|
// 상태
|
|
'status' => $status,
|
|
'error_message' => $status !== 'success' ? implode('; ', $errors) : null,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 스코프: 사업자번호로 검색
|
|
*/
|
|
public function scopeByCompanyKey($query, string $companyKey)
|
|
{
|
|
return $query->where('company_key', $companyKey);
|
|
}
|
|
|
|
/**
|
|
* 스코프: 기간으로 검색
|
|
*/
|
|
public function scopeBetweenDates($query, $startDate, $endDate)
|
|
{
|
|
return $query->whereBetween('inquired_at', [$startDate, $endDate]);
|
|
}
|
|
|
|
/**
|
|
* 스코프: 이슈 있는 것만
|
|
*/
|
|
public function scopeWithIssues($query)
|
|
{
|
|
return $query->where(function ($q) {
|
|
$q->where('short_term_overdue_cnt', '>', 0)
|
|
->orWhere('negative_info_kci_cnt', '>', 0)
|
|
->orWhere('negative_info_pb_cnt', '>', 0)
|
|
->orWhere('negative_info_cb_cnt', '>', 0)
|
|
->orWhere('suspension_info_cnt', '>', 0)
|
|
->orWhere('workout_cnt', '>', 0);
|
|
});
|
|
}
|
|
}
|