'integer', 'additional_unit' => 'integer', 'additional_price' => 'integer', 'is_active' => 'boolean', 'sort_order' => 'integer', ]; /** * 서비스 유형 상수 */ public const TYPE_CARD = 'card'; public const TYPE_TAX_INVOICE = 'tax_invoice'; public const TYPE_BANK_ACCOUNT = 'bank_account'; /** * 서비스 유형 라벨 */ public static function getServiceTypeLabels(): array { return [ self::TYPE_CARD => '법인카드 등록', self::TYPE_TAX_INVOICE => '계산서 발행', self::TYPE_BANK_ACCOUNT => '계좌조회 수집', ]; } /** * 서비스 유형 라벨 Accessor */ public function getServiceTypeLabelAttribute(): string { return self::getServiceTypeLabels()[$this->service_type] ?? $this->service_type; } /** * 활성화된 정책만 조회 */ public function scopeActive($query) { return $query->where('is_active', true); } /** * 서비스 유형별 정책 조회 */ public static function getByServiceType(string $serviceType): ?self { return static::where('service_type', $serviceType) ->where('is_active', true) ->first(); } /** * 모든 활성 정책 조회 (캐시) */ public static function getAllActive(): \Illuminate\Database\Eloquent\Collection { return static::active() ->orderBy('sort_order') ->get(); } /** * 추가 과금액 계산 * * @param int $usageCount 사용량 * @return array ['free_count' => int, 'billable_count' => int, 'billable_amount' => int] */ public function calculateBilling(int $usageCount): array { // 무료 제공량 초과분 $excessCount = max(0, $usageCount - $this->free_quota); if ($excessCount === 0 || $this->additional_price === 0) { return [ 'free_count' => min($usageCount, $this->free_quota), 'billable_count' => 0, 'billable_amount' => 0, ]; } // 추가 과금 단위에 따른 계산 // 예: 50건 단위면 51건도 100건도 동일하게 1단위 과금 $billableUnits = ceil($excessCount / $this->additional_unit); $billableAmount = (int) ($billableUnits * $this->additional_price); return [ 'free_count' => $this->free_quota, 'billable_count' => $excessCount, 'billable_amount' => $billableAmount, ]; } /** * 정책 설명 문자열 생성 */ public function getPolicyDescriptionAttribute(): string { $parts = []; if ($this->free_quota > 0) { $parts[] = "기본 {$this->free_quota}{$this->free_quota_unit} 무료"; } if ($this->additional_price > 0) { $priceFormatted = number_format($this->additional_price); if ($this->additional_unit > 1) { $parts[] = "추가 {$this->additional_unit}{$this->additional_unit_label} 단위 {$priceFormatted}원"; } else { $parts[] = "추가 1{$this->additional_unit_label}당 {$priceFormatted}원"; } } return implode(', ', $parts); } }