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

7.4 KiB

Scratchpad: Tax Import Service Porting + BackNav Fix + Notification Reconciliation

Decisions

  1. Skip adapters and externalTaxImportService — Moving accounting adapters to @alga-psa/integrations creates a circular dependency: integrations→billing→integrations (adapters import AccountingMappingResolver etc. from billing; billing imports QboClientService/XeroClientService from integrations). Deferred to future PR with a strategy to extract shared types to @alga-psa/types first.

  2. Adopt package notification email.ts version — rate limiting is centralized in TenantEmailService.sendEmail(), inline check in server version is redundant.

  3. Keep server emailLocaleResolver.tssendEventEmail.ts imports it locally. Don't force server infrastructure to import from package.

  4. Delete orphan invoiceAdapters.ts — zero callers in server; the billing package has its own independent copy at packages/billing/src/lib/adapters/invoiceAdapters.ts.

  5. Use @alga-psa/core for parseCSV — csvTaxImportService currently imports from server/src/lib/utils/csvParser, but @alga-psa/core exports the same function (already used by XeroCsvTaxImportService in the integrations package).

Key File Paths

Tax Import Services

  • Source: server/src/lib/services/csvTaxImportValidator.ts (745 LOC)
  • Source: server/src/lib/services/csvTaxImportService.ts (595 LOC)
  • Source: server/src/lib/utils/csvFieldNormalizer.ts (323 LOC)
  • Target: packages/integrations/src/services/ and packages/integrations/src/lib/
  • Barrel: packages/integrations/src/services/index.ts (currently: export * from './email')
  • Reference pattern: packages/integrations/src/services/xeroCsvTaxImportService.ts
  • Caller: server/src/lib/api/controllers/ApiCSVAccountingController.ts

BackNav Fix

  • Fix: packages/ui/src/components/BackNav.tsx line 7
  • Target: packages/ui/src/context/UnsavedChangesContext.tsx (identical API)

Notification Dual-Copies

  • Delete: server/src/lib/notifications/email.ts (561 LOC)
  • Delete: server/src/lib/notifications/emailChannel.ts (7 LOC, identical to package)
  • Keep: server/src/lib/notifications/emailLocaleResolver.ts (255 LOC)
  • Keep: server/src/lib/notifications/emailService.ts (273 LOC)
  • Keep: server/src/lib/notifications/sendEventEmail.ts (509 LOC)
  • Keep: server/src/lib/notifications/NotificationAccumulator.ts (459 LOC)
  • Package barrel: packages/notifications/src/index.ts — add getEmailNotificationService export
  • Package email.ts: packages/notifications/src/notifications/email.ts (504 LOC)
  • Package emailChannel: packages/notifications/src/emailChannel.ts (already in barrel)

Orphan Deletion

  • Delete: server/src/lib/adapters/invoiceAdapters.ts (0 callers)

Discoveries

Circular Dependency: Adapters ↔ Billing

  • server/src/lib/adapters/accounting/quickBooksOnlineAdapter.ts imports from @alga-psa/billing (AccountingMappingResolver, CompanyAccountingSyncService, etc.)
  • server/src/lib/adapters/accounting/xeroAdapter.ts imports from @alga-psa/billing (same)
  • server/src/lib/adapters/accounting/quickBooksCSVAdapter.ts imports from @alga-psa/billing
  • server/src/lib/adapters/accounting/xeroCsvAdapter.ts imports from @alga-psa/billing
  • packages/billing/src/services/companySync/adapters/xeroCompanyAdapter.ts imports from @alga-psa/integrations
  • packages/billing/src/services/companySync/adapters/quickBooksCompanyAdapter.ts imports from @alga-psa/integrations
  • Adding @alga-psa/billing to integrations package.json → circular dependency

Type Availability

  • TaxSource, IExternalTaxImport, IExternalTaxImportResult — all in @alga-psa/types
  • AccountingExportBatch, AccountingExportLine — in packages/types/src/interfaces/accountingExport.interfaces.ts but NOT exported from barrel (needed for future adapter migration)
  • parseCSV — available from @alga-psa/core

Notification Differences

  • Server email.ts (561 LOC) vs package email.ts (504 LOC): server has inline rate limiting (lines 399-412) that package removed
  • emailLocaleResolver: functionally identical between server (255 LOC) and package (212 LOC), just different import paths
  • emailChannel: byte-for-byte identical (7 LOC each)
  • Package barrel already exports emailChannel but NOT EmailNotificationService/getEmailNotificationService

Callers Summary

csvTaxImportService:

  • server/src/lib/api/controllers/ApiCSVAccountingController.tsgetCSVTaxImportService

email.ts (EmailNotificationService):

  • server/src/lib/jobs/handlers/expiringCreditsNotificationHandler.tsgetEmailNotificationService

emailChannel:

  • server/src/lib/eventBus/subscribers/ticketEmailSubscriber.tsgetEmailEventChannel
  • server/src/lib/eventBus/subscribers/projectEmailSubscriber.tsgetEmailEventChannel
  • server/src/lib/eventBus/publishers/index.tsgetEmailEventChannel
  • server/src/lib/api/services/TicketService.tsgetEmailEventChannel
  • server/src/test/integration/ticketEmailDelimiters.test.tsEMAIL_EVENT_CHANNEL

Implementation Order

  1. Move csvFieldNormalizer.ts → packages/integrations/src/lib/
  2. Move csvTaxImportValidator.ts → packages/integrations/src/services/ (update csvFieldNormalizer import)
  3. Move csvTaxImportService.ts → packages/integrations/src/services/ (update db, types, parseCSV imports)
  4. Update integrations services barrel
  5. Update ApiCSVAccountingController.ts caller
  6. Delete server copies of tax services + csvFieldNormalizer
  7. Fix BackNav.tsx import
  8. Add getEmailNotificationService to notifications barrel
  9. Update 6 notification callers
  10. Delete server email.ts and emailChannel.ts
  11. Delete orphan invoiceAdapters.ts
  12. Verify build (npm run build && npm run build:shared)

Gotchas

  • parseCSV signature: verify @alga-psa/core's parseCSV returns string[][] (same as server's csvParser). XeroCsvTaxImportService uses it with as string[][] cast.
  • csvTaxImportValidator.ts uses any type for knex parameter — keep as-is, don't try to type-narrow in this PR.
  • The packages/integrations/src/services/index.ts currently only exports ./email. Adding CSV tax exports here. Make sure the export doesn't conflict with any existing names.
  • After deleting server emailChannel.ts, verify that sendEventEmail.ts doesn't import from it (it doesn't — only imports from emailLocaleResolver).
  • DISCOVERED during implementation: emailService.ts (kept in server) also imports from ./emailChannel — needed to update this caller too (not in original plan's caller list). Updated to @alga-psa/notifications.
  • DISCOVERED during implementation: UnsavedChangesContext in packages/ui/src/context/UnsavedChangesContext.tsx was declared with const (not export const). The server version exports it directly. Had to add export keyword to the package version for BackNav.tsx to import it.

Commands

# Verify build after changes
npm run build:shared && npm run build

# Check for remaining boundary violations
grep -r "from 'server/src/lib/services/csvTaxImport" --include="*.ts" --include="*.tsx" | grep -v "docs/"
grep -r "from 'server/src/contexts/UnsavedChangesContext" --include="*.ts" --include="*.tsx" packages/
grep -r "from.*lib/notifications/emailChannel" --include="*.ts" --include="*.tsx" server/src/
grep -r "from.*lib/notifications/email'" --include="*.ts" --include="*.tsx" server/src/