Source code for Acquire.Accounting._transactioninfo


from enum import Enum as _Enum

__all__ = ["TransactionInfo", "TransactionCode"]


[docs]class TransactionCode(_Enum): CREDIT = "CR" DEBIT = "DR" CURRENT_LIABILITY = "CL" ACCOUNT_RECEIVABLE = "AR" RECEIVED_RECEIPT = "RR" SENT_RECEIPT = "SR" RECEIVED_REFUND = "RF" SENT_REFUND = "SF"
[docs]class TransactionInfo: """This class is used to encode and extract the type of transaction and value to/from an object store key """ def __init__(self, key=None): """Construct, optionally from the passed key""" if key is not None: t = TransactionInfo.from_key(key) import copy as _copy self.__dict__ = _copy.copy(t.__dict__) else: from Acquire.Accounting import create_decimal as _create_decimal self._value = _create_decimal(0) self._receipted_value = _create_decimal(0) self._code = None self._datetime = None self._uid = None def __str__(self): if self._receipted_value is None: return "TransactionInfo(code==%s, value==%s)" % \ (self._code.value, self._value) else: return "TransactionInfo(code==%s, value==%s, receipted==%s)" % \ (self._code.value, self._value, self._receipted_value) def __eq__(self, other): if isinstance(other, self.__class__): return self._code == other._code and \ self._value == other._value else: return False def __ne__(self, other): return not self.__eq__(other) @staticmethod def _get_code(code): """Return the TransactionCode matching 'code'""" return TransactionCode(code)
[docs] @staticmethod def encode(code, value, receipted_value=None): """Encode the passed code and value into a simple string that can be used as part of an object store key. If 'receipted_value' is passed, then encode the receipted value of the provisional transaction too """ if receipted_value is None: return "%2s%013.6f" % (code.value, value) else: return "%2s%013.6fT%013.6f" % (code.value, value, receipted_value)
[docs] def rescind(self): """Return a TransactionInfo that corresponds to rescinding this transaction info. This is useful if you want to update the ledger to remove this object (since we can't delete anything from the ledger) """ t = TransactionInfo() t._uid = self._uid[-1::-1] t._value = self._value t._datetime = self._datetime if self._code is TransactionCode.DEBIT: t._code = TransactionCode.CREDIT elif self._code is TransactionCode.CREDIT: t._code = TransactionCode.DEBIT elif self._code is TransactionCode.CURRENT_LIABILITY: t._value = -(self._value) elif self._code is TransactionCode.ACCOUNT_RECEIVABLE: t._value = -(self._value) else: raise PermissionError( "Do not have permission to rescind a %s" % str(self)) return t
[docs] def value(self): """Return the value of the transaction. This will be the receipted value if this has been set""" if self._receipted_value is not None: return self._receipted_value else: return self._value
[docs] def uid(self): """Return the UID of this transaction""" return self._uid
[docs] def dated_uid(self): """Return the full dated uid of the transaction. This is isoformat(datetime)/uid """ return "%s/%s" % (self._datetime.isoformat(), self._uid)
[docs] def datetime(self): """Return the datetime of this transaction""" return self._datetime
[docs] @staticmethod def from_key(key): """Extract information from the passed object store key. This looks for a string that is; isoformat_datetime/UID/transactioncode where transactioncode is a string that matches '2 letters followed by a number' CL000100.005000 DR000004.234100 etc. For sent and received receipts there are two values; the receipted value and the original estimate. These have the standard format if the values are the same, e.g. RR000100.005000 however, they have original value T receipted value if they are different, e.g. RR000100.005000T000090.000000 Args: key: Object store key """ from Acquire.ObjectStore import string_to_datetime \ as _string_to_datetime from Acquire.Accounting import create_decimal as _create_decimal parts = key.split("/") # start at the end... nparts = len(parts) for i in range(0, nparts): j = nparts - i - 1 t = TransactionInfo() try: t._datetime = _string_to_datetime(parts[j-2]) except: continue t._uid = parts[j-1] part = parts[j] try: code = TransactionInfo._get_code(part[0:2]) if code == TransactionCode.SENT_RECEIPT or \ code == TransactionCode.RECEIVED_RECEIPT: values = part[2:].split("T") try: value = _create_decimal(values[0]) receipted_value = _create_decimal(values[1]) t._code = code t._value = value t._receipted_value = receipted_value return t except: pass value = _create_decimal(part[2:]) t._code = code t._value = value t._receipted_value = None return t except: pass raise ValueError("Cannot extract transaction info from '%s'" % (key))
[docs] def to_key(self): """Return this transaction encoded to a key""" from Acquire.ObjectStore import datetime_to_string \ as _datetime_to_string return "%s/%s/%s" % (_datetime_to_string(self._datetime), self._uid, TransactionInfo.encode( code=self._code, value=self._value, receipted_value=self._receipted_value))
[docs] def receipted_value(self): """Return the receipted value of the transaction. This may be different to value() when the transaction was provisional, and the receipted value is less than the provisional value. This returns None if this transaction wasn't receipted Returns: Decimal: Receipted value of Transaction """ return self._receipted_value
[docs] def original_value(self): """Return the original (pre-receipted) value of the transaction""" return self._value
[docs] def is_credit(self): """Return whether or not this is a credit Returns: bool: True if this is a credit, else False """ return self._code == TransactionCode.CREDIT
[docs] def is_debit(self): """Return whether or not this is a debit Returns: bool: True if this is a debit, else False """ return self._code == TransactionCode.DEBIT
[docs] def is_liability(self): """Return whether or not this is a liability Returns: bool: True if this is a liability, else False """ return self._code == TransactionCode.CURRENT_LIABILITY
[docs] def is_accounts_receivable(self): """Return whether or not this is accounts receivable Returns: bool: True if this is accounts receivable, else False """ return self._code == TransactionCode.ACCOUNT_RECEIVABLE
[docs] def is_sent_receipt(self): """Return whether or not this is a sent receipt Returns: bool: True if this is accounts receivable, else False """ return self._code == TransactionCode.SENT_RECEIPT
[docs] def is_received_receipt(self): """Return whether or not this is a received receipt Returns: bool: True if this is a received receipt, else False """ return self._code == TransactionCode.RECEIVED_RECEIPT
[docs] def is_sent_refund(self): """Return whether or not this is a sent refund Returns: bool: True if this is a sent refund, else False """ return self._code == TransactionCode.SENT_REFUND
[docs] def is_received_refund(self): """Return whether or not this is a received refund Returns: bool: True if this is a received refund, else False """ return self._code == TransactionCode.RECEIVED_REFUND