feat:수퍼관리자 가망고객 삭제 기능 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
김보곤
2026-02-07 08:17:49 +09:00
parent 1d6489ac25
commit a337b7afb4
4 changed files with 119 additions and 2 deletions

View File

@@ -224,7 +224,9 @@ private function getIndexData(Request $request): array
];
});
return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters');
$isSuperAdmin = auth()->user()->isSuperAdmin();
return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters', 'isSuperAdmin');
}
/**
@@ -302,6 +304,29 @@ public function updateCommissionDate(int $id, Request $request)
]);
}
/**
* 가망고객 삭제 (슈퍼관리자 전용)
*/
public function destroy(int $id)
{
$prospect = TenantProspect::findOrFail($id);
// 연관 데이터 삭제
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
if ($management) {
SalesCommission::where('management_id', $management->id)->delete();
$management->delete();
}
SalesScenarioChecklist::where('tenant_prospect_id', $prospect->id)->delete();
$prospect->delete();
return response()->json([
'success' => true,
'message' => "'{$prospect->company_name}' 가망고객이 삭제되었습니다.",
]);
}
/**
* 수당 날짜 삭제 (초기화)
*/

View File

@@ -52,6 +52,36 @@ class="refresh-btn inline-flex items-center gap-1.5 px-4 py-2 text-sm text-gray-
</div>
</div>
<!-- 삭제 확인 모달 -->
@if(auth()->user()->isSuperAdmin())
<div id="deleteModal" class="hidden fixed inset-0 z-50 overflow-y-auto">
<div class="fixed inset-0 bg-black bg-opacity-50 transition-opacity" onclick="closeDeleteModal()"></div>
<div class="flex min-h-full items-center justify-center p-4">
<div class="relative bg-white rounded-xl shadow-2xl w-full max-w-md p-6">
<div class="text-center">
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4">
<svg class="h-6 w-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
</svg>
</div>
<h3 class="text-lg font-bold text-gray-900 mb-2">가망고객 삭제</h3>
<p class="text-sm text-gray-500 mb-1">다음 가망고객을 삭제하시겠습니까?</p>
<p id="deleteTargetName" class="text-base font-semibold text-red-600 mb-4"></p>
<p class="text-xs text-gray-400 mb-6">관련된 시나리오 체크리스트, 관리 정보, 수당 정보가 함께 삭제됩니다.</p>
</div>
<div class="flex gap-3">
<button type="button" onclick="closeDeleteModal()" class="flex-1 px-4 py-2.5 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition">
취소
</button>
<button type="button" id="confirmDeleteBtn" onclick="confirmDelete()" class="flex-1 px-4 py-2.5 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-lg transition">
삭제
</button>
</div>
</div>
</div>
</div>
@endif
<!-- 상세 모달 -->
<div id="detailModal" class="hidden fixed inset-0 z-50 overflow-y-auto">
<div class="fixed inset-0 bg-black bg-opacity-50 transition-opacity"></div>
@@ -165,6 +195,55 @@ function closeDetailModal() {
}
});
// 삭제 모달
let deleteProspectId = null;
function openDeleteModal(id, companyName) {
deleteProspectId = id;
document.getElementById('deleteTargetName').textContent = companyName;
document.getElementById('deleteModal').classList.remove('hidden');
document.body.style.overflow = 'hidden';
}
function closeDeleteModal() {
document.getElementById('deleteModal').classList.add('hidden');
document.body.style.overflow = '';
deleteProspectId = null;
}
function confirmDelete() {
if (!deleteProspectId) return;
const btn = document.getElementById('confirmDeleteBtn');
btn.disabled = true;
btn.textContent = '삭제 중...';
fetch(`/sales/admin-prospects/${deleteProspectId}`, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(result => {
if (result.success) {
closeDeleteModal();
window.location.reload();
} else {
alert(result.message || '삭제에 실패했습니다.');
btn.disabled = false;
btn.textContent = '삭제';
}
})
.catch(error => {
console.error('Error:', error);
alert('삭제 중 오류가 발생했습니다.');
btn.disabled = false;
btn.textContent = '삭제';
});
}
// 수당 날짜 저장 (date input에서 호출)
function saveCommissionDate(prospectId, field, date) {
const input = document.querySelector(`input[data-prospect-id="${prospectId}"][data-field="${field}"]`);

View File

@@ -213,7 +213,19 @@ class="text-xs font-medium rounded-lg px-2 py-1 border cursor-pointer
{{ $prospect->created_at->format('Y-m-d') }}
</td>
<td class="px-4 py-3 whitespace-nowrap text-right text-sm font-medium">
<button type="button" onclick="openDetailModal({{ $prospect->id }})" class="text-blue-600 hover:text-blue-900">상세</button>
<div class="flex items-center justify-end gap-2">
<button type="button" onclick="openDetailModal({{ $prospect->id }})" class="text-blue-600 hover:text-blue-900">상세</button>
@if($isSuperAdmin)
<button type="button"
onclick="openDeleteModal({{ $prospect->id }}, '{{ addslashes($prospect->company_name) }}')"
class="text-red-500 hover:text-red-700"
title="삭제">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
@endif
</div>
</td>
</tr>
@empty

View File

@@ -1151,6 +1151,7 @@
Route::post('admin-prospects/{id}/hq-status', [\App\Http\Controllers\Sales\AdminProspectController::class, 'updateHqStatus'])->name('admin-prospects.update-hq-status');
Route::post('admin-prospects/{id}/commission-date', [\App\Http\Controllers\Sales\AdminProspectController::class, 'updateCommissionDate'])->name('admin-prospects.update-commission-date');
Route::delete('admin-prospects/{id}/commission-date', [\App\Http\Controllers\Sales\AdminProspectController::class, 'clearCommissionDate'])->name('admin-prospects.clear-commission-date');
Route::delete('admin-prospects/{id}', [\App\Http\Controllers\Sales\AdminProspectController::class, 'destroy'])->name('admin-prospects.destroy')->middleware('super.admin');
// 영업 시나리오 관리
Route::prefix('scenarios')->name('scenarios.')->group(function () {