'카드', self::CATEGORY_CONGRATULATORY => '경조사', self::CATEGORY_GIFT_CERTIFICATE => '상품권', self::CATEGORY_ENTERTAINMENT => '접대비', ]; /** * 인정이자율 (연도별) */ public const INTEREST_RATES = [ 2024 => 4.6, 2025 => 4.6, ]; /** * 기본 인정이자율 (연도 미설정시) */ public const DEFAULT_INTEREST_RATE = 4.6; /** * 세금 요율 */ public const CORPORATE_TAX_RATE = 0.19; // 법인세 추가 19% public const INCOME_TAX_RATE = 0.35; // 소득세 추가 35% public const LOCAL_TAX_RATE = 0.10; // 지방소득세 10% // ========================================================================= // 모델 설정 // ========================================================================= protected $fillable = [ 'tenant_id', 'user_id', 'loan_date', 'amount', 'purpose', 'settlement_date', 'settlement_amount', 'status', 'category', 'metadata', 'withdrawal_id', 'created_by', 'updated_by', 'deleted_by', ]; protected $casts = [ 'loan_date' => 'date', 'settlement_date' => 'date', 'amount' => 'decimal:2', 'settlement_amount' => 'decimal:2', 'metadata' => 'array', ]; // ========================================================================= // 관계 정의 // ========================================================================= /** * 가지급금 수령자 */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * 출금 내역 */ public function withdrawal(): BelongsTo { return $this->belongsTo(Withdrawal::class); } /** * 생성자 */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } /** * 수정자 */ public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } // ========================================================================= // 접근자 (Accessors) // ========================================================================= /** * 상태 레이블 */ public function getStatusLabelAttribute(): string { return match ($this->status) { self::STATUS_OUTSTANDING => '미정산', self::STATUS_SETTLED => '정산완료', self::STATUS_PARTIAL => '부분정산', self::STATUS_HOLDING => '보유', self::STATUS_USED => '사용', self::STATUS_DISPOSED => '폐기', default => $this->status, }; } /** * 카테고리 라벨 */ public function getCategoryLabelAttribute(): string { return self::CATEGORY_LABELS[$this->category] ?? $this->category ?? '카드'; } /** * 미정산 잔액 */ public function getOutstandingAmountAttribute(): float { $settlementAmount = (float) ($this->settlement_amount ?? 0); return (float) $this->amount - $settlementAmount; } /** * 경과일수 계산 */ public function getElapsedDaysAttribute(): int { if ($this->settlement_date) { return $this->loan_date->diffInDays($this->settlement_date); } return $this->loan_date->diffInDays(now()); } // ========================================================================= // 상태 체크 메서드 // ========================================================================= /** * 수정 가능 여부 (미정산 상태 또는 상품권) */ public function isEditable(): bool { if ($this->category === self::CATEGORY_GIFT_CERTIFICATE) { return true; } return in_array($this->status, [ self::STATUS_OUTSTANDING, self::STATUS_HOLDING, ]); } /** * 삭제 가능 여부 (미정산/보유 상태 또는 상품권) */ public function isDeletable(): bool { if ($this->category === self::CATEGORY_GIFT_CERTIFICATE) { return true; } return in_array($this->status, [ self::STATUS_OUTSTANDING, self::STATUS_HOLDING, ]); } /** * 정산 가능 여부 */ public function isSettleable(): bool { return in_array($this->status, [self::STATUS_OUTSTANDING, self::STATUS_PARTIAL]); } // ========================================================================= // 인정이자 계산 메서드 // ========================================================================= /** * 연도별 인정이자율 조회 */ public static function getInterestRate(int $year): float { return self::INTEREST_RATES[$year] ?? self::DEFAULT_INTEREST_RATE; } /** * 인정이자 계산 * * @param int|null $elapsedDays 경과일수 (미지정시 자동 계산) * @param int|null $year 연도 (미지정시 지급일 연도) */ public function calculateRecognizedInterest(?int $elapsedDays = null, ?int $year = null): float { $days = $elapsedDays ?? $this->elapsed_days; $rateYear = $year ?? $this->loan_date->year; $annualRate = self::getInterestRate($rateYear); $dailyRate = $annualRate / 365 / 100; return (float) $this->outstanding_amount * $dailyRate * $days; } /** * 세금 계산 (인정이자 기반) * * @param float|null $recognizedInterest 인정이자 (미지정시 자동 계산) */ public function calculateTaxes(?float $recognizedInterest = null): array { $interest = $recognizedInterest ?? $this->calculateRecognizedInterest(); $corporateTax = $interest * self::CORPORATE_TAX_RATE; $incomeTax = $interest * self::INCOME_TAX_RATE; $localTax = $incomeTax * self::LOCAL_TAX_RATE; $totalTax = $corporateTax + $incomeTax + $localTax; return [ 'recognized_interest' => round($interest, 2), 'corporate_tax' => round($corporateTax, 2), 'income_tax' => round($incomeTax, 2), 'local_tax' => round($localTax, 2), 'total_tax' => round($totalTax, 2), ]; } }