fix:수동입력 잔액 자동계산을 거래일 기준으로 개선
- 거래일 기준으로 해당 계좌의 직전 거래 잔액을 찾아 기준잔액 설정 - 계좌/거래일/거래시간 변경 시에도 기준잔액 재계산 - 수정 모드에서 자기 자신 거래를 제외하고 직전 잔액 검색 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -799,23 +799,40 @@ className="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 t
|
||||
|
||||
const isEditMode = !!editData;
|
||||
|
||||
// 선택된 계좌의 최근 잔액 찾기
|
||||
const findLatestBalance = (accountNum) => {
|
||||
// 거래일 기준으로 해당 계좌의 직전 거래 잔액 찾기
|
||||
const findBaseBalanceByDate = (accountNum, transDate, transTime) => {
|
||||
if (!accountNum || !logs || logs.length === 0) return 0;
|
||||
// logs는 날짜 내림차순 정렬이므로 첫 번째 매칭이 가장 최근
|
||||
const accountLog = logs.find(l => l.bankAccountNum === accountNum);
|
||||
return accountLog ? (accountLog.balance || 0) : 0;
|
||||
const targetDt = (transDate || '') + (transTime || '000000');
|
||||
// 같은 계좌의 거래만 필터 (수정 중인 건은 제외)
|
||||
const accountLogs = logs.filter(l =>
|
||||
l.bankAccountNum === accountNum &&
|
||||
!(editData && l.isManual && l.dbId === editData.dbId)
|
||||
);
|
||||
if (accountLogs.length === 0) return 0;
|
||||
// logs는 날짜 내림차순 정렬 → 입력일보다 이전인 첫 번째 거래의 잔액이 기준
|
||||
for (const log of accountLogs) {
|
||||
const logDt = (log.transDate || '') + (log.transTime || '');
|
||||
if (logDt < targetDt) {
|
||||
return log.balance || 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
// 기준잔액 재계산 (계좌, 날짜, 시간 변경 시)
|
||||
const recalcBase = (accountNum, transDate, transTime) => {
|
||||
const base = findBaseBalanceByDate(accountNum, transDate, transTime);
|
||||
setBaseBalance(base);
|
||||
return base;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
if (editData) {
|
||||
const isRegisteredAccount = accounts.some(a => a.bankAccountNum === editData.bankAccountNum);
|
||||
// 수정 모드: 이전 잔액 역산 (입금이면 잔액-입금, 출금이면 잔액+출금)
|
||||
const prevBalance = editData.deposit > 0
|
||||
? editData.balance - editData.deposit
|
||||
: editData.balance + editData.withdraw;
|
||||
setBaseBalance(prevBalance);
|
||||
// 수정 모드: 직전 거래 잔액을 찾아서 기준잔액으로 설정
|
||||
const base = findBaseBalanceByDate(editData.bankAccountNum, editData.transDate, editData.transTime);
|
||||
setBaseBalance(base);
|
||||
setForm({
|
||||
bank_account_num: editData.bankAccountNum || '',
|
||||
bank_code: editData.bankCode || '',
|
||||
@@ -895,25 +912,39 @@ className="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 t
|
||||
const handleAccountSelect = (accNum) => {
|
||||
if (accNum === '__manual__') {
|
||||
setBaseBalance(0);
|
||||
setForm(prev => ({ ...prev, bank_account_num: '', bank_code: '', bank_name: '', _manualAccount: true, balance: 0 }));
|
||||
setForm(prev => {
|
||||
const newBal = calcBalance(0, prev.trans_type, prev.amount);
|
||||
return { ...prev, bank_account_num: '', bank_code: '', bank_name: '', _manualAccount: true, balance: newBal };
|
||||
});
|
||||
} else {
|
||||
const acc = accounts.find(a => a.bankAccountNum === accNum);
|
||||
if (acc) {
|
||||
const latestBal = findLatestBalance(acc.bankAccountNum);
|
||||
setBaseBalance(latestBal);
|
||||
const newBalance = calcBalance(latestBal, form.trans_type, form.amount);
|
||||
setForm(prev => ({
|
||||
...prev,
|
||||
bank_account_num: acc.bankAccountNum,
|
||||
bank_code: acc.bankCode || '',
|
||||
bank_name: acc.bankName || '',
|
||||
_manualAccount: false,
|
||||
balance: newBalance,
|
||||
}));
|
||||
setForm(prev => {
|
||||
const base = recalcBase(acc.bankAccountNum, prev.trans_date, prev.trans_time);
|
||||
const newBalance = calcBalance(base, prev.trans_type, prev.amount);
|
||||
return {
|
||||
...prev,
|
||||
bank_account_num: acc.bankAccountNum,
|
||||
bank_code: acc.bankCode || '',
|
||||
bank_name: acc.bankName || '',
|
||||
_manualAccount: false,
|
||||
balance: newBalance,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 거래일 변경 시 기준잔액 재계산
|
||||
const handleDateChange = (field, value) => {
|
||||
setForm(prev => {
|
||||
const newForm = { ...prev, [field]: value };
|
||||
const base = recalcBase(newForm.bank_account_num, newForm.trans_date, newForm.trans_time);
|
||||
const newBalance = calcBalance(base, newForm.trans_type, newForm.amount);
|
||||
return { ...newForm, balance: newBalance };
|
||||
});
|
||||
};
|
||||
|
||||
const formatAmount = (val) => {
|
||||
const num = String(val).replace(/[^\d]/g, '');
|
||||
return num ? Number(num).toLocaleString() : '';
|
||||
@@ -993,7 +1024,7 @@ className="px-3 py-2 border border-stone-200 rounded-lg text-sm focus:ring-2 foc
|
||||
<input
|
||||
type="text"
|
||||
value={form.trans_date || ''}
|
||||
onChange={(e) => setForm(prev => ({ ...prev, trans_date: e.target.value.replace(/[^\d]/g, '').slice(0, 8) }))}
|
||||
onChange={(e) => handleDateChange('trans_date', e.target.value.replace(/[^\d]/g, '').slice(0, 8))}
|
||||
placeholder="YYYYMMDD"
|
||||
maxLength={8}
|
||||
className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none"
|
||||
@@ -1004,7 +1035,7 @@ className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:rin
|
||||
<input
|
||||
type="text"
|
||||
value={form.trans_time || ''}
|
||||
onChange={(e) => setForm(prev => ({ ...prev, trans_time: e.target.value.replace(/[^\d]/g, '').slice(0, 6) }))}
|
||||
onChange={(e) => handleDateChange('trans_time', e.target.value.replace(/[^\d]/g, '').slice(0, 6))}
|
||||
placeholder="HHMMSS"
|
||||
maxLength={6}
|
||||
className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none"
|
||||
|
||||
Reference in New Issue
Block a user