feat: [esign] 전자계약 수정 기능 추가
- draft 상태 계약의 제목, 설명, 서명자 정보, 파일 수정 가능 - 계약 상세 페이지에 '계약 정보 수정' 버튼 추가 - create.blade.php를 생성/수정 겸용으로 확장
This commit is contained in:
@@ -572,6 +572,97 @@ public function store(Request $request): JsonResponse
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 계약 수정 (draft 상태만)
|
||||
*/
|
||||
public function update(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', 1);
|
||||
$contract = EsignContract::forTenant($tenantId)->findOrFail($id);
|
||||
|
||||
if ($contract->status !== 'draft') {
|
||||
return response()->json(['success' => false, 'message' => '초안 상태의 계약만 수정할 수 있습니다.'], 422);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:200',
|
||||
'description' => 'nullable|string',
|
||||
'sign_order_type' => 'required|in:counterpart_first,creator_first',
|
||||
'expires_at' => 'nullable|date',
|
||||
'signers' => 'required|array|size:2',
|
||||
'signers.*.name' => 'required|string|max:100',
|
||||
'signers.*.email' => 'required|email|max:200',
|
||||
'signers.*.phone' => 'nullable|string|max:20',
|
||||
'signers.*.role' => 'required|in:creator,counterpart',
|
||||
'file' => 'nullable|file|mimes:pdf,doc,docx|max:20480',
|
||||
]);
|
||||
|
||||
$userId = auth()->id();
|
||||
|
||||
// PDF 파일 교체
|
||||
if ($request->hasFile('file')) {
|
||||
// 기존 파일 삭제
|
||||
if ($contract->original_file_path && Storage::disk('local')->exists($contract->original_file_path)) {
|
||||
Storage::disk('local')->delete($contract->original_file_path);
|
||||
}
|
||||
|
||||
$file = $request->file('file');
|
||||
$converter = new DocxToPdfConverter;
|
||||
$result = $converter->convertAndStore($file, "esign/{$tenantId}/contracts");
|
||||
|
||||
$contract->original_file_path = $result['path'];
|
||||
$contract->original_file_name = $result['name'];
|
||||
$contract->original_file_hash = $result['hash'];
|
||||
$contract->original_file_size = $result['size'];
|
||||
}
|
||||
|
||||
$contract->title = $request->input('title');
|
||||
$contract->description = $request->input('description');
|
||||
$contract->sign_order_type = $request->input('sign_order_type');
|
||||
$contract->expires_at = $request->input('expires_at')
|
||||
? \Carbon\Carbon::parse($request->input('expires_at'))
|
||||
: $contract->expires_at;
|
||||
$contract->updated_by = $userId;
|
||||
$contract->save();
|
||||
|
||||
// 서명자 정보 업데이트
|
||||
$signers = $request->input('signers');
|
||||
foreach ($signers as $signerData) {
|
||||
$existingSigner = EsignSigner::withoutGlobalScopes()
|
||||
->where('contract_id', $contract->id)
|
||||
->where('role', $signerData['role'])
|
||||
->first();
|
||||
|
||||
if ($existingSigner) {
|
||||
$existingSigner->update([
|
||||
'name' => $signerData['name'],
|
||||
'email' => $signerData['email'],
|
||||
'phone' => $signerData['phone'] ?? null,
|
||||
'sign_order' => $signerData['role'] === 'creator'
|
||||
? ($request->input('sign_order_type') === 'creator_first' ? 1 : 2)
|
||||
: ($request->input('sign_order_type') === 'counterpart_first' ? 1 : 2),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
EsignAuditLog::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'contract_id' => $contract->id,
|
||||
'action' => 'contract_updated',
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
'metadata' => ['updated_by' => $userId],
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '계약이 수정되었습니다.',
|
||||
'data' => $contract->load('signers'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 계약 취소
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user