From 352b521fcf444b939315ef239cd2e20d31d74d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 10 Feb 2026 17:17:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=EC=88=98=EB=8F=99/API=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=20=EA=B1=B0=EB=9E=98=20=EC=A0=9C=EA=B1=B0=20(mergeWithDedup)?= =?UTF-8?q?=20+=20=EB=94=94=EB=B2=84=EA=B7=B8=20=EB=A1=9C=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Barobill/EaccountController.php | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Barobill/EaccountController.php b/app/Http/Controllers/Barobill/EaccountController.php index e6828386..76acee2e 100644 --- a/app/Http/Controllers/Barobill/EaccountController.php +++ b/app/Http/Controllers/Barobill/EaccountController.php @@ -395,9 +395,9 @@ public function transactions(Request $request): JsonResponse // 데이터 파싱 (저장된 계정과목 + 오버라이드 병합) $logs = $this->parseTransactionLogs($resultData, '', $savedData, $tenantId); - // 수동 입력 건 병합 + // 수동 입력 건 병합 (중복 제거: 수동 거래와 동일한 API 거래는 제외) $manualLogs = $this->convertManualToLogs($manualTransactions); - $mergedLogs = array_merge($logs['logs'], $manualLogs['logs']); + $mergedLogs = $this->mergeWithDedup($logs['logs'], $manualLogs['logs']); // 날짜/시간 기준 정렬 (최신순) usort($mergedLogs, function ($a, $b) { @@ -410,11 +410,11 @@ public function transactions(Request $request): JsonResponse $baseBalance = $this->findBaseBalance($tenantId, $startDate, $bankAccountNum); $mergedLogs = $this->recalcManualBalances($mergedLogs, $baseBalance); - // summary 합산 + // summary 합산 (중복 제거 후 count 재계산) $mergedSummary = [ 'totalDeposit' => $logs['summary']['totalDeposit'] + $manualLogs['summary']['totalDeposit'], 'totalWithdraw' => $logs['summary']['totalWithdraw'] + $manualLogs['summary']['totalWithdraw'], - 'count' => $logs['summary']['count'] + $manualLogs['summary']['count'], + 'count' => count($mergedLogs), ]; return response()->json([ @@ -499,12 +499,10 @@ private function getAllAccountsTransactions(string $userId, string $startDate, s } } - // 수동 입력 건 병합 + // 수동 입력 건 병합 (중복 제거: 수동 거래와 동일한 API 거래는 제외) if ($manualTransactions && $manualTransactions->isNotEmpty()) { $manualLogs = $this->convertManualToLogs($manualTransactions); - foreach ($manualLogs['logs'] as $mLog) { - $allLogs[] = $mLog; - } + $allLogs = $this->mergeWithDedup($allLogs, $manualLogs['logs']); $totalDeposit += $manualLogs['summary']['totalDeposit']; $totalWithdraw += $manualLogs['summary']['totalWithdraw']; } @@ -1516,6 +1514,53 @@ private function findBaseBalance(int $tenantId, string $startDate, ?string $bank return $balance; } + /** + * API 로그와 수동 로그 병합 (중복 제거) + * 수동 거래와 동일한 API 거래가 있으면 API 거래를 제외하고 수동 거래를 유지 + * 매칭 기준: 계좌번호 + 거래일시 + 입금액 + 출금액 (잔액 제외 - 수동 거래는 재계산됨) + */ + private function mergeWithDedup(array $apiLogs, array $manualLogs): array + { + if (empty($manualLogs)) { + return $apiLogs; + } + + // 수동 거래의 매칭 키 생성 (잔액 제외) + $manualKeys = []; + foreach ($manualLogs as $mLog) { + $key = implode('|', [ + $mLog['bankAccountNum'] ?? '', + ($mLog['transDate'] ?? '') . ($mLog['transTime'] ?? ''), + (int) ($mLog['deposit'] ?? 0), + (int) ($mLog['withdraw'] ?? 0), + ]); + $manualKeys[$key] = true; + } + + // API 로그에서 수동 거래와 중복되는 것 제외 + $dedupedApiLogs = []; + $removedCount = 0; + foreach ($apiLogs as $aLog) { + $key = implode('|', [ + $aLog['bankAccountNum'] ?? '', + ($aLog['transDate'] ?? '') . ($aLog['transTime'] ?? ''), + (int) ($aLog['deposit'] ?? 0), + (int) ($aLog['withdraw'] ?? 0), + ]); + if (isset($manualKeys[$key])) { + $removedCount++; + continue; // 수동 거래가 우선, API 거래 스킵 + } + $dedupedApiLogs[] = $aLog; + } + + if ($removedCount > 0) { + Log::info('[Eaccount] 중복 거래 제거', ['removed' => $removedCount]); + } + + return array_merge($dedupedApiLogs, $manualLogs); + } + private function recalcManualBalances(array $logs, ?float $baseBalance = null): array { if (empty($logs)) return $logs;