From 8f7a441900fce841ee1e2e820366fc07a0ef30ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Fri, 13 Feb 2026 06:25:01 +0900 Subject: [PATCH] =?UTF-8?q?feat:=EC=84=9C=EB=AA=85=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=EC=8B=9C=20=EA=B3=84=EC=95=BD=EC=84=9C=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EB=B0=9C=EC=86=A1=20=EB=B0=8F=20=EA=B0=90=EC=82=AC?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EsignCompletedMail Mailable 생성 (완료 알림 + PDF 다운로드 링크) - completed.blade.php 이메일 뷰 템플릿 생성 (초록색 테마) - submitSignature에 contract_completed 감사 로그 추가 - 모든 서명자에게 완료 이메일 발송 + completion_email_sent 감사 로그 - 이메일 발송 실패 시 try-catch로 계약 완료 보호 Co-Authored-By: Claude Opus 4.6 --- .../ESign/EsignPublicController.php | 42 ++++++++- app/Mail/EsignCompletedMail.php | 46 ++++++++++ .../views/emails/esign/completed.blade.php | 89 +++++++++++++++++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 app/Mail/EsignCompletedMail.php create mode 100644 resources/views/emails/esign/completed.blade.php 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 @@ + + + + + + 전자계약 서명 완료 + + + + + + +
+ + + + + + + + + + + + + +
+

+ 전자계약 서명 완료 +

+
+

안녕하세요, {{ $signerName }}님.

+

+ 아래 전자계약의 모든 서명이 완료되었습니다.
+ 완성된 계약서를 다운로드하여 보관해 주세요. +

+ + + + + + +
+

계약 제목

+

{{ $contractTitle }}

+

완료 일시

+

{{ $completedAt }}

+
+ + +

서명자 목록

+ + + + + + + @foreach($allSigners as $s) + + + + + + @endforeach +
서명자서명 일시상태
{{ $s->name }}{{ $s->signed_at?->format('Y-m-d H:i') ?? '-' }}
+ + + + + + +
+ + 계약서 다운로드 + +
+ +

+ 위 버튼이 동작하지 않으면 아래 링크를 브라우저에 직접 입력해 주세요:
+ {{ $downloadUrl }} +

+
+

+ 본 메일은 SAM 전자계약 시스템에서 자동 발송되었습니다. +

+
+
+ +