fix:카드별 사용금액 프로그래스바 바로빌 실거래 데이터 반영
- summary API에 cardUsages(카드번호별 사용금액) 응답 추가 - 카드 목록 프로그래스바가 바로빌 거래 합산 기준으로 표시 - 체크카드도 사용금액 있으면 금액 표시 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -228,8 +228,8 @@ public function summary(): JsonResponse
|
||||
// 카드번호 목록
|
||||
$cardNumbers = $activeCards->pluck('card_number')->toArray();
|
||||
|
||||
// 사용금액 계산
|
||||
$billingUsage = $this->calculateBillingUsage(
|
||||
// 사용금액 계산 (전체 + 카드별)
|
||||
$usageResult = $this->calculateBillingUsage(
|
||||
$tenantId,
|
||||
$billingStart->format('Y-m-d'),
|
||||
$billingEnd->format('Y-m-d'),
|
||||
@@ -251,7 +251,8 @@ public function summary(): JsonResponse
|
||||
'start' => $billingStart->format('Y-m-d'),
|
||||
'end' => $billingEnd->format('Y-m-d'),
|
||||
],
|
||||
'billingUsage' => $billingUsage,
|
||||
'billingUsage' => $usageResult['total'],
|
||||
'cardUsages' => $usageResult['perCard'],
|
||||
'prepaidAmount' => (int) $prepayment->amount,
|
||||
'prepaidMemo' => $prepayment->memo ?? '',
|
||||
],
|
||||
@@ -328,13 +329,13 @@ private function getAdjustedPaymentDate(int $tenantId, int $year, int $month, in
|
||||
/**
|
||||
* 청구기간 사용금액 계산 (바로빌 카드거래 합산)
|
||||
*/
|
||||
private function calculateBillingUsage(int $tenantId, string $startDate, string $endDate, array $cardNumbers): int
|
||||
private function calculateBillingUsage(int $tenantId, string $startDate, string $endDate, array $cardNumbers): array
|
||||
{
|
||||
// 카드번호 정규화 (하이픈 제거)
|
||||
// 카드번호 정규화 (하이픈 제거) + 원본↔정규화 매핑
|
||||
$normalizedNums = array_map(fn($num) => str_replace('-', '', $num), $cardNumbers);
|
||||
|
||||
if (empty($normalizedNums)) {
|
||||
return 0;
|
||||
return ['total' => 0, 'perCard' => []];
|
||||
}
|
||||
|
||||
// use_date는 YYYYMMDD 형식
|
||||
@@ -351,18 +352,24 @@ private function calculateBillingUsage(int $tenantId, string $startDate, string
|
||||
->get();
|
||||
|
||||
$total = 0;
|
||||
$perCard = [];
|
||||
foreach ($transactions as $tx) {
|
||||
if ($hiddenKeys->contains($tx->unique_key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$amount = 0;
|
||||
if ($tx->approval_type === '1') {
|
||||
$total += (int) $tx->approval_amount; // 승인
|
||||
$amount = (int) $tx->approval_amount;
|
||||
} elseif ($tx->approval_type === '2') {
|
||||
$total -= (int) $tx->approval_amount; // 취소
|
||||
$amount = -(int) $tx->approval_amount;
|
||||
}
|
||||
|
||||
$total += $amount;
|
||||
$cardNum = $tx->card_num;
|
||||
$perCard[$cardNum] = ($perCard[$cardNum] ?? 0) + $amount;
|
||||
}
|
||||
|
||||
return $total;
|
||||
return ['total' => $total, 'perCard' => (object) $perCard];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +397,13 @@ function CorporateCardsManagement() {
|
||||
return 'bg-emerald-500';
|
||||
};
|
||||
|
||||
// 카드번호로 바로빌 사용금액 조회 (하이픈 제거 매칭)
|
||||
const getCardBillingUsage = (cardNumber) => {
|
||||
if (!summaryData?.cardUsages || !cardNumber) return 0;
|
||||
const normalized = cardNumber.replace(/-/g, '');
|
||||
return summaryData.cardUsages[normalized] || 0;
|
||||
};
|
||||
|
||||
// 총 한도 및 사용액
|
||||
const totalLimit = cards.filter(c => c.status === 'active' && c.cardType === 'credit').reduce((sum, c) => sum + c.creditLimit, 0);
|
||||
const totalUsage = cards.filter(c => c.status === 'active').reduce((sum, c) => sum + c.currentUsage, 0);
|
||||
@@ -602,24 +609,43 @@ className={`grid grid-cols-12 gap-4 px-4 py-3 border-b border-gray-100 cursor-po
|
||||
|
||||
{/* 사용현황 */}
|
||||
<div className="col-span-3 flex items-center gap-2">
|
||||
{card.cardType === 'debit' ? (
|
||||
<span className="px-2 py-0.5 bg-blue-100 text-blue-700 text-xs font-medium rounded">체크카드</span>
|
||||
) : card.creditLimit > 0 ? (
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between text-xs mb-1">
|
||||
<span className="text-gray-500">{formatCurrency(card.currentUsage)}원</span>
|
||||
<span className="text-gray-400">{getUsagePercent(card.currentUsage, card.creditLimit)}%</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-1.5">
|
||||
<div
|
||||
className={`h-1.5 rounded-full ${getUsageColor(getUsagePercent(card.currentUsage, card.creditLimit))}`}
|
||||
style={{ width: `${Math.min(getUsagePercent(card.currentUsage, card.creditLimit), 100)}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<span className="px-2 py-0.5 bg-violet-100 text-violet-700 text-xs font-medium rounded">신용카드</span>
|
||||
)}
|
||||
{(() => {
|
||||
const billingUsage = getCardBillingUsage(card.cardNumber);
|
||||
if (card.cardType === 'debit') {
|
||||
return billingUsage > 0 ? (
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<span className="text-gray-500">{formatCurrency(billingUsage)}원</span>
|
||||
<span className="px-1.5 py-0.5 bg-blue-100 text-blue-700 text-xs font-medium rounded">체크</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<span className="px-2 py-0.5 bg-blue-100 text-blue-700 text-xs font-medium rounded">체크카드</span>
|
||||
);
|
||||
}
|
||||
if (card.creditLimit > 0) {
|
||||
const pct = getUsagePercent(billingUsage, card.creditLimit);
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between text-xs mb-1">
|
||||
<span className="text-gray-500">{formatCurrency(billingUsage)}원</span>
|
||||
<span className="text-gray-400">{pct}%</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-1.5">
|
||||
<div
|
||||
className={`h-1.5 rounded-full ${getUsageColor(pct)}`}
|
||||
style={{ width: `${Math.min(pct, 100)}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return billingUsage > 0 ? (
|
||||
<span className="text-xs text-gray-500">{formatCurrency(billingUsage)}원</span>
|
||||
) : (
|
||||
<span className="px-2 py-0.5 bg-violet-100 text-violet-700 text-xs font-medium rounded">신용카드</span>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{/* 상태 */}
|
||||
|
||||
Reference in New Issue
Block a user