Files
sam-manage/app/Models/Credit/CreditInquiry.php
2026-02-25 11:45:01 +09:00

319 lines
10 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 = [
'tenant_id',
'inquiry_key',
'company_key',
'company_name',
'ceo_name',
'company_address',
'business_type',
'business_item',
'establishment_date',
'nts_status',
'nts_status_code',
'nts_tax_type',
'nts_closure_date',
'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',
'raw_company_info',
'raw_nts_status',
'status',
'error_message',
];
protected $casts = [
'inquired_at' => 'datetime',
'establishment_date' => 'date',
'nts_closure_date' => 'date',
'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',
'raw_company_info' => 'array',
'raw_nts_status' => '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 [
'companyInfo' => $this->raw_company_info,
'ntsStatus' => $this->raw_nts_status,
'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,
];
}
/**
* 국세청 상태가 정상(영업중)인지 확인
*/
public function isNtsActive(): bool
{
return $this->nts_status_code === '01';
}
/**
* 국세청 상태 라벨
*/
public function getNtsStatusLabelAttribute(): string
{
return match ($this->nts_status_code) {
'01' => '계속사업자',
'02' => '휴업자',
'03' => '폐업자',
default => $this->nts_status ?: '미확인',
};
}
/**
* API 응답으로부터 모델 생성
*
* @param string $companyKey 사업자번호
* @param array $apiResult 쿠콘 API 결과
* @param array|null $ntsResult 국세청 API 결과
* @param int|null $userId 조회자 ID
* @param int|null $tenantId 테넌트 ID
*/
public static function createFromApiResponse(
string $companyKey,
array $apiResult,
?array $ntsResult = null,
?int $userId = null,
?int $tenantId = null
): self {
// 요약 정보에서 건수 추출
$summaryData = $apiResult['summary']['data'] ?? [];
$creditSummaryList = $summaryData['data']['creditSummaryList'][0]
?? $summaryData['creditSummaryList'][0]
?? [];
// 기업 기본정보 추출 (OA08)
$companyInfoData = $apiResult['companyInfo']['data']['data'] ?? $apiResult['companyInfo']['data'] ?? [];
$companyName = $companyInfoData['korentrnm'] ?? $companyInfoData['entrpNm'] ?? null;
$ceoName = $companyInfoData['korreprnm'] ?? $companyInfoData['reprNm'] ?? null;
$companyAddress = $companyInfoData['addr'] ?? $companyInfoData['address'] ?? null;
$businessType = $companyInfoData['bizcnd'] ?? $companyInfoData['indutyNm'] ?? null;
$businessItem = $companyInfoData['bizitm'] ?? $companyInfoData['indutyDetailNm'] ?? null;
$establishmentDate = null;
if (! empty($companyInfoData['estbDt']) || ! empty($companyInfoData['estbDate'])) {
$estbDt = $companyInfoData['estbDt'] ?? $companyInfoData['estbDate'];
if (strlen($estbDt) === 8) {
$establishmentDate = substr($estbDt, 0, 4).'-'.substr($estbDt, 4, 2).'-'.substr($estbDt, 6, 2);
}
}
// 국세청 상태 추출
$ntsStatus = null;
$ntsStatusCode = null;
$ntsTaxType = null;
$ntsClosureDate = null;
if ($ntsResult && ($ntsResult['success'] ?? false)) {
$ntsData = $ntsResult['data'] ?? [];
$ntsStatus = $ntsData['b_stt'] ?? null;
$ntsStatusCode = $ntsData['b_stt_cd'] ?? null;
$ntsTaxType = $ntsData['tax_type'] ?? null;
if (! empty($ntsData['end_dt']) && strlen($ntsData['end_dt']) === 8) {
$ntsClosureDate = substr($ntsData['end_dt'], 0, 4).'-'.substr($ntsData['end_dt'], 4, 2).'-'.substr($ntsData['end_dt'], 6, 2);
}
}
// 성공/실패 상태 판단
$successCount = 0;
$totalCount = 7; // companyInfo 추가
$errors = [];
foreach (['companyInfo', '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([
'tenant_id' => $tenantId,
'company_key' => $companyKey,
'user_id' => $userId,
'inquired_at' => now(),
// 기업 기본정보
'company_name' => $companyName,
'ceo_name' => $ceoName,
'company_address' => $companyAddress,
'business_type' => $businessType,
'business_item' => $businessItem,
'establishment_date' => $establishmentDate,
// 국세청 상태
'nts_status' => $ntsStatus,
'nts_status_code' => $ntsStatusCode,
'nts_tax_type' => $ntsTaxType,
'nts_closure_date' => $ntsClosureDate,
// 요약 건수
'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_company_info' => $apiResult['companyInfo'] ?? null,
'raw_nts_status' => $ntsResult,
'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);
});
}
}