Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
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-exportfromrelease/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.jsonee/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.tsserver/src/app/api/v1/accounting-exports/xero-csv/tax-import/route.ts
Frontend:
- Created
XeroCsvSettingscomponent (server/src/components/settings/integrations/XeroCsvSettings.tsx) - Updated
XeroIntegrationSettingswith 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
AccountingExportsTabfor 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.tsxto addxero_csvas a fourth integration option - Created
XeroCsvIntegrationSettings.tsxfollowing theCSVIntegrationSettingspattern- Merged settings from old
XeroCsvSettings.tsx(date format, currency, setup acknowledgement) - Added mapping manager integration
- Added workflow guide and navigation
- Merged settings from old
- Created
xeroCsvMappingModules.tsfor Xero CSV-specific mapping modules- Clients, Items/Services, Tax Codes, Payment Terms
- Xero-specific terminology and identifiers
- Created
XeroCsvMappingManager.tsxcomponent using the sharedAccountingMappingManager - Updated CSV integration index exports
- Removed old
XeroCsvSettings.tsx(merged intoXeroCsvIntegrationSettings.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_csvtoAccountingAdapterTypeincompanySync.types.ts - Updated
XeroCsvAdapter.deliver()to create invoice mappings viaKnexInvoiceMappingRepository - Added
xero_csvtoshouldIncludePendingExternalDrafts()in invoice selector
Tax Blocking State:
- Verified existing tax blocking logic in
taxSourceActions.tshandlespending_externalstate - Confirmed
XeroCsvTaxImportServiceproperly updatestax_sourcefrompending_externaltoexternal - 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
company→clientfor xero_csv mappings - Normalizes
tax_region→tax_codefor xero and xero_csv mappings - Both up and down migrations implemented
- Normalizes
- 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
- Persists client mappings per tenant + adapter type via
Client Sync UI:
- Created
XeroCsvClientSyncPanel.tsxcomponent- 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
XeroCsvClientSyncPanelintoXeroCsvIntegrationSettings.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.tsStatus: 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_importswith 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.tsStatus: 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_csvtoAccountingAdapterType
9. External Tax Blocking State (tax-blocking-state)
Files:
-
server/src/lib/actions/taxSourceActions.ts -
server/src/lib/services/accountingExportInvoiceSelector.tsStatus: 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 forpending_externaltax source -
Added
xero_csvtoshouldIncludePendingExternalDrafts()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
- Terminology: Alga “Customers” are Clients; all UI/labels should use “Client”.
- Outcome Parity: Xero CSV should use the same mapping resolver, batch persistence, and “already exported” handling as automated exports.
- Reconciliation Identifiers: Prefer stable identifiers embedded in the CSV (InvoiceNumber + Reference containing Alga invoice ID) over relying on fragile matching rules.
- Immutability: Exports are immutable; “re-export” is implemented via explicit lock reset with warnings (invoice-level and batch-level).
- 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)