Files
sam-api/app/Services/Barobill/BarobillUsageService.php
김보곤 ac94602cf1 feat: [barobill] 구독/과금/사용량 관리 API 이관
- BarobillBillingService 생성 (구독 CRUD, 월별 과금 배치, 사용량 과금, 집계)
- BarobillUsageService 생성 (회원별 사용량 조회, 통계, 정책 기반 과금 계산)
- BarobillBillingController 생성 (9개 엔드포인트)
  - 구독 관리, 월별 현황, 과금 배치, 연간 추이, 정책 관리
- BarobillUsageController 생성 (4개 엔드포인트)
  - 사용량 목록/통계, 회원별 상세, 과금 정책 정보
- finance.php 라우트 등록 (barobill/billing/*, barobill/usage/*)
2026-03-22 19:59:41 +09:00

164 lines
5.3 KiB
PHP

<?php
namespace App\Services\Barobill;
use App\Models\Barobill\BarobillBankTransaction;
use App\Models\Barobill\BarobillCardTransaction;
use App\Models\Barobill\BarobillMember;
use App\Models\Barobill\BarobillPricingPolicy;
use App\Models\Barobill\HometaxInvoice;
use App\Services\Service;
class BarobillUsageService extends Service
{
/**
* 전체 회원사 사용량 목록
*/
public function getUsageList(string $startDate, string $endDate, ?int $tenantId = null): array
{
$query = BarobillMember::withoutGlobalScopes()
->where('status', 'active');
if ($tenantId) {
$query->where('tenant_id', $tenantId);
}
$members = $query->get();
$usageList = [];
foreach ($members as $member) {
$usageList[] = $this->getMemberUsage($member, $startDate, $endDate);
}
return $usageList;
}
/**
* 단일 회원사 사용량 상세
*/
public function getMemberUsage(BarobillMember $member, string $startDate, string $endDate): array
{
$taxInvoiceCount = $this->getTaxInvoiceCount($member, $startDate, $endDate);
$bankAccountCount = $this->getBankAccountCount($member);
$cardCount = $this->getCardCount($member);
$hometaxCount = $this->getHometaxCount($member, $startDate, $endDate);
$taxInvoiceBilling = $this->calculateBillingByPolicy('tax_invoice', $taxInvoiceCount);
return [
'member_id' => $member->id,
'tenant_id' => $member->tenant_id,
'biz_no' => $member->biz_no,
'corp_name' => $member->corp_name,
'barobill_id' => $member->barobill_id,
'server_mode' => $member->server_mode ?? 'test',
'tax_invoice_count' => $taxInvoiceCount,
'bank_account_count' => $bankAccountCount,
'card_count' => $cardCount,
'hometax_count' => $hometaxCount,
'tax_invoice_billing' => $taxInvoiceBilling,
'total_amount' => $taxInvoiceBilling['billable_amount'] ?? 0,
];
}
/**
* 사용량 통계 집계
*/
public function aggregateStats(array $usageList): array
{
$stats = [
'total_members' => count($usageList),
'total_tax_invoice_count' => 0,
'total_bank_account_count' => 0,
'total_card_count' => 0,
'total_hometax_count' => 0,
'total_amount' => 0,
];
foreach ($usageList as $usage) {
$stats['total_tax_invoice_count'] += $usage['tax_invoice_count'];
$stats['total_bank_account_count'] += $usage['bank_account_count'];
$stats['total_card_count'] += $usage['card_count'];
$stats['total_hometax_count'] += $usage['hometax_count'];
$stats['total_amount'] += $usage['total_amount'];
}
return $stats;
}
/**
* 과금 정책 정보
*/
public static function getPriceInfo(): array
{
$policies = BarobillPricingPolicy::withoutGlobalScopes()
->where('is_active', true)
->orderBy('sort_order')
->get();
$info = [];
foreach ($policies as $policy) {
$info[$policy->service_type] = [
'name' => $policy->name,
'free_quota' => $policy->free_quota,
'free_quota_unit' => $policy->free_quota_unit,
'additional_unit' => $policy->additional_unit,
'additional_unit_label' => $policy->additional_unit_label,
'additional_price' => $policy->additional_price,
];
}
return $info;
}
/**
* 정책 기반 과금액 계산
*/
public static function calculateBillingByPolicy(string $serviceType, int $usageCount): array
{
$policy = BarobillPricingPolicy::withoutGlobalScopes()
->where('service_type', $serviceType)
->where('is_active', true)
->first();
if (! $policy) {
return ['free_count' => $usageCount, 'billable_count' => 0, 'billable_amount' => 0];
}
return $policy->calculateBilling($usageCount);
}
protected function getTaxInvoiceCount(BarobillMember $member, string $startDate, string $endDate): int
{
return HometaxInvoice::withoutGlobalScopes()
->where('tenant_id', $member->tenant_id)
->where('invoice_type', 'sales')
->whereBetween('write_date', [$startDate, $endDate])
->count();
}
protected function getBankAccountCount(BarobillMember $member): int
{
return BarobillBankTransaction::withoutGlobalScopes()
->where('tenant_id', $member->tenant_id)
->distinct('bank_account_num')
->count('bank_account_num');
}
protected function getCardCount(BarobillMember $member): int
{
return BarobillCardTransaction::withoutGlobalScopes()
->where('tenant_id', $member->tenant_id)
->distinct('card_num')
->count('card_num');
}
protected function getHometaxCount(BarobillMember $member, string $startDate, string $endDate): int
{
return HometaxInvoice::withoutGlobalScopes()
->where('tenant_id', $member->tenant_id)
->whereBetween('write_date', [$startDate, $endDate])
->count();
}
}