diff --git a/app/Http/Controllers/ESign/EsignPublicController.php b/app/Http/Controllers/ESign/EsignPublicController.php index 07facce3..65f95b0c 100644 --- a/app/Http/Controllers/ESign/EsignPublicController.php +++ b/app/Http/Controllers/ESign/EsignPublicController.php @@ -8,7 +8,9 @@ use App\Models\ESign\EsignSigner; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Mail\EsignCompletedMail; use App\Mail\EsignRequestMail; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use App\Services\ESign\PdfSignatureService; use Illuminate\Support\Facades\Storage; @@ -250,11 +252,49 @@ public function submitSignature(Request $request, string $token): JsonResponse $pdfService = new PdfSignatureService(); $pdfService->mergeSignatures($contract); } catch (\Throwable $e) { - \Illuminate\Support\Facades\Log::error('PDF 서명 합성 실패', [ + Log::error('PDF 서명 합성 실패', [ 'contract_id' => $contract->id, 'error' => $e->getMessage(), ]); } + + // 계약 완료 감사 로그 + EsignAuditLog::create([ + 'tenant_id' => $contract->tenant_id, + 'contract_id' => $contract->id, + 'signer_id' => $signer->id, + 'action' => 'contract_completed', + 'ip_address' => $request->ip(), + 'user_agent' => $request->userAgent(), + 'metadata' => ['total_signers' => $allSigners->count()], + 'created_at' => now(), + ]); + + // 모든 서명자에게 완료 이메일 발송 + foreach ($allSigners as $completedSigner) { + try { + Mail::to($completedSigner->email)->send( + new EsignCompletedMail($contract, $completedSigner, $allSigners) + ); + + EsignAuditLog::create([ + 'tenant_id' => $contract->tenant_id, + 'contract_id' => $contract->id, + 'signer_id' => $completedSigner->id, + 'action' => 'completion_email_sent', + 'ip_address' => $request->ip(), + 'user_agent' => $request->userAgent(), + 'metadata' => ['email' => $completedSigner->email], + 'created_at' => now(), + ]); + } catch (\Throwable $e) { + Log::error('계약 완료 이메일 발송 실패', [ + 'contract_id' => $contract->id, + 'signer_id' => $completedSigner->id, + 'error' => $e->getMessage(), + ]); + } + } } else { $contract->update(['status' => 'partially_signed']); diff --git a/app/Mail/EsignCompletedMail.php b/app/Mail/EsignCompletedMail.php new file mode 100644 index 00000000..64bb52b0 --- /dev/null +++ b/app/Mail/EsignCompletedMail.php @@ -0,0 +1,46 @@ +contract->title}", + ); + } + + public function content(): Content + { + $downloadUrl = config('app.url') . '/esign/sign/' . $this->signer->access_token . '/api/document'; + + return new Content( + html: 'emails.esign.completed', + with: [ + 'contractTitle' => $this->contract->title, + 'signerName' => $this->signer->name, + 'completedAt' => $this->contract->completed_at?->format('Y-m-d H:i'), + 'allSigners' => $this->allSigners, + 'downloadUrl' => $downloadUrl, + ], + ); + } +} diff --git a/resources/views/emails/esign/completed.blade.php b/resources/views/emails/esign/completed.blade.php new file mode 100644 index 00000000..bfb577fa --- /dev/null +++ b/resources/views/emails/esign/completed.blade.php @@ -0,0 +1,89 @@ + + +
+ + +| + + | +