Skip to main content

Version Docs Updated

Purpose

MHM Rentiva uses a financial engine called "Model B" β€” immutable and always auditable. This document explains how vendor earnings are calculated and how payout processes are managed atomically.

πŸ’³ Financial Engine & Payout Cycle

The system calculates vendor balances using an append-only ledger rather than a dynamic balance field.


πŸ—οΈ 1. Model B Ledger Structure​

The Ledger is the single source of truth for all financial data in the system.

Immutability Principle​

  • Update/Delete Prohibited: No ledger row can be updated or deleted.
  • Correction Entries: A faulty transaction can only be corrected by a reversal entry.
  • SaaS Isolation: Each entry is associated with a tenant_id.

Entry Types​

TypeDirectionDescription
commission_credit+Earnings from a completed booking.
payout_debitβˆ’Balance reduction from an approved payout request.
refundβˆ’Refund from a cancelled booking.

βš›οΈ 2. Atomic Payout Process (AtomicPayoutService)​

Payout approvals occur within a database-level Transaction. This ensures the entire process is rolled back if any step fails.

Process Steps:​

  1. Pre-flight Check: Balance and status verification (outside transaction).
  2. START TRANSACTION: DB lock initiated.
  3. Concurrent Guard: post_status is re-read from the DB (race condition prevention).
  4. Ledger Write: payout_pending_debit entry is created.
  5. CPT Update: Payout post is set to publish status.
  6. COMMIT: All operations are persisted if successful.

πŸ›‘οΈ 3. Double-Spending Prevention Layers​

Four layers of protection exist against double-spending risk:

LayerMechanismLevel
L1: Applicationvendor_has_pending_payout() check.PHP / AJAX
L2: BalanceLedger::get_balance() >= amount validation.Domain Logic
L3: TransactionInnoDB Row Lock and concurrent status guard.Database
L4: IdempotencyUnique UUID in payout_{id} format.DB Unique Key

βš™οΈ 4. Technical API Reference​

Balance Query​

// Returns the sum of entries with 'cleared' and 'reserved' statuses only.
$balance = Ledger::get_balance($vendor_id);

Creating a Payout Request​

// PayoutService::request_payout()
// 1. Minimum limit (mhm_min_payout_amount) is checked.
// 2. Presence of a pending request is verified.
// 3. mhm_payout post is created.

πŸ“§ 5. Notifications & Hooks​

HookTriggerRecipient
mhm_rentiva_payout_approvedWhen payout is atomically approved.Vendor
mhm_rentiva_payout_rejectedWhen payout is rejected by the admin.Vendor

Section Summary​

  • The Ledger table uses an APPEND-ONLY architecture.
  • AtomicPayoutService guarantees database consistency via transactions.
  • Double-spending prevention (Idempotency) is enforced at the UUID level.

Changelog​

DateVersionNote
23.04.20264.27.2English translation added.
19.03.20264.21.2Model B Engine, Atomic Transactions, and SaaS isolation details added.