taks-p.4.3
This commit is contained in:
582
plans/task-p.4-discovery-report.md
Normal file
582
plans/task-p.4-discovery-report.md
Normal file
@@ -0,0 +1,582 @@
|
||||
# Task P.4 Discovery Report
|
||||
|
||||
## Scope
|
||||
|
||||
This report documents the mandatory discovery phase for `task-p.4.md` before any implementation begins.
|
||||
|
||||
Task P.4 requires:
|
||||
|
||||
- introducing a dedicated Product Item page between the existing Customer Detail page and Condition + Signature page
|
||||
- using the existing CRM template management workflow
|
||||
- creating new template versions only
|
||||
- preserving backward compatibility for existing quotation template versions
|
||||
|
||||
No implementation has been performed at the time of writing this report.
|
||||
|
||||
---
|
||||
|
||||
## 1. Existing Architecture
|
||||
|
||||
### 1.1 CRM Template Module
|
||||
|
||||
The CRM template settings page is served by:
|
||||
|
||||
- [src/app/dashboard/crm/settings/templates/page.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/dashboard/crm/settings/templates/page.tsx:9)
|
||||
|
||||
This page:
|
||||
|
||||
- checks access with `crmDocumentTemplateRead`
|
||||
- prefetches quotation PDFMe templates via `documentTemplatesQueryOptions({ documentType: 'quotation', fileType: 'pdfme' })`
|
||||
- renders the admin UI through `TemplateSettings`
|
||||
|
||||
The main template admin UI lives in:
|
||||
|
||||
- [src/features/foundation/document-template/components/template-settings.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/components/template-settings.tsx:720)
|
||||
|
||||
This module already supports:
|
||||
|
||||
- template metadata CRUD
|
||||
- template version CRUD
|
||||
- raw `schemaJson` editing
|
||||
- mapping CRUD
|
||||
- version activation
|
||||
- template detail inspection
|
||||
|
||||
Important internal UI areas:
|
||||
|
||||
- template metadata dialog: [template-settings.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/components/template-settings.tsx:241)
|
||||
- version dialog: [template-settings.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/components/template-settings.tsx:292)
|
||||
- version JSON editing: [template-settings.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/components/template-settings.tsx:360)
|
||||
- template detail card and version tabs: [template-settings.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/components/template-settings.tsx:527)
|
||||
|
||||
### 1.2 Template APIs
|
||||
|
||||
Template/version/mapping APIs already exist and are reused by the CRM settings route group:
|
||||
|
||||
- [src/app/api/crm/document-templates/[id]/versions/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/document-templates/[id]/versions/route.ts:1)
|
||||
- [src/app/api/crm/settings/document-templates/versions/[id]/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/settings/document-templates/versions/[id]/route.ts:1)
|
||||
- [src/app/api/crm/settings/document-templates/versions/[id]/mappings/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/settings/document-templates/versions/[id]/mappings/route.ts:1)
|
||||
|
||||
### 1.3 Document Template Foundation
|
||||
|
||||
The main document-template business logic is centralized in:
|
||||
|
||||
- [src/features/foundation/document-template/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:1)
|
||||
|
||||
Important responsibilities already covered:
|
||||
|
||||
- template resolution for runtime documents
|
||||
- version resolution
|
||||
- mapping resolution
|
||||
- mapping-to-input transformation
|
||||
- active/default template handling
|
||||
|
||||
Key functions:
|
||||
|
||||
- `resolveTemplateMappings`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:168)
|
||||
- `createDocumentTemplateVersion`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:424)
|
||||
- `updateDocumentTemplateVersion`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:449)
|
||||
- `setDocumentTemplateVersionActive`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:474)
|
||||
- `resolveTemplateForDocument`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:612)
|
||||
- `mapDocumentDataToTemplateInput`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:745)
|
||||
|
||||
### 1.4 Quotation Document Runtime
|
||||
|
||||
Quotation document runtime logic is handled in:
|
||||
|
||||
- [src/features/crm/quotations/document/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:263)
|
||||
|
||||
Key functions:
|
||||
|
||||
- `buildQuotationDocumentData`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:263)
|
||||
- `getQuotationDocumentPreviewData`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:661)
|
||||
- `prepareApprovedQuotationSnapshot`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/service.ts:718)
|
||||
|
||||
Topic-based dynamic layout is currently handled by:
|
||||
|
||||
- [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:66)
|
||||
|
||||
Formatting helpers are in:
|
||||
|
||||
- [src/features/crm/quotations/document/server/pdfme-transforms.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdfme-transforms.ts:86)
|
||||
|
||||
### 1.5 PDF Generation Foundation
|
||||
|
||||
PDF generation is centralized in:
|
||||
|
||||
- [src/features/foundation/pdf-generator/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:99)
|
||||
|
||||
Important capabilities already provided:
|
||||
|
||||
- font loading
|
||||
- PDFMe plugin registration
|
||||
- preview PDF generation
|
||||
- download PDF generation
|
||||
- approved PDF artifact generation and persistence
|
||||
|
||||
Key functions:
|
||||
|
||||
- `getPdfPlugins`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:44)
|
||||
- `resolvePdfFonts`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:53)
|
||||
- `generatePdfFromTemplate`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:99)
|
||||
- `generateQuotationPdf`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:300)
|
||||
- `generateQuotationPreviewPdf`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:317)
|
||||
- `generateApprovedQuotationPdf`: [service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:321)
|
||||
|
||||
---
|
||||
|
||||
## 2. Dependency Graph
|
||||
|
||||
### 2.1 Runtime Flow
|
||||
|
||||
Quotation to PDF currently flows as:
|
||||
|
||||
1. quotation APIs request document data or document preview
|
||||
2. quotation server service builds normalized `documentData`
|
||||
3. runtime resolves the active template and active version
|
||||
4. runtime resolves mappings for the selected version
|
||||
5. document data is transformed into PDFMe `templateInput`
|
||||
6. topic engine clones and expands the topic page dynamically
|
||||
7. merged template plus merged inputs are passed to PDFMe generator
|
||||
8. resulting PDF is returned as preview, download, or approved artifact
|
||||
|
||||
### 2.2 Route-Level Graph
|
||||
|
||||
- document data route: [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:15)
|
||||
- calls `buildQuotationDocumentData`
|
||||
- document preview route: [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:15)
|
||||
- calls `getQuotationDocumentPreviewData`
|
||||
- PDF preview route: [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:15)
|
||||
- calls `generateQuotationPreviewPdf`
|
||||
- PDF download route: [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:15)
|
||||
- calls `generateQuotationPdf`
|
||||
- approved PDF route: [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:20)
|
||||
- calls approved artifact retrieval/generation flow
|
||||
|
||||
### 2.3 UI Preview Graph
|
||||
|
||||
Client document preview uses:
|
||||
|
||||
- [src/features/crm/quotations/document/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/service.ts:1)
|
||||
- [src/features/crm/quotations/document/queries.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/queries.ts:1)
|
||||
- [src/features/crm/quotations/components/quotation-document-preview.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/components/quotation-document-preview.tsx:1)
|
||||
|
||||
This preview currently renders document data and item summaries for inspection, but it is not the PDF layout engine itself.
|
||||
|
||||
---
|
||||
|
||||
## 3. Current Template Lifecycle
|
||||
|
||||
### 3.1 Storage Model
|
||||
|
||||
Template entities are stored in:
|
||||
|
||||
- `crm_document_templates`: [schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts:880)
|
||||
- `crm_document_template_versions`: [schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts:909)
|
||||
- `crm_document_template_mappings`: [schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts:933)
|
||||
- `crm_document_template_table_columns`: [schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts:957)
|
||||
|
||||
### 3.2 Lifecycle Rules
|
||||
|
||||
Observed lifecycle:
|
||||
|
||||
1. create template metadata
|
||||
2. create template version with raw `schemaJson`
|
||||
3. add/update mappings for placeholders
|
||||
4. activate the desired version
|
||||
5. runtime automatically resolves the active version
|
||||
|
||||
### 3.3 Selection Rules at Runtime
|
||||
|
||||
Runtime template resolution is implemented in:
|
||||
|
||||
- [resolveTemplateForDocument](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:612)
|
||||
|
||||
Selection behavior:
|
||||
|
||||
- only active templates are considered
|
||||
- product-type-specific match is preferred
|
||||
- default product type fallback exists
|
||||
- active versions are filtered
|
||||
- the latest active version by creation order is selected
|
||||
|
||||
### 3.4 Activation and Default Handling
|
||||
|
||||
- default template normalization is handled by `normalizeDefaultTemplate`
|
||||
- version activation is handled by `setDocumentTemplateVersionActive`
|
||||
- inactive versions remain stored for traceability
|
||||
|
||||
### 3.5 Template Source / Seed Coupling
|
||||
|
||||
Current template source loading in seeds and audit utilities still points to:
|
||||
|
||||
- `ALLA_template_pdfme_fainal3.json`
|
||||
- `ONVALLA_template_pdfme_fainal3.json`
|
||||
|
||||
References:
|
||||
|
||||
- [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)
|
||||
- [scripts/reseed-pdf-template-version.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/scripts/reseed-pdf-template-version.ts:1)
|
||||
|
||||
This means any new product-item template version likely needs seed/audit support updates.
|
||||
|
||||
---
|
||||
|
||||
## 4. Runtime Rendering Flow
|
||||
|
||||
### 4.1 Current Preview Builder
|
||||
|
||||
`getQuotationDocumentPreviewData` currently does the following:
|
||||
|
||||
1. builds quotation document data
|
||||
2. resolves the active quotation PDFMe template
|
||||
3. resolves version mappings
|
||||
4. maps document data to template inputs
|
||||
5. normalizes aliases between field names and placeholder tokens
|
||||
6. runs the topic engine
|
||||
7. returns merged template input plus rendered schema
|
||||
|
||||
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)
|
||||
|
||||
### 4.2 Topic Engine Behavior
|
||||
|
||||
The existing topic engine:
|
||||
|
||||
- clones template pages
|
||||
- assumes the dynamic topic page is at `targetPageIndex: 1`
|
||||
- looks for `topic` and `data_topic`
|
||||
- inserts repeated topic blocks
|
||||
- moves signature/keep-together fields to the last generated page when needed
|
||||
|
||||
Key implementation details:
|
||||
|
||||
- default options: [pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:14)
|
||||
- target page lookup: [pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:76)
|
||||
- dynamic field lookup: [pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:83)
|
||||
- page break behavior: [pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:147)
|
||||
- keep-together footer/signature handling: [pdf-topic-engine.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/document/server/pdf-topic-engine.ts:169)
|
||||
|
||||
### 4.3 PDF Generator Runtime
|
||||
|
||||
The generator currently registers these PDFMe plugins:
|
||||
|
||||
- `text`
|
||||
- `image`
|
||||
- `line`
|
||||
- `table`
|
||||
|
||||
Reference:
|
||||
|
||||
- [src/features/foundation/pdf-generator/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/pdf-generator/server/service.ts:44)
|
||||
|
||||
This is important because Product Item page support should reuse the existing official PDFMe `table` plugin instead of introducing a custom renderer.
|
||||
|
||||
---
|
||||
|
||||
## 5. Existing PDF Templates
|
||||
|
||||
### 5.1 Located Template Files
|
||||
|
||||
Current PDFMe template assets found in the repository:
|
||||
|
||||
- [src/pdfme_template/ALLA_template_pdfme_fainal3.json](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/pdfme_template/ALLA_template_pdfme_fainal3.json)
|
||||
- [src/pdfme_template/ONVALLA_template_pdfme_fainal3.json](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/pdfme_template/ONVALLA_template_pdfme_fainal3.json)
|
||||
|
||||
### 5.2 Current Page Count
|
||||
|
||||
Both templates currently contain exactly 2 pages.
|
||||
|
||||
### 5.3 Page Purposes
|
||||
|
||||
For `ALLA_template_pdfme_fainal3.json`:
|
||||
|
||||
- Page 1
|
||||
- company header
|
||||
- customer detail
|
||||
- quotation meta
|
||||
- project fields
|
||||
- quotation price summary table
|
||||
- Page 2
|
||||
- dynamic topic label/table placeholders
|
||||
- closing message
|
||||
- signature blocks
|
||||
|
||||
Observed markers from template JSON:
|
||||
|
||||
- page 1 price table field `quotation_price_data`
|
||||
- page 2 dynamic topic fields `topic` and `data_topic`
|
||||
- page 2 static closing/signature fields `Please_do_not`, `yours_faithfuly`, `app1`, `app2`, `app3`
|
||||
|
||||
Relevant references:
|
||||
|
||||
- quotation price table marker: [ALLA template](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/pdfme_template/ALLA_template_pdfme_fainal3.json:345)
|
||||
- topic marker: [ALLA template](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/pdfme_template/ALLA_template_pdfme_fainal3.json:962)
|
||||
- topic data marker: [ALLA template](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/pdfme_template/ALLA_template_pdfme_fainal3.json:1031)
|
||||
|
||||
### 5.4 Base PDF Structure
|
||||
|
||||
The current templates use PDFMe object-style `basePdf` with width/height/padding and static schema, not an imported fixed PDF file path.
|
||||
|
||||
This is favorable for dynamic table layout and page growth.
|
||||
|
||||
---
|
||||
|
||||
## 6. Product Item Flow
|
||||
|
||||
### 6.1 Data Origin
|
||||
|
||||
Quotation product items originate from:
|
||||
|
||||
- `crm_quotation_items`: [schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts:613)
|
||||
|
||||
Current persisted fields include:
|
||||
|
||||
- `itemNumber`
|
||||
- `productType`
|
||||
- `description`
|
||||
- `quantity`
|
||||
- `unit`
|
||||
- `unitPrice`
|
||||
- `discount`
|
||||
- `discountType`
|
||||
- `taxRate`
|
||||
- `totalPrice`
|
||||
- `notes`
|
||||
|
||||
### 6.2 Server Mapping
|
||||
|
||||
Quotation item records are normalized in:
|
||||
|
||||
- [src/features/crm/quotations/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/quotations/server/service.ts:208)
|
||||
|
||||
Quotation document data currently exposes item fields in:
|
||||
|
||||
- [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)
|
||||
|
||||
Currently exposed document item fields:
|
||||
|
||||
- `itemNumber`
|
||||
- `productTypeCode`
|
||||
- `productTypeLabel`
|
||||
- `description`
|
||||
- `quantity`
|
||||
- `unitCode`
|
||||
- `unitLabel`
|
||||
- `unitPrice`
|
||||
- `discount`
|
||||
- `discountTypeCode`
|
||||
- `taxRate`
|
||||
- `totalPrice`
|
||||
- `notes`
|
||||
|
||||
### 6.3 Existing Table Mapping Support
|
||||
|
||||
There is already existing seed/audit support for an `items_table` mapping:
|
||||
|
||||
- [scripts/pdf-audit-utils.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/scripts/pdf-audit-utils.ts:312)
|
||||
|
||||
Current seeded columns:
|
||||
|
||||
- `Item` → `itemNumber`
|
||||
- `Description` → `description`
|
||||
- `Qty` → `quantity`
|
||||
- `Unit` → `unitLabel`
|
||||
- `Unit Price` → `unitPrice`
|
||||
- `Total` → `totalPrice`
|
||||
|
||||
This suggests the architecture already anticipated table-based quotation item rendering, even though the currently active production template files are still only 2 pages.
|
||||
|
||||
### 6.4 Gaps Against P.4 Requirements
|
||||
|
||||
Task P.4 requires these columns or concepts:
|
||||
|
||||
- product code
|
||||
- description
|
||||
- specification
|
||||
- quantity
|
||||
- unit
|
||||
- unit price
|
||||
- discount
|
||||
- amount
|
||||
- remark
|
||||
|
||||
Observed current gap:
|
||||
|
||||
- no dedicated `specification` field was found in `crm_quotation_items`
|
||||
- `remark` appears to correspond most closely to `notes`, unless business rules say otherwise
|
||||
|
||||
This is a discovery risk and must be resolved before final implementation behavior is locked in.
|
||||
|
||||
---
|
||||
|
||||
## 7. Layout Engine Assessment
|
||||
|
||||
### 7.1 What Already Exists
|
||||
|
||||
The current layout foundation already supports:
|
||||
|
||||
- page cloning
|
||||
- dynamic page generation
|
||||
- page splitting based on vertical overflow
|
||||
- repeated topic block creation
|
||||
- keep-together footer/signature placement
|
||||
|
||||
This is provided by:
|
||||
|
||||
- [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:66)
|
||||
|
||||
### 7.2 What Does Not Yet Exist Explicitly
|
||||
|
||||
No dedicated runtime was found yet for:
|
||||
|
||||
- dynamic product item page insertion between page 1 and topic/signature page
|
||||
- generic dynamic page marker resolution
|
||||
- generalized page numbering helper
|
||||
- product-table-specific pagination layer separate from topic engine
|
||||
|
||||
### 7.3 Key Constraint
|
||||
|
||||
The existing topic engine is hard-wired to `targetPageIndex: 1`, which currently means:
|
||||
|
||||
- it expects the dynamic topic page to be page 2
|
||||
- it expects signature fields on that same logical target page
|
||||
|
||||
If a new Product Item page is inserted between the current page 1 and current page 2 without changing runtime behavior, the topic engine will target the wrong page.
|
||||
|
||||
This is the most important architecture finding of the discovery phase.
|
||||
|
||||
---
|
||||
|
||||
## 8. Files Expected to Be Modified
|
||||
|
||||
Likely implementation touchpoints:
|
||||
|
||||
- [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:66)
|
||||
- [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)
|
||||
- [src/features/foundation/document-template/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/document-template/server/service.ts:612)
|
||||
- [scripts/pdf-audit-utils.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/scripts/pdf-audit-utils.ts:312)
|
||||
- [scripts/reseed-pdf-template-version.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/scripts/reseed-pdf-template-version.ts:1)
|
||||
- possibly [src/db/seeds/foundation.seed.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/seeds/foundation.seed.ts:854)
|
||||
|
||||
Possible UI/admin edits may be needed only if additional metadata or better preview labeling is required, but no mandatory UI gap was found yet for basic version creation and activation.
|
||||
|
||||
---
|
||||
|
||||
## 9. New Files Expected to Be Created
|
||||
|
||||
Expected new template assets:
|
||||
|
||||
- `src/pdfme_template/ALLA_template_pdfme_product_v1.json`
|
||||
- `src/pdfme_template/ONVALLA_template_pdfme_product_v1.json`
|
||||
|
||||
No separate parallel rendering pipeline should be created.
|
||||
|
||||
---
|
||||
|
||||
## 10. Backward Compatibility Analysis
|
||||
|
||||
Backward compatibility is achievable if the implementation follows these rules:
|
||||
|
||||
1. do not modify existing `*_fainal3.json` template files
|
||||
2. create new template versions only
|
||||
3. keep runtime able to render both old and new version structures
|
||||
4. make topic-page resolution robust enough to support the new page sequence
|
||||
5. avoid changing existing approved PDF artifact behavior
|
||||
|
||||
Why compatibility is realistic:
|
||||
|
||||
- runtime already resolves active versions dynamically
|
||||
- template mappings are version-specific
|
||||
- old versions remain stored
|
||||
- admin UI already supports multiple versions and activation switching
|
||||
|
||||
Main compatibility risk:
|
||||
|
||||
- current topic engine assumes old page order and must be generalized without breaking old templates
|
||||
|
||||
---
|
||||
|
||||
## 11. Risk Assessment
|
||||
|
||||
### 11.1 High Risk
|
||||
|
||||
- topic engine currently assumes page 2 is the dynamic topic/signature page
|
||||
- inserting a new middle page will break runtime unless page targeting becomes marker-based or otherwise dynamic
|
||||
|
||||
### 11.2 Medium Risk
|
||||
|
||||
- current quotation item payload does not clearly expose a standalone `specification` field
|
||||
- page numbering requirement exists in Task P.4, but current templates do not expose obvious page-number fields
|
||||
- reseed/audit utilities still point to legacy file names and will need alignment for new template assets
|
||||
|
||||
### 11.3 Lower Risk
|
||||
|
||||
- CRM settings workflow itself is already sufficient for version CRUD
|
||||
- PDF generator already registers the official PDFMe `table` plugin
|
||||
- template storage model already supports table mappings
|
||||
|
||||
---
|
||||
|
||||
## 12. Migration Strategy
|
||||
|
||||
Recommended migration path:
|
||||
|
||||
1. generalize runtime topic page detection so it is not tied to fixed page index 1
|
||||
2. create new Product Item template JSON files for ALLA and ONVALLA
|
||||
3. add or update mappings for the product item table placeholders
|
||||
4. ensure new versions can be created and activated through the existing template settings flow
|
||||
5. update reseed/audit helpers to recognize the new product template source files where needed
|
||||
6. verify all runtime modes
|
||||
|
||||
Required verification modes:
|
||||
|
||||
- document preview route
|
||||
- PDF preview route
|
||||
- PDF download route
|
||||
- approved PDF generation
|
||||
- old template version behavior
|
||||
- new template version behavior
|
||||
|
||||
---
|
||||
|
||||
## 13. Final Discovery Conclusion
|
||||
|
||||
Task P.4 should proceed by extending the current document-template and quotation-document runtime foundations, not by creating a new rendering path.
|
||||
|
||||
The critical architecture change is:
|
||||
|
||||
- make the topic/signature dynamic-page resolution independent from the old hardcoded second-page layout
|
||||
|
||||
Once that is in place, the new Product Item page can be introduced as a new template version while preserving existing templates unchanged.
|
||||
|
||||
---
|
||||
|
||||
## References Reviewed
|
||||
|
||||
### Governance and Standards
|
||||
|
||||
- [AGENTS.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/AGENTS.md)
|
||||
- [docs/standards/project-foundations.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/project-foundations.md)
|
||||
- [docs/standards/architecture-rules.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/architecture-rules.md)
|
||||
- [docs/standards/ui-ux-rules.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/ui-ux-rules.md)
|
||||
- [docs/standards/task-catalog.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/task-catalog.md)
|
||||
- [docs/standards/task-review-checklist.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/task-review-checklist.md)
|
||||
|
||||
### ADRs and Business Docs
|
||||
|
||||
- [docs/adr/0008-attachment-storage-strategy.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/adr/0008-attachment-storage-strategy.md)
|
||||
- [docs/adr/0009-approved-document-storage-lifecycle.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/adr/0009-approved-document-storage-lifecycle.md)
|
||||
- [docs/adr/0012-approval-signature-strategy.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/adr/0012-approval-signature-strategy.md)
|
||||
- [docs/adr/0013-pdf-visual-parity-strategy.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/adr/0013-pdf-visual-parity-strategy.md)
|
||||
- [docs/business/pdf-mapping-registry.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/business/pdf-mapping-registry.md)
|
||||
- [docs/business/pdf-placeholder-registry.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/business/pdf-placeholder-registry.md)
|
||||
|
||||
### Implementation Lineage
|
||||
|
||||
- [docs/implementation/task-g-document-preview-foundation.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-g-document-preview-foundation.md)
|
||||
- [docs/implementation/task-h-pdf-generation-persistence.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-h-pdf-generation-persistence.md)
|
||||
- [docs/implementation/pdfme-runtime-audit.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/pdfme-runtime-audit.md)
|
||||
- [docs/implementation/pdfme-legacy-audit.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/pdfme-legacy-audit.md)
|
||||
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
|
||||
67
plans/task-p.4.1.md
Normal file
67
plans/task-p.4.1.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Task P.4.1 - PDFMe Product Item Template Runtime Verification
|
||||
|
||||
Before implementing Task P.4, perform runtime verification against the real codebase.
|
||||
|
||||
Do not implement yet.
|
||||
|
||||
Verify:
|
||||
|
||||
1. Current quotation PDF runtime
|
||||
- document-preview
|
||||
- pdf-preview
|
||||
- pdf-download
|
||||
- approved-pdf
|
||||
|
||||
Confirm whether they use the same active template/version/mapping pipeline.
|
||||
|
||||
2. Current template page structure
|
||||
- load active quotation PDFMe template from runtime source
|
||||
- dump page count
|
||||
- dump schema names per page
|
||||
- confirm topic/signature page index
|
||||
|
||||
3. PDFMe table capability
|
||||
Create a temporary verification only.
|
||||
Test official PDFMe table with:
|
||||
- 5 rows
|
||||
- 30 rows
|
||||
- 100 rows
|
||||
|
||||
Confirm:
|
||||
- repeat header
|
||||
- auto page break
|
||||
- multi-page behavior
|
||||
- row height behavior
|
||||
|
||||
4. Product item mapping
|
||||
Verify actual source fields for:
|
||||
- product code
|
||||
- description
|
||||
- specification
|
||||
- quantity
|
||||
- unit
|
||||
- unit price
|
||||
- discount
|
||||
- amount
|
||||
- remark
|
||||
|
||||
If no field exists, document the gap.
|
||||
|
||||
5. Seed/runtime source
|
||||
Confirm whether runtime uses:
|
||||
- database active template
|
||||
- JSON file template
|
||||
- both
|
||||
|
||||
Explain whether seed scripts must be updated.
|
||||
|
||||
Output required:
|
||||
- verified runtime findings
|
||||
- evidence/log snippets
|
||||
- final implementation strategy
|
||||
- rollback plan
|
||||
- regression test matrix
|
||||
|
||||
Do not modify production template files.
|
||||
Do not create a new rendering pipeline.
|
||||
Do not begin implementation until this verification report is complete.
|
||||
1228
plans/task-p.4.2-runtime-design.md
Normal file
1228
plans/task-p.4.2-runtime-design.md
Normal file
File diff suppressed because it is too large
Load Diff
475
plans/task-p.4.2.md
Normal file
475
plans/task-p.4.2.md
Normal file
@@ -0,0 +1,475 @@
|
||||
# Task P.4.2 - PDF Runtime Architecture & Section-based Rendering Design
|
||||
|
||||
## Objective
|
||||
|
||||
Design the next-generation PDF runtime architecture for the CRM document system.
|
||||
|
||||
The new runtime must support:
|
||||
|
||||
* Dynamic page insertion
|
||||
* Section-based document composition
|
||||
* Optional document sections
|
||||
* Future extensibility
|
||||
* Full backward compatibility
|
||||
|
||||
This is an architecture task only.
|
||||
|
||||
Do NOT modify production code.
|
||||
|
||||
Do NOT modify template JSON.
|
||||
|
||||
Do NOT modify database schema.
|
||||
|
||||
---
|
||||
|
||||
# Inputs
|
||||
|
||||
Reuse verified findings from
|
||||
|
||||
* Task P.4 Discovery
|
||||
* Task P.4.1 Runtime Verification
|
||||
|
||||
Do not repeat discovery.
|
||||
|
||||
---
|
||||
|
||||
# Design Principles
|
||||
|
||||
The runtime must become
|
||||
|
||||
* page-role driven
|
||||
* section-based
|
||||
* version compatible
|
||||
* renderer independent
|
||||
* extensible
|
||||
|
||||
Business logic must not depend on page indexes.
|
||||
|
||||
---
|
||||
|
||||
# Core Architecture
|
||||
|
||||
The runtime shall assemble a document from independent sections.
|
||||
|
||||
Instead of
|
||||
|
||||
```text
|
||||
Template
|
||||
|
||||
↓
|
||||
|
||||
Mutate Page 2
|
||||
|
||||
↓
|
||||
|
||||
Generate PDF
|
||||
```
|
||||
|
||||
the runtime shall become
|
||||
|
||||
```text
|
||||
Quotation Document Data
|
||||
|
||||
↓
|
||||
|
||||
Template Resolver
|
||||
|
||||
↓
|
||||
|
||||
Mapping Resolver
|
||||
|
||||
↓
|
||||
|
||||
Compatibility Adapter
|
||||
|
||||
↓
|
||||
|
||||
Page Resolver
|
||||
|
||||
↓
|
||||
|
||||
Section Composer
|
||||
|
||||
↓
|
||||
|
||||
Template Assembler
|
||||
|
||||
↓
|
||||
|
||||
PDF Generator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Section-based Rendering
|
||||
|
||||
Introduce the concept of
|
||||
|
||||
Document Sections.
|
||||
|
||||
Examples
|
||||
|
||||
* Customer
|
||||
* Product Items
|
||||
* Topics
|
||||
* Conditions
|
||||
* Signature
|
||||
* Attachments
|
||||
* Appendix
|
||||
* Warranty
|
||||
* Cover
|
||||
|
||||
A section represents logical document content rather than physical pages.
|
||||
|
||||
A section may generate
|
||||
|
||||
* zero pages
|
||||
* one page
|
||||
* multiple pages
|
||||
|
||||
---
|
||||
|
||||
# Optional Sections
|
||||
|
||||
The runtime must support optional sections.
|
||||
|
||||
A section may be
|
||||
|
||||
* Required
|
||||
* Optional
|
||||
|
||||
The runtime shall be capable of skipping optional sections without requiring another template version.
|
||||
|
||||
Examples
|
||||
|
||||
```text
|
||||
Customer
|
||||
Required
|
||||
|
||||
Product Items
|
||||
Optional
|
||||
|
||||
Topics
|
||||
Optional
|
||||
|
||||
Conditions
|
||||
Optional
|
||||
|
||||
Signature
|
||||
Required
|
||||
```
|
||||
|
||||
This capability is architectural only.
|
||||
|
||||
No UI configuration is required in this task.
|
||||
|
||||
---
|
||||
|
||||
# Render Policy
|
||||
|
||||
Design a Render Policy abstraction.
|
||||
|
||||
Example
|
||||
|
||||
```ts
|
||||
interface RenderPolicy {
|
||||
section: PageRole;
|
||||
|
||||
enabled: boolean;
|
||||
|
||||
required: boolean;
|
||||
|
||||
visibleWhenEmpty: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
The runtime shall evaluate Render Policy before rendering each section.
|
||||
|
||||
The policy source is intentionally undefined in this task.
|
||||
|
||||
Future tasks may provide it from
|
||||
|
||||
* user selection
|
||||
* customer preference
|
||||
* template defaults
|
||||
* organization defaults
|
||||
|
||||
---
|
||||
|
||||
# Runtime Pipeline
|
||||
|
||||
Design
|
||||
|
||||
```text
|
||||
Document Data
|
||||
|
||||
↓
|
||||
|
||||
Template Resolver
|
||||
|
||||
↓
|
||||
|
||||
Mapping Resolver
|
||||
|
||||
↓
|
||||
|
||||
Compatibility Adapter
|
||||
|
||||
↓
|
||||
|
||||
Page Resolver
|
||||
|
||||
↓
|
||||
|
||||
Render Policy Resolver
|
||||
|
||||
↓
|
||||
|
||||
Section Composer
|
||||
|
||||
↓
|
||||
|
||||
Customer Section
|
||||
|
||||
↓
|
||||
|
||||
Product Item Section
|
||||
|
||||
↓
|
||||
|
||||
Topic Section
|
||||
|
||||
↓
|
||||
|
||||
Condition Section
|
||||
|
||||
↓
|
||||
|
||||
Signature Section
|
||||
|
||||
↓
|
||||
|
||||
Template Assembler
|
||||
|
||||
↓
|
||||
|
||||
PDF Generator
|
||||
```
|
||||
|
||||
Describe every stage.
|
||||
|
||||
---
|
||||
|
||||
# Runtime Components
|
||||
|
||||
Design responsibilities for
|
||||
|
||||
* Template Resolver
|
||||
* Mapping Resolver
|
||||
* Compatibility Adapter
|
||||
* Page Resolver
|
||||
* Render Policy Resolver
|
||||
* Customer Section Builder
|
||||
* Product Item Engine
|
||||
* Topic Engine
|
||||
* Condition Engine
|
||||
* Signature Resolver
|
||||
* Template Assembler
|
||||
* PDF Render Gateway
|
||||
|
||||
Each component must have a single responsibility.
|
||||
|
||||
---
|
||||
|
||||
# Page Marker Strategy
|
||||
|
||||
Design page discovery using logical markers instead of indexes.
|
||||
|
||||
Support
|
||||
|
||||
* explicit page markers
|
||||
* legacy inference
|
||||
* fallback detection
|
||||
|
||||
The runtime must never rely on
|
||||
|
||||
```ts
|
||||
schemas[1]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Runtime Contracts
|
||||
|
||||
Define contracts for
|
||||
|
||||
* ResolvedTemplate
|
||||
* ResolvedPages
|
||||
* RenderPolicy
|
||||
* BuiltSection
|
||||
* RuntimeIssue
|
||||
* AssembledTemplate
|
||||
|
||||
Document ownership and responsibilities.
|
||||
|
||||
---
|
||||
|
||||
# Compatibility Strategy
|
||||
|
||||
Support
|
||||
|
||||
* legacy templates
|
||||
* future templates
|
||||
|
||||
without duplicating runtime logic.
|
||||
|
||||
Legacy templates shall work through the Compatibility Adapter.
|
||||
|
||||
---
|
||||
|
||||
# Future Extensibility
|
||||
|
||||
The architecture shall allow adding new document sections without changing existing section builders.
|
||||
|
||||
Examples
|
||||
|
||||
* Drawing
|
||||
* Specification
|
||||
* Gallery
|
||||
* Warranty
|
||||
* Appendix
|
||||
* Inspection Report
|
||||
|
||||
A new section should require only
|
||||
|
||||
1. PageRole
|
||||
2. Section Builder
|
||||
3. Marker Rule
|
||||
4. Assembly Rule
|
||||
|
||||
---
|
||||
|
||||
# Error Handling
|
||||
|
||||
Design behavior for
|
||||
|
||||
* missing marker
|
||||
* duplicate marker
|
||||
* missing mappings
|
||||
* empty optional section
|
||||
* empty required section
|
||||
* invalid template
|
||||
|
||||
Runtime shall fail gracefully and accumulate Runtime Issues.
|
||||
|
||||
---
|
||||
|
||||
# Migration Strategy
|
||||
|
||||
Design migration from
|
||||
|
||||
Current Runtime
|
||||
|
||||
↓
|
||||
|
||||
Section-based Runtime
|
||||
|
||||
without breaking
|
||||
|
||||
* Preview
|
||||
* Download
|
||||
* Approved PDF
|
||||
* Existing Template Versions
|
||||
|
||||
No database migration.
|
||||
|
||||
No API changes.
|
||||
|
||||
---
|
||||
|
||||
# Sequence Diagrams
|
||||
|
||||
Produce
|
||||
|
||||
* Current Runtime
|
||||
* Proposed Runtime
|
||||
|
||||
including
|
||||
|
||||
* Render Policy
|
||||
* Section Composition
|
||||
|
||||
---
|
||||
|
||||
# Component Diagram
|
||||
|
||||
Include
|
||||
|
||||
* Template Resolver
|
||||
* Compatibility Adapter
|
||||
* Page Resolver
|
||||
* Render Policy Resolver
|
||||
* Section Composer
|
||||
* Section Builders
|
||||
* Template Assembler
|
||||
* PDF Generator
|
||||
|
||||
---
|
||||
|
||||
# Implementation Roadmap
|
||||
|
||||
Split implementation into phases.
|
||||
|
||||
Example
|
||||
|
||||
Phase 1
|
||||
|
||||
Runtime Contracts
|
||||
|
||||
Phase 2
|
||||
|
||||
Compatibility Adapter
|
||||
|
||||
Phase 3
|
||||
|
||||
Page Resolver
|
||||
|
||||
Phase 4
|
||||
|
||||
Section Composer
|
||||
|
||||
Phase 5
|
||||
|
||||
Product Item Engine
|
||||
|
||||
Phase 6
|
||||
|
||||
Template Upgrade
|
||||
|
||||
Phase 7
|
||||
|
||||
Regression Tests
|
||||
|
||||
Each phase must be independently testable.
|
||||
|
||||
---
|
||||
|
||||
# Constraints
|
||||
|
||||
* Architecture only.
|
||||
* No production implementation.
|
||||
* No template modification.
|
||||
* No database changes.
|
||||
* No API changes.
|
||||
|
||||
---
|
||||
|
||||
# Acceptance Criteria
|
||||
|
||||
* Runtime is section-based rather than page-index-based.
|
||||
* Optional sections are supported by design.
|
||||
* Product Item pages are independent from Topic pages.
|
||||
* Existing template versions remain compatible.
|
||||
* Future document sections can be added without redesigning the runtime.
|
||||
* Template Version is used only for structural/layout differences, not for enabling or disabling document sections.
|
||||
* The design is ready for implementation in Task P.4.3 with minimal architectural decisions remaining.
|
||||
437
plans/task-p.4.3.md
Normal file
437
plans/task-p.4.3.md
Normal file
@@ -0,0 +1,437 @@
|
||||
# Task P.4.3 - PDF Runtime Refactoring (Regression-first)
|
||||
|
||||
## Objective
|
||||
|
||||
Implement the new section-based PDF runtime architecture designed in Task P.4.2.
|
||||
|
||||
This task is a **runtime refactor only**.
|
||||
|
||||
The primary objective is to replace the current page-index-driven runtime with the new section-based runtime **without changing the rendered output of existing templates**.
|
||||
|
||||
This task must not introduce new PDF layouts or Product Item pages yet.
|
||||
|
||||
---
|
||||
|
||||
# Prerequisites
|
||||
|
||||
Complete and reuse:
|
||||
|
||||
* Task P.4 Discovery
|
||||
* Task P.4.1 Runtime Verification
|
||||
* Task P.4.2 Runtime Design
|
||||
|
||||
Do not redesign the architecture.
|
||||
|
||||
Implement the approved design only.
|
||||
|
||||
---
|
||||
|
||||
# Primary Goal
|
||||
|
||||
Move from
|
||||
|
||||
```text
|
||||
Hardcoded Page Index
|
||||
|
||||
↓
|
||||
|
||||
Topic Engine
|
||||
|
||||
↓
|
||||
|
||||
PDF
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```text
|
||||
Section-based Runtime
|
||||
|
||||
↓
|
||||
|
||||
Section Composer
|
||||
|
||||
↓
|
||||
|
||||
Template Assembler
|
||||
|
||||
↓
|
||||
|
||||
PDF
|
||||
```
|
||||
|
||||
while maintaining identical output for all existing templates.
|
||||
|
||||
---
|
||||
|
||||
# Regression-first Rule
|
||||
|
||||
This task follows a strict Regression-first strategy.
|
||||
|
||||
Before introducing any new rendering capability:
|
||||
|
||||
* existing templates must continue producing identical PDFs
|
||||
* preview, download and approved PDF must remain unchanged
|
||||
* all regression tests must pass
|
||||
|
||||
Feature additions are intentionally deferred.
|
||||
|
||||
---
|
||||
|
||||
# Scope
|
||||
|
||||
Implement only runtime architecture.
|
||||
|
||||
Included
|
||||
|
||||
* runtime contracts
|
||||
* compatibility adapter
|
||||
* page resolver
|
||||
* section composer
|
||||
* render context
|
||||
* topic engine refactor
|
||||
* template assembler
|
||||
* runtime diagnostics
|
||||
|
||||
Excluded
|
||||
|
||||
* Product Item page
|
||||
* Product Item rendering
|
||||
* new template JSON
|
||||
* CRM Template UI
|
||||
* user render options
|
||||
* template version changes
|
||||
* database changes
|
||||
|
||||
---
|
||||
|
||||
# Implementation Requirements
|
||||
|
||||
## Phase 1 — Runtime Contracts
|
||||
|
||||
Create runtime contracts.
|
||||
|
||||
At minimum
|
||||
|
||||
* SectionRole
|
||||
* RenderContext
|
||||
* ResolvedTemplate
|
||||
* ResolvedPages
|
||||
* BuiltSection
|
||||
* RuntimeIssue
|
||||
* AssembledTemplate
|
||||
|
||||
Responsibilities must match Task P.4.2.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Compatibility Adapter
|
||||
|
||||
Implement
|
||||
|
||||
TemplateCompatibilityAdapter
|
||||
|
||||
Responsibilities
|
||||
|
||||
* explicit marker support
|
||||
* legacy marker inference
|
||||
* normalize legacy templates
|
||||
* expose Runtime Issues
|
||||
|
||||
Legacy templates must continue working without modification.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Page Resolver
|
||||
|
||||
Replace page-index assumptions.
|
||||
|
||||
The runtime must never depend on
|
||||
|
||||
```ts
|
||||
schemas[1]
|
||||
```
|
||||
|
||||
Responsibilities
|
||||
|
||||
* discover pages
|
||||
* classify by SectionRole
|
||||
* detect duplicates
|
||||
* detect missing markers
|
||||
* produce insertion anchors
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Render Context
|
||||
|
||||
Introduce a shared runtime context.
|
||||
|
||||
Example
|
||||
|
||||
```ts
|
||||
interface RenderContext {
|
||||
documentData;
|
||||
template;
|
||||
mappings;
|
||||
pages;
|
||||
policies;
|
||||
issues;
|
||||
}
|
||||
```
|
||||
|
||||
Every runtime component should consume RenderContext instead of receiving unrelated parameters.
|
||||
|
||||
The context must remain immutable where possible.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Section Registry
|
||||
|
||||
Implement a registry-based architecture.
|
||||
|
||||
Example
|
||||
|
||||
```ts
|
||||
interface SectionBuilder {
|
||||
role: SectionRole;
|
||||
|
||||
build(context: RenderContext): BuiltSection;
|
||||
}
|
||||
```
|
||||
|
||||
The runtime must discover builders through registration rather than hardcoded orchestration.
|
||||
|
||||
Section Composer must not know implementation details of builders.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Section Composer
|
||||
|
||||
Implement
|
||||
|
||||
SectionComposer
|
||||
|
||||
Responsibilities
|
||||
|
||||
* execute builders
|
||||
* skip disabled sections
|
||||
* collect Runtime Issues
|
||||
* preserve logical order
|
||||
* return assembled section outputs
|
||||
|
||||
The composer must not contain rendering logic.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7 — Topic Engine Refactor
|
||||
|
||||
Refactor Topic Engine.
|
||||
|
||||
Current behavior
|
||||
|
||||
```text
|
||||
Page Index
|
||||
|
||||
↓
|
||||
|
||||
Topic Engine
|
||||
```
|
||||
|
||||
New behavior
|
||||
|
||||
```text
|
||||
Resolved Page
|
||||
|
||||
↓
|
||||
|
||||
Topic Engine
|
||||
```
|
||||
|
||||
The generated output must remain identical.
|
||||
|
||||
---
|
||||
|
||||
## Phase 8 — Template Assembler
|
||||
|
||||
Implement
|
||||
|
||||
TemplateAssembler
|
||||
|
||||
Responsibilities
|
||||
|
||||
* preserve existing pages
|
||||
* assemble generated sections
|
||||
* merge template inputs
|
||||
* preserve page order
|
||||
* return final template
|
||||
|
||||
No Product Item pages yet.
|
||||
|
||||
---
|
||||
|
||||
## Phase 9 — PDF Runtime Integration
|
||||
|
||||
Wire the new runtime into
|
||||
|
||||
* Preview
|
||||
* Download
|
||||
* Approved PDF
|
||||
|
||||
All three flows must use the same runtime.
|
||||
|
||||
No duplicated pipelines.
|
||||
|
||||
---
|
||||
|
||||
# Runtime Diagnostics
|
||||
|
||||
Implement RuntimeIssue collection.
|
||||
|
||||
Support
|
||||
|
||||
* MISSING_MARKER
|
||||
* DUPLICATE_MARKER
|
||||
* INVALID_TEMPLATE
|
||||
* MISSING_MAPPING
|
||||
* LEGACY_COMPAT_MODE
|
||||
|
||||
Diagnostics must be available during Preview for debugging.
|
||||
|
||||
---
|
||||
|
||||
# Backward Compatibility
|
||||
|
||||
Existing templates must continue working without modification.
|
||||
|
||||
Current
|
||||
|
||||
* ALLA
|
||||
* ONVALLA
|
||||
|
||||
templates must render exactly as before.
|
||||
|
||||
No migration required.
|
||||
|
||||
---
|
||||
|
||||
# Refactoring Constraints
|
||||
|
||||
Do NOT
|
||||
|
||||
* modify template JSON
|
||||
* introduce Product Item pages
|
||||
* change template mappings
|
||||
* modify database schema
|
||||
* change API contracts
|
||||
* change CRM Template UI
|
||||
|
||||
---
|
||||
|
||||
# Code Quality Requirements
|
||||
|
||||
* Single Responsibility Principle
|
||||
* Dependency Injection where appropriate
|
||||
* Immutable runtime contracts where practical
|
||||
* No duplicated rendering logic
|
||||
* No duplicated template resolution
|
||||
* No duplicated mapping resolution
|
||||
* Strong typing
|
||||
* Comprehensive inline documentation for new runtime components
|
||||
|
||||
---
|
||||
|
||||
# Testing Requirements
|
||||
|
||||
Regression tests are mandatory.
|
||||
|
||||
Verify
|
||||
|
||||
## Runtime
|
||||
|
||||
* Preview
|
||||
* Download
|
||||
* Approved PDF
|
||||
|
||||
## Templates
|
||||
|
||||
* ALLA
|
||||
* ONVALLA
|
||||
|
||||
## Rendering
|
||||
|
||||
* Topic rendering
|
||||
* Signature placement
|
||||
* Mapping resolution
|
||||
* Pagination
|
||||
|
||||
Expected result
|
||||
|
||||
Rendered PDF must remain visually identical to the previous runtime.
|
||||
|
||||
---
|
||||
|
||||
# Deliverables
|
||||
|
||||
Implementation must include
|
||||
|
||||
* Runtime Contracts
|
||||
* Compatibility Adapter
|
||||
* Page Resolver
|
||||
* RenderContext
|
||||
* Section Registry
|
||||
* Section Composer
|
||||
* Refactored Topic Engine
|
||||
* Template Assembler
|
||||
* Runtime Diagnostics
|
||||
* Updated Runtime Integration
|
||||
* Regression Tests
|
||||
|
||||
---
|
||||
|
||||
# Acceptance Criteria
|
||||
|
||||
* No hardcoded page indexes remain.
|
||||
* Runtime becomes section-based.
|
||||
* Topic Engine no longer depends on page position.
|
||||
* Legacy templates render without modification.
|
||||
* Preview, Download and Approved PDF use one shared runtime.
|
||||
* Existing PDF output remains unchanged.
|
||||
* Runtime is ready for Product Item Engine implementation in Task P.4.4.
|
||||
* No functional regression is introduced.
|
||||
|
||||
---
|
||||
|
||||
# Out of Scope
|
||||
|
||||
The following work belongs to later tasks:
|
||||
|
||||
**Task P.4.4**
|
||||
|
||||
* Product Item Engine
|
||||
* Product Item pagination
|
||||
* Product Item section rendering
|
||||
|
||||
**Task P.4.5**
|
||||
|
||||
* New PDF template versions
|
||||
* Product Item template layout
|
||||
|
||||
**Task P.4.6**
|
||||
|
||||
* CRM Template integration
|
||||
* Template activation
|
||||
* Version publishing
|
||||
|
||||
**Task P.4.7**
|
||||
|
||||
* Render Policy configuration
|
||||
* User-selectable section visibility
|
||||
* Organization default rendering options
|
||||
|
||||
---
|
||||
|
||||
# Final Success Condition
|
||||
|
||||
At the end of Task P.4.3, the internal PDF runtime architecture shall be completely refactored to the new section-based design while producing identical output to the legacy runtime.
|
||||
|
||||
No new user-visible functionality is expected in this task. The success metric is architectural modernization with zero regression, providing a stable foundation for subsequent Product Item and optional section features.
|
||||
326
plans/task-p.4.md
Normal file
326
plans/task-p.4.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# Task P.4 - PDFMe Product Item Table Template Refactoring
|
||||
|
||||
## Objective
|
||||
|
||||
Redesign the PDFMe quotation template to support dynamic Product Item tables by introducing a dedicated Product Item page between the existing Customer Detail page and Condition & Signature page.
|
||||
|
||||
The implementation **must not modify or replace the existing template**. A completely new template version shall be created while maintaining full backward compatibility.
|
||||
|
||||
---
|
||||
|
||||
# Mandatory Discovery Phase (Required)
|
||||
|
||||
Before implementing anything, inspect the actual project structure and produce a discovery report.
|
||||
|
||||
Do NOT make architectural assumptions.
|
||||
|
||||
The implementation may only begin after the discovery phase is completed.
|
||||
|
||||
---
|
||||
|
||||
# Discovery Scope
|
||||
|
||||
Inspect the current implementation under the CRM Template module.
|
||||
|
||||
At minimum review:
|
||||
|
||||
## 1. CRM Template Module
|
||||
|
||||
Inspect everything related to
|
||||
|
||||
```
|
||||
/dashboard/crm/settings/templates
|
||||
```
|
||||
|
||||
including
|
||||
|
||||
* pages
|
||||
* components
|
||||
* dialogs
|
||||
* APIs
|
||||
* services
|
||||
* repositories
|
||||
* database schema
|
||||
* template versioning
|
||||
* template preview
|
||||
* template import/export
|
||||
* template activation flow
|
||||
|
||||
Document how the template lifecycle currently works.
|
||||
|
||||
---
|
||||
|
||||
## 2. PDF Generation Runtime
|
||||
|
||||
Inspect the entire rendering pipeline.
|
||||
|
||||
Including
|
||||
|
||||
* quotation-preview.tsx
|
||||
* PDF preview flow
|
||||
* PDF download flow
|
||||
* pdfme template loader
|
||||
* template selector
|
||||
* font loader
|
||||
* plugin registration
|
||||
* input builder
|
||||
* layout engine
|
||||
* topic engine
|
||||
* schema builder
|
||||
* adapter layer
|
||||
|
||||
Produce a dependency graph showing how a quotation becomes a PDF.
|
||||
|
||||
---
|
||||
|
||||
## 3. Existing PDF Templates
|
||||
|
||||
Locate every existing PDFMe template.
|
||||
|
||||
Document
|
||||
|
||||
* current page count
|
||||
* page purpose
|
||||
* schema layout
|
||||
* static schema
|
||||
* dynamic schema
|
||||
* reusable components
|
||||
|
||||
Do not assume the current template structure.
|
||||
|
||||
---
|
||||
|
||||
## 4. Product Item Flow
|
||||
|
||||
Locate where quotation product items originate.
|
||||
|
||||
Trace
|
||||
|
||||
Quotation
|
||||
|
||||
↓
|
||||
|
||||
Export Payload
|
||||
|
||||
↓
|
||||
|
||||
Preview Model
|
||||
|
||||
↓
|
||||
|
||||
Input Builder
|
||||
|
||||
↓
|
||||
|
||||
PDF Template
|
||||
|
||||
↓
|
||||
|
||||
PDF Generator
|
||||
|
||||
Document every transformation layer.
|
||||
|
||||
Do NOT duplicate DTOs or adapters if an existing one already provides the required data.
|
||||
|
||||
---
|
||||
|
||||
## 5. Layout Engine
|
||||
|
||||
Inspect the existing layout implementation.
|
||||
|
||||
Determine whether it already supports
|
||||
|
||||
* page insertion
|
||||
* page cloning
|
||||
* page replacement
|
||||
* page splitting
|
||||
* dynamic page generation
|
||||
* table pagination
|
||||
* automatic page break
|
||||
|
||||
If not supported,
|
||||
|
||||
design the extension before implementation.
|
||||
|
||||
---
|
||||
|
||||
# Discovery Output
|
||||
|
||||
Before coding, provide
|
||||
|
||||
1. Existing architecture
|
||||
|
||||
2. Dependency graph
|
||||
|
||||
3. Current template lifecycle
|
||||
|
||||
4. Runtime rendering flow
|
||||
|
||||
5. Files that will be modified
|
||||
|
||||
6. New files that will be created
|
||||
|
||||
7. Backward compatibility analysis
|
||||
|
||||
8. Risk assessment
|
||||
|
||||
9. Migration strategy
|
||||
|
||||
Implementation may only begin after this report.
|
||||
|
||||
---
|
||||
|
||||
# Functional Requirements
|
||||
|
||||
Current document
|
||||
|
||||
```
|
||||
Page 1
|
||||
Customer Detail
|
||||
|
||||
Page 2
|
||||
Condition + Signature
|
||||
```
|
||||
|
||||
shall become
|
||||
|
||||
```
|
||||
Page 1
|
||||
Customer Detail
|
||||
|
||||
Page 2
|
||||
Product Item Detail Table
|
||||
|
||||
Page 3
|
||||
Condition & Signature
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Product Item Page
|
||||
|
||||
The Product Item page shall contain
|
||||
|
||||
* quotation items
|
||||
* item number
|
||||
* product code
|
||||
* description
|
||||
* specification
|
||||
* quantity
|
||||
* unit
|
||||
* unit price
|
||||
* discount
|
||||
* amount
|
||||
* remark (if available)
|
||||
|
||||
The table shall support
|
||||
|
||||
* unlimited rows
|
||||
* automatic page break
|
||||
* repeated table header
|
||||
* automatic page numbering if multiple product pages are required
|
||||
|
||||
No fixed maximum row count.
|
||||
|
||||
---
|
||||
|
||||
# PDFMe Table
|
||||
|
||||
Use the official PDFMe Table implementation.
|
||||
|
||||
Do not create a custom HTML rendering solution.
|
||||
|
||||
Support
|
||||
|
||||
* automatic pagination
|
||||
* repeated headers
|
||||
* dynamic row height
|
||||
* variable content length
|
||||
|
||||
---
|
||||
|
||||
# Template Versioning
|
||||
|
||||
Do NOT modify
|
||||
|
||||
* existing template JSON
|
||||
* existing production template
|
||||
* existing preview template
|
||||
|
||||
Create a new version.
|
||||
|
||||
Example
|
||||
|
||||
```
|
||||
ALLA_template_pdfme_product_v1.json
|
||||
|
||||
ONVALLA_template_pdfme_product_v1.json
|
||||
```
|
||||
|
||||
The existing templates must continue working without any behavior changes.
|
||||
|
||||
---
|
||||
|
||||
# Runtime Compatibility
|
||||
|
||||
The preview system must support both
|
||||
|
||||
Legacy Template
|
||||
|
||||
and
|
||||
|
||||
Product Item Template
|
||||
|
||||
through template selection.
|
||||
|
||||
No breaking changes.
|
||||
|
||||
---
|
||||
|
||||
# CRM Template Module Compatibility
|
||||
|
||||
The implementation must integrate with the existing
|
||||
|
||||
```
|
||||
/dashboard/crm/settings/templates
|
||||
```
|
||||
|
||||
workflow.
|
||||
|
||||
Do not bypass
|
||||
|
||||
* template storage
|
||||
* template CRUD
|
||||
* version management
|
||||
* preview
|
||||
* activation
|
||||
|
||||
The new template shall behave exactly like existing templates.
|
||||
|
||||
---
|
||||
|
||||
# Non-Functional Requirements
|
||||
|
||||
* No breaking changes
|
||||
* No duplicated rendering pipeline
|
||||
* No duplicated adapters
|
||||
* No duplicated DTOs
|
||||
* No duplicated services
|
||||
* Reuse existing layout engine whenever possible
|
||||
* Extend existing architecture instead of replacing it
|
||||
|
||||
---
|
||||
|
||||
# Acceptance Criteria
|
||||
|
||||
* Discovery report completed before implementation.
|
||||
* Existing templates remain unchanged.
|
||||
* New Product Item template added as a separate version.
|
||||
* Product Item page inserted between Customer Detail and Condition page.
|
||||
* Unlimited Product Item rows supported.
|
||||
* Automatic page break works correctly.
|
||||
* Table headers repeat across pages.
|
||||
* Preview works correctly.
|
||||
* PDF download works correctly.
|
||||
* Existing templates continue functioning without modification.
|
||||
* `/dashboard/crm/settings/templates` fully supports the new template without regression.
|
||||
Reference in New Issue
Block a user