Customers & accounts
ERP & Accounting Bridge
Indicative price, not an offer: EUR 500-2000/year or EUR 1500-3000 one-off
Generated from docs/plan/paid/erp-accounting-bridge/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
ERP & Accounting Bridge automatically syncs orders, payments, and inventory between AstroBaaS and accounting systems (Odoo, QuickBooks, Xero, NetSuite) to keep financial records in sync.
The problem
Store and accounting system have different data; reconciliation is manual and error-prone.
What it does
- OAuth or API key integration with Odoo, QuickBooks, Xero, NetSuite
- Sync orders to accounting as invoices or sales orders
- Sync payments (captured) as sales receipts
- Sync refunds as credit memos
- Sync inventory levels (if accounting has inventory module)
- Sync customer master (name, address, tax ID)
- Two-way sync: read product/customer from accounting (optional)
- Chart of accounts mapping: order income to correct GL account
- Tax mapping: store tax rates to accounting tax codes
- Reconciliation report: show discrepancies between store orders and accounting invoices
- Audit log: every sync, data mismatches, manual corrections
- Retry and backoff: failed syncs retried
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Manual invoice generation — auto-sync only
- Payment method mapping (Stripe to Credit Card GL) — order-amount sync only
- Multi-currency reconciliation — single currency per store
- Custom field sync (sales_rep field) — standard fields only
- Expense tracking (supplier invoices) — order/sales sync only
- Budget forecasting — analytics feature
Data model
AccountingIntegration: store_id, provider, api_key (encrypted), oauth_tokens (encrypted), is_active, last_sync_at, created_at. AccountingMapping: store_id, source_type, source_id, accounting_id, sync_status, synced_at, error_msg. GlAccountMapping: store_id, astrobaas_category, gl_account_code. TaxCodeMapping: store_id, store_tax_rate, accounting_tax_code. AccountingReconciliation: store_id, date_range, store_count, accounting_count, match_count, mismatch_count, generated_at. Migration: add 5 tables.
API
- POST /admin/integrations/accounting/connect
- GET /admin/integrations/accounting/status
- POST /admin/integrations/accounting/sync-now
- POST /admin/integrations/accounting/disconnect
- GET /admin/integrations/accounting/mappings
- PATCH /admin/integrations/accounting/mappings
- GET /admin/integrations/accounting/reconciliation
- POST /admin/integrations/accounting/reconciliation/export
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Accounting panel: connection status, provider, last sync, errors. Sync settings: direction (store to accounting or bidirectional), frequency. GL mapping: dropdowns for GL accounts (order income, shipping, discounts). Tax mapping: store rates to accounting codes. Manual sync button. Reconciliation dashboard: orders vs invoices, mismatches table.
The seam — why this is paid
Core owns: Order/Payment/Refund/Customer/Product tables, sync hooks (order.created, order.paid, refund.created). Paid module owns: accounting API integration (OAuth, calls), mapping UI, sync scheduling, reconciliation logic, credential encryption, retry queue.
Requires ERP credentials (Odoo, SAP, NetSuite, QuickBooks). Significant integration work and ongoing support commitment.
Dependencies
- customer-profiles
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- Connect Odoo via OAuth, select GL 4000-Sales, create order in store; syncs to Odoo invoice on 4000
- 100 EUR order, 100 EUR payment captured, 50 EUR refunded; Odoo shows invoice 100 EUR + credit memo 50 EUR
- Order synced; reconciliation shows 1 match (store#123 = Odoo#456)
- Sync failed (network); retry 1h later succeeds; audit shows ‘Failed 10:00, retried 11:00, succeeded’
- Change GL mapping 4000 to 5000; next sync uses 5000, old orders stay 4000
- Reconciliation Sept 2024: store 100 orders, Odoo 98 invoices; 98 matched, 2 unmatched (show which)
Risks
API key leaked causes attacker to create fake invoices. Wrong GL account causes all orders mis-categorized. Order synced but payment not (race condition). Reconciliation never reconciles (sync backlog). Manual correction in accounting not verified. Rate limit hit, no alert.
Commercial context
| Suggested price | EUR 500-2000/year or EUR 1500-3000 one-off |
| Rival anchor | Webkul Odoo ERP Connector, Embedded ERP (Purchases, Logistics) |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.