160 lines
4.5 KiB
PHP
160 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Barobill;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* 바로빌 과금 정책 모델
|
|
*
|
|
* @property int $id
|
|
* @property string $service_type 서비스 유형 (card, tax_invoice, bank_account)
|
|
* @property string $name 정책명
|
|
* @property string|null $description 설명
|
|
* @property int $free_quota 무료 기본 제공량
|
|
* @property string $free_quota_unit 무료 제공 단위
|
|
* @property int $additional_unit 추가 과금 단위
|
|
* @property string $additional_unit_label 추가 단위 라벨
|
|
* @property int $additional_price 추가 과금 금액
|
|
* @property bool $is_active 활성화 여부
|
|
* @property int $sort_order 정렬 순서
|
|
* @property \Carbon\Carbon $created_at
|
|
* @property \Carbon\Carbon $updated_at
|
|
*/
|
|
class BarobillPricingPolicy extends Model
|
|
{
|
|
protected $table = 'barobill_pricing_policies';
|
|
|
|
protected $fillable = [
|
|
'service_type',
|
|
'name',
|
|
'description',
|
|
'free_quota',
|
|
'free_quota_unit',
|
|
'additional_unit',
|
|
'additional_unit_label',
|
|
'additional_price',
|
|
'is_active',
|
|
'sort_order',
|
|
];
|
|
|
|
protected $casts = [
|
|
'free_quota' => '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);
|
|
}
|
|
}
|