service

CashFlowService — cash-flow read workflow

Workflow #5. Fans into QBO (cash position + AR/AP aging), Fishbowl (open SO/PO) and ClaritySoft (weighted pipeline) in parallel, assembles the unified cash view with divergence + runway alerts.

ServiceRead workflow — direct request/response, no events

Overview

src/workflows/cash-flow/cash-flow.service.ts. Three parallel vendor reads, one assembled CashFlowView:

  • Accounting Read (customers · reports · aging)Accounting Read (customers · reports · aging)Queryv0.1.0QBO customers, cash-flow/P&L reports and AR/AP aging (OAuth2 with rotated-token write-back).Ownervisionary-engineeringMapView docs → QBO cash-flow report + receivables/payables aging buckets
  • Inventory Read (customers · open SO/PO)Inventory Read (customers · open SO/PO)Queryv0.1.0Fishbowl customers and open sales/purchase orders via data queries (session-login → bearer re-auth).Ownervisionary-engineeringMapView docs → Fishbowl open sales/purchase orders (the SO/PO rollup)
  • CRM Read (accounts · contacts · opportunities)CRM Read (accounts · contacts · opportunities)Queryv0.1.0Paginated reads of ClaritySoft accounts, contacts and opportunities (api-key body-envelope auth).Ownervisionary-engineeringMapView docs → ClaritySoft opportunities (the stage-weighted pipeline rollup)

Then the derived layer: cash position (ending cash, burn, runway months), the so-po-divergence alert and the cash-runway-pipeline alert.

Degradation (Fishbowl is not live): the inventory read is allowed to be ABSENT — openOrders is omitted, unavailableSources: ['fishbowl'] is set, the divergence alert is suppressed (never guessed), and the MCP layer attaches an explicit “do not report absence as fact” note. A Fishbowl outage degrades the view; it never fails the tool call.

Layering: MCP tool → this workflow service (orchestration, cross-system joins) → foundational services (clean domain models, vendor envelope stripped) → clients (raw vendor APIs) — each behind DI, every connector swappable to fixtures via *_USE_MOCK.

CQRS note: reads are the “typical reactions” side — normal request/response, no event lifecycle. Only commands flow through the Approval Bus (command service — owns the queue)Approval Bus (command service — owns the queue)Servicev0.1.0The command side: owns the proposal queue. propose_* only queue; a cleared human approves in the card; only then does th...Publishesproposal-created, proposal-approved +3Subscribespropose-vendor-bill, propose-bill-date-correction +6Ownervisionary-engineeringMapRepoView docs.

Architecture diagram