Skip to main content

reporting-service

Bounded Context: Reporting (Supporting) · Owner: PMS-BackOffice · Phase: 1 · Storage: Cloud SQL Postgres (templates, runs, schedules) + GCS (artifacts) + BigQuery (read replica from analytics-service) · Bundle: services/reporting-service/

reporting-service is the document-rendering and delivery surface of Ghasi Melmastoon. It turns curated facts about a tenant's hotel operations into operational, financial, and regulatory documents — PDF, Excel, CSV — and delivers them to staff, owners, and (where the law requires) to government registers. It does not compute the underlying numbers. Every metric, total, count, and ledger figure originates from billing-service, reservation-service, inventory-service, housekeeping-service, staff-service, and is read either via versioned read-replicas in BigQuery or via curated projections owned by analytics-service.

Reports are facts at a point in time, frozen into a portable artifact, signed by the platform, and traceable end-to-end. Once a report is rendered and delivered, it is immutable. Re-running with the same inputs and the same template version produces a byte-identical artifact (modulo embedded timestamps), so an auditor can re-derive any historical report from the same template snapshot and source data.

Purpose

  • Be the single rendering surface so every PDF / Excel / CSV the platform produces follows one layout system, one branding pipeline, one signing scheme, and one delivery audit log.
  • Decouple what to compute (analytics-service projections, billing ledger, reservation aggregate) from how to render and deliver it (reporting templates, schedules, subscriptions).
  • Provide a regulatory submission harness for jurisdictions that mandate daily/periodic transmission of guest-registration, tax, or occupancy data to a government register or tourism authority (Afghanistan, Tajikistan, Iran, GCC variants).
  • Surface manager-grade composite reports that pull from multiple services in one document — the kind of "monthly P&L plus occupancy plus housekeeping productivity" an owner expects on the 1st of every month.
  • Replicate subscribed reports and a window of recent runs to the Electron desktop so a GM on a flaky link still sees yesterday's arrivals report and last week's revenue summary.

Key responsibilities

  1. Template registry — versioned ReportTemplate aggregates with column definitions, filter shapes, layout (header/footer/section blocks), branding hooks, locale variants (Pashto/Dari/Persian/Arabic/EN/FR), and RTL/LTR toggles. Templates are append-versioned; a template never mutates after publish.
  2. On-demand generation (POST /api/v1/reports/runs) — caller picks templateId@version, supplies filters (date range, property, room type, channel, …), the service creates a ReportRun, dispatches it to the rendering worker, returns 202 with the run id; staff or BFF polls or subscribes to completion.
  3. Scheduled generationReportSchedule aggregates declare cron expressions and target subscriptions; Cloud Scheduler fires melmastoon.reporting.schedule.fired.v1 which the service handles by snapshotting the template, materializing inputs from BigQuery / read-replicas, and queueing a ReportRun.
  4. Rendering pipeline — Puppeteer (PDF) running in a sandboxed Cloud Run worker; exceljs (XLSX) and a streaming CSV writer (fast-csv) for tabular outputs. All artifacts land in GCS under a tenant-partitioned, KMS-encrypted bucket with V4 signed URLs issued for delivery.
  5. Subscription & deliveryReportSubscription aggregates declare per-recipient channels (email via notification-service, in-app via bff-backoffice-service push, desktop via sync, WebDAV / SFTP for legacy partner integrations Phase 3+).
  6. Regulatory submissions — special class of templates marked regulatory=true with per-jurisdiction submission adapters (HTTP form post, signed XML, CSV-over-SFTP, paper-print fallback). Failed submissions emit melmastoon.reporting.regulatory.submission_due.v1 to notification-service with a P1 escalation path.
  7. Audit log — every read of every artifact, every download, every email delivery is recorded so a tax auditor can demonstrate chain-of-custody for any rendered figure.

Aggregates owned

AggregatePurposeIdentity prefix
ReportTemplateVersioned spec: columns, filters, layout, locale variants, branding, retention classtpl_rep_
ReportLogical report instance (the thing the user asks for; carries name, default template, latest runs index)rep_
ReportRunA single execution of a template at a point in time, with its inputs, outputs (artifacts), status, signing chainrun_
ReportScheduleCron rule + target template + filters + subscription setsch_
ReportSubscriptionRecipient + channel + format + delivery auditsub_
ReportFilterReusable saved filter (shareable across runs in a tenant)flt_
ExportArtifactConcrete file in GCS (PDF/XLSX/CSV) with checksum, signed URL state, retention classart_
RegulatorySubmissionA ReportRun directed at a government register, plus submission adapter outcome and retry/audit chainreg_

Key APIs (REST, /api/v1/reports)

MethodPathPurpose
POST/templatesPublish a new template version (template author / platform admin)
GET/templatesList templates (filter by category, regulatory, jurisdiction)
GET/templates/:id/versionsVersion history of a template
POST/runsCreate a ReportRun from a template + filters
GET/runs/:idStatus + artifact links of a run
GET/runs/:id/artifacts/:artId/downloadIssue a short-lived V4 signed URL
POST/runs/:id/cancelCancel a queued or in-progress run
POST/schedulesCreate a schedule
PATCH/schedules/:idUpdate schedule (paused, recipients, filter, template version pin)
DELETE/schedules/:idDisable a schedule
POST/subscriptionsCreate a per-user/per-channel subscription
DELETE/subscriptions/:idCancel subscription
POST/regulatory/submissions/:runId/retryManually retry a regulatory submission
GET/regulatory/submissionsList regulatory submissions and their statuses

Consumed by bff-backoffice-service (desktop, web manager dashboards) and selected service callers (e.g., billing-service post-end-of-day) via internal service tokens.

Key events published

EventTrigger
melmastoon.reporting.report.requested.v1A user / scheduler requested a run
melmastoon.reporting.report.started.v1Worker picked up the run
melmastoon.reporting.report.completed.v1Artifact written to GCS, signed URL minted
melmastoon.reporting.report.failed.v1Render or data-fetch failed terminally (post-retries)
melmastoon.reporting.report.delivered.v1Recipient delivery confirmed (per channel)
melmastoon.reporting.template.published.v1A new template version was published
melmastoon.reporting.template.archived.v1Template archived (no new runs allowed)
melmastoon.reporting.schedule.created.v1Schedule created
melmastoon.reporting.schedule.fired.v1Cloud Scheduler hit the schedule
melmastoon.reporting.schedule.disabled.v1Schedule disabled (manual or after N consecutive failures)
melmastoon.reporting.subscription.created.v1New subscription
melmastoon.reporting.subscription.cancelled.v1Subscription cancelled
melmastoon.reporting.regulatory.submission_due.v1Regulatory submission window opened (used to alert tenants)
melmastoon.reporting.regulatory.submission_succeeded.v1Government register accepted the submission
melmastoon.reporting.regulatory.submission_failed.v1Government register rejected (with reason code from adapter)

Key events consumed

EventEffect
melmastoon.tenant.settings.changed.v1Refresh per-tenant branding, locale defaults, regulatory jurisdiction settings
melmastoon.theme_config.theme.updated.v1Re-cache tenant branding for renderer
melmastoon.notification.delivery.recorded.v1Mark a ReportSubscription delivery as confirmed/failed
melmastoon.analytics.projection.refreshed.v1Optional invalidate-and-rerun for streaming/near-realtime templates
melmastoon.tenant.deleted.v1Cascade purge — soft-delete all template overrides, runs, artifacts within retention requirements
Cloud Scheduler push (/internal/jobs/schedule-fire)Translated into schedule.fired.v1 then run dispatch

Upstream / downstream

Upstream (we read from): analytics-service (BigQuery curated tables — primary fact source), billing-service (folio + ledger read replica), reservation-service (read replica for arrivals/departures composites), inventory-service, housekeeping-service, staff-service, tenant-service (branding + jurisdiction), theme-config-service (logo, color tokens), iam-service (recipient authorization).

Downstream (we publish for): notification-service (email delivery), bff-backoffice-service (in-app + desktop sync), audit-service (every artifact and delivery is auditable), analytics-service (run telemetry), regulatory partner endpoints (per-jurisdiction adapters — outside the platform).

Non-functional requirements

NFRTarget
On-demand p95 render latency, ≤ 50k-row tabular< 12 s end-to-end (queue → artifact ready)
On-demand p95 render latency, regulatory PDF< 25 s
Scheduled report on-time rate> 99.5% monthly (fired within ±60 s of cron)
Regulatory submission success rate> 99.9% monthly (post-retries)
Artifact retention (operational)2 years in GCS Standard, then 7 years in Coldline
Artifact retention (regulatory)10 years in GCS Coldline, with object-lock retention policy
API availability99.9% monthly
Sync footprintSubscribed reports + most recent 30 runs per template per device
ReplicasMin 2 Cloud Run instances (API); separate worker pool (autoscaling 0→20) for rendering

Where to go next

  • Implementation-grade detail: services/reporting-service/SERVICE_OVERVIEW.md and the rest of the 17-doc bundle.
  • Source-of-truth fact tables consumed: services/analytics-service/DATA_MODEL.md (fact_* and dim_* tables).
  • Branding & locale variants: docs/03-microservices/theme-config-service.md.
  • Notification delivery contracts: docs/03-microservices/notification-service.md.
  • Desktop subscription UX: docs/frontend/desktop/06-desktop-app-specification.md.
  • Audit / Merkle anchoring: docs/07-security-compliance-tenancy.md §9.