taks-p.4.3
This commit is contained in:
457
plans/task-p.4.1-verification-report.md
Normal file
457
plans/task-p.4.1-verification-report.md
Normal file
@@ -0,0 +1,457 @@
|
||||
# Task P.4.1 Verification Report
|
||||
|
||||
## Scope
|
||||
|
||||
This report completes the runtime verification requested by [task-p.4.1.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/plans/task-p.4.1.md).
|
||||
|
||||
No production template files were modified.
|
||||
No new rendering pipeline was created.
|
||||
No implementation for Task P.4 has started yet.
|
||||
|
||||
---
|
||||
|
||||
## 1. Verified Runtime Findings
|
||||
|
||||
### 1.1 Current quotation PDF runtime chain
|
||||
|
||||
The current quotation document routes do not use separate template pipelines.
|
||||
|
||||
Verified route chain:
|
||||
|
||||
- `document-data` calls `buildQuotationDocumentData`
|
||||
- [src/app/api/crm/quotations/[id]/document-data/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/quotations/[id]/document-data/route.ts:39)
|
||||
- `document-preview` calls `getQuotationDocumentPreviewData`
|
||||
- [src/app/api/crm/quotations/[id]/document-preview/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/quotations/[id]/document-preview/route.ts:39)
|
||||
- `pdf-preview` calls `generateQuotationPreviewPdf`
|
||||
- [src/app/api/crm/quotations/[id]/pdf-preview/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/quotations/[id]/pdf-preview/route.ts:39)
|
||||
- `pdf-download` calls `generateQuotationPdf`
|
||||
- [src/app/api/crm/quotations/[id]/pdf-download/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/quotations/[id]/pdf-download/route.ts:39)
|
||||
- `approved-pdf` reads stored artifact first and falls back to generation path when needed
|
||||
- [src/app/api/crm/quotations/[id]/approved-pdf/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/quotations/[id]/approved-pdf/route.ts:44)
|
||||
|
||||
Verified shared pipeline:
|
||||
|
||||
- `generateQuotationPdf()` calls `getQuotationDocumentPreviewData()`
|
||||
- [src/features/foundation/pdf-generator/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:304)
|
||||
- `generateQuotationPreviewPdf()` simply delegates to `generateQuotationPdf()`
|
||||
- [src/features/foundation/pdf-generator/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:317)
|
||||
- `generateApprovedQuotationPdf()` also calls `getQuotationDocumentPreviewData()`
|
||||
- [src/features/foundation/pdf-generator/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:326)
|
||||
|
||||
Verified preview builder chain:
|
||||
|
||||
- `getQuotationDocumentPreviewData()` builds `documentData`
|
||||
- resolves active template and active version
|
||||
- resolves version mappings
|
||||
- maps `documentData` to `templateInput`
|
||||
- applies topic page expansion
|
||||
|
||||
Reference:
|
||||
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:661)
|
||||
|
||||
### 1.2 Same active template/version/mapping pipeline
|
||||
|
||||
Confirmed: `document-preview`, `pdf-preview`, `pdf-download`, and approved PDF generation all depend on the same active template/version/mapping pipeline.
|
||||
|
||||
Shared resolution calls:
|
||||
|
||||
- `resolveTemplateForDocument()`
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:669)
|
||||
- `resolveTemplateMappings()`
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:674)
|
||||
- `mapDocumentDataToTemplateInput()`
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:688)
|
||||
|
||||
Conclusion:
|
||||
|
||||
- there is one active runtime pipeline for quotation PDF generation
|
||||
- there is no separate preview-only template source
|
||||
- there is no separate download-only template source
|
||||
- approved PDF generation reuses the same active version before persistence
|
||||
|
||||
---
|
||||
|
||||
## 2. Active Template Runtime Source Verification
|
||||
|
||||
### 2.1 Database active versions
|
||||
|
||||
Verified against live database:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"organizationName": "ALLA",
|
||||
"templateName": "ALLA Quotation Standard",
|
||||
"version": "1.0",
|
||||
"filePath": "src/pdfme_template/ALLA_template_pdfme_fainal3.json",
|
||||
"mappingCount": "20"
|
||||
},
|
||||
{
|
||||
"organizationName": "ONVALLA",
|
||||
"templateName": "ONVALLA Quotation Standard",
|
||||
"version": "1.0",
|
||||
"filePath": "src/pdfme_template/ONVALLA_template_pdfme_fainal3.json",
|
||||
"mappingCount": "20"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Interpretation:
|
||||
|
||||
- runtime selects active version rows from DB
|
||||
- each active version still keeps `filePath` pointing to the original JSON file source
|
||||
- mapping count is currently `20` for both active versions
|
||||
|
||||
### 2.2 DB schema vs file source
|
||||
|
||||
Verified that the active version `schema_json` in DB matches the JSON file on disk exactly for both organizations.
|
||||
|
||||
Evidence:
|
||||
|
||||
```json
|
||||
{
|
||||
"organization": "ALLA",
|
||||
"filePath": "src/pdfme_template/ALLA_template_pdfme_fainal3.json",
|
||||
"matches": true
|
||||
}
|
||||
{
|
||||
"organization": "ONVALLA",
|
||||
"filePath": "src/pdfme_template/ONVALLA_template_pdfme_fainal3.json",
|
||||
"matches": true
|
||||
}
|
||||
```
|
||||
|
||||
Conclusion:
|
||||
|
||||
- runtime renders from `schema_json` stored in DB
|
||||
- the current DB value is seeded from the JSON file and currently matches it
|
||||
- changing only the JSON file will not change runtime behavior unless DB version rows are reseeded or updated
|
||||
|
||||
### 2.3 Seed/runtime source conclusion
|
||||
|
||||
Runtime uses both, but with different roles:
|
||||
|
||||
- DB active template/version/mapping is the actual runtime source
|
||||
- JSON file is the seed/reseed source of truth for version payload creation
|
||||
|
||||
This means P.4 must update:
|
||||
|
||||
- new template JSON files
|
||||
- seed or reseed logic that publishes those JSON files into DB versions
|
||||
|
||||
Relevant current source selectors:
|
||||
|
||||
- [src/db/seeds/foundation.seed.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/seeds/foundation.seed.ts:854)
|
||||
- [scripts/pdf-audit-utils.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/scripts/pdf-audit-utils.ts:667)
|
||||
|
||||
---
|
||||
|
||||
## 3. Current Template Page Structure
|
||||
|
||||
### 3.1 Active page count
|
||||
|
||||
Verified from active DB runtime schema:
|
||||
|
||||
- `ALLA` active template version has `2` pages
|
||||
- `ONVALLA` active template version has `2` pages
|
||||
|
||||
### 3.2 Schema names per page
|
||||
|
||||
Verified runtime schema dump for `ALLA`:
|
||||
|
||||
```text
|
||||
PAGE 1 FIELDS:
|
||||
company1, company2, company_addr1, company_addr2, company_tel, company_email,
|
||||
company_tax, line, customer_name, customer_addr, customer_tel, customer_email,
|
||||
dear_sirs, quotation_price_data, quotation_date_labe, quotation_date_data,
|
||||
quotation_code_lable, quotation_code_data, customer_att, project_name,
|
||||
site_location, colon, colon copy, colon_tel, colon_fax, colon_email,
|
||||
colon_att, colon_project, colon_site, tel_label, email_label,
|
||||
att_label, project_label, site_label
|
||||
|
||||
PAGE 2 FIELDS:
|
||||
topic, data_topic, Please_do_not, yours_faithfuly,
|
||||
app1, app1_position, app2, app2_position, app3, app3_position
|
||||
```
|
||||
|
||||
Verified runtime schema dump for `ONVALLA`:
|
||||
|
||||
```text
|
||||
PAGE 1 FIELDS:
|
||||
company, company_addr1, company_addr2, company_tel, company_email,
|
||||
company_tax, line, customer_name, customer_addr, customer_tel, customer_email,
|
||||
dear_sirs, quotation_price_data, quotation_date_labe, quotation_date_data,
|
||||
quotation_code_lable, quotation_code_data, customer_att, project_name,
|
||||
site_location, colon, colon copy, colon_tel, colon_fax, colon_email,
|
||||
colon_att, colon_project, colon_site, tel_label, email_label,
|
||||
att_label, project_label, site_label
|
||||
|
||||
PAGE 2 FIELDS:
|
||||
topic, data_topic, Please_do_not, yours_faithfuly,
|
||||
app1, app1_position, app2, app2_position, app3, app3_position
|
||||
```
|
||||
|
||||
### 3.3 Topic/signature page index
|
||||
|
||||
Confirmed:
|
||||
|
||||
- topic/signature page is currently page index `1` in zero-based runtime terms
|
||||
- this matches the hardcoded topic engine default
|
||||
|
||||
Reference:
|
||||
|
||||
- [src/features/crm/quotations/document/server/pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:14)
|
||||
|
||||
This is the key verification that explains why inserting a new page in the middle will break the current engine if no runtime change is made first.
|
||||
|
||||
---
|
||||
|
||||
## 4. PDFMe Table Capability Verification
|
||||
|
||||
### 4.1 Verification method
|
||||
|
||||
Temporary verification was performed using:
|
||||
|
||||
- `@pdfme/generator`
|
||||
- `@pdfme/schemas` table plugin
|
||||
- `@pdfme/pdf-lib` for page counting
|
||||
|
||||
No production template was modified.
|
||||
|
||||
A temporary verification PDF was generated at:
|
||||
|
||||
- [rows_30_short.pdf](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/artifacts/task-p4-verification/rows_30_short.pdf)
|
||||
|
||||
### 4.2 Runtime source-code evidence for repeat header
|
||||
|
||||
The installed table plugin contains explicit repeat-header logic:
|
||||
|
||||
```text
|
||||
node_modules/@pdfme/schemas/dist/dynamicTemplate-CXBCt5wk.js:488
|
||||
schema.showHead = schema.showHead === false ? false : !schema.__isSplit || schema.repeatHead === true;
|
||||
|
||||
node_modules/@pdfme/schemas/dist/dynamicTemplate-CXBCt5wk.js:704
|
||||
if (!(schema.repeatHead && isBlankPdf(args.basePdf) && headerHeight > 0)) return baseHeights;
|
||||
```
|
||||
|
||||
Interpretation:
|
||||
|
||||
- `repeatHead` is a real runtime behavior in the installed table plugin
|
||||
- repeated header behavior is only applied when using blank/object-style `basePdf`
|
||||
- this matches the P.4 requirement and also matches the project’s current template style
|
||||
|
||||
### 4.3 Temporary generation results
|
||||
|
||||
Verified generation results:
|
||||
|
||||
```json
|
||||
{"label":"rows_5_short","rowCount":5,"pageCount":1,"pdfBytes":8869}
|
||||
{"label":"rows_30_short","rowCount":30,"pageCount":2,"pdfBytes":21737}
|
||||
{"label":"rows_100_short","rowCount":100,"pageCount":4,"pdfBytes":55297}
|
||||
{"label":"rows_30_long","rowCount":30,"pageCount":3,"pdfBytes":26739}
|
||||
```
|
||||
|
||||
Verified conclusions:
|
||||
|
||||
- `5 rows` fits on `1` page
|
||||
- `30 rows` breaks to `2` pages
|
||||
- `100 rows` breaks to `4` pages
|
||||
- `30` long-description rows consume `3` pages instead of `2`
|
||||
|
||||
### 4.4 Table behavior conclusions
|
||||
|
||||
Confirmed:
|
||||
|
||||
- auto page break works
|
||||
- multi-page table generation works
|
||||
- row height behavior changes pagination when descriptions become longer
|
||||
- repeat header is implemented in the installed runtime and tied to `repeatHead: true`
|
||||
|
||||
Important nuance:
|
||||
|
||||
- visual image-based confirmation was not performed because this environment does not have PDF raster/text inspection tools installed
|
||||
- however the runtime code path plus successful multi-page generation confirms the feature support exists in the actual installed library
|
||||
|
||||
---
|
||||
|
||||
## 5. Product Item Mapping Verification
|
||||
|
||||
### 5.1 Actual source fields found
|
||||
|
||||
Verified live DB columns for `crm_quotation_items`:
|
||||
|
||||
```text
|
||||
id
|
||||
organization_id
|
||||
quotation_id
|
||||
item_number
|
||||
product_type
|
||||
description
|
||||
quantity
|
||||
unit
|
||||
unit_price
|
||||
discount
|
||||
discount_type
|
||||
tax_rate
|
||||
total_price
|
||||
notes
|
||||
sort_order
|
||||
created_at
|
||||
updated_at
|
||||
deleted_at
|
||||
```
|
||||
|
||||
### 5.2 Actual document runtime fields exposed
|
||||
|
||||
Verified quotation document runtime exposes:
|
||||
|
||||
- `itemNumber`
|
||||
- `productTypeCode`
|
||||
- `productTypeLabel`
|
||||
- `description`
|
||||
- `quantity`
|
||||
- `unitCode`
|
||||
- `unitLabel`
|
||||
- `unitPrice`
|
||||
- `discount`
|
||||
- `discountTypeCode`
|
||||
- `taxRate`
|
||||
- `totalPrice`
|
||||
- `notes`
|
||||
|
||||
Reference:
|
||||
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:564)
|
||||
- [src/features/crm/quotations/document/types.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/types.ts:83)
|
||||
|
||||
### 5.3 Actual mapping coverage for `items_table`
|
||||
|
||||
Verified active mapping rows already include `items_table` for both organizations.
|
||||
|
||||
Current columns:
|
||||
|
||||
- `Item` → `itemNumber`
|
||||
- `Description` → `description`
|
||||
- `Qty` → `quantity`
|
||||
- `Unit` → `unitLabel`
|
||||
- `Unit Price` → `unitPrice`
|
||||
- `Total` → `totalPrice`
|
||||
|
||||
### 5.4 Gap analysis against Task P.4.1 required fields
|
||||
|
||||
| Required field | Verified source | Status |
|
||||
| --- | --- | --- |
|
||||
| product code | no dedicated field found | gap |
|
||||
| description | `description` | available |
|
||||
| specification | no dedicated field found | gap |
|
||||
| quantity | `quantity` | available |
|
||||
| unit | `unit` / `unitLabel` | available |
|
||||
| unit price | `unitPrice` | available |
|
||||
| discount | `discount` | available |
|
||||
| amount | `totalPrice` | available |
|
||||
| remark | closest existing field is `notes` | gap / mapping decision needed |
|
||||
|
||||
Conclusion:
|
||||
|
||||
- `product code` does not exist as a standalone quotation item field in the current model
|
||||
- `specification` does not exist as a standalone quotation item field in the current model
|
||||
- `remark` likely maps to `notes`, but this should be treated as a business decision, not assumed silently
|
||||
|
||||
---
|
||||
|
||||
## 6. Final Implementation Strategy
|
||||
|
||||
Recommended implementation order:
|
||||
|
||||
1. generalize topic/signature runtime targeting so it no longer depends on hardcoded page index `1`
|
||||
2. create new template JSON files
|
||||
- `ALLA_template_pdfme_product_v1.json`
|
||||
- `ONVALLA_template_pdfme_product_v1.json`
|
||||
3. place the Product Item page between customer detail and topic/signature pages
|
||||
4. configure the Product Item page with official PDFMe `table` schema using:
|
||||
- `showHead: true`
|
||||
- `repeatHead: true`
|
||||
- blank/object-style `basePdf`
|
||||
5. keep old versions untouched and inactive/active-switchable
|
||||
6. update reseed/audit source selectors so the new JSON files can be published into DB
|
||||
7. verify runtime behavior for both old and new versions through the existing routes
|
||||
|
||||
Important implementation constraint:
|
||||
|
||||
- because runtime currently renders from DB `schema_json`, adding only new JSON files is not sufficient
|
||||
- reseed or explicit version creation in template admin is required for runtime adoption
|
||||
|
||||
---
|
||||
|
||||
## 7. Rollback Plan
|
||||
|
||||
Recommended rollback:
|
||||
|
||||
1. do not delete the current active `1.0` versions
|
||||
2. publish the new Product Item design as a separate version only
|
||||
3. if regression occurs, deactivate the new version
|
||||
4. reactivate the current `1.0` version in `/dashboard/crm/settings/templates`
|
||||
5. if needed, revert reseed script changes independently from runtime code changes
|
||||
|
||||
Why rollback is low-risk:
|
||||
|
||||
- versioned template storage already exists
|
||||
- runtime resolves active version dynamically
|
||||
- current production version remains intact
|
||||
|
||||
---
|
||||
|
||||
## 8. Regression Test Matrix
|
||||
|
||||
### 8.1 Runtime routes
|
||||
|
||||
Verify for both `ALLA` and `ONVALLA`:
|
||||
|
||||
- `GET /api/crm/quotations/[id]/document-data`
|
||||
- `GET /api/crm/quotations/[id]/document-preview`
|
||||
- `GET /api/crm/quotations/[id]/pdf-preview`
|
||||
- `GET /api/crm/quotations/[id]/pdf-download`
|
||||
- approved PDF generation flow
|
||||
- approved PDF retrieval flow after artifact exists
|
||||
|
||||
### 8.2 Template versions
|
||||
|
||||
Verify both:
|
||||
|
||||
- old version `1.0`
|
||||
- new product-item version
|
||||
|
||||
### 8.3 Row-volume cases
|
||||
|
||||
Verify with quotation items around:
|
||||
|
||||
- 5 rows
|
||||
- 30 rows
|
||||
- 100 rows
|
||||
- long wrapped descriptions
|
||||
|
||||
### 8.4 Output expectations
|
||||
|
||||
Verify:
|
||||
|
||||
- old template still renders exactly as before
|
||||
- new template inserts Product Item page between page 1 and topic/signature page
|
||||
- topic/signature block still lands on the correct page
|
||||
- repeated table header appears when multiple product pages exist
|
||||
- long descriptions affect row height without layout corruption
|
||||
- preview and download use the same selected version
|
||||
- approved PDF persists the expected template version ID
|
||||
|
||||
---
|
||||
|
||||
## 9. Summary
|
||||
|
||||
Task P.4.1 verification confirms:
|
||||
|
||||
- quotation PDF runtime uses one shared active template/version/mapping pipeline
|
||||
- current active runtime template is still the 2-page `*_fainal3.json` structure
|
||||
- runtime source is DB `schema_json`, while JSON files remain the seed/reseed source
|
||||
- official PDFMe table support is sufficient for multi-page product item tables
|
||||
- current quotation item model is missing dedicated `product code` and `specification` fields
|
||||
- the biggest implementation blocker is still the topic engine’s hardcoded page targeting, not the table plugin itself
|
||||
Reference in New Issue
Block a user