eCourt-Doc-Edit/backend/WordVersioning.Api/Data/AppDbContext.cs
Suphonchai Phoonsawat 9bb4a48c00 Phase 10: field editor (FR-14)
เพิ่ม editor ต่อ template field — ผู้ดูแลเลือกรูปแบบช่องกรอกในฟอร์มสร้างเอกสารได้:
text → textbox/textarea, number/date → control ตาม type (presentation metadata
ล้วน — validation ยังยึด Type, ค่า field เป็น string ทั้ง flow, ไม่แตะ generate/sync/add-in)

- Backend: TemplateField.Editor (nullable, null = default ของ type) +
  migration AddTemplateFieldEditor + validate ตาม type ใน PUT templates
  (ค่าไม่รู้จัก/ไม่เข้ากับ type → 400, normalize-on-write, API คืน resolved เสมอ)
- Web: util fieldEditor.ts + editor select หน้าแก้ template (desktop+mobile,
  ซ่อนเมื่อ type มีทางเดียว) + ฟอร์มสร้างเอกสาร render ตาม editor +
  แก้ prefill re-generate ของ field date จาก ISO timestamp เต็ม (input[type=date]
  รับเฉพาะ yyyy-MM-dd เดิมแสดงว่าง)
- Docs: spec v6 (FR-14/AC-17) + plan Phase 10 + sub-plan field-editor.md +
  acceptance-review AC-17 + README/CLAUDE.md
- Tests: backend 60/60 (FieldEditorTests ใหม่ 8 กรณี) · web 46/46 + build ผ่าน

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-22 09:17:15 +07:00

93 lines
3.8 KiB
C#

using Microsoft.EntityFrameworkCore;
using WordVersioning.Api.Models;
namespace WordVersioning.Api.Data;
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Document> Documents => Set<Document>();
public DbSet<DocumentVersion> DocumentVersions => Set<DocumentVersion>();
public DbSet<Template> Templates => Set<Template>();
public DbSet<TemplateField> TemplateFields => Set<TemplateField>();
public DbSet<DocumentFieldValue> DocumentFieldValues => Set<DocumentFieldValue>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Document>(entity =>
{
entity.HasKey(x => x.Id);
entity.Property(x => x.FileName).HasMaxLength(512);
entity.Property(x => x.AddInSignature).HasMaxLength(64);
// FR-10: เอกสารผูกกับ template — Restrict เพราะ template ต้อง soft-delete เท่านั้น
// (แถว Template ไม่ควรถูกลบจริงตรงๆ แต่กันไว้เผื่อมือสั่น)
entity.HasOne(x => x.Template)
.WithMany(t => t.Documents)
.HasForeignKey(x => x.TemplateId)
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<DocumentVersion>(entity =>
{
entity.HasKey(x => x.Id);
// กัน versionNumber ซ้ำตอน upload พร้อมกัน (retry ที่ controller เมื่อชน constraint)
entity.HasIndex(x => new { x.DocumentId, x.VersionNumber }).IsUnique();
entity.Property(x => x.ObjectKey).HasMaxLength(1024);
entity.Property(x => x.ContentHash).HasMaxLength(64);
entity.Property(x => x.Message).HasMaxLength(2048); // FR-13 commit message — นโยบายเดียวกับ Template.Description
entity.HasOne(x => x.Document)
.WithMany(d => d.Versions)
.HasForeignKey(x => x.DocumentId);
});
modelBuilder.Entity<Template>(entity =>
{
entity.HasKey(x => x.Id);
entity.Property(x => x.Name).HasMaxLength(256);
entity.Property(x => x.Description).HasMaxLength(2048);
entity.Property(x => x.ObjectKey).HasMaxLength(1024);
entity.HasMany(x => x.Documents)
.WithOne(d => d.Template)
.HasForeignKey(d => d.TemplateId);
});
modelBuilder.Entity<TemplateField>(entity =>
{
entity.HasKey(x => x.Id);
// Key = SDT tag ต้อง unique ต่อ template (spec ส่วน 9 เพิ่มเติม v2)
entity.HasIndex(x => new { x.TemplateId, x.Key }).IsUnique();
entity.Property(x => x.Key).HasMaxLength(256);
entity.Property(x => x.Label).HasMaxLength(512);
entity.Property(x => x.Type).HasMaxLength(16);
entity.Property(x => x.Editor).HasMaxLength(16);
entity.HasOne(x => x.Template)
.WithMany(t => t.Fields)
.HasForeignKey(x => x.TemplateId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<DocumentFieldValue>(entity =>
{
// latest value ต่อ (document, field) — ตาม spec ส่วน 7 ไม่มี Id แยก
entity.HasKey(x => new { x.DocumentId, x.FieldKey });
entity.Property(x => x.FieldKey).HasMaxLength(256);
entity.HasOne<Document>()
.WithMany()
.HasForeignKey(x => x.DocumentId)
.OnDelete(DeleteBehavior.Cascade);
});
}
}