'date', 'maturity_date' => 'date', 'amount' => 'decimal:2', 'client_id' => 'integer', 'bank_account_id' => 'integer', 'installment_count' => 'integer', 'is_electronic' => 'boolean', // V8 확장 casts 'acceptance_date' => 'date', 'acceptance_refusal_date' => 'date', 'discount_date' => 'date', 'discount_rate' => 'decimal:2', 'discount_amount' => 'decimal:2', 'endorsement_date' => 'date', 'collection_request_date' => 'date', 'collection_fee' => 'decimal:2', 'collection_complete_date' => 'date', 'collection_deposit_date' => 'date', 'collection_deposit_amount' => 'decimal:2', 'actual_payment_date' => 'date', 'renewal_date' => 'date', 'recourse_date' => 'date', 'recourse_amount' => 'decimal:2', 'buyback_date' => 'date', 'buyback_amount' => 'decimal:2', 'dishonored_date' => 'date', 'protest_date' => 'date', 'recourse_notice_date' => 'date', 'recourse_notice_deadline' => 'date', 'is_discounted' => 'boolean', 'has_protest' => 'boolean', 'is_split' => 'boolean', ]; /** * 배열/JSON 변환 시 날짜 형식 지정 */ /** * 날짜 cast 필드 목록 (toArray에서 Y-m-d 형식 변환용) */ private const DATE_FIELDS = [ 'issue_date', 'maturity_date', 'acceptance_date', 'acceptance_refusal_date', 'discount_date', 'endorsement_date', 'collection_request_date', 'collection_complete_date', 'collection_deposit_date', 'actual_payment_date', 'renewal_date', 'recourse_date', 'buyback_date', 'dishonored_date', 'protest_date', 'recourse_notice_date', 'recourse_notice_deadline', ]; public function toArray(): array { $array = parent::toArray(); foreach (self::DATE_FIELDS as $field) { if (isset($array[$field]) && $this->{$field}) { $array[$field] = $this->{$field}->format('Y-m-d'); } } return $array; } /** * 어음 구분 목록 */ public const BILL_TYPES = [ 'received' => '수취', 'issued' => '발행', ]; /** * 증권종류 */ public const INSTRUMENT_TYPES = [ 'promissory' => '약속어음', 'exchange' => '환어음', 'cashierCheck' => '자기앞수표', 'currentCheck' => '당좌수표', ]; /** * 수취 어음 상태 목록 */ public const RECEIVED_STATUSES = [ 'stored' => '보관중', 'endorsed' => '배서양도', 'discounted' => '할인', 'collectionRequest' => '추심의뢰', 'collectionComplete' => '추심완료', 'maturityDeposit' => '만기입금', 'paymentComplete' => '결제완료', 'dishonored' => '부도', 'renewed' => '개서', 'buyback' => '환매', // 하위호환 'maturityAlert' => '만기입금(7일전)', 'maturityResult' => '만기결과', ]; /** * 수취 수표 상태 목록 */ public const RECEIVED_CHECK_STATUSES = [ 'stored' => '보관중', 'endorsed' => '배서양도', 'deposited' => '입금', 'dishonored' => '부도', ]; /** * 발행 어음 상태 목록 */ public const ISSUED_STATUSES = [ 'stored' => '보관중', 'issued' => '지급대기', 'maturityPayment' => '만기결제', 'paymentComplete' => '결제완료', 'dishonored' => '부도', 'renewed' => '개서', // 하위호환 'maturityAlert' => '만기입금(7일전)', 'collectionRequest' => '추심의뢰', 'collectionComplete' => '추심완료', 'suing' => '추소중', ]; /** * 발행 수표 상태 목록 */ public const ISSUED_CHECK_STATUSES = [ 'stored' => '보관중', 'issued' => '지급대기', 'cashed' => '현금화', 'dishonored' => '부도', ]; /** * 거래처 관계 */ public function client(): BelongsTo { return $this->belongsTo(\App\Models\Orders\Client::class); } /** * 입금/출금 계좌 관계 */ public function bankAccount(): BelongsTo { return $this->belongsTo(BankAccount::class); } /** * 차수 관계 */ public function installments(): HasMany { return $this->hasMany(BillInstallment::class); } /** * 생성자 관계 */ public function creator(): BelongsTo { return $this->belongsTo(\App\Models\Members\User::class, 'created_by'); } /** * 거래처명 조회 (회원/비회원 통합) */ public function getDisplayClientNameAttribute(): string { if ($this->client) { return $this->client->name; } return $this->client_name ?? ''; } /** * 어음 구분 라벨 */ public function getBillTypeLabelAttribute(): string { return self::BILL_TYPES[$this->bill_type] ?? $this->bill_type; } /** * 상태 라벨 */ public function getStatusLabelAttribute(): string { $isCheck = in_array($this->instrument_type, ['cashierCheck', 'currentCheck']); if ($this->bill_type === 'received') { $statuses = $isCheck ? self::RECEIVED_CHECK_STATUSES : self::RECEIVED_STATUSES; return $statuses[$this->status] ?? self::RECEIVED_STATUSES[$this->status] ?? $this->status; } $statuses = $isCheck ? self::ISSUED_CHECK_STATUSES : self::ISSUED_STATUSES; return $statuses[$this->status] ?? self::ISSUED_STATUSES[$this->status] ?? $this->status; } /** * 증권종류 라벨 */ public function getInstrumentTypeLabelAttribute(): string { return self::INSTRUMENT_TYPES[$this->instrument_type] ?? $this->instrument_type ?? '약속어음'; } /** * 만기까지 남은 일수 */ public function getDaysToMaturityAttribute(): int { return now()->diffInDays($this->maturity_date, false); } /** * 만기 7일 전 여부 */ public function isMaturityAlertPeriod(): bool { $days = $this->days_to_maturity; return $days >= 0 && $days <= 7; } }