fix: [payroll] 수정 모드에서 공제항목 자동 재계산 방지

- 수정 모드(editingPayrollId)에서는 /calculate API 호출 생략
- 기본급 등 변경 시 총지급액/실수령액만 로컬 재합산
- 재계산 버튼 클릭 시에만 최신 요율로 서버 계산 실행
This commit is contained in:
김보곤
2026-02-27 16:56:28 +09:00
parent a88774339c
commit 3f27c2f7c0

View File

@@ -535,6 +535,28 @@ function recalculate() {
}
function doRecalculate() {
const baseSalary = parseMoneyValue(document.getElementById('payrollBaseSalary'));
const overtimePay = parseMoneyValue(document.getElementById('payrollOvertimePay'));
const bonus = parseMoneyValue(document.getElementById('payrollBonus'));
let allowancesTotal = 0;
document.querySelectorAll('#allowancesContainer > div').forEach(row => {
allowancesTotal += parseMoneyValue(row.querySelector('.allowance-amount'));
});
const grossSalary = baseSalary + overtimePay + bonus + allowancesTotal;
const taxableBase = grossSalary - bonus;
document.getElementById('calcGross').textContent = numberFormat(grossSalary);
document.getElementById('calcTaxableBase').textContent = numberFormat(taxableBase);
// 수정 모드: 공제항목은 기존 저장값 유지, 총지급액/실수령액만 재합산
if (editingPayrollId) {
updateDeductionTotals();
return;
}
// 신규 등록 모드: 서버에서 요율 기반 자동 계산
const allowances = [];
document.querySelectorAll('#allowancesContainer > div').forEach(row => {
const name = row.querySelector('.allowance-name').value;
@@ -550,9 +572,9 @@ function doRecalculate() {
});
const data = {
base_salary: parseMoneyValue(document.getElementById('payrollBaseSalary')),
overtime_pay: parseMoneyValue(document.getElementById('payrollOvertimePay')),
bonus: parseMoneyValue(document.getElementById('payrollBonus')),
base_salary: baseSalary,
overtime_pay: overtimePay,
bonus: bonus,
allowances: allowances,
deductions: deductions,
user_id: parseInt(document.getElementById('payrollUserId').value) || null,
@@ -583,8 +605,6 @@ function doRecalculate() {
const el = document.getElementById(id);
if (!el.dataset.manual) setMoneyValue(el, val);
});
document.getElementById('calcGross').textContent = numberFormat(d.gross_salary);
document.getElementById('calcTaxableBase').textContent = numberFormat(d.taxable_base);
if (d.family_count) {
const fcEl = document.getElementById('calcFamilyCount');
if (fcEl) fcEl.textContent = d.family_count + '명';
@@ -621,7 +641,63 @@ function resetDeductionOverrides() {
el.classList.remove('bg-yellow-50', 'border-yellow-300');
el.classList.add('border-gray-200');
});
recalculate();
// 재계산 버튼: 수정 모드에서도 서버 API 호출하여 최신 요율로 재계산
forceRecalculate();
}
function forceRecalculate() {
const baseSalary = parseMoneyValue(document.getElementById('payrollBaseSalary'));
const overtimePay = parseMoneyValue(document.getElementById('payrollOvertimePay'));
const bonus = parseMoneyValue(document.getElementById('payrollBonus'));
const allowances = [];
document.querySelectorAll('#allowancesContainer > div').forEach(row => {
const name = row.querySelector('.allowance-name').value;
const amount = parseMoneyValue(row.querySelector('.allowance-amount'));
if (name && amount > 0) allowances.push({name, amount});
});
const deductions = [];
document.querySelectorAll('#deductionsContainer > div').forEach(row => {
const name = row.querySelector('.deduction-name').value;
const amount = parseMoneyValue(row.querySelector('.deduction-amount'));
if (name && amount !== 0) deductions.push({name, amount});
});
const data = {
base_salary: baseSalary, overtime_pay: overtimePay, bonus: bonus,
allowances: allowances, deductions: deductions,
user_id: parseInt(document.getElementById('payrollUserId').value) || null,
};
fetch('{{ route("api.admin.hr.payrolls.calculate") }}', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}', 'Accept': 'application/json' },
body: JSON.stringify(data),
})
.then(r => r.json())
.then(result => {
if (result.success) {
const d = result.data;
const fields = {
'calcPension': d.pension, 'calcHealth': d.health_insurance,
'calcLongTermCare': d.long_term_care, 'calcEmployment': d.employment_insurance,
'calcIncomeTax': d.income_tax, 'calcResidentTax': d.resident_tax,
};
Object.entries(fields).forEach(([id, val]) => {
const el = document.getElementById(id);
if (!el.dataset.manual) setMoneyValue(el, val);
});
document.getElementById('calcGross').textContent = numberFormat(d.gross_salary);
document.getElementById('calcTaxableBase').textContent = numberFormat(d.taxable_base);
if (d.family_count) {
const fcEl = document.getElementById('calcFamilyCount');
if (fcEl) fcEl.textContent = d.family_count + '명';
}
updateDeductionTotals();
}
})
.catch(console.error);
}
function updateDeductionTotals() {