diff --git a/app/Models/ESign/EsignHandwritingVerification.php b/app/Models/ESign/EsignHandwritingVerification.php new file mode 100644 index 00000000..8fface6f --- /dev/null +++ b/app/Models/ESign/EsignHandwritingVerification.php @@ -0,0 +1,62 @@ + 'integer', + 'similarity_score' => 'decimal:2', + 'is_passed' => 'boolean', + 'hwr_confidence' => 'decimal:2', + 'hwr_raw_response' => 'array', + 'attempt_number' => 'integer', + 'verified_at' => 'datetime', + 'options' => 'array', + ]; + + public function contract(): BelongsTo + { + return $this->belongsTo(EsignContract::class, 'contract_id'); + } + + public function signer(): BelongsTo + { + return $this->belongsTo(EsignSigner::class, 'signer_id'); + } + + public function scopeForTenant($query, $tenantId) + { + return $query->where('tenant_id', $tenantId); + } + + public function scopePassed($query) + { + return $query->where('is_passed', true); + } +} diff --git a/app/Models/ESign/EsignVerificationTemplate.php b/app/Models/ESign/EsignVerificationTemplate.php new file mode 100644 index 00000000..c75bf4b3 --- /dev/null +++ b/app/Models/ESign/EsignVerificationTemplate.php @@ -0,0 +1,54 @@ + 'array', + 'pass_threshold' => 'decimal:2', + 'max_attempts' => 'integer', + 'is_active' => 'boolean', + 'options' => 'array', + ]; + + public function scopeForTenant($query, $tenantId) + { + return $query->where('tenant_id', $tenantId); + } + + public function scopeActive($query) + { + return $query->where('is_active', true); + } + + public function getOption(string $key, mixed $default = null): mixed + { + $options = $this->options ?? []; + + return $options[$key] ?? $default; + } + + public function setOption(string $key, mixed $value): void + { + $options = $this->options ?? []; + $options[$key] = $value; + $this->options = $options; + } +} diff --git a/database/migrations/2026_03_22_100000_create_esign_verification_templates_table.php b/database/migrations/2026_03_22_100000_create_esign_verification_templates_table.php new file mode 100644 index 00000000..6519c830 --- /dev/null +++ b/database/migrations/2026_03_22_100000_create_esign_verification_templates_table.php @@ -0,0 +1,32 @@ +id(); + $table->unsignedBigInteger('tenant_id'); + $table->string('name', 100); + $table->string('category', 50)->nullable(); + $table->json('steps'); // [{ "order": 1, "text": "본인은 위 내용을 확인하였습니다", "threshold": 80 }] + $table->decimal('pass_threshold', 5, 2)->default(80.00); + $table->unsignedTinyInteger('max_attempts')->default(5); + $table->boolean('is_active')->default(true); + $table->unsignedBigInteger('created_by')->nullable(); + $table->json('options')->nullable(); + $table->timestamps(); + + $table->index(['tenant_id', 'is_active'], 'idx_tenant_active'); + }); + } + + public function down(): void + { + Schema::dropIfExists('esign_verification_templates'); + } +}; diff --git a/database/migrations/2026_03_22_110000_create_esign_handwriting_verifications_table.php b/database/migrations/2026_03_22_110000_create_esign_handwriting_verifications_table.php new file mode 100644 index 00000000..b0cd089b --- /dev/null +++ b/database/migrations/2026_03_22_110000_create_esign_handwriting_verifications_table.php @@ -0,0 +1,51 @@ +id(); + $table->unsignedBigInteger('tenant_id'); + $table->unsignedBigInteger('contract_id'); + $table->unsignedBigInteger('signer_id'); + $table->unsignedTinyInteger('step_order')->default(1); + $table->string('prompt_text', 200); + $table->string('recognized_text', 500)->nullable(); + $table->decimal('similarity_score', 5, 2)->nullable(); + $table->boolean('is_passed')->default(false); + $table->string('handwriting_image', 500)->nullable(); + $table->string('hwr_engine', 50)->nullable(); + $table->decimal('hwr_confidence', 5, 2)->nullable(); + $table->json('hwr_raw_response')->nullable(); + $table->unsignedTinyInteger('attempt_number')->default(1); + $table->timestamp('verified_at')->nullable(); + $table->string('ip_address', 45)->nullable(); + $table->string('user_agent', 500)->nullable(); + $table->json('options')->nullable(); + $table->timestamps(); + + $table->index(['contract_id', 'signer_id'], 'idx_contract_signer'); + $table->index('tenant_id', 'idx_tenant'); + + $table->foreign('contract_id') + ->references('id') + ->on('esign_contracts') + ->onDelete('cascade'); + + $table->foreign('signer_id') + ->references('id') + ->on('esign_signers') + ->onDelete('cascade'); + }); + } + + public function down(): void + { + Schema::dropIfExists('esign_handwriting_verifications'); + } +};