506 lines
8.8 KiB
Markdown
506 lines
8.8 KiB
Markdown
# Task H.5.3: PDFME Template Version Remap + Static Label Mapping Fix
|
|
|
|
## Goal
|
|
|
|
รองรับการแก้ไข PDFME template version ใหม่ทั้งหมด หลังจากมีการลบ/เพิ่ม/เปลี่ยน field ใน template
|
|
|
|
พร้อมแก้ปัญหา static label เช่น:
|
|
|
|
```txt
|
|
Tel
|
|
Email
|
|
Att
|
|
Project
|
|
Location
|
|
```
|
|
|
|
ไม่แสดงใน PDF
|
|
|
|
---
|
|
|
|
# Background
|
|
|
|
Current issue:
|
|
|
|
Template แสดงค่าฝั่งข้อมูล เช่น:
|
|
|
|
```txt
|
|
02-000-1000
|
|
demo-customer@local.test
|
|
Task H.1 Contact
|
|
Task H.5 Audit Fixture
|
|
Bangkok HQ
|
|
```
|
|
|
|
แต่ label ฝั่งซ้ายไม่แสดง:
|
|
|
|
```txt
|
|
Tel
|
|
Email
|
|
Att
|
|
Project
|
|
Location
|
|
```
|
|
|
|
Cause:
|
|
|
|
Field label เช่น:
|
|
|
|
```txt
|
|
tel_label
|
|
email_label
|
|
att_label
|
|
project_label
|
|
site_label
|
|
```
|
|
|
|
ยังไม่มี runtime input / mapping ที่ตรงกับ template version ใหม่
|
|
|
|
อีกทั้ง template มีการลบ field แล้ว จึงต้อง remap ใหม่ทั้ง version
|
|
|
|
---
|
|
|
|
# Important Rule
|
|
|
|
Do NOT patch the old template version in-place.
|
|
|
|
Create a new template version.
|
|
|
|
Example:
|
|
|
|
```txt
|
|
ALLA Quotation Standard v1.0
|
|
→
|
|
ALLA Quotation Standard v1.1
|
|
```
|
|
|
|
Approved PDF เดิมต้องยังอ้าง version เดิมได้
|
|
|
|
---
|
|
|
|
# Must Read
|
|
|
|
```txt
|
|
docs/business/pdf-mapping-registry.md
|
|
docs/business/pdf-placeholder-registry.md
|
|
docs/adr/0013-pdf-visual-parity-strategy.md
|
|
docs/implementation/task-h5-pdf-mapping-audit-visual-parity.md
|
|
docs/implementation/task-h51-pdf-integrity-audit.md
|
|
|
|
src/features/foundation/document-template/**
|
|
src/features/foundation/pdf-generator/**
|
|
src/features/crm/quotations/document/**
|
|
src/db/seeds/foundation.seed.ts
|
|
scripts/audit-pdf-template-inventory.ts
|
|
scripts/audit-pdf-mapping-coverage.ts
|
|
scripts/audit-pdf-runtime-payload.ts
|
|
scripts/generate-pdf-integrity-report.ts
|
|
```
|
|
|
|
---
|
|
|
|
# Scope H5.3.1 Template Version Ingestion
|
|
|
|
Add support to ingest/register new PDFME template JSON as a new version.
|
|
|
|
Required behavior:
|
|
|
|
* read latest ALLA / ONVALLA template JSON
|
|
* create new `crm_document_template_versions`
|
|
* mark new version active
|
|
* deactivate previous active version for same template
|
|
* do not delete old version
|
|
* preserve approved snapshots that reference old version
|
|
|
|
Rules:
|
|
|
|
```txt
|
|
one active version per template
|
|
approved snapshots remain immutable
|
|
```
|
|
|
|
---
|
|
|
|
# Scope H5.3.2 Full Field Inventory From New Template
|
|
|
|
For the new template version, scan all schema names.
|
|
|
|
Classify fields into:
|
|
|
|
```txt
|
|
static input field
|
|
dynamic topic template
|
|
readonly/static visual field
|
|
system field
|
|
unknown field
|
|
deleted field from previous version
|
|
new field
|
|
```
|
|
|
|
Special handling:
|
|
|
|
Dynamic topic template fields:
|
|
|
|
```txt
|
|
topic
|
|
data_topic
|
|
```
|
|
|
|
must not become static mappings.
|
|
|
|
Runtime generated fields:
|
|
|
|
```txt
|
|
topic_*
|
|
item_topic_*
|
|
```
|
|
|
|
must not be stored in DB mapping.
|
|
|
|
---
|
|
|
|
# Scope H5.3.3 Full Mapping Rebuild For New Version
|
|
|
|
For the new template version:
|
|
|
|
1. create mappings only for fields that exist in the new template
|
|
2. do not copy orphan mappings from old version
|
|
3. do not map deleted fields
|
|
4. use `pdf-placeholder-registry.md` and actual field inventory
|
|
5. create missing mappings for valid fields
|
|
6. mark unsupported fields as warning, not silent pass
|
|
|
|
Mapping categories:
|
|
|
|
## Static Label Fields
|
|
|
|
```txt
|
|
tel_label -> pdfme.labels.tel
|
|
email_label -> pdfme.labels.email
|
|
att_label -> pdfme.labels.att
|
|
project_label -> pdfme.labels.project
|
|
site_label -> pdfme.labels.location
|
|
```
|
|
|
|
Expected values:
|
|
|
|
```txt
|
|
Tel
|
|
Email
|
|
Att
|
|
Project
|
|
Location
|
|
```
|
|
|
|
or Thai labels if configured:
|
|
|
|
```txt
|
|
โทร
|
|
อีเมล
|
|
เรียน
|
|
โครงการ
|
|
สถานที่
|
|
```
|
|
|
|
## Customer Fields
|
|
|
|
```txt
|
|
customer_name -> customer.name
|
|
customer_addr -> customer.address
|
|
customer_tel -> customer.phone
|
|
customer_email -> customer.email
|
|
customer_att -> quotation.attention
|
|
```
|
|
|
|
## Project / Quotation Fields
|
|
|
|
```txt
|
|
project_name -> quotation.projectName
|
|
site_location -> quotation.projectLocation
|
|
quotation_code -> quotation.code
|
|
quotation_code_data -> quotation.code
|
|
quotation_date -> pdfme.quotation_date
|
|
quotation_date_data -> pdfme.quotation_date
|
|
```
|
|
|
|
## Price Table
|
|
|
|
Canonical:
|
|
|
|
```txt
|
|
quotation_price_data -> pdfme.quotation_price_data
|
|
```
|
|
|
|
Keep compatibility if template still has scalar placeholders:
|
|
|
|
```txt
|
|
quotation_price -> pdfme.quotation_price
|
|
currency -> pdfme.currency
|
|
```
|
|
|
|
## Exclusion
|
|
|
|
```txt
|
|
exclusion_data -> pdfme.exclusion_data
|
|
```
|
|
|
|
## Signature
|
|
|
|
```txt
|
|
app1 -> signatures.preparedBy.name
|
|
app1_position -> signatures.preparedBy.position
|
|
app2 -> signatures.approvedBy.name
|
|
app2_position -> signatures.approvedBy.position
|
|
app3 -> signatures.authorizedBy.name
|
|
app3_position -> signatures.authorizedBy.position
|
|
```
|
|
|
|
---
|
|
|
|
# Scope H5.3.4 Runtime Document Data Update
|
|
|
|
Update:
|
|
|
|
```txt
|
|
src/features/crm/quotations/document/server/service.ts
|
|
```
|
|
|
|
Ensure `documentData.pdfme.labels` exists:
|
|
|
|
```ts
|
|
pdfme: {
|
|
labels: {
|
|
tel: "Tel";
|
|
email: "Email";
|
|
att: "Att";
|
|
project: "Project";
|
|
location: "Location";
|
|
}
|
|
}
|
|
```
|
|
|
|
Optional Thai mode:
|
|
|
|
```ts
|
|
pdfme: {
|
|
labels: {
|
|
tel: "โทร";
|
|
email: "อีเมล";
|
|
att: "เรียน";
|
|
project: "โครงการ";
|
|
location: "สถานที่";
|
|
}
|
|
}
|
|
```
|
|
|
|
Rules:
|
|
|
|
* never return undefined
|
|
* label values should be controlled by terminology/config later
|
|
* for now default to current PDF language
|
|
* do not hardcode in template only
|
|
|
|
---
|
|
|
|
# Scope H5.3.5 Resolver Safety
|
|
|
|
Update mapping resolver to:
|
|
|
|
* resolve nested paths such as `pdfme.labels.tel`
|
|
* fallback to mapping.defaultValue
|
|
* fallback to `"-"` if still empty
|
|
* preserve table values as `string[][]`
|
|
* not stringify table input
|
|
|
|
---
|
|
|
|
# Scope H5.3.6 Audit Update
|
|
|
|
Update audit scripts to support version remap.
|
|
|
|
Checks:
|
|
|
|
```txt
|
|
new version active
|
|
old version inactive but retained
|
|
deleted fields removed from mapping
|
|
new fields mapped or classified
|
|
label fields resolved
|
|
price table present
|
|
dynamic topics still valid
|
|
signature fields still valid
|
|
approved snapshot parity still pass for newly generated artifact
|
|
```
|
|
|
|
Special check:
|
|
|
|
```txt
|
|
tel_label
|
|
email_label
|
|
att_label
|
|
project_label
|
|
site_label
|
|
```
|
|
|
|
must be non-empty.
|
|
|
|
---
|
|
|
|
# Scope H5.3.7 Seed / Migration Strategy
|
|
|
|
Update:
|
|
|
|
```txt
|
|
src/db/seeds/foundation.seed.ts
|
|
```
|
|
|
|
or create a dedicated script:
|
|
|
|
```txt
|
|
scripts/reseed-pdf-template-version.ts
|
|
```
|
|
|
|
Recommended:
|
|
|
|
Use dedicated script for remap:
|
|
|
|
```txt
|
|
npm run seed:pdf-template-version
|
|
```
|
|
|
|
because template version remap is operationally different from foundation seed.
|
|
|
|
Rules:
|
|
|
|
* no hardcoded organizationId
|
|
* handles every organization
|
|
* handles ALLA / ONVALLA branch template
|
|
* idempotent per template version
|
|
* no duplicate active versions
|
|
|
|
---
|
|
|
|
# Scope H5.3.8 Approved Snapshot Rule
|
|
|
|
Existing approved artifacts:
|
|
|
|
* keep using old template version
|
|
* do not regenerate automatically
|
|
* do not update old snapshot mapping
|
|
|
|
New approved artifacts:
|
|
|
|
* use new active template version
|
|
* use new mappings
|
|
* pass parity audit
|
|
|
|
---
|
|
|
|
# Scope H5.3.9 Verification
|
|
|
|
Run:
|
|
|
|
```txt
|
|
npm run seed:pdf-template-version
|
|
npm run audit:pdf
|
|
```
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
Overall Status: PASS
|
|
Template Version: PASS
|
|
Placeholder Integrity: PASS
|
|
Payload Parity: PASS
|
|
Topic Runtime: PASS
|
|
Approved Snapshot Parity: PASS
|
|
Price Table: PASS
|
|
Static Labels: PASS
|
|
```
|
|
|
|
Visual check:
|
|
|
|
```txt
|
|
Tel : 02-000-1000
|
|
Email : demo-customer@local.test
|
|
Att : Task H.1 Contact
|
|
Project : Task H.5 Audit Fixture
|
|
Location : Bangkok HQ
|
|
```
|
|
|
|
---
|
|
|
|
# Scope H5.3.10 Documentation
|
|
|
|
Update:
|
|
|
|
```txt
|
|
docs/business/pdf-mapping-registry.md
|
|
docs/business/pdf-placeholder-registry.md
|
|
docs/implementation/task-h5-pdf-mapping-audit-visual-parity.md
|
|
docs/implementation/technical-debt.md
|
|
```
|
|
|
|
Add:
|
|
|
|
```txt
|
|
Template version remap process
|
|
Static label mapping strategy
|
|
Deleted field handling
|
|
Dynamic topic reserved fields
|
|
Approved snapshot immutability rule
|
|
```
|
|
|
|
---
|
|
|
|
# Explicit Non-Scope
|
|
|
|
Do NOT implement:
|
|
|
|
```txt
|
|
visual template designer
|
|
signature image / draw signature
|
|
digital signature
|
|
currency exchange calculation
|
|
report center
|
|
permission center
|
|
```
|
|
|
|
---
|
|
|
|
# Output
|
|
|
|
After completion, summarize:
|
|
|
|
1. Files Added
|
|
2. Files Modified
|
|
3. New Template Version Created
|
|
4. Deleted Fields Detected
|
|
5. New Field Inventory
|
|
6. Mappings Rebuilt
|
|
7. Static Labels Fixed
|
|
8. Audit Result
|
|
9. Remaining Risks
|
|
|
|
---
|
|
|
|
# Definition of Done
|
|
|
|
Task H.5.3 passes when:
|
|
|
|
* new template version is created
|
|
* old template version is retained
|
|
* old mappings are not blindly copied
|
|
* deleted fields do not remain as active mappings
|
|
* new fields are mapped or classified
|
|
* `tel_label` renders
|
|
* `email_label` renders
|
|
* `att_label` renders
|
|
* `project_label` renders
|
|
* `site_label` renders
|
|
* price table still renders
|
|
* dynamic topics still render
|
|
* signatures still render
|
|
* approved snapshot parity passes for newly generated approved PDF
|
|
* `npm run audit:pdf` returns Overall Status PASS
|