feat:계약 대시보드 선택 삭제 기능 추가

- EsignApiController에 destroy 메서드 추가 (복수 삭제 지원)
- 관련 파일(PDF, 서명이미지) 및 레코드(서명자, 필드, 감사로그) 일괄 삭제
- 서명 진행 중(pending, partially_signed) 계약은 삭제 차단
- DELETE /esign/contracts/destroy 라우트 추가
- 대시보드에 체크박스 전체/개별 선택 + 삭제 버튼 UI 추가
- 삭제 전 confirm 확인 다이얼로그

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
김보곤
2026-02-13 06:32:09 +09:00
parent 506f115415
commit 2dea60de23
3 changed files with 138 additions and 10 deletions

View File

@@ -219,6 +219,66 @@ public function cancel(Request $request, int $id): JsonResponse
return response()->json(['success' => true, 'message' => '계약이 취소되었습니다.']);
}
/**
* 계약 삭제 (단건/복수)
*/
public function destroy(Request $request): JsonResponse
{
$request->validate([
'ids' => 'required|array|min:1',
'ids.*' => 'required|integer',
]);
$tenantId = session('selected_tenant_id', 1);
$ids = $request->input('ids');
$contracts = EsignContract::forTenant($tenantId)->whereIn('id', $ids)->get();
if ($contracts->isEmpty()) {
return response()->json(['success' => false, 'message' => '삭제할 계약을 찾을 수 없습니다.'], 404);
}
// 진행 중인 계약(pending, partially_signed) 차단
$activeContracts = $contracts->filter(fn ($c) => in_array($c->status, ['pending', 'partially_signed']));
if ($activeContracts->isNotEmpty()) {
return response()->json([
'success' => false,
'message' => '서명 진행 중인 계약은 삭제할 수 없습니다. 먼저 취소해 주세요.',
], 422);
}
$deletedCount = 0;
foreach ($contracts as $contract) {
// 관련 파일 삭제
if ($contract->original_file_path && Storage::disk('local')->exists($contract->original_file_path)) {
Storage::disk('local')->delete($contract->original_file_path);
}
if ($contract->signed_file_path && Storage::disk('local')->exists($contract->signed_file_path)) {
Storage::disk('local')->delete($contract->signed_file_path);
}
// 서명 이미지 파일 삭제
$signers = EsignSigner::withoutGlobalScopes()->where('contract_id', $contract->id)->get();
foreach ($signers as $signer) {
if ($signer->signature_image_path && Storage::disk('local')->exists($signer->signature_image_path)) {
Storage::disk('local')->delete($signer->signature_image_path);
}
}
// 관련 레코드 삭제
EsignSignField::where('contract_id', $contract->id)->delete();
EsignAuditLog::where('contract_id', $contract->id)->delete();
EsignSigner::withoutGlobalScopes()->where('contract_id', $contract->id)->delete();
$contract->delete();
$deletedCount++;
}
return response()->json([
'success' => true,
'message' => "{$deletedCount}건의 계약이 삭제되었습니다.",
]);
}
/**
* 서명 위치 설정
*/