RevBank::Cart

The current, unfinished transaction


Synopsis

sub command_bounty($self, $cart, $command, @) {
    return run => sub {
        $cart
            ->add(+10, "Bounty")
            ->add_contra("-expenses/bounties", -10, "Bounty for \$you");

        return ACCEPT;
    };
}

for my $entry ($cart->entries('product')) { ... }

$cart->checkout($account);

Description

The cart holds the entries of the transaction that is being built, until it is checked out to an account or aborted. Command methods and most hooks receive it as $cart.

Each entry is a RevBank::Cart::Entry, with an amount from the perspective of the account that will check out: negative to pay, positive to receive. Every entry needs contras that balance it, added with $entry->add_contra, or checkout fails.

The shell replaces the cart with a new one after a checkout or an abort, so don't keep a reference to it across commands.

Methods

Entries

add($amount, $description, $attributes = {})

Adds an entry and returns it, so that add_contra can be chained. The amount may be a RevBank::Amount or a string that parse_string accepts. $attributes is a hash reference of initial entry attributes.

Calls hook_add_entry before and hook_added_entry after adding. The new entry becomes the selected one.

add_entry($entry)

Like add, for an entry that was made with RevBank::Cart::Entry->new.

entries($attribute = undef)

Returns the entries, or only those that have the given attribute defined.

size

Returns the number of entries.

delete($entry)

Removes the entry, and returns the number of entries removed.

select($entry), selected

Commands like repeat act on the selected entry. Adding an entry selects it, and a plugin can select another; deduplicate selects the entry that an added one was merged into. selected returns undef for an empty cart.

Totals

sum

Returns the sum of the entries' amounts times their quantities, as a RevBank::Amount, or undef for an empty cart. Contras are not included.

deltas($account)

Returns a hash reference of how much each account's balance would change if the cart were checked out to $account, including $account itself.

Attributes

attribute($key), attribute($key => $value)

Per-cart storage for plugins that need to remember something for the duration of the current transaction. Plugins can access each other's attributes: in a way, they act like global variables. Prefix the key with the plugin's name to avoid collisions.

The two argument form sets the attribute and returns the new value.

When a checkout is aborted recoverably (see "Exceptions" in RevBank::Plugins), the attributes are restored together with the rest of the cart.

has_attribute($key)

Returns whether the attribute exists and is defined.

Display

display($prefix = "")

Prints the entries, each line prefixed with $prefix.

changed($keep = 0)

Returns whether the cart or any of its entries changed since the last call, and resets that unless $keep is true. The shell uses this to redisplay the cart before a prompt, so a plugin that only wants to know should pass a true $keep.

Checkout

checkout($account)

Finalizes the transaction for the given account, which must exist, unless it is a hidden account; see RevBank::Accounts. Call it from a command's run, which should then return ACCEPT.

Checkout is refused when more input follows on the same line without a ;. It dies when an entry has the refuse_checkout attribute or is unbalanced.

The hooks run in this order: hook_checkout_prepare, then with the global lock held, hook_checkout, deferred code, the balance updates, and hook_checkout_done, and after the lock, hook_checkout_followup. See "Hooks" in RevBank::Plugins.

From hook_checkout on, the cart is sealed: reading it works, but anything that would change the cart or its entries dies.

assert_checkout_possible

Dies like checkout would for trailing input or a refuse_checkout entry. checkout calls it first; a command that adds entries before its checkout should call it before adding them. See "Cart state" in RevBank::Plugins.

defer($code)

Queues $code to run during checkout, after hook_checkout, with the transaction ID as its argument. Only valid in hook_checkout_prepare. See hook_checkout_prepare in RevBank::Plugins for why.

Author

Juerd Waalboer #####@juerd.nl