From 32e680dce8855986601f9f274bec3e160afc87b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Wed, 4 Mar 2026 11:02:06 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[payables]=20=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=EA=B8=89=EA=B8=88=EA=B4=80=EB=A6=AC=20=EC=A0=84=ED=91=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 일반전표 상세 행에 삭제 버튼(휴지통 아이콘) 추가 - DELETE /finance/payables/journal-entry/{id} API 추가 - journal_entry_id 필드를 프론트에 전달하도록 쿼리 수정 - 삭제 후 데이터 자동 새로고침 --- .../Controllers/Finance/PayableController.php | 18 ++++++++++ resources/views/finance/payables.blade.php | 34 +++++++++++++++++-- routes/web.php | 1 + 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Finance/PayableController.php b/app/Http/Controllers/Finance/PayableController.php index b3c43e64..8d2c20bf 100644 --- a/app/Http/Controllers/Finance/PayableController.php +++ b/app/Http/Controllers/Finance/PayableController.php @@ -313,6 +313,7 @@ public function integrated(Request $request): JsonResponse $journalDetails = (clone $journalQuery) ->select( 'journal_entry_lines.id', + 'journal_entry_lines.journal_entry_id', 'journal_entry_lines.trading_partner_name', 'journal_entry_lines.account_code', 'journal_entry_lines.account_name', @@ -505,4 +506,21 @@ public function journalPayables(Request $request): JsonResponse ], ]); } + + /** + * 미지급금 관련 전표 강제 삭제 (soft delete) + */ + public function deleteJournalEntry(int $id): JsonResponse + { + $tenantId = session('selected_tenant_id', 1); + + $entry = JournalEntry::where('tenant_id', $tenantId)->findOrFail($id); + + $entry->delete(); + + return response()->json([ + 'success' => true, + 'message' => "전표 {$entry->entry_no}이(가) 삭제되었습니다.", + ]); + } } diff --git a/resources/views/finance/payables.blade.php b/resources/views/finance/payables.blade.php index a14715a1..dcc74d1d 100644 --- a/resources/views/finance/payables.blade.php +++ b/resources/views/finance/payables.blade.php @@ -48,6 +48,7 @@ const TrendingUp = createIcon('trending-up'); const TrendingDown = createIcon('trending-down'); const Layers = createIcon('layers'); +const Trash2 = createIcon('trash-2'); const formatCurrency = (num) => num ? Number(num).toLocaleString() : '0'; const formatInputCurrency = (value) => { @@ -81,6 +82,25 @@ function IntegratedTab({ startDate, endDate, account, vendorSearch }) { useEffect(() => { fetchData(); }, [fetchData]); + const handleDeleteJournal = async (journalEntryId, entryNo) => { + if (!confirm(`전표 ${entryNo}을(를) 삭제하시겠습니까?`)) return; + try { + const res = await fetch(`/finance/payables/journal-entry/${journalEntryId}`, { + method: 'DELETE', + headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content }, + }); + const json = await res.json(); + if (json.success) { + alert(json.message); + fetchData(); + } else { + alert('삭제 실패: ' + (json.message || '')); + } + } catch (err) { + alert('삭제 오류: ' + err.message); + } + }; + if (loading) return ; if (!data) return ; @@ -233,9 +253,17 @@ function IntegratedTab({ startDate, endDate, account, vendorSearch }) { {j.dc_type === 'debit' ? '차변(상계)' : '대변(발생)'} - - {formatCurrency(j.dc_type === 'debit' ? j.debit_amount : j.credit_amount)}원 - +
+ + {formatCurrency(j.dc_type === 'debit' ? j.debit_amount : j.credit_amount)}원 + + {j.journal_entry_id && ( + + )} +
))} diff --git a/routes/web.php b/routes/web.php index 51d43ed3..40c74720 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1383,6 +1383,7 @@ Route::put('/{id}', [\App\Http\Controllers\Finance\PayableController::class, 'update'])->name('update'); Route::post('/{id}/pay', [\App\Http\Controllers\Finance\PayableController::class, 'pay'])->name('pay'); Route::delete('/{id}', [\App\Http\Controllers\Finance\PayableController::class, 'destroy'])->name('destroy'); + Route::delete('/journal-entry/{id}', [\App\Http\Controllers\Finance\PayableController::class, 'deleteJournalEntry'])->name('delete-journal'); }); // 기타