PSA/ee/docs/plans/xero-csv-export-progress.md
Hermes 284313f908
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
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

16 KiB

Xero CSV Export/Import - Implementation Progress (Updated for 2025 Accounting Plan)

Overview

This document tracks the implementation progress of the Xero CSV Export/Import feature. The goal is a CSV-based Xero integration (no OAuth required) that has the same outcomes and invariants as the automated accounting export system (batches, mappings, audit trail, and “already exported” behavior) — the only difference should be the manual import step.

Branch: feature/xero-csv-export Feature File: ee/docs/plans/features-xero-csv-export.json Started: 2024-12-16 Last Updated: 2025-12-18


Progress Summary

Category Completed Total Progress
Backend 9 9 100%
Frontend 8 8 100%
Data model / migrations 2 2 100%
Documentation 1 1 100%
Testing 0 5 0%
Overall 20 25 80%

Implementation Log

2024-12-16 - Project Setup

  • Created feature branch feature/xero-csv-export from release/0.15.0
  • Set up development environment with unique ports (3007, 5434, 6381, 6434, 1236)
  • Created feature tracking files:
    • ee/docs/plans/features-xero-csv-export.json
    • ee/docs/plans/xero-csv-export-progress.md (this file)
  • Completed codebase exploration and planning phase

2025-12-18 - Plan refresh after QuickBooks CSV work

  • Updated plan to reflect the new unified Accounting Integrations setup + CSV mapping/export patterns.
  • Updated feature list to include missing "full integration" work: mappings UI/modules, batch immutability, client (contact) export/import, lock reset warnings, and parity with automated exports.

2025-12-18 - Core Implementation

Backend:

  • Created XeroCsvAdapter (server/src/lib/adapters/accounting/xeroCsvAdapter.ts)
    • File-based delivery mode with Xero-compatible CSV format
    • Fixed tracking categories: "Source System"/"AlgaPSA" and "External Invoice ID"/{invoice_id}
    • Tax delegation support (exports as Draft for Xero tax calculation)
  • Registered adapter in server/src/lib/adapters/accounting/registry.ts
  • Created XeroCsvTaxImportService (server/src/lib/services/xeroCsvTaxImportService.ts)
    • Parses Xero Invoice Details Report CSV format
    • Matches invoices using tracking categories
    • Preview and import functionality with audit trail
  • Created server actions (server/src/lib/actions/integrations/xeroCsvActions.ts)
  • Created API routes:
    • server/src/app/api/v1/accounting-exports/[batchId]/download/route.ts
    • server/src/app/api/v1/accounting-exports/xero-csv/tax-import/route.ts

Frontend:

  • Created XeroCsvSettings component (server/src/components/settings/integrations/XeroCsvSettings.tsx)
  • Updated XeroIntegrationSettings with CSV/OAuth mode toggle
  • Created XeroCsvExportPanel (server/src/components/billing-dashboard/accounting/XeroCsvExportPanel.tsx)
  • Created XeroCsvTaxImportPanel (server/src/components/billing-dashboard/accounting/XeroCsvTaxImportPanel.tsx)
  • Updated AccountingExportsTab for Xero CSV batch support

Documentation:

  • Created user guide (ee/docs/guides/xero-csv-integration.md)
    • Setup instructions (tracking categories, mappings)
    • Invoice export workflow
    • Tax import workflow
    • Client export/import instructions
    • Lock reset and batch reversal documentation
    • Troubleshooting guide

2025-12-18 - Integration with Unified Accounting Setup

After merging release/0.15.0, adapted Xero CSV integration to work with the new unified accounting integrations infrastructure:

Infrastructure Integration:

  • Updated AccountingIntegrationsSetup.tsx to add xero_csv as a fourth integration option
  • Created XeroCsvIntegrationSettings.tsx following the CSVIntegrationSettings pattern
    • Merged settings from old XeroCsvSettings.tsx (date format, currency, setup acknowledgement)
    • Added mapping manager integration
    • Added workflow guide and navigation
  • Created xeroCsvMappingModules.ts for Xero CSV-specific mapping modules
    • Clients, Items/Services, Tax Codes, Payment Terms
    • Xero-specific terminology and identifiers
  • Created XeroCsvMappingManager.tsx component using the shared AccountingMappingManager
  • Updated CSV integration index exports
  • Removed old XeroCsvSettings.tsx (merged into XeroCsvIntegrationSettings.tsx)

2025-12-18 - Backend Completion

Completed all remaining backend tasks:

Client Export/Import:

  • Created XeroCsvClientSyncService (server/src/lib/services/xeroCsvClientSyncService.ts)
    • Export Alga clients to Xero Contacts CSV format
    • Import Xero Contacts CSV with preview and matching logic
    • Persist external ID mappings per tenant + adapter type
  • Added client sync actions to xeroCsvActions.ts
  • Created client export API route (/api/v1/accounting-exports/xero-csv/client-export/route.ts)
  • Created client import API route (/api/v1/accounting-exports/xero-csv/client-import/route.ts)

Batch Parity:

  • Added xero_csv to AccountingAdapterType in companySync.types.ts
  • Updated XeroCsvAdapter.deliver() to create invoice mappings via KnexInvoiceMappingRepository
  • Added xero_csv to shouldIncludePendingExternalDrafts() in invoice selector

Tax Blocking State:

  • Verified existing tax blocking logic in taxSourceActions.ts handles pending_external state
  • Confirmed XeroCsvTaxImportService properly updates tax_source from pending_external to external
  • Invoice finalization is blocked until tax is imported (via validateInvoiceFinalization)

2025-12-18 - Data Model & Client Sync UI Completion

Data Model / Migrations:

  • Created server/migrations/20251218010000_add_xero_csv_mapping_normalization.cjs
    • Normalizes companyclient for xero_csv mappings
    • Normalizes tax_regiontax_code for xero and xero_csv mappings
    • Both up and down migrations implemented
  • External ID mapping persistence already handled by XeroCsvClientSyncService
    • Persists client mappings per tenant + adapter type via tenant_external_entity_mappings
    • Used for client import reconciliation

Client Sync UI:

  • Created XeroCsvClientSyncPanel.tsx component
    • Export clients to Xero Contacts CSV with download
    • Import clients from Xero CSV with preview table
    • Match options: name, email, or Xero contact ID
    • Create/update/skip actions per client
    • Full preview → confirm → execute workflow
  • Integrated XeroCsvClientSyncPanel into XeroCsvIntegrationSettings.tsx

Backend Tasks

1. Xero CSV Adapter (adapter-create)

File: server/src/lib/adapters/accounting/xeroCsvAdapter.ts Status: DONE

  • Create adapter class implementing AccountingExportAdapter
  • Implement capabilities() with deliveryMode: 'file'
  • Implement transform() to generate Xero-compatible CSV
  • Include stable reconciliation identifiers (tracking categories)
  • Implement deliver() to prepare file artifact

2. Register Adapter (adapter-register)

File: server/src/lib/adapters/accounting/registry.ts Status: DONE

  • Import XeroCsvAdapter
  • Add to createDefault() adapter list

3. CSV Mapping Modules (mapping-modules)

File: server/src/components/integrations/csv/xeroCsvMappingModules.ts Status: DONE

  • Implement mapping modules for adapterType: 'xero_csv'
  • Support mappings for: Clients, Items/Services, Tax Codes, Payment Terms
  • Ensure terminology uses "Clients" (not "Customers") throughout UI/config
  • Default the mapping tab view to "Clients"

4. Client Export/Import (client-export-import)

Files:

  • server/src/lib/services/xeroCsvClientSyncService.ts

  • server/src/app/api/v1/accounting-exports/xero-csv/client-export/route.ts

  • server/src/app/api/v1/accounting-exports/xero-csv/client-import/route.ts Status: DONE

  • Export Alga Clients to Xero Contacts CSV (manual import to Xero)

  • Import Xero Contacts CSV back into Alga (match/update existing clients; optionally create new clients)

  • Persist external-id/linking mappings for clients per tenant + adapter type

5. Tax Import Service (tax-import-service)

File: server/src/lib/services/xeroCsvTaxImportService.ts Status: DONE

  • Parse Xero Invoice Details Report CSV format
  • Match invoices back to Alga using tracking categories
  • Create previewTaxImport() method
  • Create importTaxFromReport() method
  • Record imports in external_tax_imports with consistent audit trail

6. Export/TX Import Actions (server-actions)

File: server/src/lib/actions/integrations/xeroCsvActions.ts Status: DONE

  • Settings read/write for Xero CSV mode
  • Export: create/execute batch and return download artifact
  • Import: preview + execute tax import
  • Import: preview + execute client import

7. Xero CSV API Routes (api-routes)

Files: server/src/app/api/v1/accounting-exports/... Status: DONE

  • Export download endpoint ([batchId]/download/route.ts)
  • Tax import endpoint (xero-csv/tax-import/route.ts)
  • Client export endpoint (xero-csv/client-export/route.ts)
  • Client import endpoint (xero-csv/client-import/route.ts)

8. Batch Parity / Immutability (batch-parity)

Files:

  • server/src/lib/adapters/accounting/xeroCsvAdapter.ts

  • server/src/lib/services/accountingExportInvoiceSelector.ts

  • server/src/lib/services/companySync/companySync.types.ts Status: DONE

  • Ensure exports create persisted batches with an audit trail (no in-memory-only exports)

  • Match OAuth export behavior for "already exported invoices" and date overlap handling

  • Added invoice mapping persistence in XeroCsvAdapter.deliver() to prevent re-export

  • Added xero_csv to AccountingAdapterType

9. External Tax Blocking State (tax-blocking-state)

Files:

  • server/src/lib/actions/taxSourceActions.ts

  • server/src/lib/services/accountingExportInvoiceSelector.ts Status: DONE

  • If Xero is the tax source, treat invoices as blocked from finalization until tax is imported

  • Default export selection to include Draft invoices when invoices are awaiting external tax

  • validateInvoiceFinalization() blocks finalization for pending_external tax source

  • Added xero_csv to shouldIncludePendingExternalDrafts() for draft invoice inclusion


Data model / migrations tasks

A. Mapping type normalization (mapping-normalization)

Files: server/migrations/20251218010000_add_xero_csv_mapping_normalization.cjs Status: DONE

  • Add/verify migrations to normalize mapping types (company → client, tax_region → tax_code) for xero_csv
  • Ensure the mapping resolver uses canonical mapping types across adapters

B. External ID mapping persistence (external-id-mapping)

Files: server/src/lib/services/xeroCsvClientSyncService.ts Status: DONE

  • Persist Xero external identifiers for clients and invoices per tenant + adapter type
  • Use these mappings for client import and tax import reconciliation

Frontend Tasks

10. Xero CSV Integration Settings Panel (xero-csv-settings)

File: server/src/components/settings/integrations/XeroCsvIntegrationSettings.tsx Status: DONE

  • Show instructions for manual import/export workflows (contacts + invoices + tax import)
  • Surface key defaults (invoice numbering/reference scheme; date formatting if needed)
  • Link users to mapping setup (must complete before exporting)

11. Accounting Integrations Setup Wiring (integrations-setup)

File: server/src/components/settings/integrations/AccountingIntegrationsSetup.tsx Status: DONE

  • Keep Xero OAuth visible but disabled / "Coming soon" when in CSV mode
  • Add Xero CSV as a selectable integration option (fourth card)
  • Ensure only the selected integration's panes are displayed

12. Mapping Manager UI (mapping-manager)

File: server/src/components/integrations/csv/XeroCsvMappingManager.tsx Status: DONE

  • Use shared mapping manager UI (standard tab control + primary color)
  • Default to the "Clients" tab on load
  • Ensure "Add Client Mapping" language (not "Customer")

13. Xero CSV Export UI (export-panel)

File: server/src/components/billing-dashboard/accounting/XeroCsvExportPanel.tsx Status: DONE

  • Export dialog that matches OAuth export invariants (status defaults, overlap behavior, lock handling)
  • Provide "Reset export lock" / "Reverse batch" actions with warnings

14. Xero CSV Tax Import UI (tax-import-panel)

File: server/src/components/billing-dashboard/accounting/XeroCsvTaxImportPanel.tsx Status: DONE

  • Upload + preview + execute flow with clear reconciliation identifiers
  • History + rollback UI (consistent with CSV tax import patterns)

15. Accounting Exports Tab Update (exports-tab-update)

File: server/src/components/billing-dashboard/accounting/AccountingExportsTab.tsx Status: DONE

  • Ensure Xero CSV batches behave the same as other adapters (download, errors, lines, status)
  • Link to Xero CSV tax import + client export/import panels where appropriate

16. Client Export/Import UI (client-sync-ui)

File: server/src/components/settings/integrations/XeroCsvClientSyncPanel.tsx Status: DONE

  • Export clients (contacts CSV) action + instructions
  • Import clients from Xero contacts CSV with preview + confirmation
  • Clear matching rules and "create vs update" outcomes

Documentation Tasks

17. User Instructions (user-instructions)

File: ee/docs/guides/xero-csv-integration.md Status: DONE

  • Xero contacts (clients) import/export guide
  • Invoice export workflow instructions
  • Tax import workflow instructions + rollback semantics
  • Troubleshooting section

Testing Tasks

18. Adapter Tests (adapter-tests)

File: server/src/test/unit/accounting/xeroCsvAdapter.spec.ts Status: Not Started

  • CSV generation tests
  • Reconciliation identifier inclusion tests
  • Multi-invoice batch tests

19. Import Service Tests (import-tests)

File: server/src/test/unit/accounting/xeroCsvTaxImportService.spec.ts Status: Not Started

  • CSV parsing tests
  • Invoice matching tests
  • Tax application tests

20. Client Sync Tests (client-sync-tests)

File: server/src/test/unit/accounting/xeroCsvClientSyncService.spec.ts Status: Not Started

  • Client export CSV tests
  • Client import matching/creation tests

21. Integration Tests (integration-tests)

File: server/src/test/integration/accounting/xeroCsvExport.integration.test.ts Status: Not Started

  • Full export workflow test
  • Full import workflow test
  • Error handling tests

22. Playwright Smoke Tests (ui-smoke-tests)

File: server/src/test/playwright/accounting/xeroCsv.spec.ts Status: Not Started

  • Integrations setup navigation + disabled OAuth cards
  • Mapping manager default tab + save mapping flows
  • Export + tax import smoke

Notes & Decisions

Key Implementation Notes

  1. Terminology: Alga “Customers” are Clients; all UI/labels should use “Client”.
  2. Outcome Parity: Xero CSV should use the same mapping resolver, batch persistence, and “already exported” handling as automated exports.
  3. Reconciliation Identifiers: Prefer stable identifiers embedded in the CSV (InvoiceNumber + Reference containing Alga invoice ID) over relying on fragile matching rules.
  4. Immutability: Exports are immutable; “re-export” is implemented via explicit lock reset with warnings (invoice-level and batch-level).
  5. External Tax: When Xero is tax source, invoices should be blocked from finalization until taxes are imported (state is derived, not stored as a new field).

Technical Debt / Future Improvements

  • Consider adding batch progress tracking for large exports
  • Consider adding retry logic for partial imports
  • Consider caching Xero report column mappings per tenant (once the report format is finalized)

Commits

Date Commit Description
2024-12-16 TBD Initial feature setup and planning files

Last Updated: 2025-12-18 (Backend, Frontend, Data Model Complete - 80%; Only Testing Remains)