Refactor document versioning to extract fields from uploaded .docx files on the server side

- Removed the `fields` parameter from the version upload form, as it is now extracted from the uploaded .docx file using the `extractContentControls` function.
- Updated related types and interfaces to reflect the new structure of version fields.
- Modified the OpenAPI specification to document the changes in the versioning process.
- Adjusted tests to ensure compliance with the new behavior, including validation for the absence of the `fields` parameter.
- Implemented a new function `extractDocumentSnapshot` to handle the extraction of content controls and document properties from .docx files.
- Updated metadata and versioning services to align with the new extraction logic.
This commit is contained in:
Suphonchai Phoonsawat 2026-10-31 10:21:17 +07:00
parent bc61f0fd2e
commit cdae1ceedd
17 changed files with 380 additions and 179 deletions

View file

@ -2,7 +2,8 @@
// versioningService หลังปลด mock (2026-10-27) — คุมทั้งสองโหมด:
// - ของจริง: sign-in ผ่าน signInWithTicket ให้ได้ Bearer ก่อน แล้วตรวจ FormData ของ
// uploadVersion ตรง contract POST /api/documents/versions (ห้ามส่ง userId/userName/
// templateId — identity มาจาก Bearer หมด), getVersions แปลง DTO, getDownloadLink ใส่ ?format=
// templateId — identity มาจาก Bearer หมด · และห้ามส่ง fields — server แกะจากไฟล์เอง
// 2026-10-30), getVersions แปลง DTO, getDownloadLink ใส่ ?format=
// - โหมด ?addindemo: ใช้ mock ในเครื่อง (ไม่ยิง network เลย)
import { createHmac, webcrypto } from "node:crypto";
import { afterEach, describe, expect, it, vi } from "vitest";
@ -83,12 +84,14 @@ describe("versioningService (real mode)", () => {
expect((form.get("file") as File).name).toBe("คำฟ้อง.docx");
expect((form.get("pdf") as File).name).toBe("document.pdf");
expect(form.get("clientVersionId")).toBe("client-vid-1");
expect(JSON.parse(form.get("fields") as string)).toEqual({ blackno: "ด1" });
expect(form.get("message")).toBe("แก้ไขย่อหน้า 3"); // trim แล้ว
// contract 2026-10-22: ห้ามมี field identity/template เหลืออยู่เลย
expect(form.has("userId")).toBe(false);
expect(form.has("userName")).toBe(false);
expect(form.has("templateId")).toBe(false);
// contract 2026-10-30: fields ก็ห้ามส่ง — server แกะจากไฟล์ .docx เอง
// (ตัวเดียวกับ /api/template/extract) แม้ caller จะ pass เข้ามาตาม signature เดิม
expect(form.has("fields")).toBe(false);
});
it("pdf ว่าง/ไม่แนบ = ไม่ append field pdf (ไฟล์เปล่า = version ไม่มี PDF)", async () => {
@ -105,6 +108,8 @@ describe("versioningService (real mode)", () => {
it("getVersions แปลง DocumentVersionDTO → VersionRecord ครบทุก field", async () => {
await signInReal();
// fields = ก้อนเดียวกับ return ของ /api/template/extract (server แกะจากไฟล์เอง)
const fields = { cc: { blackno: "ด1" }, bookmark: {}, properties: { custom: {} }, verify: {} };
const fetchMock = vi.fn(
async (_url: string, _init?: RequestInit) =>
new Response(
@ -116,7 +121,7 @@ describe("versioningService (real mode)", () => {
createdByUserId: "oom",
createdByUserName: "สรวิชญ์",
contentHash: "ab",
fields: { blackno: "ด1" },
fields,
message: null,
hasPdf: true,
},
@ -134,7 +139,7 @@ describe("versioningService (real mode)", () => {
createdByUserId: "oom",
createdByUserName: "สรวิชญ์",
contentHash: "ab",
fields: { blackno: "ด1" },
fields,
message: null,
hasPdf: true,
},