From 6eff3e0d554898bf37f1b2602a08f58c4cffb848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 24 Feb 2026 19:53:46 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20[ecard]=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=EB=B3=84=20=EA=B0=9C=EB=B3=84=20=EB=B6=84?= =?UTF-8?q?=EA=B0=9C=20=EC=83=9D=EC=84=B1=20=EA=B5=AC=EC=A1=B0=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 multi-split 번들 분개를 단일 split 개별 분개로 교체 - 원본 행 분개 열에 split별 집계 상태 표시 (N/M, 완료) - 각 분리 행에 독립 분개 버튼 추가 (splitSourceKey 기반) - handleOpenJournalModal에 singleSplit 파라미터 추가 - CardJournalModal 거래 정보에 개별 split 정보 표시 - 합계금액 열에 split 분개 진행률 표시 --- .../views/barobill/ecard/index.blade.php | 174 +++++++++++------- 1 file changed, 109 insertions(+), 65 deletions(-) diff --git a/resources/views/barobill/ecard/index.blade.php b/resources/views/barobill/ecard/index.blade.php index b068a3f6..bc1acb87 100644 --- a/resources/views/barobill/ecard/index.blade.php +++ b/resources/views/barobill/ecard/index.blade.php @@ -703,58 +703,56 @@ className={`px-3 py-1.5 text-sm cursor-pointer ${index === highlightIndex ? 'bg- // 기본 분개 라인 const getDefaultLines = () => { - // splits 데이터가 있으면 분리 항목 기반으로 라인 생성 - const splits = log._splits || []; - if (splits.length > 0) { - const debitLines = []; + // 단일 split 분개 (분리 항목별 개별 분개) + const singleSplit = log._split; + if (singleSplit) { + const splitSupply = Math.round(parseFloat(singleSplit.split_supply_amount ?? singleSplit.supplyAmount ?? singleSplit.split_amount ?? singleSplit.amount ?? 0)); + const splitTax = Math.round(parseFloat(singleSplit.split_tax ?? singleSplit.tax ?? 0)); + const splitDeductionType = singleSplit.deduction_type || singleSplit.deductionType || 'non_deductible'; + const splitAccountCode = singleSplit.account_code || singleSplit.accountCode || '826'; + const splitAccountName = singleSplit.account_name || singleSplit.accountName || '잡비'; + + const lines = []; let totalDebitSum = 0; - splits.forEach(split => { - const splitSupply = Math.round(parseFloat(split.split_supply_amount ?? split.supplyAmount ?? split.split_amount ?? split.amount ?? 0)); - const splitTax = Math.round(parseFloat(split.split_tax ?? split.tax ?? 0)); - const splitDeductionType = split.deduction_type || split.deductionType || 'non_deductible'; - const splitAccountCode = split.account_code || split.accountCode || '826'; - const splitAccountName = split.account_name || split.accountName || '잡비'; - - if (splitDeductionType === 'deductible') { - // 공제: 비용 계정 = 공급가액, 부가세대급금 = 세액 - debitLines.push({ - dc_type: 'debit', account_code: splitAccountCode, account_name: splitAccountName, - debit_amount: splitSupply, credit_amount: 0, - trading_partner_id: null, trading_partner_name: '', description: split.memo || '' + if (splitDeductionType === 'deductible') { + // 공제: 비용 계정 = 공급가액, 부가세대급금 = 세액 + lines.push({ + dc_type: 'debit', account_code: splitAccountCode, account_name: splitAccountName, + debit_amount: splitSupply, credit_amount: 0, + trading_partner_id: null, trading_partner_name: '', description: singleSplit.memo || '' + }); + totalDebitSum += splitSupply; + if (splitTax > 0) { + lines.push({ + dc_type: 'debit', account_code: '135', account_name: '부가세대급금', + debit_amount: splitTax, credit_amount: 0, + trading_partner_id: null, trading_partner_name: '', description: '' }); - totalDebitSum += splitSupply; - if (splitTax > 0) { - debitLines.push({ - dc_type: 'debit', account_code: '135', account_name: '부가세대급금', - debit_amount: splitTax, credit_amount: 0, - trading_partner_id: null, trading_partner_name: '', description: '' - }); - totalDebitSum += splitTax; - } - } else { - // 불공제: 비용 계정 = 공급가액 + 세액 - const combined = splitSupply + splitTax; - debitLines.push({ - dc_type: 'debit', account_code: splitAccountCode, account_name: splitAccountName, - debit_amount: combined, credit_amount: 0, - trading_partner_id: null, trading_partner_name: '', description: split.memo || '' - }); - totalDebitSum += combined; + totalDebitSum += splitTax; } - }); + } else { + // 불공제: 비용 계정 = 공급가액 + 세액 + const combined = splitSupply + splitTax; + lines.push({ + dc_type: 'debit', account_code: splitAccountCode, account_name: splitAccountName, + debit_amount: combined, credit_amount: 0, + trading_partner_id: null, trading_partner_name: '', description: singleSplit.memo || '' + }); + totalDebitSum += combined; + } - // 대변: 미지급비용 = 전체 합계 - debitLines.push({ + // 대변: 미지급비용 = 합계 + lines.push({ dc_type: 'credit', account_code: '205', account_name: '미지급비용', debit_amount: 0, credit_amount: totalDebitSum, trading_partner_id: null, trading_partner_name: '', description: '' }); - return debitLines; + return lines; } - // splits가 없으면 기존 로직 (원본 금액 기반) + // splits가 없으면 기존 로직 (원본 금액 기반, 분리 없는 거래용) const expenseCode = log.accountCode || '826'; const expenseName = log.accountName || '잡비'; @@ -915,14 +913,22 @@ className={`px-3 py-1.5 text-sm cursor-pointer ${index === highlightIndex ? 'bg-
공급가액: {formatCurrency(supplyAmount)}
세액: {formatCurrency(taxAmount)}
- {(log._splits || []).length > 0 && ( -
- - 분리 데이터 기반 ({log._splits.length}건) - - {isEditMode && ( - 저장된 분개가 있어 참고용으로 표시됩니다 - )} + {log._split && ( +
+
+ + 분리 항목 분개 + + {isEditMode && ( + 저장된 분개가 있어 참고용으로 표시됩니다 + )} +
+
+
계정: {log._split.account_name || log._split.accountName || '미지정'}
+
공제: {(log._split.deduction_type || log._split.deductionType) === 'deductible' ? '공제' : '불공제'}
+
공급가액: {formatCurrency(Math.round(parseFloat(log._split.split_supply_amount ?? log._split.supplyAmount ?? log._split.split_amount ?? log._split.amount ?? 0)))}
+
세액: {formatCurrency(Math.round(parseFloat(log._split.split_tax ?? log._split.tax ?? 0)))}
+
)}
@@ -1573,6 +1579,23 @@ className="p-1.5 text-amber-500 hover:bg-amber-100 rounded-lg transition-colors" {/* 분개 열 */} {(() => { + if (hasSplits) { + // 분리 항목별 분개 집계 + const splitJournalCount = logSplits.filter(s => journalMap[`${uniqueKey}|split:${s.id}`]).length; + if (splitJournalCount === logSplits.length) { + return ( + + 완료 + + ); + } else { + return ( + 0 ? 'text-purple-600' : 'text-stone-400'}`}> + {splitJournalCount}/{logSplits.length} + + ); + } + } const jInfo = journalMap[uniqueKey]; if (jInfo) { return ( @@ -1584,16 +1607,6 @@ className="px-1.5 py-0.5 bg-emerald-100 text-emerald-700 rounded text-[10px] fon 완료 ); - } else if (hasSplits) { - return ( - - ); } else { return ( + ); + } else { + return ( + + ); + } + })()} + └ 분리 #{splitIdx + 1} {split.memo && `- ${split.memo}`} @@ -2105,13 +2148,14 @@ className="px-3 py-1 bg-green-500 text-white text-xs rounded-lg hover:bg-green-6 }; // 복식부기 분개 모달 열기 - const handleOpenJournalModal = (log, uniqueKey, hasJournal, logSplits) => { + const handleOpenJournalModal = (log, sourceKey, hasJournal, logSplits, singleSplit) => { const logWithJournalInfo = { ...log, - uniqueKey, + uniqueKey: sourceKey, _hasJournal: hasJournal, _journalData: null, _splits: logSplits || [], + _split: singleSplit || null, }; setJournalModalLog(logWithJournalInfo); setJournalModalOpen(true);