ปรับปรุง phase 6 ให้ครบถ้วน

This commit is contained in:
Suphonchai Phoonsawat 2026-08-20 11:15:04 +07:00
parent 93570d38d8
commit a196b8f9a8
14 changed files with 747 additions and 40 deletions

View file

@ -335,6 +335,69 @@ public class DocumentsController(
}
}
/// <summary>FR-12 — detail ของเอกสาร: ข้อมูลหัวเรื่อง + template + ค่าล่าสุดของทุก field
/// (นิยามจาก TemplateField merge กับ DocumentFieldValue — รองรับ template เปลี่ยนนิยามหลังเอกสารสร้างแล้ว)</summary>
[HttpGet("{documentId:guid}")]
[ProducesResponseType(typeof(DocumentDetail), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<DocumentDetail>> GetDetail(Guid documentId, CancellationToken ct)
{
var doc = await db.Documents
.AsNoTracking()
.Where(d => d.Id == documentId)
.Select(d => new
{
d.Id,
d.FileName,
d.CreatedAt,
d.TemplateId,
TemplateName = d.Template != null ? d.Template.Name : null,
TemplateIsActive = d.Template != null && d.Template.IsActive,
})
.FirstOrDefaultAsync(ct);
if (doc is null)
return NotFound($"ไม่พบ document {documentId}");
var fields = new List<DocumentFieldItem>();
if (doc.TemplateId is not null)
{
// โหลดสองข้างแยกแล้ว merge ใน memory (แบบเดียวกับ FieldSyncService) —
// ไม่ใช้ Join เพราะ inner join จะทิ้ง orphan ทั้งสองฝั่งเงียบๆ
var defs = await db.TemplateFields
.AsNoTracking()
.Where(f => f.TemplateId == doc.TemplateId)
.OrderBy(f => f.SortOrder)
.Select(f => new { f.Key, f.Label, f.Type, f.IsRequired })
.ToListAsync(ct);
var values = await db.DocumentFieldValues
.AsNoTracking()
.Where(v => v.DocumentId == documentId)
.ToDictionaryAsync(v => v.FieldKey, ct);
foreach (var def in defs)
{
values.TryGetValue(def.Key, out var value);
fields.Add(new DocumentFieldItem(
def.Key, def.Label, def.Type, def.IsRequired,
value?.Value ?? string.Empty,
value?.SourceVersionId, value?.UpdatedByUserId, value?.UpdatedAt));
}
// ค่าที่เก็บไว้แต่ key ไม่มีในนิยามปัจจุบัน (replace ไฟล์แล้ว tag หาย) — ต่อท้ายโดยไม่มีนิยาม
foreach (var (key, value) in values.Where(kv => defs.All(d => d.Key != kv.Key)).OrderBy(kv => kv.Key))
{
fields.Add(new DocumentFieldItem(
key, null, null, null,
value.Value,
value.SourceVersionId, value.UpdatedByUserId, value.UpdatedAt));
}
}
return Ok(new DocumentDetail(
doc.Id, doc.FileName, doc.CreatedAt, doc.TemplateId, doc.TemplateName, doc.TemplateIsActive, fields));
}
/// <summary>FR-6 — version history เรียงใหม่ → เก่า (พร้อม snapshot fields ต่อ version)</summary>
[HttpGet("{documentId:guid}/versions")]
[ProducesResponseType(typeof(IReadOnlyList<VersionListItem>), StatusCodes.Status200OK)]