Customer-advance reconciliation

The API combines reviewed liability, revenue, receivables and cash flow disclosures to answer two questions:

  • What net advance cash is compatible with these disclosures?

  • How much net noncash movement would an alternative cash interpretation require?

CustomerAdvanceBridge compiles a provider-neutral mapping into the existing named-linear solver. Source retrieval, unit normalization, accounting review and the choice of a hypothetical cash ceiling remain explicit inputs. These APIs are available in updatesupport-finance>=0.1.6 with updatesupport>=0.1.7.

Declare the accounting mapping

import updatesupport_finance as f

scope = f.DisclosureScope(
    "ExampleCo", "advance liabilities", "USD million", "2026-06-30", "H1",
    "all customers", period_start="2026-01-01", currency="USD",
)
bridge = f.CustomerAdvanceBridge(
    name="advances", scope=scope, opening="opening", closing="closing",
    movements=[
        f.AdvanceMovement("cash", "net_cash", "Net cash including old unpaid collections"),
        f.AdvanceMovement("recognized", "recognition", "Recognition from advance liabilities"),
        f.AdvanceMovement("unpaid_open", "unpaid_opening", "Opening unpaid advances"),
        f.AdvanceMovement("unpaid_close", "unpaid_closing", "Closing unpaid advances"),
        f.AdvanceMovement("other", "noncash", "All other signed noncash movements"),
    ],
    accounting_regime="Reviewed source-specific policy",
    recognition_basis="All recognition from advances, including current-period cohorts",
    complete=True,
    completeness_basis="Reviewed exhaustive movement classes; noncash amounts unknown",
)

The identity is:

closing = opening + net cash + unpaid change + net noncash - recognition

Net cash includes collections of old unpaid advance bills and subtracts refunds. It is distinct from gross receipts and from the indirect cash-flow statement’s liability adjustment. Recognition from an opening cohort is only one component of total recognition; map other cohorts separately or retain a bounded unknown. Do not substitute total company revenue without reviewing its relationship to this liability and cohort.

Movement kind

Primitive domain

Effect on the liability

net_cash

Signed

Addition

cash_receipt

Nonnegative magnitude

Addition

cash_refund

Nonnegative magnitude

Reduction

recognition

Nonnegative magnitude

Reduction

unpaid_opening

Nonnegative stock

Reduction

unpaid_closing

Nonnegative stock

Addition

unpaid_change

Signed change

Addition

noncash

Signed

Addition; effect=-1 reverses a source sign

Multiple primitives may belong to a category. Net cash cannot be mixed with gross receipts/refunds. Use both unpaid endpoints, including a constrained zero when appropriate, or a signed change; mixing the representations is rejected. A source-positive noncash reduction uses effect=-1; its amount is still signed unless a separate source or policy constraint establishes a magnitude domain.

complete=True is the caller’s assertion that the mapping covers every movement class. Unresolved amounts remain unknown: an unrestricted noncash primitive can keep the cash interval unbounded. Absent categories in a complete mapping have zero contribution because of this declaration. It requires a written completeness_basis; the package does not verify an issuer’s accounting policy.

Use complete=False if movement classes may be omitted. The compiler adds a signed bridge.unclassified residual that may include cash, recognition or noncash movements. Zero totals for omitted categories refer only to supplied primitives. The residual is never automatically attributed to noncash, and the minimum-noncash explanation helper rejects an incomplete mapping.

Add evidence and separate the cash-flow diagnostic

Supply source bounds with disclosure_fact_constraint, after normalizing to the scope’s numerical unit. This retains source precision and provenance. Each primitive is created once; other cash measures can reuse its name. Arbitrary amount caps belong in explicit evidence or ConstraintPolicy constraints. For example, gross AR can constrain unpaid advance bills only after reviewing entity, cohort, date, allowance treatment and whether those bills are included. Net AR alone is not automatically a gross-billing cap.

problem = bridge.problem(
    constraints=source_constraints,
    variables=[f.disclosure_variable("cfo", lower=None, unit=scope.unit)],
)

The default tier is reported. Custom tiers retain the bridge’s structural identities in every scenario. Additional variables must use the same numerical unit; variable names cannot replace generated primitives. The caller must review currency, dates, cohort and definitions of those additional inputs. Normalize currencies separately; the package does not infer FX or unit conversions here.

An optional cash_flow_adjustment="cf_adjustment" creates a signed input and a separate target, bridge.cash_flow_gap:

gap = closing - opening - indirect cash-flow liability adjustment

The gap is diagnostic. The compiler never equates it to receipts or to a particular noncash cause. Keep ASC 606 financing, acquisition, FX and reclassification mappings separate from ASC 842 straight-line adjustments; the accounting_regime and recognition_basis record the reviewed meanings.

Solve the alternative interpretation

analysis = f.minimum_advance_explanation(
    bridge, problem,
    cash_ceiling={"cfo": .8},
    ceiling_description="Hypothetical net cash at most 80% of reported CFO",
)
required = analysis.report.interval(
    target=bridge.noncash, scenario="advance_explanation",
)
print(required.lower, required.upper, required.status)

The ceiling can be an amount, a variable name, a coefficient mapping or a NamedLinearExpression with a constant. All use the bridge’s numerical unit. A fractional CFO expression imposes a linear condition; it does not compute a ratio or certify a positive denominator. Establish positive CFO separately if interpreting the result as a share.

The lower endpoint is the minimum signed net noncash addition needed under the condition. A negative minimum is retained. A missing endpoint with unbounded status means the encoded evidence imposes no finite bound; infeasible means the alternative contradicts active constraints and yields a conflict report. Endpoint assignments are feasible partial accounting explanations, not complete financial statements or claims about economic plausibility.

The condition is labeled analyst_policy, so support is explicitly conditional. release_constraints can remove active policies or management expectations, following break_even_analysis; it cannot remove reported facts or accounting identities. The helper also checks that its bridge variables, targets and identities remain intact in the selected tier.

An acquisition-only amount cap cannot bound all noncash effects. Interest expense net of capitalized amounts cannot automatically cap customer financing accretion. Qualitative words such as “primarily” do not generate numeric bounds. The workflow reports necessary alternative explanations without assigning their probabilities or estimating recurring CFO.

Audit and replay

Use the ordinary claim, allocation witness, constraint attribution and conflict APIs on the compiled problem. Save bridge.snapshot_context() in an offline DisclosureSnapshot, merged with normalization records. The saved mapping records accounting regime, recognition basis, cash basis and completeness; the snapshot preserves source facts and all compiled relationships for replay.

The complete synthetic offline example shows an unidentified cash interval, a minimum alternative explanation and a separate exhaustive table that reconstructs cash. Regression controls also reproduce disclosed Core Scientific cash amounts from public SEC filings and check conditional noncash requirements using public Nebius figures. They test accounting mapping and arithmetic; they do not establish novel discovery or superiority over a spreadsheet solver.