# Đề xuất data contract cho sinh DOCX trong DSCons

## 1. Mục tiêu

Tài liệu này chốt lớp data contract cho workflow sinh DOCX trong DSCons.

Trọng tâm:

- chuẩn hóa dữ liệu đầu vào theo `document_type`
- chuẩn hóa template và placeholder
- tách mapping dữ liệu khỏi tầng render DOCX
- đánh giá `confidence`, `generation readiness`, `review`
- giữ phù hợp với hướng triển khai trong `README.md`, `workflow.md` và `docs/document-generation-implementation-plan.md`

Nguyên tắc:

- làm foundation dữ liệu trước, không bắt đầu từ DOCX engine
- không đẩy business rule xuống tầng render
- phân biệt rõ dữ liệu đã xác minh, dữ liệu gợi ý và dữ liệu phải nhập tay
- render chỉ là bước cuối cùng, sau readiness và review

## 2. Vai trò của data contract trong DSCons

Trong DSCons:

- Qdrant giữ tri thức, template tham chiếu, hồ sơ nguồn
- PostgreSQL giữ dữ liệu vận hành và trạng thái xử lý
- workflow sinh tài liệu là lớp trung gian biến dữ liệu có cấu trúc thành payload có thể render

Data contract này giúp:

- cùng một `document_type` có cùng schema đầu vào
- template cũ được chuẩn hóa bằng placeholder thống nhất
- mỗi field đều truy được nguồn và mức tin cậy
- readiness và review được tính trước khi phát hành
- có thể thay DOCX engine sau này mà không đổi logic nghiệp vụ

## 3. Phạm vi hiện tại

### Trong phạm vi
- schema đầu vào cho sinh tài liệu
- template registry ở mức metadata
- placeholder definition
- mapping từ dữ liệu nguồn sang placeholder
- field status với `confidence`
- object `generation readiness`
- object `review`

### Ngoài phạm vi
- chọn thư viện DOCX cụ thể
- thiết kế chi tiết API route mới
- lưu trữ production end-to-end
- xử lý toàn bộ loại hồ sơ cùng lúc

## 4. Kiến trúc logic đề xuất

Workflow nên tách thành 6 lớp:

| Lớp | Vai trò |
| --- | --- |
| Input payload | dữ liệu đầu vào theo từng loại hồ sơ |
| Template registry | metadata template, version, placeholder bắt buộc |
| Mapping | ánh xạ dữ liệu nguồn sang placeholder |
| Field assessment | gắn confidence, warning, blocker, manual input |
| Generation readiness | quyết định có đủ điều kiện sinh nháp/render hay chưa |
| Review workflow | quản lý trạng thái bản nháp sau khi sinh |

Lưu ý:

- tầng render không tự suy diễn nghiệp vụ
- tầng render chỉ nhận:
  - template đã chọn
  - placeholder values đã chuẩn hóa
  - trạng thái readiness đủ điều kiện theo policy

## 5. Ranh giới giữa dữ liệu và render

### Tầng dữ liệu phải chịu trách nhiệm
- định nghĩa schema theo `document_type`
- chuẩn hóa tên placeholder
- map dữ liệu nguồn sang field chuẩn
- xác định field nào bắt buộc
- gắn `confidence`, warning, blocker
- tính `generation readiness`
- lưu trạng thái review ở mức dữ liệu

### Tầng render chỉ nên chịu trách nhiệm
- nạp template đã được duyệt
- thay placeholder bằng value đã có
- báo placeholder chưa resolve được
- xuất bản nháp hoặc file cuối theo trạng thái cho phép

### Không nên để render xử lý
- suy luận ai là người ký
- tự chọn dữ liệu “có vẻ đúng”
- kiểm tra logic hồ sơ đủ hay thiếu
- quyết định tài liệu đã được phát hành hay chưa

## 6. Data contract cốt lõi

## 6.1. Document generation request

Đây là object đầu vào ở mức nghiệp vụ.

| Trường | Ý nghĩa |
| --- | --- |
| `schema_version` | version của contract |
| `document_type` | loại tài liệu cần sinh |
| `template_code` | template dự kiến dùng |
| `project_context` | dữ liệu dự án/công trình/gói thầu |
| `document_context` | dữ liệu riêng của tài liệu |
| `parties` | các bên tham gia |
| `signatories` | người ký theo từng bên |
| `source_references` | danh sách nguồn đã dùng để map |
| `generation_metadata` | metadata nội bộ phục vụ workflow |

Gợi ý tối thiểu:

```json
{
  "schema_version": "1.0",
  "document_type": "bien_ban_ban_giao_mat_bang",
  "template_code": "tpl_bien_ban_ban_giao_mat_bang_v1",
  "project_context": {},
  "document_context": {},
  "parties": [],
  "signatories": [],
  "source_references": [],
  "generation_metadata": {}
}
```

## 6.2. Template registry

Mỗi template nên có metadata ổn định, độc lập với file DOCX thô.

| Trường | Bắt buộc | Ghi chú |
| --- | --- | --- |
| `template_code` | có | mã template duy nhất |
| `document_type` | có | map với loại hồ sơ |
| `template_version` | có | version hóa template |
| `knowledge_type` | có | dùng `template_form` |
| `doc_stage` | có | ví dụ `execution` |
| `doc_family` | có | nhóm hồ sơ |
| `placeholders` | có | danh sách placeholder khai báo |
| `required_placeholders` | có | placeholder bắt buộc |
| `is_active` | có | template đang dùng hay không |
| `notes` | không | ghi chú nội bộ |

Ví dụ rút gọn:

```json
{
  "template_code": "tpl_bien_ban_ban_giao_mat_bang_v1",
  "document_type": "bien_ban_ban_giao_mat_bang",
  "template_version": "v1",
  "knowledge_type": "template_form",
  "doc_stage": "execution",
  "doc_family": "execution",
  "required_placeholders": [
    "project_name",
    "handover_date",
    "transferor_org_name",
    "recipient_org_name"
  ],
  "is_active": true
}
```

## 6.3. Placeholder definition

Mỗi placeholder là một hợp đồng dữ liệu nhỏ giữa mapping và render.

| Trường | Ý nghĩa |
| --- | --- |
| `name` | tên placeholder dạng `snake_case` |
| `label` | nhãn dễ đọc cho reviewer |
| `required` | có bắt buộc hay không |
| `source_hint` | gợi ý nguồn dữ liệu |
| `example_value` | ví dụ dữ liệu |
| `minimum_confidence` | mức tin cậy tối thiểu |

Quy ước:

- dùng `snake_case`
- mô tả ý nghĩa nghiệp vụ, không mô tả vị trí hiển thị
- không gắn placeholder với paragraph hay table cụ thể
- cùng một khái niệm phải dùng cùng một tên giữa các template nếu có thể

Danh sách placeholder khởi tạo cho pilot:

- `document_title`
- `document_number`
- `project_name`
- `site_name`
- `handover_date`
- `handover_location`
- `transferor_org_name`
- `transferor_org_address`
- `transferor_signatory_full_name`
- `transferor_signatory_title`
- `recipient_org_name`
- `recipient_org_address`
- `recipient_signatory_full_name`
- `recipient_signatory_title`
- `handover_scope_summary`
- `handover_notes`
- `legal_basis_summary`

## 6.4. Mapping result và field status

Sau khi map, mỗi field nên có trạng thái riêng để phục vụ UI, readiness và review.

| Trường | Ý nghĩa |
| --- | --- |
| `field_name` | tên field theo schema nội bộ |
| `placeholder_name` | placeholder tương ứng |
| `value` | giá trị hiện tại |
| `is_required` | field bắt buộc hay không |
| `confidence` | mức tin cậy |
| `source_reference` | nguồn lấy dữ liệu |
| `needs_manual_input` | có cần nhập tay không |
| `review_note` | ghi chú cho reviewer |
| `is_ready` | field này đã đạt điều kiện chưa |

Ví dụ rút gọn:

```json
{
  "field_name": "document_context.handover_date",
  "placeholder_name": "handover_date",
  "value": "2026-03-10",
  "is_required": true,
  "confidence": "verified_from_source",
  "source_reference": "docs/duong-ong-nam-hung-khanh-metadata-schema-example.json",
  "needs_manual_input": false,
  "review_note": "",
  "is_ready": true
}
```

## 6.5. Generation readiness

Readiness là trạng thái dữ liệu trước render, không phải trạng thái phê duyệt phát hành.

| Trường | Ý nghĩa |
| --- | --- |
| `status` | trạng thái readiness tổng |
| `missing_required_fields` | field bắt buộc còn thiếu |
| `manual_input_required_fields` | field cần nhập tay |
| `review_required_fields` | field cần reviewer xác nhận |
| `warnings` | cảnh báo không chặn |
| `summary` | tóm tắt ngắn |

Trạng thái chuẩn dùng trong pilot:

- `not_ready`
- `draft_ready`
- `review_required`
- `ready_for_render`

## 6.6. Review object

Review là vòng đời hậu mapping hoặc hậu render nháp.

| Trường | Ý nghĩa |
| --- | --- |
| `status` | trạng thái review |
| `reviewer_id` hoặc `reviewer_name` | người review |
| `reviewed_at` | thời điểm review |
| `revision_note` | ghi chú chỉnh sửa |
| `issued_at` | thời điểm phát hành |
| `issue_reference` | mã tham chiếu phát hành nếu có |

Trạng thái review đề xuất:

- `draft_generated`
- `awaiting_review`
- `needs_revision`
- `approved_for_issue`
- `issued`

## 7. Confidence policy

## 7.1. Mức confidence dùng trong pilot

Dùng 3 mức đơn giản, dễ vận hành:

- `verified_from_source`
- `suggested_from_similar_template`
- `manual_input_required`

## 7.2. Ý nghĩa từng mức

| Confidence | Ý nghĩa | Cách dùng |
| --- | --- | --- |
| `verified_from_source` | lấy từ hồ sơ hoặc dữ liệu đã xác minh | có thể dùng cho readiness |
| `suggested_from_similar_template` | dữ liệu gợi ý, chưa đủ chắc chắn | cần reviewer xác nhận |
| `manual_input_required` | hệ thống chưa có dữ liệu tin cậy | không coi là ready cho field bắt buộc |

## 7.3. Quy tắc tối thiểu

- field bắt buộc + thiếu value => `not_ready`
- field bắt buộc + `manual_input_required` => `not_ready`
- field bắt buộc + `suggested_from_similar_template` => tối thiểu `review_required`
- field bắt buộc + `verified_from_source` => có thể đạt readiness
- field không bắt buộc + `manual_input_required` => warning hoặc để trống theo policy template

## 8. Logic tính generation readiness

Thứ tự đánh giá nên là:

1. thiếu field bắt buộc -> `not_ready`
2. có field bắt buộc cần nhập tay -> `not_ready`
3. có field bắt buộc ở mức suggested -> `review_required`
4. chỉ còn warning không chặn -> `draft_ready`
5. mọi field bắt buộc đã verified hoặc đạt policy -> `ready_for_render`

Lưu ý:

- `ready_for_render` không đồng nghĩa `issued`
- một tài liệu có thể render nháp nhưng vẫn chờ review
- readiness là trạng thái dữ liệu, review là trạng thái con người phê duyệt

## 9. Mapping giữa dữ liệu nguồn và placeholder

## 9.1. Nguyên tắc mapping

- không bind object business thô trực tiếp vào template
- luôn giữ được `source_reference`
- cho phép fallback có kiểm soát
- field nhạy cảm phải gắn confidence thấp hơn nếu chỉ suy diễn
- mapping phải độc lập với thư viện DOCX

## 9.2. Nguồn dữ liệu trong DSCons

| Nguồn | Vai trò |
| --- | --- |
| metadata hồ sơ công trình | cung cấp project, loại hồ sơ, ngày, tổ chức |
| template cũ đã chuẩn hóa | cung cấp cấu trúc và wording tham chiếu |
| dữ liệu vận hành nội bộ | bổ sung trạng thái, người phụ trách, ghi chú |
| reviewer nhập tay | chốt field còn thiếu hoặc chưa chắc chắn |

## 9.3. Bảng mapping khởi tạo cho pilot

| Placeholder | Nguồn dự kiến | Confidence mặc định |
| --- | --- | --- |
| `project_name` | metadata dự án/hồ sơ | `verified_from_source` nếu có nguồn chính thức |
| `site_name` | thông tin công trình/địa điểm | `manual_input_required` nếu chưa rõ |
| `handover_date` | dữ liệu biên bản hoặc lịch thực hiện | `suggested_from_similar_template` nếu chỉ suy diễn |
| `handover_location` | địa điểm công trình hoặc nơi ký | thường cần review |
| `transferor_org_name` | hồ sơ pháp lý hoặc metadata tổ chức | ưu tiên verified |
| `recipient_org_name` | hồ sơ pháp lý hoặc metadata tổ chức | ưu tiên verified |
| `transferor_signatory_full_name` | dữ liệu người ký/đại diện | manual nếu chưa có nguồn chắc chắn |
| `recipient_signatory_full_name` | dữ liệu người ký/đại diện | manual nếu chưa có nguồn chắc chắn |
| `handover_scope_summary` | mô tả phạm vi bàn giao | thường cần nhập tay hoặc review |
| `handover_notes` | ghi chú bổ sung | thường không bắt buộc |

## 10. Payload pilot đề xuất

Pilot hiện phù hợp với:

- `document_type = bien_ban_ban_giao_mat_bang`

Payload nên biểu diễn được:

- metadata tài liệu
- dự án/công trình/gói thầu
- thông tin biên bản bàn giao
- bên giao và bên nhận
- người đại diện ký
- thời gian, địa điểm bàn giao
- phạm vi bàn giao
- ghi chú và căn cứ
- metadata nội bộ phục vụ generation

Ví dụ rút gọn:

```json
{
  "schema_version": "1.0",
  "document_type": "bien_ban_ban_giao_mat_bang",
  "template_code": "tpl_bien_ban_ban_giao_mat_bang_v1",
  "project_context": {
    "project_code": "DS-HK-2026-001",
    "project_name": "Cải tạo, sửa chữa tuyến đường từ nhà ông Nam đến cống chùa Hưng Khánh",
    "package_code": "GOI-04-TCXL-MSTB",
    "contract_code": "08.3.SCKM/2026/HĐTCXD"
  },
  "document_context": {
    "document_title": "Biên bản bàn giao mặt bằng",
    "handover_date": "2026-03-10",
    "handover_location": "Xã Kiến Minh",
    "handover_scope_summary": "Bàn giao hiện trạng và phạm vi thi công theo hồ sơ thiết kế được duyệt."
  },
  "parties": [
    {
      "party_role": "transferor",
      "org_name": "Phòng Kinh tế xã Kiến Minh"
    },
    {
      "party_role": "recipient",
      "org_name": "Công ty TNHH Xây dựng Định Sơn"
    }
  ],
  "signatories": [
    {
      "party_role": "transferor",
      "full_name": "Nguyễn Văn A",
      "title": "Đại diện đơn vị quản lý dự án"
    },
    {
      "party_role": "recipient",
      "full_name": "Phạm Văn D",
      "title": "Chỉ huy trưởng công trình"
    }
  ]
}
```

## 11. Pipeline áp dụng thực tế

Thứ tự nên giữ đúng như sau:

1. chốt schema theo `document_type`
2. chuẩn hóa template cũ thành placeholder
3. map dữ liệu nguồn sang placeholder
4. gắn field status và `confidence`
5. tính `generation readiness`
6. chuyển qua review workflow
7. chỉ render khi đạt policy

Lợi ích:

- tránh nhầm giữa “có thể sinh nháp” và “có thể phát hành”
- dễ giải thích vì sao một tài liệu chưa render được
- dễ mở rộng sang loại hồ sơ khác mà không viết lại logic

## 12. Những khoảng trống cần theo dõi

Hiện tại vẫn cần theo dõi các điểm sau:

- chưa chốt DOCX engine cụ thể
- chưa có registry template production trong code
- dữ liệu người ký nhiều bên còn thiếu nguồn chuẩn ở một số hồ sơ
- một số field nghiệp vụ như phạm vi bàn giao vẫn có thể phải nhập tay
- review workflow mới ở mức contract, chưa phải triển khai hoàn chỉnh

## 13. Kết luận

Hướng phù hợp cho DSCons là lấy data contract làm trung tâm của workflow sinh DOCX.

Cần giữ rõ 4 lớp:

- dữ liệu đầu vào theo `document_type`
- template registry và placeholder
- mapping + confidence + readiness
- review trước khi render/phát hành

Nếu làm đúng thứ tự này, DSCons sẽ:

- tận dụng được template cũ mà không lệ thuộc file thô
- truy vết được vì sao một field được điền
- tách bạch tri thức, dữ liệu vận hành và render
- sẵn sàng nối DOCX engine ở giai đoạn sau với rủi ro thấp hơn