Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
183 lines
10 KiB
Markdown
183 lines
10 KiB
Markdown
# PRD — Invoice Designer Paper Presets and Margins
|
|
|
|
- Slug: `invoice-designer-paper-presets-and-margins`
|
|
- Date: `2026-03-14`
|
|
- Status: Draft
|
|
|
|
## Summary
|
|
|
|
Add first-class print settings to the invoice template designer so template authors can choose a named paper preset and a configurable uniform page margin, and have the designer canvas, preview surface, and generated PDFs all honor the same settings.
|
|
|
|
V1 scope is intentionally constrained:
|
|
|
|
- named paper presets only
|
|
- one uniform page margin value in millimeters
|
|
- no custom paper sizes
|
|
- no per-side margin controls
|
|
|
|
The implementation should introduce a shared print-settings model and a shared PDF print-options resolver so both current PDF generation paths behave consistently without requiring a full service consolidation in the same change.
|
|
|
|
## Problem
|
|
|
|
The invoice template designer currently has no intentional page-setup model.
|
|
|
|
Instead, page size and printable area are split across unrelated hard-coded implementations:
|
|
|
|
- the design canvas uses a fixed `816 x 1056` surface, which is US Letter at `96dpi`
|
|
- the page node defaults include `40px` padding that acts like a content margin
|
|
- the preview shell uses a separate fixed “paper” chrome with different dimensions and padding
|
|
- one PDF generation path hard-codes `A4` with explicit `10mm` margins
|
|
- another PDF generation path hard-codes `A4` with no explicit margin block
|
|
|
|
This creates three user-facing failures:
|
|
|
|
1. template authors cannot intentionally choose a target sheet size
|
|
2. PDF output margin behavior is inconsistent and not user-configurable
|
|
3. designer, preview, and exported PDF can disagree about what the page actually is
|
|
|
|
## Goals
|
|
|
|
- Let template authors choose a named paper preset from the designer UI.
|
|
- Let template authors set a uniform page margin value for the template.
|
|
- Make the designer artboard reshape immediately when the selected paper preset changes.
|
|
- Make the preview shell reflect the same page dimensions and printable inset as the selected settings.
|
|
- Make both current PDF generation paths honor the same resolved paper preset and margin settings.
|
|
- Preserve compatibility for existing templates without requiring a database migration.
|
|
- Keep one authoritative template-level source of truth for print settings.
|
|
|
|
## Non-goals
|
|
|
|
- Custom paper sizes in v1.
|
|
- Separate top/right/bottom/left margin controls in v1.
|
|
- Full multi-page pagination or page-break authoring improvements.
|
|
- Full consolidation of the package-level and server-level PDF services in this plan.
|
|
- New observability, metrics, rollout flags, or operational tooling beyond normal validation and regression coverage.
|
|
|
|
## Users and Primary Flows
|
|
|
|
### Primary users
|
|
|
|
- Billing admins authoring invoice templates.
|
|
- Implementers validating that visual designer output matches exported PDFs.
|
|
|
|
### Primary flows
|
|
|
|
1. **Choose a paper preset**
|
|
- User opens the invoice template designer.
|
|
- User selects `Letter`, `A4`, or `Legal`.
|
|
- The artboard, rulers, and visible page chrome reshape immediately.
|
|
|
|
2. **Adjust page margin**
|
|
- User edits the page margin in millimeters.
|
|
- The printable area inset updates in the designer and preview.
|
|
- Saving the template persists the setting.
|
|
|
|
3. **Preview with production parity**
|
|
- User opens preview for a sample or existing invoice.
|
|
- Preview reflects the same sheet size and margin as the design surface.
|
|
|
|
4. **Generate a PDF**
|
|
- User generates or downloads a PDF through any existing invoice PDF flow.
|
|
- The generated PDF uses the selected paper preset and margin instead of hard-coded defaults.
|
|
|
|
5. **Open an older template**
|
|
- User opens an existing template that predates explicit print settings.
|
|
- The system infers or falls back to sensible resolved settings without breaking load, preview, save, or PDF generation.
|
|
|
|
## UX / UI Notes
|
|
|
|
- Print settings must be reachable even though the `page` node is not normally selectable on the canvas.
|
|
- V1 should expose page setup in a dedicated, obvious control surface in the designer, such as:
|
|
- a document/page settings section in the inspector when no specific child node is selected, or
|
|
- a page setup control area in the designer shell/toolbar
|
|
- Paper preset control:
|
|
- dropdown/select with named presets
|
|
- initial preset list for v1: `Letter`, `A4`, `Legal`
|
|
- Margin control:
|
|
- numeric input in millimeters
|
|
- one value applied uniformly to all sides
|
|
- live updates while editing, with validation/clamping for obviously invalid values
|
|
- The preview paper shell should stop using independent fixed dimensions and instead derive its chrome from resolved print settings.
|
|
- The code tab remains generated/read-only; no raw print-settings JSON editor is needed in v1.
|
|
|
|
## Requirements
|
|
|
|
### Functional Requirements
|
|
|
|
- `FR-001` Add a shared invoice print preset registry for at least `Letter`, `A4`, and `Legal`.
|
|
- `FR-002` Represent template print settings as first-class invoice template AST metadata, including paper preset identity and uniform margin.
|
|
- `FR-003` Keep print settings additive and backward-compatible so templates without explicit print metadata still load and render.
|
|
- `FR-004` Infer legacy/resolved print settings from existing page/document width, height, and padding when explicit metadata is absent and known preset dimensions are detected.
|
|
- `FR-005` Preserve print settings through designer workspace import/export, save, reopen, and preview flows.
|
|
- `FR-006` Add a designer store action that applies print settings by synchronizing runtime geometry and authored style/layout state for the hidden document/page nodes.
|
|
- `FR-007` Initialize new designer workspaces with default print settings and matching document/page geometry.
|
|
- `FR-008` Add reachable UI controls for selecting a named paper preset in the visual designer.
|
|
- `FR-009` Add reachable UI controls for editing a uniform margin value in millimeters.
|
|
- `FR-010` Validate paper preset and margin input so invalid settings are rejected or corrected before they produce broken layout/PDF output.
|
|
- `FR-011` Update the design canvas, artboard bounds, and rulers to derive dimensions from resolved print settings instead of fixed constants alone.
|
|
- `FR-012` Update the preview paper shell to derive visible sheet dimensions and printable inset from resolved print settings instead of hard-coded CSS dimensions and padding.
|
|
- `FR-013` Ensure authoritative preview export/render uses the resolved page size and margin so preview content matches the configured print settings.
|
|
- `FR-014` Introduce a shared resolver that converts template print settings into Puppeteer PDF options.
|
|
- `FR-015` Wire the server-side invoice PDF generation service to the shared print-settings resolver instead of hard-coded `A4`/margin defaults.
|
|
- `FR-016` Wire the package-level billing PDF generation service to the same shared print-settings resolver instead of hard-coded `A4` defaults.
|
|
- `FR-017` Ensure both current PDF generation paths produce the same paper preset and margin behavior for the same template settings.
|
|
- `FR-018` Preserve older templates with no explicit print metadata through preview and PDF generation without schema migration or manual repair.
|
|
|
|
### Non-functional Requirements
|
|
|
|
- `NFR-001` Mapping from named paper preset -> designer size -> preview shell -> Puppeteer options must be deterministic and centralized.
|
|
- `NFR-002` Existing invoice templates must remain loadable and editable without a breaking schema migration.
|
|
- `NFR-003` The designer should reshape quickly enough that switching paper presets feels immediate in normal editing flows.
|
|
- `NFR-004` Print setting changes must not create parity drift between preview and generated PDFs.
|
|
- `NFR-005` V1 should minimize scope by reusing the existing template AST, workspace import/export, preview pipeline, and PDF generation entry points.
|
|
|
|
## Data / API / Integrations
|
|
|
|
- Extend invoice template AST metadata to include a print-settings shape, for example:
|
|
- `paperPreset`
|
|
- `marginMm`
|
|
- Keep template-level metadata as the semantic source of truth.
|
|
- Continue exporting resolved width/height/padding into the AST layout/styles needed by the current renderer paths so existing HTML/CSS rendering behavior stays compatible.
|
|
- Add a shared preset/dimension utility that can:
|
|
- map preset -> physical size in mm
|
|
- map preset -> editor size in px at `96dpi`
|
|
- convert uniform margin mm -> preview/canvas padding representation
|
|
- convert resolved settings -> Puppeteer `format` and `margin`
|
|
- Update the workspace import/export layer so explicit metadata wins, while legacy width/height/padding can still be interpreted when metadata is absent.
|
|
- No new external API endpoints are required for v1.
|
|
|
|
## Security / Permissions
|
|
|
|
- No new permission model is introduced.
|
|
- Existing invoice template edit permissions continue to govern who can change print settings.
|
|
- Existing invoice/PDF read or generate permissions continue to govern who can preview or export invoices.
|
|
|
|
## Observability
|
|
|
|
- No new observability scope is included in v1 beyond normal editor validation states and existing error surfacing.
|
|
|
|
## Rollout / Migration
|
|
|
|
- No database migration is required.
|
|
- Existing templates without explicit print metadata should load through inference or fallback behavior.
|
|
- New templates should initialize with explicit print settings so they no longer depend on legacy hard-coded geometry alone.
|
|
- This plan does not require immediate consolidation of the two PDF services, but it does require both services to share one print-settings resolution path.
|
|
|
|
## Open Questions
|
|
|
|
- None blocking for the v1 plan. The selected scope is:
|
|
- named presets only
|
|
- uniform margin only
|
|
- no custom sizes
|
|
|
|
## Acceptance Criteria (Definition of Done)
|
|
|
|
- A template author can choose a named paper preset in the invoice designer.
|
|
- A template author can set a uniform page margin in millimeters.
|
|
- Changing the selected preset reshapes the designer canvas to the matching page size.
|
|
- Preview reflects the same page size and printable inset as the selected settings.
|
|
- Both current PDF generation paths honor the same selected preset and margin instead of hard-coded defaults.
|
|
- Existing templates without explicit print settings still load, preview, save, and export successfully.
|
|
- Saving and reopening a template preserves the configured paper preset and margin.
|
|
- Automated coverage exists for schema/import-export behavior, canvas reshape behavior, preview shell behavior, and both PDF paths.
|