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
388 lines
16 KiB
Markdown
388 lines
16 KiB
Markdown
# 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
|
|
|
|
- [x] Created feature branch `feature/xero-csv-export` from `release/0.15.0`
|
|
- [x] Set up development environment with unique ports (3007, 5434, 6381, 6434, 1236)
|
|
- [x] Created feature tracking files:
|
|
- `ee/docs/plans/features-xero-csv-export.json`
|
|
- `ee/docs/plans/xero-csv-export-progress.md` (this file)
|
|
- [x] Completed codebase exploration and planning phase
|
|
|
|
### 2025-12-18 - Plan refresh after QuickBooks CSV work
|
|
|
|
- [x] Updated plan to reflect the new unified Accounting Integrations setup + CSV mapping/export patterns.
|
|
- [x] 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:**
|
|
- [x] 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)
|
|
- [x] Registered adapter in `server/src/lib/adapters/accounting/registry.ts`
|
|
- [x] 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
|
|
- [x] Created server actions (`server/src/lib/actions/integrations/xeroCsvActions.ts`)
|
|
- [x] 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:**
|
|
- [x] Created `XeroCsvSettings` component (`server/src/components/settings/integrations/XeroCsvSettings.tsx`)
|
|
- [x] Updated `XeroIntegrationSettings` with CSV/OAuth mode toggle
|
|
- [x] Created `XeroCsvExportPanel` (`server/src/components/billing-dashboard/accounting/XeroCsvExportPanel.tsx`)
|
|
- [x] Created `XeroCsvTaxImportPanel` (`server/src/components/billing-dashboard/accounting/XeroCsvTaxImportPanel.tsx`)
|
|
- [x] Updated `AccountingExportsTab` for Xero CSV batch support
|
|
|
|
**Documentation:**
|
|
- [x] 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:**
|
|
- [x] Updated `AccountingIntegrationsSetup.tsx` to add `xero_csv` as a fourth integration option
|
|
- [x] 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
|
|
- [x] Created `xeroCsvMappingModules.ts` for Xero CSV-specific mapping modules
|
|
- Clients, Items/Services, Tax Codes, Payment Terms
|
|
- Xero-specific terminology and identifiers
|
|
- [x] Created `XeroCsvMappingManager.tsx` component using the shared `AccountingMappingManager`
|
|
- [x] Updated CSV integration index exports
|
|
- [x] Removed old `XeroCsvSettings.tsx` (merged into `XeroCsvIntegrationSettings.tsx`)
|
|
|
|
### 2025-12-18 - Backend Completion
|
|
|
|
Completed all remaining backend tasks:
|
|
|
|
**Client Export/Import:**
|
|
- [x] 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
|
|
- [x] Added client sync actions to `xeroCsvActions.ts`
|
|
- [x] Created client export API route (`/api/v1/accounting-exports/xero-csv/client-export/route.ts`)
|
|
- [x] Created client import API route (`/api/v1/accounting-exports/xero-csv/client-import/route.ts`)
|
|
|
|
**Batch Parity:**
|
|
- [x] Added `xero_csv` to `AccountingAdapterType` in `companySync.types.ts`
|
|
- [x] Updated `XeroCsvAdapter.deliver()` to create invoice mappings via `KnexInvoiceMappingRepository`
|
|
- [x] Added `xero_csv` to `shouldIncludePendingExternalDrafts()` in invoice selector
|
|
|
|
**Tax Blocking State:**
|
|
- [x] Verified existing tax blocking logic in `taxSourceActions.ts` handles `pending_external` state
|
|
- [x] Confirmed `XeroCsvTaxImportService` properly updates `tax_source` from `pending_external` to `external`
|
|
- [x] Invoice finalization is blocked until tax is imported (via `validateInvoiceFinalization`)
|
|
|
|
### 2025-12-18 - Data Model & Client Sync UI Completion
|
|
|
|
**Data Model / Migrations:**
|
|
- [x] Created `server/migrations/20251218010000_add_xero_csv_mapping_normalization.cjs`
|
|
- Normalizes `company` → `client` for xero_csv mappings
|
|
- Normalizes `tax_region` → `tax_code` for xero and xero_csv mappings
|
|
- Both up and down migrations implemented
|
|
- [x] 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:**
|
|
- [x] 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
|
|
- [x] Integrated `XeroCsvClientSyncPanel` into `XeroCsvIntegrationSettings.tsx`
|
|
|
|
---
|
|
|
|
## Backend Tasks
|
|
|
|
### 1. Xero CSV Adapter (adapter-create)
|
|
**File:** `server/src/lib/adapters/accounting/xeroCsvAdapter.ts`
|
|
**Status:** DONE
|
|
|
|
- [x] Create adapter class implementing AccountingExportAdapter
|
|
- [x] Implement capabilities() with deliveryMode: 'file'
|
|
- [x] Implement transform() to generate Xero-compatible CSV
|
|
- [x] Include stable reconciliation identifiers (tracking categories)
|
|
- [x] Implement deliver() to prepare file artifact
|
|
|
|
### 2. Register Adapter (adapter-register)
|
|
**File:** `server/src/lib/adapters/accounting/registry.ts`
|
|
**Status:** DONE
|
|
|
|
- [x] Import XeroCsvAdapter
|
|
- [x] Add to createDefault() adapter list
|
|
|
|
### 3. CSV Mapping Modules (mapping-modules)
|
|
**File:** `server/src/components/integrations/csv/xeroCsvMappingModules.ts`
|
|
**Status:** DONE
|
|
|
|
- [x] Implement mapping modules for `adapterType: 'xero_csv'`
|
|
- [x] Support mappings for: Clients, Items/Services, Tax Codes, Payment Terms
|
|
- [x] Ensure terminology uses "Clients" (not "Customers") throughout UI/config
|
|
- [x] 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
|
|
|
|
- [x] Export Alga Clients to Xero Contacts CSV (manual import to Xero)
|
|
- [x] Import Xero Contacts CSV back into Alga (match/update existing clients; optionally create new clients)
|
|
- [x] 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
|
|
|
|
- [x] Parse Xero Invoice Details Report CSV format
|
|
- [x] Match invoices back to Alga using tracking categories
|
|
- [x] Create previewTaxImport() method
|
|
- [x] Create importTaxFromReport() method
|
|
- [x] 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
|
|
|
|
- [x] Settings read/write for Xero CSV mode
|
|
- [x] Export: create/execute batch and return download artifact
|
|
- [x] Import: preview + execute tax import
|
|
- [x] Import: preview + execute client import
|
|
|
|
### 7. Xero CSV API Routes (api-routes)
|
|
**Files:** `server/src/app/api/v1/accounting-exports/...`
|
|
**Status:** DONE
|
|
|
|
- [x] Export download endpoint (`[batchId]/download/route.ts`)
|
|
- [x] Tax import endpoint (`xero-csv/tax-import/route.ts`)
|
|
- [x] Client export endpoint (`xero-csv/client-export/route.ts`)
|
|
- [x] 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
|
|
|
|
- [x] Ensure exports create persisted batches with an audit trail (no in-memory-only exports)
|
|
- [x] Match OAuth export behavior for "already exported invoices" and date overlap handling
|
|
- [x] Added invoice mapping persistence in `XeroCsvAdapter.deliver()` to prevent re-export
|
|
- [x] 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
|
|
|
|
- [x] If Xero is the tax source, treat invoices as blocked from finalization until tax is imported
|
|
- [x] Default export selection to include Draft invoices when invoices are awaiting external tax
|
|
- [x] `validateInvoiceFinalization()` blocks finalization for `pending_external` tax source
|
|
- [x] 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
|
|
|
|
- [x] Add/verify migrations to normalize mapping types (company → client, tax_region → tax_code) for `xero_csv`
|
|
- [x] 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
|
|
|
|
- [x] Persist Xero external identifiers for clients and invoices per tenant + adapter type
|
|
- [x] 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
|
|
|
|
- [x] Show instructions for manual import/export workflows (contacts + invoices + tax import)
|
|
- [x] Surface key defaults (invoice numbering/reference scheme; date formatting if needed)
|
|
- [x] 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
|
|
|
|
- [x] Keep Xero OAuth visible but disabled / "Coming soon" when in CSV mode
|
|
- [x] Add Xero CSV as a selectable integration option (fourth card)
|
|
- [x] 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
|
|
|
|
- [x] Use shared mapping manager UI (standard tab control + primary color)
|
|
- [x] Default to the "Clients" tab on load
|
|
- [x] 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
|
|
|
|
- [x] Export dialog that matches OAuth export invariants (status defaults, overlap behavior, lock handling)
|
|
- [x] 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
|
|
|
|
- [x] Upload + preview + execute flow with clear reconciliation identifiers
|
|
- [x] 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
|
|
|
|
- [x] Ensure Xero CSV batches behave the same as other adapters (download, errors, lines, status)
|
|
- [x] 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
|
|
|
|
- [x] Export clients (contacts CSV) action + instructions
|
|
- [x] Import clients from Xero contacts CSV with preview + confirmation
|
|
- [x] 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
|
|
|
|
- [x] Xero contacts (clients) import/export guide
|
|
- [x] Invoice export workflow instructions
|
|
- [x] Tax import workflow instructions + rollback semantics
|
|
- [x] 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)*
|