diff --git a/app/Http/Controllers/Api/Admin/HR/PayrollController.php b/app/Http/Controllers/Api/Admin/HR/PayrollController.php index 9fc3335c..2ad457f6 100644 --- a/app/Http/Controllers/Api/Admin/HR/PayrollController.php +++ b/app/Http/Controllers/Api/Admin/HR/PayrollController.php @@ -749,13 +749,18 @@ public function generateJournalEntry(Request $request): JsonResponse ], 422); } - // 기타공제(deductions JSON) 합산 포함 - $extraDeductionsTotal = 0; + // 기타공제(deductions JSON) 항목별 합산 + $extraDeductionsByName = []; foreach ($payrolls as $p) { foreach ($p->deductions ?? [] as $d) { - $extraDeductionsTotal += (int) ($d['amount'] ?? 0); + $name = $d['name'] ?? '기타공제'; + $amount = (int) ($d['amount'] ?? 0); + if ($amount != 0) { + $extraDeductionsByName[$name] = ($extraDeductionsByName[$name] ?? 0) + $amount; + } } } + $extraDeductionsTotal = array_sum($extraDeductionsByName); $sums = (object) [ 'total_gross' => $payrolls->sum('gross_salary'), @@ -827,10 +832,11 @@ public function generateJournalEntry(Request $request): JsonResponse [(int) $sums->total_resident_tax, '강서구청', "{$monthLabel} 지방소득세"], ]; - // 기타공제 - $extraDeductions = (int) $sums->total_extra_deductions; - if ($extraDeductions != 0) { - $deductionItems[] = [$extraDeductions, '임직원', '기타공제']; + // 기타공제 (항목별) + foreach ($extraDeductionsByName as $deductionName => $deductionAmount) { + if ($deductionAmount != 0) { + $deductionItems[] = [$deductionAmount, '임직원', $deductionName]; + } } // 1. 차변: 801 급여 / 임직원 — 총지급액 diff --git a/app/Http/Controllers/Finance/JournalEntryController.php b/app/Http/Controllers/Finance/JournalEntryController.php index 69a81698..4b72635d 100644 --- a/app/Http/Controllers/Finance/JournalEntryController.php +++ b/app/Http/Controllers/Finance/JournalEntryController.php @@ -149,8 +149,8 @@ public function store(Request $request): JsonResponse 'lines.*.account_name' => 'required|string|max:100', 'lines.*.trading_partner_id' => 'nullable|integer', 'lines.*.trading_partner_name' => 'nullable|string|max:100', - 'lines.*.debit_amount' => 'required|integer|min:0', - 'lines.*.credit_amount' => 'required|integer|min:0', + 'lines.*.debit_amount' => 'required|integer', + 'lines.*.credit_amount' => 'required|integer', 'lines.*.description' => 'nullable|string|max:300', ]); @@ -265,8 +265,8 @@ public function update(Request $request, int $id): JsonResponse 'lines.*.account_name' => 'required|string|max:100', 'lines.*.trading_partner_id' => 'nullable|integer', 'lines.*.trading_partner_name' => 'nullable|string|max:100', - 'lines.*.debit_amount' => 'required|integer|min:0', - 'lines.*.credit_amount' => 'required|integer|min:0', + 'lines.*.debit_amount' => 'required|integer', + 'lines.*.credit_amount' => 'required|integer', 'lines.*.description' => 'nullable|string|max:300', ]); @@ -570,8 +570,8 @@ public function storeFromBank(Request $request): JsonResponse 'lines.*.account_name' => 'required|string|max:100', 'lines.*.trading_partner_id' => 'nullable|integer', 'lines.*.trading_partner_name' => 'nullable|string|max:100', - 'lines.*.debit_amount' => 'required|integer|min:0', - 'lines.*.credit_amount' => 'required|integer|min:0', + 'lines.*.debit_amount' => 'required|integer', + 'lines.*.credit_amount' => 'required|integer', 'lines.*.description' => 'nullable|string|max:300', ]); @@ -1038,8 +1038,8 @@ public function storeFromCard(Request $request): JsonResponse 'lines.*.account_name' => 'required|string|max:100', 'lines.*.trading_partner_id' => 'nullable|integer', 'lines.*.trading_partner_name' => 'nullable|string|max:100', - 'lines.*.debit_amount' => 'required|integer|min:0', - 'lines.*.credit_amount' => 'required|integer|min:0', + 'lines.*.debit_amount' => 'required|integer', + 'lines.*.credit_amount' => 'required|integer', 'lines.*.description' => 'nullable|string|max:300', ]); diff --git a/resources/views/finance/journal-entries.blade.php b/resources/views/finance/journal-entries.blade.php index b00c136b..d886a8d9 100644 --- a/resources/views/finance/journal-entries.blade.php +++ b/resources/views/finance/journal-entries.blade.php @@ -65,12 +65,16 @@ const formatCurrency = (num) => num ? Number(num).toLocaleString() : '0'; const formatInputCurrency = (value) => { if (!value && value !== 0) return ''; + const isNegative = Number(value) < 0; const num = String(value).replace(/[^\d]/g, ''); - return num ? Number(num).toLocaleString() : ''; + if (!num) return ''; + return (isNegative ? '-' : '') + Number(num).toLocaleString(); }; const parseInputCurrency = (value) => { + const isNegative = String(value).includes('-'); const num = String(value).replace(/[^\d]/g, ''); - return num ? parseInt(num, 10) : 0; + const parsed = num ? parseInt(num, 10) : 0; + return isNegative ? -parsed : parsed; }; const notify = (message, type = 'info') => {