From a2674816f6acebb0cb040dae02e5a813fd777f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 17 Mar 2026 13:18:05 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[finance]=20=EC=9D=80=ED=96=89=EA=B1=B0?= =?UTF-8?q?=EB=9E=98=20=EB=A0=88=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=A0=84=EC=9A=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 은행거래 행에 레코드 삭제 버튼 추가 (분개 유무 무관) - 삭제 시 연결된 분개 전표도 함께 삭제 - 관리자(isAdmin) 권한 검증 적용 --- .../Finance/JournalEntryController.php | 35 +++++++++++++++ .../views/finance/journal-entries.blade.php | 43 ++++++++++++++++--- routes/web.php | 1 + 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Finance/JournalEntryController.php b/app/Http/Controllers/Finance/JournalEntryController.php index 3da24b19..be09a659 100644 --- a/app/Http/Controllers/Finance/JournalEntryController.php +++ b/app/Http/Controllers/Finance/JournalEntryController.php @@ -477,6 +477,7 @@ public function bankTransactions(Request $request): JsonResponse $accountBalances[$accNum] = $newBal; $logs[] = [ + 'id' => $tx->id, 'uniqueKey' => $tx->unique_key, 'transDate' => $tx->trans_date, 'transTime' => $tx->trans_time, @@ -761,6 +762,40 @@ public function deleteBankJournal(int $id): JsonResponse ]); } + /** + * 은행거래 레코드 삭제 — 관리자 이상만 가능 + */ + public function destroyBankTransaction(int $id): JsonResponse + { + $user = auth()->user(); + if (! $user || ! $user->isAdmin()) { + return response()->json([ + 'success' => false, + 'message' => '은행거래 삭제는 관리자만 가능합니다.', + ], 403); + } + + $tenantId = session('selected_tenant_id', 1); + $tx = BankTransaction::where('tenant_id', $tenantId)->findOrFail($id); + + // 연결된 분개 전표도 함께 삭제 + $journal = JournalEntry::where('tenant_id', $tenantId) + ->where('source_type', 'bank_transaction') + ->where('source_key', $tx->unique_key) + ->first(); + + if ($journal) { + $journal->delete(); + } + + $tx->delete(); + + return response()->json([ + 'success' => true, + 'message' => '은행거래 레코드가 삭제되었습니다.', + ]); + } + /** * 조회기간 이전의 계좌별 잔액 계산 * EaccountController::findBaseBalance() 패턴을 계좌별로 확장 diff --git a/resources/views/finance/journal-entries.blade.php b/resources/views/finance/journal-entries.blade.php index ed088c88..09a4fe2a 100644 --- a/resources/views/finance/journal-entries.blade.php +++ b/resources/views/finance/journal-entries.blade.php @@ -1166,6 +1166,26 @@ className="px-2.5 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-f } }; + const handleDeleteBankTx = async (bankTxId, description) => { + if (!bankTxId) return; + if (!confirm(`"${description}" 은행거래 레코드를 삭제하시겠습니까?\n(연결된 분개 전표도 함께 삭제됩니다)`)) return; + try { + const res = await fetch(`/finance/journal-entries/bank-transaction/${bankTxId}`, { + method: 'DELETE', + headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }, + }); + const data = await res.json(); + if (data.success) { + notify('은행거래 레코드가 삭제되었습니다.', 'success'); + fetchData(); + } else { + notify(data.message || '삭제 실패', 'error'); + } + } catch (err) { + notify('삭제 중 오류가 발생했습니다.', 'error'); + } + }; + const handleJournal = (tx) => { setModalTransaction(tx); setShowJournalModal(true); @@ -1409,8 +1429,21 @@ className={`px-2.5 py-1 text-xs rounded-full font-medium transition-colors ${vie {row.totalCredit > 0 ? formatCurrency(row.totalCredit) : ''} - {(row.type === 'bank' || row.type === 'card') && !row.hasJournal ? ( - + {isAdmin && row.bankTx?.id && ( + + )} + + ) : row.type === 'card' && !row.hasJournal ? ( + @@ -1424,9 +1457,9 @@ className="px-2.5 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-f className="p-1 text-stone-300 group-hover:text-emerald-500 hover:bg-emerald-50 rounded transition-colors" title="수정"> - {isAdmin && ( - )} diff --git a/routes/web.php b/routes/web.php index 08052e11..2ad4d7ed 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1233,6 +1233,7 @@ Route::post('/store-from-bank', [\App\Http\Controllers\Finance\JournalEntryController::class, 'storeFromBank'])->name('store-from-bank'); Route::get('/bank-journals', [\App\Http\Controllers\Finance\JournalEntryController::class, 'bankJournals'])->name('bank-journals'); Route::delete('/bank-journal/{id}', [\App\Http\Controllers\Finance\JournalEntryController::class, 'deleteBankJournal'])->name('delete-bank-journal'); + Route::delete('/bank-transaction/{id}', [\App\Http\Controllers\Finance\JournalEntryController::class, 'destroyBankTransaction'])->name('destroy-bank-transaction'); // 카드거래 기반 분개 Route::get('/card-transactions', [\App\Http\Controllers\Finance\JournalEntryController::class, 'cardTransactions'])->name('card-transactions');