Source code for turberfield.common.accounts

#!/usr/bin/env python3
# encoding: UTF-8

# This file is part of turberfield.
#
# Turberfield is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Turberfield is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with turberfield.  If not, see <http://www.gnu.org/licenses/>.

import asyncio
from collections import defaultdict
from collections import deque
from collections import namedtuple
from decimal import Decimal
import enum
import itertools

from tallywallet.common.ledger import Exchange
from tallywallet.common.ledger import Ledger

__doc__ = """

Credit transactions
===================

The :py:class:`~turberfield.common.accounts.Accounts` class gives you
a simple way of recording goods exchange on credit (between a `merchant`
and `miner` in this example).

``Accounts.credit.ledger`` contains a sequence of transactions between
two parties. The first index supplied to the ledger is the giver
of the goods, the second is the recipient. Think of it therefore as the
book of credit on the seller's countertop.

.. code-block:: python

    accounts = Accounts()
    accounts.credit.ledger[merchant, miner].append(
        GoodsOnCredit(
            240000,
            Resource(Commodity.FOOD, Mass.Kg, 120),
            CreditRelationship.welcome)
        )
    accounts.credit.ledger[miner, merchant].append(
        GoodsOnCredit(
            240000,
            Resource(Commodity.STON, Mass.Kg, 120),
            CreditRelationship.established)
        )

:py:class:`~turberfield.common.accounts.GoodsOnCredit` is a data structure
defined for use in this way. It contains a timestamp, information on the
current nature of the
:py:class:`credit relationship <turberfield.eargain.types.CreditRelationship>`
as well as details of the
:py:class:`items <turberfield.common.inventory.Resource>` dispatched.

Currencies
==========

Banking
=======

"""

class Coin(enum.Enum):
    c = 1
    p = 1
    s = 12
    d = 100
    l = 240

[docs]class GoodsOnCredit(namedtuple("GoodsOnCredit", ["at", "resource", "status"])): """ at a timestamp (integer or :py:class:`~datetime.datetime`) resource a :py:class:`~turberfield.common.inventory.Resource` status: an enum.Enum a :py:class:`~turberfield.eargain.types.CreditRelationship` """
[docs]class Accounts: """ The accounts in Turberfield are a shareable object. You need to define it once in your main module:: accounts = Accounts(columns, ref) Elsewhere, you can grab a readable copy like this:: accounts = Accounts() """ CreditAPI = namedtuple("CreditAPI", ["ledger"]) CurrencyAPI = namedtuple("CurrencyAPI", ["ref", "exchange"]) BankingAPI = namedtuple("BankingAPI", ["ledger"]) _shared_state = {} def __init__(self, columns=None, ref=None): self.__dict__ = self._shared_state if not hasattr(self, "credit"): self.credit = Accounts.CreditAPI( ledger=defaultdict(list) ) if columns and ref and not hasattr(self, "banking"): self.currency = Accounts.CurrencyAPI( ref=ref, exchange=Exchange( {k: Decimal(1) for k in itertools.permutations( type(ref), 2)}) ) self.banking = Accounts.BankingAPI( ledger=Ledger(*columns, ref=ref) ) def _clear(self): try: del self.credit except AttributeError: pass try: del self.currency except AttributeError: pass try: del self.banking except AttributeError: pass @asyncio.coroutine def set(self, cols, val): rv = asyncio.Future() for c in cols: self.banking.ledger.commit(val, c) rv.set_result(val) return rv