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
221 lines
15 KiB
Markdown
221 lines
15 KiB
Markdown
# Alga PSA Accounting Integrations & Mapping Guide
|
||
|
||
## Audience & Scope
|
||
This document serves product, engineering, implementation, and support teams. It explains how Alga PSA connects to accounting systems (QuickBooks Online/Desktop, Xero), how mapping data is managed, how exports are produced, and how to guide customers through the related workflows. It consolidates technical architecture references, UI behaviors, and operator/user instructions.
|
||
|
||
---
|
||
|
||
## Terminology
|
||
- **Adapter** – Concrete integration for an external accounting system (e.g., `quickbooks_csv`, `quickbooks_online`, `quickbooks_desktop`, `xero`).
|
||
- **Realm / Connection ID** – Adapter-specific identifier that scopes catalog data (QBO realm ID, Xero tenant ID, etc.). CSV exports typically use no realm.
|
||
- **Mapping** – Tenant-scoped record linking an Alga entity (client, service, tax code, payment term) to an external identifier plus optional metadata.
|
||
- **Canonical export payload** – Normalized invoice data produced by `AccountingExportService` prior to adapter formatting.
|
||
- **Batch** – Logical export unit grouped by tenant, adapter, and filter set, tracked in `accounting_export_batches`.
|
||
|
||
---
|
||
|
||
## System Overview
|
||
1. Finance or onboarding staff use **Settings → Integrations → Accounting** to select an accounting package.
|
||
2. Today, **QuickBooks CSV** is available (manual import/export). **QuickBooks Online (OAuth)** and **Xero (OAuth)** are shown as **Coming soon** and are disabled in the UI.
|
||
3. The Mapping UI (generic `AccountingMappingManager`) loads adapter-provided modules and persists mappings in `tenant_external_entity_mappings`.
|
||
4. When exports run, `AccountingExportService` assembles canonical payloads from invoices/charges, resolves mappings, validates readiness, and persists `accounting_export_batches` + line-level status in `accounting_export_lines` and `accounting_export_errors`.
|
||
5. Adapters transform canonical payloads into API requests (OAuth adapters) or files (CSV) and update batch/line status.
|
||
|
||
Key architecture artifacts come from:
|
||
- UI unification plan (`ee/docs/plans/2025-10-28-accounting-mapping-ui-unification-plan.md`)
|
||
- Export abstraction plan (`ee/docs/plans/2025-10-26-accounting-export-abstraction-plan.md`)
|
||
- Generic mapping components under `server/src/components/accounting-mappings/`
|
||
- CSV module factory: `server/src/components/integrations/csv/csvMappingModules.ts`
|
||
|
||
---
|
||
|
||
## Mapping Subsystem
|
||
|
||
### Data Model
|
||
- `tenant_external_entity_mappings` (Postgres) stores `integration_type`, `alga_entity_type`, `alga_entity_id`, `external_entity_id`, optional `external_realm_id`, `metadata`, status fields, and timestamps.
|
||
- Unique constraints prevent duplicate mappings per tenant/entity/realm combination.
|
||
- Metadata enables adapter-specific payload data (e.g., Xero tax components).
|
||
|
||
### Server Actions (`server/src/lib/actions/externalMappingActions.ts`)
|
||
- Expose tenant-scoped CRUD (`getExternalEntityMappings`, `createExternalEntityMapping`, `updateExternalEntityMapping`, `deleteExternalEntityMapping`).
|
||
- Enforce RBAC (`billing_settings` read/update) and wrap operations in transactions via `withTransaction`.
|
||
- Allow filtering by adapter, entity type, entity ID, and realm.
|
||
- Used directly by mapping modules unless overridden (e.g., Playwright harness, specialized metadata handling).
|
||
|
||
### Generic React Components (`server/src/components/accounting-mappings/`)
|
||
- `AccountingMappingManager` renders tabbed modules and handles empty states. Props:
|
||
- `modules`: array of `AccountingMappingModule` config objects.
|
||
- `context`: `AccountingMappingContext` including optional `realmId`.
|
||
- Optional `realmLabel`, `tabStyles`, `defaultTabId`.
|
||
- `AccountingMappingModuleView` resolves overrides, loads mapping/catalog data, renders table actions, and orchestrates dialog/delete workflows. Supports:
|
||
- Automatic enrichment of display names.
|
||
- Adapter/realm-aware CRUD.
|
||
- Playwright overrides through `window.__ALGA_PLAYWRIGHT_ACCOUNTING__`.
|
||
- `AccountingMappingDialog` provides add/edit UI, optional JSON metadata editing, manual entry fallback when catalog data is unavailable, and realm context readout.
|
||
- `types.ts` defines configuration contracts: `AccountingMappingModule`, `AccountingMappingContext`, `AccountingMappingOverrides`, and metadata toggles.
|
||
|
||
### Module Configuration Pattern
|
||
Each adapter defines a factory that returns `AccountingMappingModule[]`. For CSV, see `createCsvMappingModules()` in `server/src/components/integrations/csv/csvMappingModules.ts`.
|
||
- Modules declare:
|
||
- `id`, `adapterType`, `algaEntityType`, `externalEntityType`.
|
||
- `labels` (tab names, table column headers, dialog copy, delete confirmations).
|
||
- `elements` for deterministic DOM ids (support QA scripts).
|
||
- `load(context)` which fetches mappings and catalog options. For CSV, Alga provides the catalog options (clients/services/tax codes/payment terms) and the external value is typically manually entered.
|
||
- `create`, `update`, `remove` operations that wrap the server actions and set adapter-specific defaults (`sync_status: 'manual_link'`, metadata persistence).
|
||
- Optional `metadata.enableJsonEditor` (enables JSON textarea in dialog).
|
||
- Optional `resolveOverrides` returning `AccountingMappingOverrides` for test harness or niche adapter logic.
|
||
|
||
### Overrides & Testing Hooks
|
||
- Playwright tests register overrides via `window.__ALGA_PLAYWRIGHT_ACCOUNTING__[adapterType][moduleId]` to stub load/create/update/delete during e2e tests.
|
||
- Modules can set `overridesKey` to reuse a shared override set across tabs when needed.
|
||
|
||
### Existing Adapter Modules
|
||
- **QuickBooks CSV**: `createCsvMappingModules()` surfaces Client, Items/Services, Tax Codes, and Payment Terms mappings. The external identifier is entered manually (no OAuth catalog lookup).
|
||
- **QuickBooks Online (OAuth)** and **Xero (OAuth)**: shown as **Coming soon** in the Accounting Integrations setup screen. When enabled, they will provide catalog-backed selectors and adapter-specific metadata where required.
|
||
|
||
### Realm Handling
|
||
- `AccountingMappingContext.realmId` is optional. OAuth adapters will pass realm/tenant identifiers; CSV exports omit it (single-tenant manual flow).
|
||
- The dialog renders the realm value read-only when provided to reduce accidental mismatches.
|
||
|
||
---
|
||
|
||
## Accounting Export Architecture
|
||
|
||
### Canonical Schema (Export Abstraction Plan Phase 1-3)
|
||
- `AccountingExportService` assembles invoices/charges into canonical structures containing invoice headers, line items, taxes, and mapping resolutions.
|
||
- Stores outputs in `accounting_export_batches` and `accounting_export_lines` with statuses (`validating`, `ready`, `delivered`, `failed`), timestamps (`validated_at`, `delivered_at`), and external references.
|
||
- Maintains currency precision, service period metadata, tracking dimensions, and mapping lookups.
|
||
|
||
### Service & Workflow Integration
|
||
- Batch creation/execution exposed through workflow actions (`accounting_export.create_batch`, `accounting_export.execute_batch`) allowing Temporal workflows/Automation Hub to orchestrate exports.
|
||
- Events (`ACCOUNTING_EXPORT_COMPLETED`, `ACCOUNTING_EXPORT_FAILED`) emitted on completion for downstream automation/notifications.
|
||
- Status updates handle retries and preserve timestamps unless overwritten.
|
||
|
||
### Adapter Interface (`server/src/lib/adapters/accounting/accountingExportAdapter.ts`)
|
||
- Defines common contract: `capabilities`, `transform(canonicalBatch)`, `deliver(transformedBatch)`, optional `postProcess`.
|
||
- `AccountingAdapterRegistry` registers QuickBooks Online/Desktop and Xero adapters, resolved via `adapter_type`.
|
||
|
||
### QuickBooks Online Adapter Highlights (Phase 4)
|
||
- Transforms canonical batches into QBO invoice DTOs using `QboClientService`.
|
||
- Resolves service, tax, and payment term mappings through the generic resolver and persists SyncToken metadata (stored in mapping `metadata`).
|
||
- Deprecates legacy workflow helpers (`lookup_qbo_item_id`, `create_qbo_invoice`) in favor of export service orchestration.
|
||
- Pending work: granular rate limiting and partial-failure retry logic.
|
||
|
||
### QuickBooks Desktop (Planned)
|
||
- Generates IIF/CSV files capturing GL transactions (`TRNS`/`SPL` rows).
|
||
- Will expose download links via export dashboard and rely on GL account mappings (new mapping module planned).
|
||
|
||
### Xero Adapter Highlights (Phase 5)
|
||
- Uses `XeroClientService` for OAuth token refresh and catalog access (`listAccounts`, `listItems`, `listTaxRates`, `listTrackingCategories`).
|
||
- Supports multi-component tax lines, tracking category metadata, and error normalization into export line records.
|
||
- Manual retry trigger UI remains outstanding but service already flags failed lines for rerun.
|
||
|
||
---
|
||
|
||
## User Workflows
|
||
|
||
### Prerequisites
|
||
1. Ensure tenant has Accounting feature toggle enabled.
|
||
2. Select an accounting integration in **Settings → Integrations → Accounting**:
|
||
- **QuickBooks CSV**: available now (manual import/export).
|
||
- **QuickBooks Online (OAuth)** and **Xero (OAuth)**: coming soon (disabled in UI).
|
||
3. Confirm user role grants `Billing Settings` permissions.
|
||
|
||
### Managing Mappings
|
||
1. Navigate to **Settings → Accounting Integrations**.
|
||
2. Select **QuickBooks CSV**. The mapping tabs are rendered by `AccountingMappingManager`.
|
||
3. For each tab:
|
||
- Click **Add … Mapping**.
|
||
- Choose an Alga entity (client/service/tax code/payment term). Locked when editing an existing mapping.
|
||
- Enter the external identifier (manual entry for CSV).
|
||
- Save; dialog displays validation errors from server actions.
|
||
4. To edit or delete:
|
||
- Use the row action menu.
|
||
- Confirm deletion in modal. Deleting removes mapping record from `tenant_external_entity_mappings`.
|
||
5. Refresh data via tab reload (automatic after create/update/delete).
|
||
|
||
### Running Exports
|
||
1. From **Billing → Accounting Exports**:
|
||
- Create a new batch for **QuickBooks CSV** (or other adapters when enabled).
|
||
- Execute the batch; file-based adapters return a downloadable artifact.
|
||
2. From **Settings → Integrations → Accounting → QuickBooks CSV**:
|
||
- Choose invoice filters (date range + statuses) and click **Export CSV**.
|
||
- The export creates (or reuses) an `accounting_export_batch`, validates mappings, and generates the file.
|
||
2. Fix issues and retry:
|
||
- Missing mappings transition the batch to `needs_attention` and the UI lists what to map.
|
||
- After adding mappings, retrying validates again and the same batch can proceed once it becomes `ready`.
|
||
3. Download artifact:
|
||
- CSV exports return a downloadable CSV compatible with QuickBooks invoice import.
|
||
4. Address failures:
|
||
- Inspect `accounting_export_lines` for errors (UI surfaces message).
|
||
- Resolve root cause (often missing mapping, invalid tax rate, or authentication).
|
||
- Re-run batch after correcting data; failed lines can be retried.
|
||
|
||
### Troubleshooting Checklist
|
||
- **Missing mapping error** – Create mapping in relevant tab; rerun export.
|
||
- **Realm mismatch** – Verify connection ID shown in dialog matches authorized accounting tenant.
|
||
- **Metadata parse failure** – Validate JSON structure in mapping dialog if your adapter expects metadata.
|
||
|
||
---
|
||
|
||
## Operational Considerations
|
||
- **Permissions** – `hasPermission(user, 'billing_settings', 'read|update')` gates mapping actions. Support teams need elevated roles to assist tenants.
|
||
- **Feature flags** – Rollout of unified mapping UI may be staged; confirm feature toggle status before enabling for tenants.
|
||
- **Logging** – Server actions log create/update/delete events with tenant context. Export flows log batch lifecycle and adapter responses.
|
||
- **Auditing** – `tenant_external_entity_mappings` retains timestamps; `accounting_export_batches` captures `triggered_by` user id for traceability.
|
||
- **Backfills & migrations** – Mappings are canonicalized to `alga_entity_type = 'client'` (customers) and `alga_entity_type = 'tax_code'` (tax). Migrations normalize legacy values in `tenant_external_entity_mappings`.
|
||
- **Testing** – Use Playwright harness overrides for deterministic UI tests; Vitest covers module factories; integration tests execute export flows against sqlite/pg fixtures. Sandbox runs against QBO/Xero demo companies capture regression fixtures.
|
||
|
||
---
|
||
|
||
## Roadmap & Open Items
|
||
- Complete remaining tasks in the UI unification plan:
|
||
- Enable OAuth-based adapters (QuickBooks Online, Xero) in the Accounting Integrations setup screen.
|
||
- Add optional catalog-backed selectors for external entities (when OAuth is available).
|
||
- Publish `docs/accounting_exports.md` once the Accounting Exports dashboard ships.
|
||
- Export abstraction plan outstanding work:
|
||
- Implement QuickBooks Online rate limiting and partial failure retries.
|
||
- Deliver QuickBooks Desktop file export and download UI.
|
||
- Surface export dashboard, invoice detail integration, and notification flows.
|
||
- Build manual retry UI for Xero adapter failures.
|
||
- Documentation backlog:
|
||
- Publish customer-facing admin guide (this doc provides internal baseline).
|
||
- Add per-adapter troubleshooting appendix once dashboard UX hardens.
|
||
|
||
---
|
||
|
||
## Key Reference Files
|
||
- `server/src/components/accounting-mappings/AccountingMappingManager.tsx`
|
||
- `server/src/components/accounting-mappings/AccountingMappingModuleView.tsx`
|
||
- `server/src/components/accounting-mappings/AccountingMappingDialog.tsx`
|
||
- `server/src/components/accounting-mappings/types.ts`
|
||
- `server/src/components/integrations/csv/CSVMappingManager.tsx`
|
||
- `server/src/components/integrations/csv/csvMappingModules.ts`
|
||
- `server/src/lib/actions/externalMappingActions.ts`
|
||
- `server/src/lib/adapters/accounting/accountingExportAdapter.ts`
|
||
- `server/src/lib/services/accountingExportService.ts`
|
||
- `server/src/lib/adapters/accounting/quickBooksCSVAdapter.ts`
|
||
- `ee/docs/plans/2025-10-28-accounting-mapping-ui-unification-plan.md`
|
||
- `ee/docs/plans/2025-10-26-accounting-export-abstraction-plan.md`
|
||
|
||
---
|
||
|
||
## Appendix: Adding a New Adapter
|
||
1. **Define adapter constants** (`adapterType`, realm semantics).
|
||
2. **Implement module factory** returning `AccountingMappingModule[]`; reuse server actions or build adapter-specific actions as needed.
|
||
3. **Expose manager** in UI (e.g., `<AccountingMappingManager modules={createAdapterModules()} context={{ realmId }} />`).
|
||
4. **Implement export adapter** conforming to `accountingExportAdapter` contract; register it in `AccountingAdapterRegistry`.
|
||
5. **Wire credential management** (OAuth/token exchange) and catalog loaders.
|
||
6. **Extend Playwright overrides** for new adapter module IDs.
|
||
7. **Document user-facing setup** within release notes and support knowledge base.
|
||
|
||
---
|
||
|
||
## Appendix: User-Facing Walkthrough Template
|
||
Use the following outline when crafting tenant-facing guides:
|
||
1. Prerequisites (permissions, connector setup, sandbox links).
|
||
2. Mapping checklist per entity type with screenshots.
|
||
3. Export run book (filters, expected processing time, verification).
|
||
4. Troubleshooting table (common errors, resolutions, escalation path).
|
||
5. Change log capturing adapter updates, credential reauthorization windows, and contact info.
|