From 01f6ea469b8d5b8dbbd455506877e3edc7fccad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Fri, 27 Feb 2026 15:40:48 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[payroll]=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EA=B3=B5=EC=A0=9C=20=ED=95=AD=EB=AA=A9=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EB=84=88=EC=8A=A4=20=EA=B8=88=EC=95=A1=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - formatMoneyInput: 음수 부호(-) 유지하도록 수정 - doRecalculate/submitPayroll: amount > 0 → amount !== 0 조건 변경 - Controller validation: deductions.*.amount에서 min:0 제약 제거 - 연말정산 환급 등 음수 공제 항목 지원 --- .../Controllers/Api/Admin/HR/PayrollController.php | 4 ++-- resources/views/hr/payrolls/index.blade.php | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/HR/PayrollController.php b/app/Http/Controllers/Api/Admin/HR/PayrollController.php index 927f0dff..9522c7d2 100644 --- a/app/Http/Controllers/Api/Admin/HR/PayrollController.php +++ b/app/Http/Controllers/Api/Admin/HR/PayrollController.php @@ -79,7 +79,7 @@ public function store(Request $request): JsonResponse 'allowances.*.amount' => 'required_with:allowances|numeric|min:0', 'deductions' => 'nullable|array', 'deductions.*.name' => 'required_with:deductions|string', - 'deductions.*.amount' => 'required_with:deductions|numeric|min:0', + 'deductions.*.amount' => 'required_with:deductions|numeric', 'deduction_overrides' => 'nullable|array', 'deduction_overrides.pension' => 'nullable|numeric|min:0', 'deduction_overrides.health_insurance' => 'nullable|numeric|min:0', @@ -128,7 +128,7 @@ public function update(Request $request, int $id): JsonResponse 'allowances.*.amount' => 'required_with:allowances|numeric|min:0', 'deductions' => 'nullable|array', 'deductions.*.name' => 'required_with:deductions|string', - 'deductions.*.amount' => 'required_with:deductions|numeric|min:0', + 'deductions.*.amount' => 'required_with:deductions|numeric', 'deduction_overrides' => 'nullable|array', 'deduction_overrides.pension' => 'nullable|numeric|min:0', 'deduction_overrides.health_insurance' => 'nullable|numeric|min:0', diff --git a/resources/views/hr/payrolls/index.blade.php b/resources/views/hr/payrolls/index.blade.php index a82b43d4..02aea483 100644 --- a/resources/views/hr/payrolls/index.blade.php +++ b/resources/views/hr/payrolls/index.blade.php @@ -561,7 +561,7 @@ function doRecalculate() { 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}); + if (name && amount !== 0) deductions.push({name, amount}); }); const data = { @@ -671,9 +671,11 @@ function parseMoneyValue(el) { function formatMoneyInput(el) { const pos = el.selectionStart; const oldLen = el.value.length; + const isNeg = el.value.indexOf('-') === 0; const raw = el.value.replace(/[^0-9]/g, ''); const num = parseInt(raw, 10); - el.value = isNaN(num) ? '' : num.toLocaleString('ko-KR'); + if (isNaN(num)) { el.value = isNeg ? '-' : ''; return; } + el.value = (isNeg ? '-' : '') + num.toLocaleString('ko-KR'); const newLen = el.value.length; const newPos = Math.max(0, pos + (newLen - oldLen)); el.setSelectionRange(newPos, newPos); @@ -689,7 +691,7 @@ function moneyBlur(el) { function setMoneyValue(el, val) { const num = parseInt(val, 10) || 0; - el.value = num === 0 ? '0' : num.toLocaleString('ko-KR'); + el.value = num === 0 ? '0' : Number(num).toLocaleString('ko-KR'); } // ===== 급여 저장 ===== @@ -705,7 +707,7 @@ function submitPayroll() { 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}); + if (name && amount !== 0) deductions.push({name, amount}); }); // 수동 수정된 공제 항목 override