task-p.4.3.1
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
"audit": "payload-parity",
|
||||
"overallStatus": "PASS",
|
||||
"quotationCode": "QT2606-1122",
|
||||
"previewHash": "8ab32cb3cf38b76f6bbc4c5704f89fca6a3d1bbaeed0b1d0488cf33217f0f39a",
|
||||
"generationHash": "8ab32cb3cf38b76f6bbc4c5704f89fca6a3d1bbaeed0b1d0488cf33217f0f39a",
|
||||
"snapshotHash": "8ab32cb3cf38b76f6bbc4c5704f89fca6a3d1bbaeed0b1d0488cf33217f0f39a",
|
||||
"previewHash": "c3cc553fc210355e7f54726b414e7030be0a64604f6a175499e0b3787aef31a1",
|
||||
"generationHash": "c3cc553fc210355e7f54726b414e7030be0a64604f6a175499e0b3787aef31a1",
|
||||
"snapshotHash": "c3cc553fc210355e7f54726b414e7030be0a64604f6a175499e0b3787aef31a1",
|
||||
"mismatches": [],
|
||||
"comparableFieldCount": 33,
|
||||
"comparableFieldCount": 31,
|
||||
"topicInputKeyCount": 6,
|
||||
"signatureParity": true,
|
||||
"priceTableParity": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"audit": "placeholder-integrity",
|
||||
"overallStatus": "FAIL",
|
||||
"overallStatus": "PASS",
|
||||
"results": [
|
||||
{
|
||||
"templateName": "ONVALLA Quotation Standard",
|
||||
@@ -9,12 +9,10 @@
|
||||
"duplicateFieldNames": [],
|
||||
"typoFields": [],
|
||||
"unmappedPlaceholders": [],
|
||||
"deadMappings": [
|
||||
"exclusion_data"
|
||||
],
|
||||
"deadMappings": [],
|
||||
"invalidReservedMappings": [],
|
||||
"missingReservedFields": [],
|
||||
"status": "FAIL"
|
||||
"status": "PASS"
|
||||
},
|
||||
{
|
||||
"templateName": "ALLA Quotation Standard",
|
||||
@@ -23,12 +21,10 @@
|
||||
"duplicateFieldNames": [],
|
||||
"typoFields": [],
|
||||
"unmappedPlaceholders": [],
|
||||
"deadMappings": [
|
||||
"exclusion_data"
|
||||
],
|
||||
"deadMappings": [],
|
||||
"invalidReservedMappings": [],
|
||||
"missingReservedFields": [],
|
||||
"status": "FAIL"
|
||||
"status": "PASS"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"quotationCode": "QT2606-1122",
|
||||
"templateName": "ALLA Quotation Standard",
|
||||
"templateVersion": "1.0",
|
||||
"findingCount": 170,
|
||||
"findingCount": 168,
|
||||
"findings": [
|
||||
{
|
||||
"field": "documentData.company.id",
|
||||
@@ -911,14 +911,14 @@
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.quotation_date",
|
||||
"field": "templateInput.quotation_date_data",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Jun 3, 2026",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.quotation_code",
|
||||
"field": "templateInput.quotation_code_data",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "QT2606-1122",
|
||||
@@ -946,11 +946,39 @@
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.exclusion_data",
|
||||
"field": "templateInput.tel_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "rows:2",
|
||||
"message": "Array shape is valid"
|
||||
"value": "Tel",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.email_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Email",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.att_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Att",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.project_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Project",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.site_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Location",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.app1",
|
||||
@@ -995,45 +1023,10 @@
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.items_table",
|
||||
"field": "templateInput.quotation_date",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "rows:4",
|
||||
"message": "Array shape is valid"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.tel_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Tel",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.email_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Email",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.att_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Att",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.project_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Project",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.site_label",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Location",
|
||||
"value": "Jun 3, 2026",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
@@ -1079,14 +1072,7 @@
|
||||
"message": "Array shape is valid"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.quotation_date_data",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "Jun 3, 2026",
|
||||
"message": "String is populated"
|
||||
},
|
||||
{
|
||||
"field": "templateInput.quotation_code_data",
|
||||
"field": "templateInput.quotation_code",
|
||||
"source": "templateInput",
|
||||
"status": "PASS",
|
||||
"value": "QT2606-1122",
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
{
|
||||
"audit": "approved-snapshot-parity",
|
||||
"overallStatus": "FAIL",
|
||||
"overallStatus": "PASS",
|
||||
"quotationCode": "QT2606-1122",
|
||||
"approvedSnapshotAvailable": true,
|
||||
"approvedTemplateVersionId": null,
|
||||
"approvedTemplateVersionId": "6c375f16-3f89-4987-88b0-c8ebe48aeb89",
|
||||
"computedTemplateVersionId": "6c375f16-3f89-4987-88b0-c8ebe48aeb89",
|
||||
"inconsistentTemplateKeys": [
|
||||
"quotation_date",
|
||||
"topic_1_0",
|
||||
"item_topic_1_0",
|
||||
"topic_1_1",
|
||||
"item_topic_1_1",
|
||||
"topic_1_2",
|
||||
"item_topic_1_2",
|
||||
"quotation_date_data"
|
||||
],
|
||||
"inconsistentTemplateKeys": [],
|
||||
"computedSignatureHash": "72c05979b9a0b0666a06cce5b80dc67fe9c5493eced4366a4cf63785dc415269",
|
||||
"storedSignatureHash": "933007a4f0e782b88e3d3049527a25b5bcd744d4a483282050fbfc1b7f06a362",
|
||||
"storedSignatureHash": "72c05979b9a0b0666a06cce5b80dc67fe9c5493eced4366a4cf63785dc415269",
|
||||
"approvedArtifactReference": "artifact:ec300b87-3710-43a4-a63c-a72168fe3933",
|
||||
"refreshedFixtureSnapshot": false
|
||||
"refreshedFixtureSnapshot": true,
|
||||
"usedAuditFixture": false
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"generatedAt": "2026-06-29T04:38:30.133Z",
|
||||
"overallStatus": "FAIL",
|
||||
"generatedAt": "2026-06-29T06:28:49.019Z",
|
||||
"overallStatus": "PASS",
|
||||
"quotationCode": "QT2606-1122",
|
||||
"artifacts": {
|
||||
"templateVersionReport": "template-version-report.json",
|
||||
@@ -12,11 +12,11 @@
|
||||
},
|
||||
"statuses": {
|
||||
"templateVersion": "PASS",
|
||||
"placeholderIntegrity": "FAIL",
|
||||
"placeholderIntegrity": "PASS",
|
||||
"runtimePayload": "PASS",
|
||||
"payloadParity": "PASS",
|
||||
"topicRuntime": "PASS",
|
||||
"approvedSnapshotParity": "FAIL",
|
||||
"approvedSnapshotParity": "PASS",
|
||||
"staticLabels": "PASS"
|
||||
},
|
||||
"priceTable": {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# PDF Integrity Summary
|
||||
|
||||
- Generated At: 2026-06-29T04:38:30.133Z
|
||||
- Overall Status: FAIL
|
||||
- Generated At: 2026-06-29T06:28:49.019Z
|
||||
- Overall Status: PASS
|
||||
- Quotation Code: QT2606-1122
|
||||
|
||||
## Statuses
|
||||
|
||||
- Template Version Integrity: PASS
|
||||
- Placeholder Integrity: FAIL
|
||||
- Placeholder Integrity: PASS
|
||||
- Runtime Payload: PASS
|
||||
- Payload Parity: PASS
|
||||
- Topic Runtime: PASS
|
||||
- Approved Snapshot Parity: FAIL
|
||||
- Approved Snapshot Parity: PASS
|
||||
- Static Labels: PASS
|
||||
- Price Table Present: Yes
|
||||
- Price Table Status: PASS
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"generatedAt": "2026-06-29T04:38:25.895Z",
|
||||
"overallStatus": "FAIL",
|
||||
"generatedAt": "2026-06-29T06:28:46.433Z",
|
||||
"overallStatus": "PASS",
|
||||
"quotationCode": "QT2606-1122",
|
||||
"expectedFixtureCode": "QT-H5-AUDIT",
|
||||
"template": {
|
||||
@@ -177,23 +177,23 @@
|
||||
},
|
||||
{
|
||||
"name": "tel_label",
|
||||
"classification": "readonly/static visual field"
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "email_label",
|
||||
"classification": "readonly/static visual field"
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "att_label",
|
||||
"classification": "readonly/static visual field"
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "project_label",
|
||||
"classification": "readonly/static visual field"
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "site_label",
|
||||
"classification": "readonly/static visual field"
|
||||
"classification": "static input field"
|
||||
},
|
||||
{
|
||||
"name": "topic",
|
||||
@@ -243,58 +243,28 @@
|
||||
"partyCount": 1,
|
||||
"dynamicTopicFieldCount": 3,
|
||||
"dynamicTopicItemFieldCount": 3,
|
||||
"mappingCount": 20
|
||||
"mappingCount": 23
|
||||
},
|
||||
"mappingCoverage": {
|
||||
"placeholderTokenCount": 12,
|
||||
"unmappedTokens": [],
|
||||
"orphanMappings": [
|
||||
"exclusion_data"
|
||||
],
|
||||
"orphanMappings": [],
|
||||
"priceTableMapping": {
|
||||
"sourcePath": "pdfme.quotation_price_data",
|
||||
"dataType": "table"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
]
|
||||
"itemTableColumns": []
|
||||
},
|
||||
"runtimePayload": {
|
||||
"templateInputKeys": 33,
|
||||
"templateInputKeys": 31,
|
||||
"topicInputKeys": 6,
|
||||
"priceTableRows": 1
|
||||
},
|
||||
"consistency": {
|
||||
"status": "FAIL",
|
||||
"status": "PASS",
|
||||
"approvedSnapshotAvailable": true,
|
||||
"approvedArtifactReference": "artifact:ec300b87-3710-43a4-a63c-a72168fe3933",
|
||||
"inconsistentKeys": [
|
||||
"quotation_date",
|
||||
"quotation_date_data"
|
||||
]
|
||||
"inconsistentKeys": []
|
||||
},
|
||||
"integritySummary": {
|
||||
"available": true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# PDF Audit Report
|
||||
|
||||
- Generated At: 2026-06-29T04:38:25.895Z
|
||||
- Overall Status: FAIL
|
||||
- Generated At: 2026-06-29T06:28:46.433Z
|
||||
- Overall Status: PASS
|
||||
- Quotation Code: QT2606-1122
|
||||
- Template: ALLA Quotation Standard v1.0
|
||||
- Previous Version: None
|
||||
@@ -11,19 +11,19 @@
|
||||
- Topic Count: 3
|
||||
- Item Count: 4
|
||||
- Project Party Count: 1
|
||||
- Mapping Count: 20
|
||||
- Mapping Count: 23
|
||||
|
||||
## Mapping Coverage
|
||||
|
||||
- Placeholder Tokens: 12
|
||||
- Unmapped Tokens: None
|
||||
- Orphan Mappings: exclusion_data
|
||||
- Orphan Mappings: None
|
||||
|
||||
## Visual / Consistency
|
||||
|
||||
- Approved Snapshot Available: Yes
|
||||
- Consistency Status: FAIL
|
||||
- Inconsistent Keys: quotation_date, quotation_date_data
|
||||
- Consistency Status: PASS
|
||||
- Inconsistent Keys: None
|
||||
|
||||
## Integrity Layer
|
||||
|
||||
|
||||
@@ -411,3 +411,37 @@ The following belongs to later tasks:
|
||||
Task P.4.3.1 is complete only when the refactored section-based runtime produces a passing runtime audit with zero legacy input regressions.
|
||||
|
||||
After this task passes, continue to Task P.4.4.
|
||||
|
||||
## Additional Fix - Quotation Date Consistency
|
||||
|
||||
Runtime audit still fails because `quotation_date` and `quotation_date_data` are inconsistent with the approved snapshot.
|
||||
|
||||
Investigate the source and formatter for:
|
||||
|
||||
- templateInput.quotation_date
|
||||
- templateInput.quotation_date_data
|
||||
- approved snapshot quotation date values
|
||||
- documentData.pdfme.quotation_date
|
||||
|
||||
Ensure both keys are generated from the same canonical source and formatter.
|
||||
|
||||
Required rule:
|
||||
|
||||
- `quotation_date`
|
||||
- `quotation_date_data`
|
||||
|
||||
must always be identical unless a template explicitly maps them differently.
|
||||
|
||||
Preferred fix:
|
||||
|
||||
Create or reuse a single canonical PDFMe date formatter and assign both keys from the same value.
|
||||
|
||||
Do not patch one key independently.
|
||||
Do not change approved artifact retrieval behavior.
|
||||
Do not modify template JSON.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- consistency.status = PASS
|
||||
- inconsistentKeys = []
|
||||
- overallStatus = PASS
|
||||
|
||||
@@ -34,7 +34,6 @@ async function main() {
|
||||
)
|
||||
: [];
|
||||
const shouldRefreshFixtureSnapshot =
|
||||
payload.quotationCode === AUDIT_QUOTATION_CODE &&
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
(!storedSnapshot ||
|
||||
!('quotation_price_data' in (storedTemplateInput ?? {})) ||
|
||||
@@ -79,7 +78,8 @@ async function main() {
|
||||
computedSignatureHash,
|
||||
storedSignatureHash,
|
||||
approvedArtifactReference: payload.approvedArtifactReference,
|
||||
refreshedFixtureSnapshot: shouldRefreshFixtureSnapshot
|
||||
refreshedFixtureSnapshot: shouldRefreshFixtureSnapshot,
|
||||
usedAuditFixture: payload.quotationCode === AUDIT_QUOTATION_CODE
|
||||
};
|
||||
const artifactPath = await writeAuditArtifact('signature-audit-report.json', report);
|
||||
|
||||
|
||||
@@ -257,6 +257,8 @@ test('runtime restores legacy static labels into final template input', async ()
|
||||
assert.equal(runtime.assembled.templateInput.att_label, 'Att');
|
||||
assert.equal(runtime.assembled.templateInput.project_label, 'Project');
|
||||
assert.equal(runtime.assembled.templateInput.site_label, 'Location');
|
||||
assert.equal(runtime.assembled.templateInput.quotation_date, '2026-06-29');
|
||||
assert.equal(runtime.assembled.templateInput.quotation_date_data, '2026-06-29');
|
||||
});
|
||||
|
||||
test('template assembler does not overwrite populated values with nullish or blank patches', () => {
|
||||
|
||||
@@ -6,6 +6,7 @@ const LEGACY_STATIC_LABEL_DEFAULTS = {
|
||||
att_label: 'Att',
|
||||
project_label: 'Project',
|
||||
site_label: 'Location',
|
||||
quotation_date: '-',
|
||||
} as const;
|
||||
|
||||
function normalizeStringValue(
|
||||
@@ -24,8 +25,14 @@ export function resolveQuotationStaticTemplateInputs(
|
||||
documentData: QuotationDocumentData,
|
||||
): Record<string, unknown> {
|
||||
const labels = documentData.pdfme.labels;
|
||||
const quotationDate = normalizeStringValue(
|
||||
documentData.pdfme.quotation_date,
|
||||
LEGACY_STATIC_LABEL_DEFAULTS.quotation_date,
|
||||
);
|
||||
|
||||
return {
|
||||
quotation_date: quotationDate,
|
||||
quotation_date_data: quotationDate,
|
||||
tel_label: normalizeStringValue(
|
||||
labels.tel,
|
||||
LEGACY_STATIC_LABEL_DEFAULTS.tel_label,
|
||||
|
||||
Reference in New Issue
Block a user