Skip to content

Billing and Finance

This page explains the financial operations that run through MIDDAG Account: invoice generation, tax invoice issuance, payment reconciliation, credit balance management, and dual-entity financial routing.

Financial data flow

Invoice generation

Invoices in MIDDAG Account are read-only reflections of Stripe data. The system does not generate invoices independently -- it syncs them from Stripe via webhooks.

The webhook flow:

  1. Stripe fires an event (e.g., invoice.created, invoice.paid, invoice.payment_failed).
  2. The webhook hits the appropriate endpoint (/webhooks/stripe/br or /webhooks/stripe/llc).
  3. The system validates the webhook signature against the account-specific secret.
  4. The invoice data is persisted locally, linked to the Organization via the Stripe Customer ID.
  5. The invoice is tagged with the originating Stripe account (middag_br or middag_global).

The system processes multiple invoice event types: creation, update, payment, payment failure, voiding, and finalization. Duplicate events are handled via idempotency checks.

Customer experience: The customer sees a unified list of invoices from both entities in the portal, with a visual indicator showing which entity issued each one. They can filter by entity, status, or date range, and download PDFs directly from Stripe.

Tax invoice (NFSe) for Brazilian operations

NFSe (Nota Fiscal de Servico Eletronica) is a Brazilian tax invoice required for service transactions. It is issued exclusively for MIDDAG BR transactions.

Automatic issuance

When a BR payment is confirmed:

  1. The system detects the entity is middag_br.
  2. It extracts service details, amounts, and the customer's tax information.
  3. It submits an XML request to the ISSNet web service (Brasilia/DF municipal authority) via SOAP.
  4. If ISSNet responds immediately with approval, the NFSe is recorded as issued.
  5. If ISSNet queues it for processing, the NFSe is recorded as pending.

Status verification

A cron job runs every 5 minutes to check pending NFSe:

  • Queries ISSNet for updated status.
  • Transitions pending to issued (with the official NFSe number and verification code) or to rejected (with the rejection reason).
  • NFSe pending for more than 24 hours triggers an admin notification.

Manual issuance

The admin can issue NFSe manually from the admin panel when automatic issuance fails or when special circumstances require manual data adjustment (e.g., correcting the service description or municipal tax code).

What the customer sees

Brazilian customers see NFSe listed alongside Stripe invoices in the portal, with a distinct label. They can download both the XML (for tax compliance) and a PDF version.

Payment reconciliation

Payment data flows from multiple sources and must be reconciled:

SourceWhat it coversSync mechanism
Stripe BRCard payments for BR entityWebhooks
Stripe GLOBALCard payments for US entityWebhooks
Banco InterPix and Boleto for BR entityWebhooks / callbacks

A reconciliation cron runs every 15 minutes to verify consistency between Stripe records and local invoice data. Discrepancies are flagged for admin review.

Unmatched invoices -- When a Stripe invoice cannot be matched to an Organization (e.g., the Stripe Customer ID is not linked), the invoice is stored with a null Organization and the admin is notified for manual linking.

Credit balance management

For SVC entitlements, the CreditBalance tracks UST consumption:

OperationEffect on balance
Service activatedBalance initialized (may start at zero)
Credits purchasedBalance increases
SR openedCredits reserved (held, not yet debited)
SR completedReserved credits debited from balance
SR cancelledReserved credits released back to balance
Credits expiredBalance decreases (per CreditPolicy)

The CreditPolicy governs:

  • Expiration period for included credits (default: 12 months) vs. purchased credits (default: 6 months)
  • Consumption order (FIFO by default -- oldest credits consumed first)
  • Grace period after expiration
  • Low-balance alerts (default: when 20% remains)

Dual-entity financial routing

Every financial transaction is routed to the correct legal entity:

Decision pointHow it is determined
Stripe accountBased on Organization's billing entity (BR or GLOBAL)
Payment methodsBR: card + Pix + Boleto. GLOBAL: card only
CurrencyBR: BRL. GLOBAL: USD
Tax invoiceBR: NFSe issued via ISSNet. GLOBAL: no tax invoice
HubSpot portalBR and GLOBAL have separate portals

An Organization can have Stripe Customer IDs and HubSpot Company IDs for both entities simultaneously. This supports customers with transactions in both currencies.

See Multi-Entity Operations for the full routing logic.

Admin financial dashboard

The admin panel provides a consolidated financial view:

  • Revenue by period (monthly, quarterly, annual)
  • Revenue split by entity (BR vs GLOBAL)
  • Outstanding payments (unpaid boletos, failed cards)
  • Overdue invoices with urgency indicators
  • Active vs cancelled subscriptions

All data is sourced from local WooCommerce records, not directly from Stripe, ensuring consistency even if Stripe is temporarily unreachable.