Skip to main content

Reports Accuracy + Completeness Validation — Findings/Fix List

LIVE-CONFIRMED ON TEST (2026-07-11, property 96a0fdb2, via POST /api/reports/v2//run)​

Not false positives — verified against the deployed env:

  • HTTP 500 on EVERY run (P-A confirmed): city-ledger-report, in-house-report, high-balance-report, meal-plan-report, night-audit-report, room-status-report, police-register, frro-c-form, folio-register. (9 reports fully broken in production RIGHT NOW.)
  • Returns 0 rows (P-C empty confirmed): tax-audit-trail, booking-enquiry-report, rate-parity-audit.
  • Controls render fine: dsr (3 rows), occupancy-report (11), manager-flash-report (1) — so the run-endpoint + property data are healthy; the broken ones are genuinely broken.
  • (The full P-A/P-B set is ~19 reports; only a sample was live-run. Every live-proxy report shares the identical mapper defect, so the same 500 is expected across the set once its required param is missing.)

SME (domain accuracy) + BA (completeness) review of all 75 analytics reports. Live-reconciliation harness deferred to a follow-up wave (per operator decision). Severity: CRITICAL (broken/legally wrong) · MATERIAL (wrong number) · MINOR/GAP (incomplete).

Status legend: [CODE-GROUNDED] verifiable in code now · [UNVERIFIED] domain judgment / cross-repo, needs live check.

Wave 1 — Statutory/Tax (7) + Core Money (10) — DONE​

CRITICAL — structurally broken (report is empty or 500s on every run)​

  1. tax-audit-trail [CODE-GROUNDED] — queries analytics EventStore for event types NO consumer writes (only banquet/channel/tenant-import write there); 2 of 4 target event types (folio.tax.adjusted, pos.order.voided) don't exist in the platform at all. → a CERT-In/GST audit report that structurally always returns 0 rows (false "no tax events"). Same bug class as #7588 (einvoice), not applied here.
  2. night-audit [CODE-GROUNDED] — liveQueryMapper never sends propertyId; the frontdesk endpoint hard-requires it → every run 500s.
  3. police-register [CODE-GROUNDED] — liveQueryMapper omits propertyId+date (frontdesk requires both) → every standard run 400s. (AB#5213 mapper bug class.)
  4. frro-c-form [CODE-GROUNDED] — (a) same missing propertyId/date → 400s; (b) the C-Form XML formatter reads field names (passportOrIdNumber/checkinDate/expectedDeparture) that DON'T match the report schema (passportNumber/checkInDate/no-departure) → every filed C-Form ships with blank passport + check-in/out dates; (c) schema is structurally incomplete vs the immigration.gov.in Form C (missing DOB, visa validity, arrival-in-India, purpose).
  5. gst-report [CODE-GROUNDED] — GSTR-3B half queries EventStore for deprecated event names (likely always empty) AND ignores the period filter entirely (unbounded historical scan) while the e-invoice half in the SAME report IS period-scoped → the two halves answer different questions; B2B/B2C split is companyId-based, disagreeing with the correct GSTIN-based GSTR-1 → GSTR-1↔3B reconciliation breaks; composite rows double-count tax if summed.

CRITICAL/MATERIAL — wrong number (accuracy)​

  1. revenue-daily [UNVERIFIED→needs live] — room revenue posted 100% to the ARRIVAL DATE at booking time, not spread per occupied night (booking-basis vs occupancy-basis error) → wrong for every future/un-audited date; no-show revenue never reversed (overstates ADR/RevPAR); occupancy denominator uses raw totalRooms not sellable (excl OOO); ÷0 → 0 not null.
  2. revenue-monthly [UNVERIFIED→needs live] — inherits the above PLUS ADR/RevPAR/occupancy computed as an AVERAGE-OF-DAILY-RATIOS instead of re-aggregated Σrev/Σrooms (mathematically wrong when room counts vary); occupancy reads a night-audit-only column so future days average in 0%.

MAJOR-GAP — completeness (declared columns render blank — schema↔feed field mismatch)​

  1. folio-register [CODE-GROUNDED] — declared folioNo/roomNo/folioStatus/roomCharges/otherCharges/totalAmount/paidAmount/balanceDue don't match the frontdesk feed (folioId/no-room/status/aggregate-only totalCharges/balance) → effectively a one-column (guest name) report; also missing ctx.propertyIds fallback → 500s on period-only runs.
  2. cash-drawer-report [CODE-GROUNDED] — declared shiftDate/cashierId/drawerStatus/expectedBalance vs real openedAt/cashier/absent/declaredCash; no receipts/payouts breakdown; missing propertyId fallback.
  3. void-register [CODE-GROUNDED] — declared voidReason/voidAmount/itemCount/outletId vs real reason/amount/items/absent → the amount + reason columns render blank.

MINOR / GAPS​

  • revenue-monthly — no chain rollup (only the first property in scope; multi-property GM silently under-reports). [CODE-GROUNDED]
  • dsr — paymentMode/orderType drill-down dims are hardcoded '' (dead) though the MV data is fetched; no outlet-name resolution. (Money columns + APC null-safe are ACCURATE.)
  • payment-collection — MV buckets on UTC date not IST business day (G4 class) → 00:00-05:30 IST payments land on the wrong day; REFUND row must be excluded from any "total collected" rollup.
  • refund-register — refundedBy (authorised-by) exists on the MV but is dropped from the schema.
  • gstr1-summary — no B2CL/B2CS split, no CDNR (credit-note Table 9B), no invoice-wise B2B detail (buyerGstin/invoiceNo/IRN); RBAC excludes COMPLIANCE_OFFICER.
  • einvoice — missing Ack Date, seller GSTIN, HSN/SAC, place-of-supply; RBAC set inconsistent with the other GST reports.
  • tally-daybook — no gateway-fee netting (Bank ledger won't tie to statement), no source-ref column, no JSON/CSV on-screen preview.
  • settlement-register — RBAC excludes ACCOUNTS (odd for a reconciliation report). ACCURATE otherwise.
  • ACCURATE + COMPLETE (clean): payment-collection (cols), settlement-register, refund-register (bar refundedBy), dsr (accuracy), revenue-daily (cols).

Systemic patterns (repeat across reports — fix once, apply widely)​

  • P-A: live-proxy mapper drops propertyId/date → 400/500 on every run (night-audit, police-register, frro-c-form, folio-register, cash-drawer; AB#5213 class already fixed for void/discount/kot — not applied here).
  • P-B: live-proxy has NO field-mapping layer — declared schema column IDs must be byte-identical to the downstream DTO or they render blank (folio-register, cash-drawer, void-register). The LiveProxyResolver only normalises the envelope, never renames fields.
  • P-C: MV fed from EventStore that no consumer writes → permanently-empty reports (gst GSTR-3B, tax-audit-trail; #7588 class).
  • P-D: ÷0 → 0 instead of null (revenue-daily/monthly) — dsr's ratioOrNull is the correct template.
  • P-E: statutory schema is the export ceiling — CSV/PDF/XML formatters render only def.schema, so a missing column is silently dropped from the filed document.

Wave 2 — Finance/Revenue (16) — BA completeness DONE (SME accuracy pending)​

CRITICAL/MAJOR — non-functional (P-A) or blank columns (P-B)​

  • city-ledger-report [CODE-GROUNDED] — P-A: mapper NEVER sends propertyId → every run 400s; P-B: 6/7 declared columns (accountCode/date/openingBalance/charges/payments/closingBalance) don't exist on the feed (which is a per-company aging snapshot, not a daily ledger). Completely non-functional.
  • high-balance-report [CODE-GROUNDED] — P-A: never sends propertyId → 400s; P-B: folioBalance↔real balanceAmount mismatch, 5/8 columns absent on feed, roomNumber hardcoded null. Only guestName populates.
  • meal-plan-report [CODE-GROUNDED] — P-A: never sends propertyId → 400s; P-B: feed returns NESTED groups ({ratePlan, mealsExpected, guestList[]}) but schema expects flat rows → renders blank/garbage (resolver has no flattening).
  • ar-aging-detail [CODE-GROUNDED] — P-A: mapper has no ctx.propertyIds fallback → a period-only/scheduled run 500s. (Columns match the feed — P-B clean.)

GAPS​

  • ageing-report — period filter is a documented NO-OP (always all open folios); single-property only (no chain rollup); RBAC excludes GM/FINANCIAL_CONTROLLER; json/csv only.
  • pnl-report — revenue is ONE "Total Revenue" line, no departmental breakout (Rooms/F&B/Banquet/Spa) despite the data carrying source; no LY/Budget/Forecast comparative (material for a GOP P&L).
  • sale-register — taxAmount lumped, no CGST/SGST/IGST split (can't reconcile GST heads).
  • pos-sales-register — no gross/discount/CGST/SGST/IGST/payment-mode/aggregator breakdown (all on the MV, none selected) → can't reconcile vs dsr/tax reports.
  • ota-commission-statement-detail — "per-booking detail" but aggregates the SAME date+channel grain as commission-report; no bookingId/confirmation → can't reconcile against the OTA extranet.
  • room-type-revenue / source-wise-revenue — single-property only (no chain rollup) despite comparative-LY implying enterprise use; RBAC excludes GM/FINANCIAL_CONTROLLER; json/csv only; source-wise missing room-nights/ADR.
  • channel-production — description promises "cancellation rate" but no such measure exists (documented-but-undelivered); RBAC-naming inconsistency.
  • commission-statement — no LY comparative. market-segment — RBAC excludes ACCOUNTS.
  • CLEAN (BA): commission-report, expense-report.

Reinforces the systemic patterns​

P-A (mapper drops/insufficiently-threads propertyId) + P-B (schema authored against an assumed shape never verified vs the real feed DTO) now confirmed across ~7 more live-proxy reports. Root cause is universal for live-proxy reports and ALL ship green because no .definition.spec.ts asserts the outbound param shape OR the response-field mapping. This is the single highest-leverage fix: (1) auto-inject ctx.propertyIds[0] + required date in LiveProxyResolver (or a shared mapper helper) so no report can omit them; (2) a contract test that each live-proxy report's declared schema field IDs match its real feed DTO; (3) a field-mapping layer in LiveProxyResolver (or per-report responseMapper) so a downstream rename can't silently blank a column.

Wave 4 — F&B/POS + HK + spa/banquet/CRM/distribution/audit (18) — DONE (combined SME+BA)​

THE CLARIFYING SPLIT: MV-backed = mostly clean; live-proxy = systemically broken; stubs = empty​

  • CLEAN (MV-backed, accurate + complete): pos-apc, pos-daypart, food-cost-report (null-cost honest), cogs-by-category (Phase-1 honest null), sync-log-report, tip-out, housekeeping-productivity. item-wise-sales + server-productivity clean bar a MINOR P-D (÷0→0 not null on avgPrice/avgOrderValue).

CRITICAL — live-proxy P-A (400/500 every period-only run) + P-B (blank columns)​

  • rate-parity-audit [CODE-GROUNDED] — MOST BROKEN: nested feed (one row per room-type with a channels[] array) vs flat schema → 6/8 cols blank + 2 mistyped; AND the channel feed has NO direct-rate concept at all, so directRate/disparity/disparityPct are unfillable without a producer change; + P-A 500.
  • kot-register [CODE-GROUNDED] — 8/9 declared columns blank (schema names match nothing in KotRegisterItem); tableNo is unfillable (no table on POSOrder/KOT). (P-A is fixed here.)
  • lost-and-found-register [CODE-GROUNDED] — P-A 500 + P-B (4/6 dims + the sole measure blank); + getLostAndFound never filters tenantId (security follow-up, deviates from sibling feeds).
  • spa-service-sales-detail [CODE-GROUNDED] — P-A 500 + P-B (therapist≠therapistName, basePrice≠serviceRevenue, no productRevenue source; 4/9 blank).
  • banquet-sales-detail [CODE-GROUNDED] — P-A 500 + P-B (no eventType, no venueRent, no combined fbRevenue — split food/bev; 5/9 blank).
  • role-change-audit [CODE-GROUNDED] — audit "WHO" is broken: changedBy hardcoded null in the producer (comment admits it) → a role-change audit can't say who changed the role; ipAddress is RBAC-gated but doesn't exist in the feed; P-B (5/9 cols blank). Compliance-surface defect.

CRITICAL — permanent empty stubs shipped as if live (P-C)​

  • linen-consumption [CODE-GROUNDED] — query unconditionally returns {rows:[], warmingUp:true}; no MV/model exists; scheduleable:true → a Laundry Supervisor's scheduled report is forever empty with no ETA.
  • crm-feedback-pulse [CODE-GROUNDED] — same permanent warmingUp stub; no GuestFeedback model; scheduleable.

MAJOR​

  • user-activity-audit [CODE-GROUNDED] — description overclaims "API activity" but the producer tracks LOGIN/LOGOUT only (weak for CERT-In/DPDP); P-B (4/7 blank, no resourceId).

P0/P1 from this batch (into the fix list)​

rate-parity-audit (producer + shaping) · kot-register (shaping) · lost-and-found (P-A+P-B+tenantId) · spa/banquet-detail (P-A+P-B) · linen/crm stubs (mark not-available or wire the MV) · role-change-audit changedBy (compliance) · user-activity-audit scope+P-B.

Wave 3b — Front-office + Performance (9) — DONE (combined SME+BA)​

NEW pattern extension: MV-backed reports ALSO empty via consumer-topic / field-name mismatch​

  • P-C is broader than EventStore: an MV-backed report is ALSO permanently empty when (a) the analytics consumer subscribes to a topic string the producer never publishes, or (b) the definition query reads MV column names that don't exist. Both are mocked-green in the specs.

CRITICAL​

  • block-group-performance [CODE-GROUNDED] — analytics ReservationConsumer subscribes reservation.group.created/modified but reservation-service publishes group.created/group.updated → topic strings NEVER match → MvGroupPerformance has no writer → permanently empty. + missing cutoff/wash/ADR.
  • forecast-pace-report [CODE-GROUNDED] — the FORECAST half is always 0: the query reads confidence/recommendationsAccepted/recommendationsRejected but the real MV columns are avgConfidence/humanApproved/humanRejected; predictedRevParLift is never written by any consumer; the SPEC mocks the FICTIONAL field names → mocked-green. Only paceBookings/paceRevenue carry real data.
  • booking-enquiry-report [CODE-GROUNDED] — MvBookingEnquiries fed by crm.lead.* topics that NO service publishes (crm-service has no Lead module) → permanently empty; AND double-counts (a row per lead-status transition, conversionRate computed per-row not as a funnel). Repoint at the existing Reservation.status=ENQUIRY or build a real lead pipeline.
  • discrepancy-report [CODE-GROUNDED] — P-A (propertyId only from filters → period-only 500) + P-B (schema vs DiscrepancyFeedItem total mismatch) + the backing controller ignores from/to (always "as of now") + the real resolution-audit (RoomDiscrepancy) is never joined so resolvedBy/resolution-time are unsourceable.
  • room-status [CODE-GROUNDED] — P-A (never sends propertyId → 400 every run) + P-B/wrong-grain (schema is per-room but the feed is floor/wing-aggregated {group, clean, dirty, OOO...}).
  • room-status-detail [CODE-GROUNDED] — P-A (never sends from/to → 400) + P-B (schema flat per-room but feed is nested {roomNumber, statusLog[]} — needs a flatten that doesn't exist).

OK / MINOR​

  • country-wise-statistics — accurate; MINOR P-D (avgStay/revenue→0 not null) + RBAC excludes front-office/reservations (needed for FRRO/visa nationality mix).
  • front-office-pace — accurate; MAJOR completeness: no days-out bucketing / pickup curve (RM teams need it); raw cross-join grid.
  • rate-plan-performance — accurate + wired correctly (ratePlanCode genuinely stamped); MINOR: RBAC excludes SALES_MGR; no channel/LOS split.

Wave 3a — Front-office ops (14) — DONE (combined SME+BA)​

NEW SYSTEMIC PATTERN P-F — RBAC gates on PHANTOM roles (report is unrunnable)​

  • 9 of 14 gate on role strings NOT in the platform UserRole enum (GM/FRONT_OFFICE_MGR/FRONT_DESK_AGENT — real roles are SUPER_ADMIN/ADMIN/MANAGER/FRONT_DESK/HOUSEKEEPING/F_AND_B/ACCOUNTS/RESERVATIONS/STAFF/OWNER). ReportRBACService does exact-membership (SUPER_ADMIN is the only bypass) → a real MANAGER/FRONT_DESK user cannot run in-house, guest-checked-in, guest-checked-out, pickup, manager-flash (the GM flash!), pre-arrival-pulse, booking, release, void. Fix = repoint to canonical roles (arrival/departure/occupancy/no-show/cancelled already do it right). [CODE-GROUNDED — highest-blast-radius, one-line-per-report fix]

CRITICAL​

  • in-house / guest-checked-in / guest-checked-out [CODE-GROUNDED] — P-A (mapper never sends propertyId; checkins/checkouts also need date) → 400 every run; P-B (measures nights/folioBalance/totalCharged/outstandingBalance don't exist in the feed DTOs; checkInDate≠checkinDate/checkinTime); roomNumber hardcoded null in the frontdesk feed → Room column always blank; + phantom RBAC.
  • pickup-report [CODE-GROUNDED] — computes the WRONG metric: diffs two DIFFERENT stay-dates' current cumulative totals, not the SAME stay-date's booking count at two points in time. Its docstring's "negative = cancellations exceeded bookings" is structurally impossible (CONFIRMED counter never decrements). Should use the existing MvFrontOfficePace (bookedDate × stayDate). The spec encodes the wrong behavior as truth.
  • pre-arrival-pulse [CODE-GROUNDED] — permanent no-op stub (return {rows:[], warmingUp:true}), catalogued+scheduleable as if working (P-C class).
  • no-show-reservation [CODE-GROUNDED] — MvDailyOccupancy.noShows is NEVER incremented in real time — only SET by night-audit → shows silent 0 until audit runs (and permanently wrong if audit is skipped/rolled back), indistinguishable from "genuinely zero."

MATERIAL — wrong semantics / mislabeled​

  • arrival / departure — count ACTUAL check-ins/outs, NOT expected arrivals/departures (every incumbent's Arrival/Departure report is a pre-event guest roster for room-prep). Zero guest-level columns (name/room/ETA/VIP/source) + no drill-down → unusable as a front-desk worklist. Single-property-only chain rollup (drops other properties).
  • occupancy-report — occupancyPct reads the night-audit-only stale column instead of computing live from the same row's occupiedRooms/totalRooms → internally inconsistent row for the current day (manager-flash does it right inline). One-line fix.
  • manager-flash — metric math OK inline, but P-D (ratios→0 not null) + roomsSold || occupiedRooms silent metric fallback + phantom RBAC (P-F) + no LY/budget comparative.
  • booking-report — "Booking Date" dimension is actually the ARRIVAL date (outright mislabel) → "bookings today" shows reservations ARRIVING today, not CREATED today. cancelled/release/void share the arrival-vs-transaction-date ambiguity (all labelled just "Date").

MINOR​

  • P-D (÷0→0 not null) on manager-flash / country-wise / booking-enquiry ratios. Doc/code drift: arrival-report reads MvDailyOccupancy not the documented MvDailyArrivals.

ALL 6 BATCHES / 75 REPORTS REVIEWED — SYSTEMIC PATTERN TALLY​

  • P-A live-proxy mapper drops propertyId/date → 400/500 every run: night-audit, police-register, frro-c-form, folio-register, cash-drawer, city-ledger, high-balance, meal-plan, ar-aging-detail, discrepancy, room-status, room-status-detail, in-house, guest-checked-in, guest-checked-out, lost-and-found, spa-service-sales-detail, banquet-sales-detail, rate-parity-audit (~19).
  • P-B live-proxy schema field IDs ≠ downstream DTO → columns render blank (no field-mapping layer): folio-register, cash-drawer, void-register, city-ledger, high-balance, meal-plan, kot-register, lost-and-found, spa/banquet-detail, rate-parity, role-change-audit, user-activity-audit, discrepancy, room-status, room-status-detail, in-house, guest-checked-in, guest-checked-out (~18).
  • P-C permanently empty (EventStore-no-writer / topic-mismatch / stub / column-name mismatch): gst GSTR-3B, tax-audit-trail, linen-consumption, crm-feedback-pulse, booking-enquiry, block-group-performance, forecast-pace (forecast half), pre-arrival-pulse (~8).
  • P-D ÷0→0 not null: revenue-daily, revenue-monthly, item-wise-sales, server-productivity, manager-flash, country-wise, booking-enquiry (~7).
  • P-E statutory schema = export ceiling (missing column silently dropped from the filed doc): gst, gstr1-summary, einvoice, police-register, frro-c-form.
  • P-F RBAC gates on PHANTOM roles → unrunnable: in-house, guest-checked-in, guest-checked-out, pickup, manager-flash, pre-arrival-pulse, booking, release, void (~9) + assorted RBAC inconsistencies elsewhere.
  • ACCURACY (real domain errors on MV-backed reports): revenue-daily/monthly (revenue-at-booking not per-night, no-show not reversed, occupancy incl OOO, monthly avg-of-ratios), pickup (wrong metric), occupancy (stale pct), gst B2B/B2C split.
  • CLEAN (accurate + complete): dsr, pos-apc, pos-daypart, food-cost, cogs-by-category, sync-log, tip-out, housekeeping-productivity, payment-collection, settlement-register, refund-register(bar authorised-by), commission-report, expense-report, revenue-daily(cols), country-wise(bar P-D), rate-plan-performance, market-segment. (~17 largely clean, mostly MV-backed with matching columns.)

META: the unit specs are green because they mock the FICTIONAL field names / pre-populate the MV — a textbook "mocked-green, only-live" failure. The gating fix is a handful of SHARED changes (LiveProxyResolver auto-inject propertyId/date; a schema↔feed contract test; a response field-mapper; a phantom-role lint; the ÷0→null helper) that fix DOZENS of reports at once — plus per-report producer/semantic fixes for the accuracy + empty-MV cases.

Wave 2 — Finance/Revenue SME ACCURACY (16) — DONE (new consumer-layer DATA-CORRUPTION bugs)​

These POISON the MV itself (not just the report) — the numbers are wrong for every report that reads these MVs:

  • sale-register [CODE-GROUNDED] — folio.consumer.ts:246 HARDCODES source:'ROOM' on MvDailySalesRegister instead of reusing the correct categoryToSource(category) var computed 35 lines above (used correctly for MvRevenueBySource) → EVERY folio-routed charge (POS-to-room, spa-to-room, phone, cancellation/no-show/late-checkout fees) is mislabeled ROOM revenue → inflates Room, suppresses F&B/Spa/Phone. Also netRevenue = revenue − taxAmount DOUBLE-subtracts tax off an already tax-exclusive base (frontdesk stores amount = taxable base) → understated garbage.
  • commission / commission-statement / ota-commission-statement-detail [CODE-GROUNDED] — MvCommission is DOUBLE-WRITTEN (ChannelConsumer.onBookingReceived + ReservationConsumer.onCheckedOut both increment the same row, no shared dedup) → OTA revenue/bookings double-counted, commission% halved; AND never reversed on cancel (unlike the G2-fixed sibling MVs) → cancelled bookings permanently inflate. Plus MvCommission has NO GST-on-commission / §194-O TDS columns → the statutory legs a finance manager needs to reconcile the OTA payout are structurally absent.
  • source-wise-revenue / channel-production [CODE-GROUNDED] — MvChannelPerformance has ZERO reverse-on-cancel path (increment-only) → same G2 monotonic-overstatement class, left unfixed here.
  • channel-production [CODE-GROUNDED] — "ADR" = revenue ÷ bookingCount, NOT ÷ room-nights → ~5× inflated for a 5-night booking; internally inconsistent with room-type-revenue/market-segment which do ADR right.
  • pos-sales-register [CODE-GROUNDED] — MvPosRevenue no void/refund reversal (voided POS revenue stays forever); OUTLET/ITEM/SERVER rows share one flat revenue column → naive export SUM triple-counts.
  • ageing-report [CODE-GROUNDED] — reads EventStore for folio.posted/folio.closed (no writer) → always all-zero AR buckets (P-C).
  • pnl — overclaims "USALI" (flat Total-Rev − Total-Exp GOP, no departmental lines); P-D on 4 percent fields. expense — ACCURATE. room-type-revenue / market-segment — accurate, MINOR P-D.

NEW pattern: P-G consumer MV-write bugs (data corruption at the source) — hardcoded/wrong source label, double-write, no reverse-on-cancel, no void-reversal. Fixed once in the CONSUMERS, corrects every report reading that MV. Reports hit: sale-register, commission×3, source-wise-revenue, channel-production, pos-sales-register, + (from earlier) revenue-daily/monthly (revenue-at-booking + no-show-not-reversed). This is the same class the 2026-07-02 G2 data-integrity sweep fixed for 2 MVs — the sweep missed MvCommission / MvChannelPerformance / MvDailySalesRegister-source / MvPosRevenue.​