fix: [finance] 분리 카드거래를 개별 행으로 확장 표시
- 백엔드: 분리 항목을 CardTransactionSplit에서 조회하여 개별 행으로 확장 - 프론트: 분리#N 배지 추가, 각 분리 행이 자체 분개 표시
This commit is contained in:
@@ -1008,11 +1008,63 @@ public function cardTransactions(Request $request): JsonResponse
|
||||
// 각 거래의 uniqueKey 수집
|
||||
$uniqueKeys = array_column($logs, 'uniqueKey');
|
||||
|
||||
// 분개 완료된 source_key 조회 (직접 매칭)
|
||||
$journaledKeys = JournalEntry::getJournaledSourceKeys($tenantId, 'ecard_transaction', $uniqueKeys);
|
||||
// 분리 데이터 조회 (uniqueKey별 splits)
|
||||
$splitsGrouped = [];
|
||||
if (! empty($uniqueKeys)) {
|
||||
$splits = CardTransactionSplit::where('tenant_id', $tenantId)
|
||||
->whereIn('original_unique_key', $uniqueKeys)
|
||||
->orderBy('original_unique_key')
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
foreach ($splits as $s) {
|
||||
$splitsGrouped[$s->original_unique_key][] = $s;
|
||||
}
|
||||
}
|
||||
|
||||
// 분리 거래 확장: 분리가 있는 카드거래는 분리 항목별 행으로 교체
|
||||
$expandedLogs = [];
|
||||
foreach ($logs as $log) {
|
||||
$key = $log['uniqueKey'];
|
||||
$logSplits = $splitsGrouped[$key] ?? [];
|
||||
|
||||
if (! empty($logSplits)) {
|
||||
// 분리 거래: 각 split을 별도 행으로 확장
|
||||
foreach ($logSplits as $split) {
|
||||
$splitSupply = (int) ($split->split_supply_amount ?? 0);
|
||||
$splitTax = (int) ($split->split_tax ?? 0);
|
||||
$splitAmount = $splitSupply + $splitTax;
|
||||
|
||||
$expandedLogs[] = array_merge($log, [
|
||||
'uniqueKey' => $key.'|split:'.$split->id,
|
||||
'parentUniqueKey' => $key,
|
||||
'isSplit' => true,
|
||||
'splitIndex' => $split->sort_order + 1,
|
||||
'splitTotal' => count($logSplits),
|
||||
'merchantName' => $split->description ?: $log['merchantName'],
|
||||
'deductionType' => $split->deduction_type ?? $log['deductionType'],
|
||||
'supplyAmount' => $splitSupply,
|
||||
'taxAmount' => $splitTax,
|
||||
'approvalAmount' => $splitAmount,
|
||||
'accountCode' => $split->account_code ?? $log['accountCode'],
|
||||
'accountName' => $split->account_name ?? $log['accountName'],
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
// 분리 없음: 원본 그대로
|
||||
$log['isSplit'] = false;
|
||||
$expandedLogs[] = $log;
|
||||
}
|
||||
}
|
||||
$logs = $expandedLogs;
|
||||
|
||||
// 확장된 uniqueKey 수집
|
||||
$allSourceKeys = array_column($logs, 'uniqueKey');
|
||||
|
||||
// 분개 완료된 source_key 조회 (직접 + 분리 키 모두 포함)
|
||||
$journaledKeys = JournalEntry::getJournaledSourceKeys($tenantId, 'ecard_transaction', $allSourceKeys);
|
||||
$journaledKeysMap = array_flip($journaledKeys);
|
||||
|
||||
// 분개된 전표 ID 조회 (직접 매칭)
|
||||
// 분개된 전표 ID 조회
|
||||
$journalMap = [];
|
||||
if (! empty($journaledKeys)) {
|
||||
$journals = JournalEntry::where('tenant_id', $tenantId)
|
||||
@@ -1025,59 +1077,13 @@ public function cardTransactions(Request $request): JsonResponse
|
||||
}
|
||||
}
|
||||
|
||||
// 분리 거래의 분개 상태 조회 (source_key LIKE 'uniqueKey|split:%')
|
||||
$splitJournalMap = []; // originalKey => [['id' => ..., 'entry_no' => ...], ...]
|
||||
if (! empty($uniqueKeys)) {
|
||||
$splitJournals = JournalEntry::where('tenant_id', $tenantId)
|
||||
->where('source_type', 'ecard_transaction')
|
||||
->where(function ($q) use ($uniqueKeys) {
|
||||
foreach ($uniqueKeys as $key) {
|
||||
$q->orWhere('source_key', 'LIKE', $key.'|split:%');
|
||||
}
|
||||
})
|
||||
->select('id', 'source_key', 'entry_no')
|
||||
->get();
|
||||
|
||||
foreach ($splitJournals as $j) {
|
||||
$originalKey = explode('|split:', $j->source_key)[0];
|
||||
$splitJournalMap[$originalKey][] = ['id' => $j->id, 'entry_no' => $j->entry_no];
|
||||
}
|
||||
}
|
||||
|
||||
// 분리 건수 조회 (전체 분개 완료 여부 판단용)
|
||||
$splitCounts = [];
|
||||
if (! empty($uniqueKeys)) {
|
||||
$counts = CardTransactionSplit::where('tenant_id', $tenantId)
|
||||
->whereIn('original_unique_key', $uniqueKeys)
|
||||
->selectRaw('original_unique_key, COUNT(*) as cnt')
|
||||
->groupBy('original_unique_key')
|
||||
->pluck('cnt', 'original_unique_key');
|
||||
$splitCounts = $counts->toArray();
|
||||
}
|
||||
|
||||
// 각 거래에 분개 상태 추가
|
||||
$journaledCount = 0;
|
||||
foreach ($logs as &$log) {
|
||||
$key = $log['uniqueKey'] ?? '';
|
||||
$directMatch = isset($journaledKeysMap[$key]);
|
||||
$splitCount = $splitCounts[$key] ?? 0;
|
||||
$splitJournals = $splitJournalMap[$key] ?? [];
|
||||
$allSplitsJournaled = $splitCount > 0 && count($splitJournals) >= $splitCount;
|
||||
|
||||
$log['hasJournal'] = $directMatch || $allSplitsJournaled;
|
||||
$log['splitJournalIds'] = [];
|
||||
|
||||
if ($directMatch) {
|
||||
$log['journalId'] = $journalMap[$key]['id'] ?? null;
|
||||
$log['journalEntryNo'] = $journalMap[$key]['entry_no'] ?? null;
|
||||
} elseif (! empty($splitJournals)) {
|
||||
$log['journalId'] = $splitJournals[0]['id'];
|
||||
$log['journalEntryNo'] = $splitJournals[0]['entry_no'];
|
||||
$log['splitJournalIds'] = array_column($splitJournals, 'id');
|
||||
} else {
|
||||
$log['journalId'] = null;
|
||||
$log['journalEntryNo'] = null;
|
||||
}
|
||||
$log['hasJournal'] = isset($journaledKeysMap[$key]);
|
||||
$log['journalId'] = $journalMap[$key]['id'] ?? null;
|
||||
$log['journalEntryNo'] = $journalMap[$key]['entry_no'] ?? null;
|
||||
|
||||
if ($log['hasJournal']) {
|
||||
$journaledCount++;
|
||||
@@ -1085,12 +1091,18 @@ public function cardTransactions(Request $request): JsonResponse
|
||||
}
|
||||
unset($log);
|
||||
|
||||
// 통계
|
||||
$totalCount = count($logs);
|
||||
$totalAmount = array_sum(array_column($logs, 'approvalAmount'));
|
||||
// 통계 (원본 거래 기준)
|
||||
$originalLogs = array_filter($logs, fn ($l) => ! ($l['isSplit'] ?? false));
|
||||
$splitParentKeys = array_unique(array_column(
|
||||
array_filter($logs, fn ($l) => ($l['isSplit'] ?? false) && ($l['splitIndex'] ?? 0) === 1),
|
||||
'parentUniqueKey'
|
||||
));
|
||||
$totalCount = count($originalLogs) + count($splitParentKeys);
|
||||
$totalAmount = 0;
|
||||
$deductibleSum = 0;
|
||||
$nonDeductibleSum = 0;
|
||||
foreach ($logs as $log) {
|
||||
$totalAmount += $log['approvalAmount'];
|
||||
if ($log['deductionType'] === 'non_deductible') {
|
||||
$nonDeductibleSum += $log['approvalAmount'];
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user