RevClamp Enterprise B2B REVENUE ASSURANCE Start Free
REVCLAMP ENGINEERING DISPATCH
← Back to Engineering Blog • SHOPIFY PLUS B2B & NET-TERMS • 4 min read

Floating-point deposit checks and credit notes broke our Shopify B2B Net-30 fulfillment holds

When a wholesale buyer places a €2,500.00 order on Shopify Plus B2B with Net-30 payment terms and a mandatory 30% upfront deposit (€750.00), warehouse fulfillment must remain locked in PENDING_DEPOSIT until the full deposit clears.

In production, two subtle bugs routinely break custom Shopify Plus B2B webhook handlers: converting decimal currency strings with IEEE-754 floating-point multiplication (19.99 * 100 === 1998.9999999999998) combined with naive orders/partially_paid triggers, and ignoring post-invoice credit notes when computing remaining wholesale balances.

SHOPIFY PLUS B2B 5-STATE INTEGER-CENT WHOLESALE RECONCILIATION ENGINE 1. PENDING_DEPOSIT fulfillmentHold: true paid < reqDeposit depositShortfallCents 2. DEPOSIT_CLEARED_ACTIVE fulfillmentHold: false paid >= reqDeposit remainingBalanceCents 3. FULLY_RECONCILED fulfillmentHold: false paid >= effectiveTotal creditDueCents / 0 4. BALANCE_OVERDUE nowSec > balanceDue overdue_balance tag remainingBalanceCents 5. ORDER_CANCELLED fulfillmentHold: true isCancelled: true refundDueCents

1. Why IEEE-754 float math and partial SEPA transfers release holds prematurely

Many B2B middleware scripts listen to Shopify's orders/partially_paid webhook and release fulfillmentOrders holds as soon as any non-zero payment arrives, or compare floats like paidAmount >= orderTotal * (depositPercent / 100).

When an enterprise buyer sends a partial SEPA bank wire of €500.00 (50000 cents) against a €2,500.00 (250000 cents) order requiring a 30% deposit (75000 cents), a handler that keys off financial_status === "partially_paid" without verifying integer-cent deposit thresholds releases the warehouse hold €250.00 early. Even worse, IEEE-754 binary floating-point arithmetic introduces 1-cent rounding drift on routine wholesale line items (Math.floor(19.99 * 100) === 1998 instead of 1999), causing deterministic ledger reconciliations to fail audit checks.

2. Post-invoice credit notes, returns, and cancelled wholesale orders

In B2B wholesale, invoices rarely stay static between deposit collection and the Net-15, Net-30, or Net-60 maturity date. Damaged pallets, SKU substitutions, and volume rebates generate credit notes (creditNoteCents) after the initial deposit is paid:

3. The 5-state integer-cent wholesale reconciliation state machine

Every wholesale order evaluation must operate strictly on safe integer cents (Number.isSafeInteger) across 5 primary wholesale ledger states (plus REFUNDED_OR_CREDITED when effectiveTotalCents === 0):

Wholesale Scenario Order & Ledger Inputs (EUR Cents) Naive Float / Webhook Bug Deterministic Integer-Cent Verdict
1. Partial Deposit Shortfall totalOrderCents: 250000, requiredDepositCents: 75000 (30%), paidAmountCents: 50000 Releases hold on first partial SEPA transfer PENDING_DEPOSIT (fulfillmentHold: true, depositShortfallCents: 25000)
2. Deposit Cleared (Net-30 Active) totalOrderCents: 250000, creditNoteCents: 10000, paidAmountCents: 80000 Float drift on 30% deposit check & adjusted balance DEPOSIT_CLEARED_ACTIVE (fulfillmentHold: false, remainingBalanceCents: 160000)
3. Credit-Note Overpayment totalOrderCents: 250000, creditNoteCents: 80000, paidAmountCents: 200000 Ignores credit note; demands €500.00 balance FULLY_RECONCILED (creditDueCents: 30000, overpaidWarning: true)
4. Past-Due Net-30 Invoice totalOrderCents: 250000, paidAmountCents: 75000, nowSec > balanceDueAtSec Leaves buyer account active past Net-30 maturity BALANCE_OVERDUE (orderTag: "b2b_net_terms:overdue_balance", remainingBalanceCents: 175000)
5. Cancelled Order Partial Refund isCancelled: true, paidAmountCents: 75000, refundedAmountCents: 25000 Orphans unrefunded €500.00 deposit on cancel ORDER_CANCELLED (fulfillmentHold: true, refundDueCents: 50000)

You can invoke the exact integer-cent reconciler over JSON-RPC 2.0 via our Model Context Protocol (MCP) server (POST https://api.revclamp.com/api/mcp) or REST simulator endpoint:

{
  "jsonrpc": "2.0",
  "id": "net-terms-check-1",
  "method": "tools/call",
  "params": {
    "name": "revclamp_reconcile_b2b_net_terms",
    "arguments": {
      "orderId": "gid://shopify/Order/908812",
      "totalOrderCents": 250000,
      "paidAmountCents": 80000,
      "creditNoteCents": 10000,
      "requiredDepositPercent": 30,
      "paymentTermsDays": 30
    }
  }
}
RevClamp Enterprise -- B2B Revenue & Compliance Guardrails
Open Free B2B Net-Terms Calculator → Test Live in MCP Playground Explore Shopify Plus B2B Vault Start Free Workspace (5,000 events/mo)