Files
hiveops-guide/backend/src/main/resources/content/analytics/transactions/claude.md
T
johannes 2f94d62769 content(guide): role-tabs (Internal/Architect/Claude) for all 63 customer modules (DRAFT, Refs #1 #3)
Full role-tab rollout: every customer module now has Customer/Internal/
Architect/Claude tabs, grounded per-module in real code. Backend serves 296
docs / 96 modules. Grounding surfaced ~20 real bugs across services (filed
separately after verification).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 12:14:54 -04:00

3.9 KiB

module, title, tab, order, audience
module title tab order audience
analytics.transactions Transactions Claude 40 internal

Act-without-guessing reference. Transactions tab = analytics UI tab id: 'journal', label: 'Transactions'JournalCoverageTab.svelteGET /api/analytics/journal-coverage. Data source of truth is hiveops-journal, not analytics.

Ownership

  • hiveops-journal OWNS the data (journal_transactions, journal_gaps, DB hiveiq_journal).
  • hiveops-analytics (port 8089) is a read-only aggregator/proxy; forwards caller JWT to journal.
  • Frontend: hiveops-analytics/frontend, analytics.bcos.cloud (port 5174).

Endpoints (METHOD path → service)

Method Path Service Auth
GET /api/analytics/journal-coverage analytics authenticated JWT, no role gate
GET /api/journal/transactions/summary?dateFrom=&dateTo= journal JWT (no method-level @PreAuthorize; filter chain enforces)
GET /api/journal/gaps?status=OPEN journal @PreAuthorize("isAuthenticated()")
GET /api/journal/transactions/top-atms?dateFrom=&dateTo=&limit=10 journal @PreAuthorize("isAuthenticated()"), size cap 50
PUT /api/journal/gaps/{id}/request-fetch journal isAuthenticated() (marks gap FETCH_REQUESTED)
  • Analytics frontend apiBase default (dev): http://localhost:8089/api/analytics; prod from window.__APP_CONFIG__.apiUrl. NGINX path /api/analytics/.
  • Analytics journalWebClient base = JOURNAL_SERVICE_URL (default http://hiveops-journal:8087).

Tables (DB hiveiq_journal)

Table Use
journal_transactions total / APPROVED / DECLINED counts, top-ATMs
journal_gaps open gaps (status OPEN)
  • No table is WRITTEN to serve this tab.
  • analytics_snapshots / ai_insights (DB hiveiq_analytics) are NOT used by this tab.

Kafka

  • None in this request path. journal-coverage is a synchronous WebClient pull.
  • (Context only, other tabs) analytics consumes journal.file-parsed, hiveops.incidents.{created,updated,resolved}; produces analytics.snapshot-ready. Journal produces journal.file-parsed, consumes journal.parse-requests.{INSTITUTION}.

Response shape (JournalCoverageResponse)

  • dailyVolume: [{date, total, successful, failed}]today only, single element.
  • parseSuccessRateToday = successful*100/total (0 if total 0).
  • openGapsTotal, atmsWithGaps: [{atmId, gapCount}] (≤20, UI shows 10).
  • topAtmsByVolume: [{atmId, transactionCount}] (≤10).

Field semantics (critical)

  • journal successful = COUNT(host_result='APPROVED'); failed = COUNT(host_result='DECLINED'); total = all rows.
  • Therefore "Parse Success Rate" and the "Successful/Failed" bars = transaction approval stats, NOT journal-parse health.
  • transactions/summary is @Cacheable("txSummary") key institutions:dateFrom:dateTo → today's numbers can be stale.
  • All scoped by InstitutionContext.resolveScope() in journal — results are per caller's institution.

Gotchas

  • Downstream failures are caught and return empty → tab shows 0 / "No data" with no user error. Grep analytics logs: JournalCoverage: failed to fetch.
  • Everything except open-gaps is LocalDate.now() (today) — early-day emptiness is expected.
  • Gap rows only created by journal's daily 06:00 UTC gap-detection job.

Do NOT

  • Do NOT claim analytics stores transaction/gap data — it does not; query journal.
  • Do NOT treat "Parse Success Rate" as an ingest/parse metric — it is approval rate.
  • Do NOT expect multi-day history on this tab — dailyVolume is today-only.
  • Do NOT assume MSP_ADMIN/BCOS_ADMIN is required — journal-coverage is any-authenticated.
  • Do NOT look for Kafka in the read path — it is a synchronous pull.
  • Do NOT add write endpoints or resolve gaps from analytics — gap fetch is PUT /api/journal/gaps/{id}/request-fetch on journal.