ScorecardService — KPI scorecard workflow
Workflow #9 — the L10 scorecard: 7 KPIs assembled from QBO, Fishbowl and ClaritySoft, with an optional bounded publish (dated snapshot row) to Smartsheet.
Overview
src/workflows/scorecard/scorecard.service.ts. Four sources, seven KPIs (cash, AR, AP, weighted pipeline, open SO, open PO, NWC), each
tagged with its source and a green/yellow/red status:
- 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 → cash + AR/AP (QBO)
- 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 → open SO/PO values (Fishbowl)
- 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 → open weighted pipeline (ClaritySoft)
- Sheets Read (scorecard sheet + columns)Sheets Read (scorecard sheet + columns)Queryv0.1.0Smartsheet sheet + column reads (static PAT) used to locate the scorecard sheet and protect formula columns on publish..Ownervisionary-engineeringMapView docs → locate the scorecard sheet + protect formula columns (Smartsheet, publish only)
Degradation (Fishbowl is not live): the two Fishbowl KPIs are omitted — never zero-filled
(a zero SO value reads as a fact) — and unavailableSources: ['fishbowl'] is set.
The CQRS exception, on purpose and flagged: with publish: true this service performs
Smartsheet Append Scorecard RowSmartsheet Append Scorecard RowCommandv0.1.0Appends a dated KPI snapshot row to the scorecard sheet, preserving formula columns. The one write that does NOT route t...Ownervisionary-engineeringMapView docs — a direct bounded write (one dated snapshot row,
formula columns preserved) throttled by WRITE_MODE but not routed through the approval bus.
The pre-showtime audit tracks it as the one seam to either route through the bus or declare as an
auto-approve exception in the rule engine (ADR §5).
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.