task-h.5.3
This commit is contained in:
@@ -1,16 +1,198 @@
|
||||
{
|
||||
"generatedAt": "2026-06-19T07:44:58.283Z",
|
||||
"overallStatus": "WARNING",
|
||||
"generatedAt": "2026-06-19T10:12:54.188Z",
|
||||
"overallStatus": "PASS",
|
||||
"quotationCode": "QT-H5-AUDIT",
|
||||
"expectedFixtureCode": "QT-H5-AUDIT",
|
||||
"template": {
|
||||
"templateName": "ALLA Quotation Standard",
|
||||
"version": "1.0",
|
||||
"versionId": "4ac3e91c-8320-4f41-81cd-5068cc9b5768",
|
||||
"fieldCount": 46,
|
||||
"version": "1.1",
|
||||
"versionId": "bd6713d5-a731-482f-a5bb-0dea9d766301",
|
||||
"fieldCount": 44,
|
||||
"previousVersion": "1.0",
|
||||
"deletedFields": [
|
||||
"exclusion_data",
|
||||
"exclusion_label"
|
||||
],
|
||||
"newFields": [],
|
||||
"duplicateFields": [],
|
||||
"unknownFields": [
|
||||
"line"
|
||||
"unknownFields": [],
|
||||
"classifications": [
|
||||
{
|
||||
"name": "company1",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company2",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company_addr1",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company_addr2",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company_tel",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company_email",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "company_tax",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "line",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "customer_name",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "customer_addr",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "customer_tel",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "customer_email",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "dear_sirs",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "quotation_price_data",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "quotation_date_labe",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "quotation_date_data",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "quotation_code_lable",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "quotation_code_data",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "customer_att",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "project_name",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "site_location",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "colon",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon copy",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_tel",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_fax",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_email",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_att",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_project",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "colon_site",
|
||||
"classification": "readonly/static visual field"
|
||||
},
|
||||
{
|
||||
"name": "tel_label",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "email_label",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "att_label",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "project_label",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "site_label",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "topic",
|
||||
"classification": "dynamic topic template"
|
||||
},
|
||||
{
|
||||
"name": "data_topic",
|
||||
"classification": "dynamic topic template"
|
||||
},
|
||||
{
|
||||
"name": "Please_do_not",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "yours_faithfuly",
|
||||
"classification": "system field"
|
||||
},
|
||||
{
|
||||
"name": "app1",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "app1_position",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "app2_position",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "app3",
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "app3_position",
|
||||
"classification": "static input field"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
@@ -19,47 +201,27 @@
|
||||
"partyCount": 3,
|
||||
"dynamicTopicFieldCount": 5,
|
||||
"dynamicTopicItemFieldCount": 5,
|
||||
"mappingCount": 19
|
||||
"mappingCount": 23
|
||||
},
|
||||
"mappingCoverage": {
|
||||
"placeholderTokenCount": 13,
|
||||
"placeholderTokenCount": 12,
|
||||
"unmappedTokens": [],
|
||||
"orphanMappings": [],
|
||||
"itemTableColumns": [
|
||||
{
|
||||
"columnName": "Item",
|
||||
"sourceField": "itemNumber"
|
||||
},
|
||||
{
|
||||
"columnName": "Description",
|
||||
"sourceField": "description"
|
||||
},
|
||||
{
|
||||
"columnName": "Qty",
|
||||
"sourceField": "quantity"
|
||||
},
|
||||
{
|
||||
"columnName": "Unit",
|
||||
"sourceField": "unitLabel"
|
||||
},
|
||||
{
|
||||
"columnName": "Unit Price",
|
||||
"sourceField": "unitPrice"
|
||||
},
|
||||
{
|
||||
"columnName": "Total",
|
||||
"sourceField": "totalPrice"
|
||||
}
|
||||
]
|
||||
"priceTableMapping": {
|
||||
"sourcePath": "pdfme.quotation_price_data",
|
||||
"dataType": "table"
|
||||
},
|
||||
"itemTableColumns": []
|
||||
},
|
||||
"runtimePayload": {
|
||||
"templateInputKeys": 31,
|
||||
"topicInputKeys": 10
|
||||
"templateInputKeys": 35,
|
||||
"topicInputKeys": 10,
|
||||
"priceTableRows": 1
|
||||
},
|
||||
"consistency": {
|
||||
"status": "WARNING",
|
||||
"approvedSnapshotAvailable": false,
|
||||
"approvedArtifactReference": null,
|
||||
"status": "PASS",
|
||||
"approvedSnapshotAvailable": true,
|
||||
"approvedArtifactReference": "artifact:a1fd951d-f0b4-4e5b-be88-073596b3829d",
|
||||
"inconsistentKeys": []
|
||||
},
|
||||
"integritySummary": {
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
# PDF Audit Report
|
||||
|
||||
- Generated At: 2026-06-19T07:44:58.283Z
|
||||
- Overall Status: WARNING
|
||||
- Generated At: 2026-06-19T10:12:54.188Z
|
||||
- Overall Status: PASS
|
||||
- Quotation Code: QT-H5-AUDIT
|
||||
- Template: ALLA Quotation Standard v1.0
|
||||
- Template: ALLA Quotation Standard v1.1
|
||||
- Previous Version: 1.0
|
||||
|
||||
## Metrics
|
||||
|
||||
- Topic Count: 5
|
||||
- Item Count: 3
|
||||
- Project Party Count: 3
|
||||
- Mapping Count: 19
|
||||
- Mapping Count: 23
|
||||
|
||||
## Mapping Coverage
|
||||
|
||||
- Placeholder Tokens: 13
|
||||
- Placeholder Tokens: 12
|
||||
- Unmapped Tokens: None
|
||||
- Orphan Mappings: None
|
||||
|
||||
## Visual / Consistency
|
||||
|
||||
- Approved Snapshot Available: No
|
||||
- Consistency Status: WARNING
|
||||
- Approved Snapshot Available: Yes
|
||||
- Consistency Status: PASS
|
||||
- Inconsistent Keys: None
|
||||
|
||||
## Integrity Layer
|
||||
|
||||
@@ -34,3 +34,9 @@
|
||||
- approved snapshot parity remains a warning when the target quotation has never generated an approved PDF artifact
|
||||
- the audit suite validates business payload parity, not pixel-perfect PDF screenshots
|
||||
- manual review is still needed when template designers move static labels or brand blocks
|
||||
|
||||
## H.5.3 Follow-up
|
||||
|
||||
- template JSON revisions now flow through a dedicated version-remap step instead of patching `1.0` in place
|
||||
- static labels such as `tel_label`, `email_label`, `att_label`, `project_label`, and `site_label` are now runtime-mapped rather than tolerated as blank designer placeholders
|
||||
- deleted fields from the previous version, notably `exclusion_data` and `exclusion_label`, are explicitly classified and removed from the active mapping set
|
||||
|
||||
@@ -38,3 +38,14 @@
|
||||
- stored approved snapshot parity still depends on generating a real approved PDF artifact for `QT-H5-AUDIT`
|
||||
- template field `line` is still treated as a tolerated designer-owned oddity rather than a normalized mapping field
|
||||
- the audit stack validates payload integrity and runtime parity, not screenshot-level pixel parity
|
||||
|
||||
## Follow-on Freeze Note
|
||||
|
||||
- `quotation_price_data` is now treated as the canonical PDFME table field for quotation price rendering
|
||||
- `quotation_price` and `currency` remain supported only as scalar compatibility fields
|
||||
|
||||
## H.5.3 Versioning Note
|
||||
|
||||
- integrity checks now accept retained inactive template versions as valid historical references for approved snapshots
|
||||
- the active-version audit also verifies that the active DB schema matches the latest JSON source file for each organization template
|
||||
- runtime payload integrity now includes explicit static-label checks so blank `tel_label`/`email_label`/`att_label`/`project_label`/`site_label` values fail the suite
|
||||
|
||||
33
docs/implementation/task-h53-pdf-template-version-remap.md
Normal file
33
docs/implementation/task-h53-pdf-template-version-remap.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Task H.5.3: PDF Template Version Remap + Static Labels
|
||||
|
||||
## Outcome
|
||||
|
||||
- created active `1.1` quotation PDF template versions for both `ALLA` and `ONVALLA`
|
||||
- retained historical `1.0` versions as inactive records
|
||||
- rebuilt active mappings from the current template inventory instead of copying the old version wholesale
|
||||
- restored runtime values for `tel_label`, `email_label`, `att_label`, `project_label`, and `site_label`
|
||||
|
||||
## Field Inventory Result
|
||||
|
||||
- deleted from previous version: `exclusion_data`, `exclusion_label`
|
||||
- new active templates keep dynamic topic bases `topic` and `data_topic`
|
||||
- designer-owned static visuals such as `line`, `quotation_date_labe`, and `quotation_code_lable` remain classified but unmapped
|
||||
- compatibility tokens `quotation_price` and `currency` remain mapped because the active price table still embeds those placeholders
|
||||
|
||||
## Seed / Remap Flow
|
||||
|
||||
- `npm run seed:pdf-template-version` reads the latest JSON from `src/pdfme_template/*.json`
|
||||
- if the schema already exists in DB, it re-activates and reconciles mappings idempotently
|
||||
- if the schema is new, it creates the next minor version, activates it, and deactivates the previous active version
|
||||
- mappings are rebuilt only for fields or tokens still present in that target version
|
||||
|
||||
## Verification
|
||||
|
||||
- `npx tsc --noEmit` passed
|
||||
- `npm run seed:pdf-template-version` passed
|
||||
- `npm run audit:pdf` passed with overall status `PASS`
|
||||
|
||||
## Remaining Risks
|
||||
|
||||
- active templates still rely on compatibility tokens `quotation_price` and `currency` inside the table content; those should be removed only in a future controlled template revision
|
||||
- the audit fixture now points to active `1.1`; production-approved historical quotations still need operator discipline so their stored template version is never rewritten manually
|
||||
@@ -207,13 +207,28 @@ Current:
|
||||
|
||||
- payment, warranty, delivery, and extra topic sections now flow through the dynamic `topic` / `data_topic` engine on page 2 instead of fixed placeholder fields
|
||||
- approval signature placeholders now resolve through the H.3 signature strategy and `crm_job_title` position lookup
|
||||
- `quotation_price_data` is now the canonical runtime table input for the price row, while active template JSON still embeds nested `{quotation_price}` and `{currency}` cells inside that table field
|
||||
|
||||
Future:
|
||||
|
||||
- keep validating pagination and closing-block placement against production designer expectations for large topic sets
|
||||
- add fixture-backed end-to-end PDF generation verification in CI once a stable runtime path is available
|
||||
- remove nested price-table placeholders in a controlled template revision once design change windows allow it
|
||||
- decide whether static template field `line` should remain a tolerated designer-only artifact or be normalized in future audits
|
||||
|
||||
### Template version remap operations
|
||||
|
||||
Current:
|
||||
|
||||
- template version remap is now handled by `npm run seed:pdf-template-version`, not by the base foundation seed
|
||||
- active `1.1` mappings intentionally preserve historical `1.0` versions for snapshot integrity
|
||||
|
||||
Future:
|
||||
|
||||
- decide whether template version promotion needs an operator-facing review/approve workflow
|
||||
- add artifacting or changelog snapshots for template-schema diffs before activation
|
||||
- decide whether the remap command should write a persistent audit history table instead of JSON-only artifacts
|
||||
|
||||
## After Task I
|
||||
|
||||
### Storage provider production rollout
|
||||
|
||||
Reference in New Issue
Block a user