Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
8.6 KiB
Products (MSP Offer Catalog) — PRD
Plan date: 2026-01-01
Owner: TBD
Status: Draft (discovery in progress)
1) Problem Statement
Alga PSA needs a first-class way for MSPs to define Products they sell to customers and then use those products consistently across:
- Contracts (recurring + one-time billing)
- Automated invoices (from billing engine)
- Manual invoices
- Tax calculation and tax reporting/export
- Accounting exports (QBO/Xero/etc.)
Today, Alga already has a Service Catalog that is used as a de-facto “sellable item” source in billing, but “Products” as a user-facing concept is not implemented end-to-end, and the billing engine’s product / license charge paths are stubbed.
2) Goals
V1 goals (no inventory)
- Provide a Products list (CRUD) with typical product properties and multi-currency sales pricing.
- Allow adding products to:
- Contract templates + contracts + assigned client contracts
- Manual invoices
- Ensure products flow through existing pipelines:
- Tax (internal calculation, with future external passthrough compatibility)
- Invoice rendering (PDF/template display)
- Accounting exports and mapping
- Keep the model extensible to support future inventory augmentation without rewriting billing.
3) Non-Goals (V1)
- Inventory counts, stock locations/warehouses, purchase orders, receiving, costing methods (FIFO/LIFO), serial numbers.
- Quotes/estimates (unless already present elsewhere).
- Full CPQ/bundling engine (simple “bundle as a product group” can be deferred).
4) Users / Personas
- MSP Admin / Billing Admin: maintains catalog, pricing, taxability, accounting mapping.
- Sales / Ops: selects products when building contracts or invoicing.
- Finance/Accounting: relies on correct tax and export mappings.
5) Proposed Domain Model
5.1 Key design decision: “Products” vs “Service Catalog”
Observation: The current service_catalog is already the authoritative “sellable item” table for billing, taxation hooks, and accounting mapping resolution.
Decision (V1): Treat Product as a subset/view of catalog items and keep a single source of truth for sellable items.
- Implement via
service_catalog.item_kind(at least:service | product) plus product fields onservice_catalog(or tightly-coupled extension tables if we want to keep the base table slimmer). - Downstream systems (contracts, invoices, accounting mapping, taxes) continue to anchor on the catalog item id (
service_catalog.service_id).
5.2 Product properties (minimum)
Required:
nameactive/ availabilitysales_price(multi-currency supported; aligned with existing service pricing)
Strongly recommended:
sku(unique per tenant; configurable requirement)descriptionunit_of_measure(defaults to “each”)tax_rate_id(nullable: “non-taxable”)categoryand/ortype(for filtering and mapping)vendor/manufacturercost(non-inventory, for margin reporting)
Deferred but designed-for:
mfr_part_numberexternal_ids(for PSA/RMM/accounting integrations)
6) Integrations & System Touchpoints
6.1 Contracts
Products must be addable to:
- Contract templates (as default included products and quantities)
- Contracts (as a line’s included items)
- Client contract assignments (snapshot and per-client override)
Key behaviors:
- Quantity can be overridden at client level
- Price source hierarchy matches existing pricing rules (template → contract → schedule → client override)
- V1 starts with recurring product billing on contracts (no bill-once behavior yet)
6.2 Billing Engine
Billing engine must produce product charges as type: 'product' based on the items attached to a client contract line.
Current calculateProductCharges / calculateLicenseCharges are placeholders and must be implemented or removed in favor of a unified path.
6.3 Invoices (manual + automated)
- Manual invoice item picker should allow selecting products and entering quantity/price overrides.
- Automated invoices must render products in the same pipeline as other charges, with consistent tax calculation and rounding.
- Invoice rendering/templates must display product lines clearly (and optionally distinguish product vs service for UX).
6.4 Taxes
- Product lines must be taxable/non-taxable via
tax_rate_id. - Must align with the tax “source of truth” approach (internal calc now; external passthrough possible later).
6.5 Accounting Export
Accounting export mapping should work seamlessly:
- If products remain in
service_catalog, existing mapping resolution can apply. - If a separate products entity is introduced, mapping + resolver must be extended accordingly.
6.6 Tickets, Projects, Time Entries
V1 must support attaching products to:
- Tickets (materials/parts used on a ticket) that flow into invoicing
- Projects (materials/parts used on a project) that flow into invoicing
- Time entries (see Open Question: attach products directly to time entries vs a separate “materials” record associated to the time entry)
Core requirement: these product usages must be attributable (which ticket/project/time entry) and must map to invoice items consistently (tax, currency, accounting mapping).
Decision (V1 billing path): Ticket/project materials should flow into invoicing via the billing engine, like usage/time:
- Materials become billable “charges” in billing runs (not direct invoice items at the time of entry).
- Invoice generation persists those charges into invoice items using the same tax/rounding/persistence pipeline as other charges.
7) UX / UI Notes (V1)
7.1 Navigation
- Add a Products entry under Billing (or Sales) that lands on a Product Manager.
- The UI can be implemented as a filtered view of catalog items (if using Option A) to avoid duplicating “Service Catalog” tooling.
7.2 Product Manager
- Table view: name, SKU, active, type/category, primary price, tax rate, last updated.
- Create/edit: name, description, SKU, pricing (multi-currency), tax rate.
- Fast filtering: active, category/type, search by name/SKU.
7.3 Contract & Invoice selection
- Product picker with search and keyboard-friendly UX.
- Display price in correct currency context (contract/client currency).
- Show “not priced in this currency” validation consistent with contract wizard behavior.
8) Rollout / Migration Strategy
- Add DB fields/tables behind a feature flag if needed.
- Backfill existing
service_catalogentries:- Default
item_kindtoservice(or map using service types/categories where possible). - Allow manually reclassifying into
productafter rollout.
- Default
- Ensure invoice rendering and accounting exports remain backwards compatible.
9) Risks & Mitigations
- Model duplication risk: creating a parallel products table can fragment pricing/tax/mapping logic. Mitigate with single catalog id.
- Billing correctness risk: product charges affect taxes, totals, and exports. Mitigate with strong integration tests.
- UX confusion risk: “Service Catalog” vs “Products” overlaps. Mitigate with clear taxonomy and filtered views.
10) Open Questions (need your answers)
Resolved:
- Products are a subset/view of Service Catalog (single catalog id).
- Licenses need term/period semantics; V1 can implement this as product properties (optionally still emitting
type: 'license'charges where appropriate). - Contracts: recurring only for V1.
- V1 product fields: SKU, cost, vendor/manufacturer, category/type, tax rate. GL/account mapping should piggyback on existing service mapping.
- Price overrides are allowed; no audit trail requirement yet.
- No line-level discounts for V1.
- Products must be usable on contracts + invoices + tickets + projects + time entries.
Still open: 8. Time-entry support: V1 starts with products/materials on tickets and projects only; model uses a separate “materials” record (not attached directly to time entries). 9. Ticket/project product usages: auto-bill for V1 (no approval workflow). 10. License semantics: V1 starts with term metadata only (no start/end dates, no proration rules).
11) Definition of Done (V1)
- Admin can CRUD products with multi-currency pricing and tax configuration.
- Products can be added to contracts and manual invoices.
- Automated billing produces product line items correctly (quantity, pricing, taxes).
- Invoice PDFs/templates render products correctly.
- Accounting exports include product lines with correct mapping and tax behavior.
- Automated tests cover core flows and edge cases (taxable vs non-taxable, missing currency price, overrides).