Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

receivables package

Overview

Package receivables publishes a receivables aging report and the resulting allowance for credit losses over invoices held in r/invoices.

An issuer registers an aging schedule — age bands in BLOCKS and a loss rate per band — and then names the invoice ids to age. This realm reads every FACT from the invoice realm (amount, amount paid, due height, status) and prices the result with p/aging. The published report is frozen: the per-bucket unpaid totals, the per-bucket provision, the grand provision, and a snapshot of the schedule that priced it.

The caller supplies the selection, the chain supplies the facts

This is the central design constraint and it is a measured one, not a preference. r/invoices exports no per-issuer id enumerator — its internal `Iterate` is unexported and nothing above it can walk an issuer's records — so a realm here CANNOT derive "every open invoice" on its own. It therefore takes the id list from the caller.

The consequence is stated rather than hidden: **a report can under-report**. An issuer who omits an overdue invoice from the list gets a provision that is too small, and no check here can see the omission. What this realm does instead is publish a COVERAGE LINE with every report — how many ids were listed, how many were aged, how many were filtered and why, and how many open invoices and stored records the issuer held at that height — so a reader can compute the shortfall themselves. See Coverage.

Under-reporting is made VISIBLE here. It is not prevented, and a reader who treats a published provision as complete without reading the coverage line is reading it wrongly.

Ages are in BLOCKS

r/invoices stores `dueHeight` as a block height, so an age is a count of blocks and every schedule edge is a count of blocks. A "30/60/90 day" schedule is a conversion the ISSUER owns and this realm never performs: nothing here knows the block time, and compiling a guess in would make every published rate wrong by whatever the guess was off by.

This realm writes no ledger entry

A provision is an accounting entry — debit a credit-loss expense, credit an allowance — and this realm deliberately does not post it. r/books derives the owner of a book structurally from its caller, so a realm that called `PostMulti` would post into ITS OWN book and not the issuer's. There is no owner parameter to pass and no delegation path to use.

So ProposedEntry returns the entry as a string in the form r/books' `PostMulti` accepts, and the issuer posts it themselves from their own account. The realm stays keyless with respect to every ledger, which is the stronger position: it cannot write a wrong entry because it cannot write.

Custody

None. This realm holds no coins, has no withdrawal path, and refuses a user call that arrives carrying any. Nothing here moves value; a provision is a statement about value, which is not the same thing.

Limitations

  • **The report is a self-report of a self-report.** r/invoices' amounts are whatever an issuer typed; an aging of them inherits that entirely and then looks like an audited artifact. No audit happens here.
  • **It can under-report, by construction.** See above and Coverage.
  • **It cannot over-report an unlisted invoice**, because every fact comes from the chain — but it CAN over-report a *listed* one whose amount the issuer inflated in r/invoices in the first place.
  • **No write-off.** p/aging prices an expected loss and never removes an obligation; a receivable this report provisions at 100% is still a live invoice in r/invoices. Voiding is that realm's operation, not this one's.
  • **A frozen report does not track the invoices.** A payment landing after publication leaves the published figures untouched, which is what "frozen" means. There is no `Verify` here: re-deriving would need the id list, which is not stored (see Publish).
  • **Buckets are floored per bucket**, so the per-bucket column sums to the grand provision exactly and both are at or below the unrounded figure. p/aging's package doc carries the counterexample.
  • **No cross-issuer aggregate.** There is no enumerator and no total provision across issuers; such a figure would sum strangers' assertions.

r/invoices: /r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/invoices r/books: /r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/books p/aging: /p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/aging

Function

Source

func Source() string
Ask AI Claude ChatGPT

Source is the realm every figure here is read from, by value from its own exported constant.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/receivables.Source()"

Result