def load_transaction(uid, bucket=None): """Load the transactionrecord with UID=uid from the ledger Args: uid (str): UID of transaction to load bucket (dict, default=None): Bucket to load data from Returns: TransactionRecord: Transaction with that UID """ if bucket is None: from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket bucket = _get_service_account_bucket() from Acquire.Accounting import TransactionRecord as _TransactionRecord from Acquire.ObjectStore import ObjectStore as _ObjectStore data = _ObjectStore.get_object_from_json(bucket, Ledger.get_key(uid)) if data is None: from Acquire.Accounting import LedgerError raise LedgerError("There is no transaction recorded in the " "ledger with UID=%s (at key %s)" % (uid, Ledger.get_key(uid))) return _TransactionRecord.from_data(data)
def refund(refund, bucket=None): """Create and record a new transaction from the passed refund. This applies the refund, thereby transferring value from the credit account to the debit account of the corresponding transaction. Note that you can only refund a transaction once! This returns the (already recorded) TransactionRecord for the refund """ from Acquire.Accounting import Refund as _Refund from Acquire.Accounting import Account as _Account from Acquire.Accounting import DebitNote as _DebitNote from Acquire.Accounting import CreditNote as _CreditNote from Acquire.Accounting import PairedNote as _PairedNote from Acquire.Accounting import TransactionRecord as _TransactionRecord if not isinstance(refund, _Refund): raise TypeError("The Refund must be of type Refund") if refund.is_null(): return _TransactionRecord() if bucket is None: from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket bucket = _get_service_account_bucket() # return value from the credit to debit accounts debit_account = _Account(uid=refund.debit_account_uid(), bucket=bucket) credit_account = _Account(uid=refund.credit_account_uid(), bucket=bucket) # remember that a refund debits from the original credit account... # (and can only refund completed (DIRECT) transactions) debit_note = _DebitNote(refund=refund, account=credit_account, bucket=bucket) # now create the credit note to return the value into the debit account try: credit_note = _CreditNote(debit_note=debit_note, refund=refund, account=debit_account, bucket=bucket) except Exception as e: # delete the debit note try: debit_account._delete_note(debit_note, bucket=bucket) except: pass # reset the transaction to its original state try: _TransactionRecord.load_test_and_set( refund.transaction_uid(), _TransactionState.REFUNDING, _TransactionState.DIRECT, bucket=bucket) except: pass raise e try: paired_notes = _PairedNote.create(debit_note, credit_note) except Exception as e: # delete all records...! try: debit_account._delete_note(debit_note, bucket=bucket) except: pass try: credit_account._delete_note(credit_note, bucket=bucket) except: pass # reset the transaction to the pending state try: _TransactionRecord.load_test_and_set( refund.transaction_uid(), _TransactionState.REFUNDING, _TransactionState.DIRECT, bucket=bucket) except: pass raise e # now record the two entries to the ledger. The below function # is guaranteed not to raise an exception return Ledger._record_to_ledger(paired_notes, refund=refund, bucket=bucket)
def _create_from_receipt(self, debit_note, receipt, account, bucket): """Internal function used to create the credit note from the passed receipt. This will actually transfer value from the debit note to the credited account debit_note (DebitNote): DebitNote from which to take value receipt (Receipt): Receipt to create CreditNote from account (Account): Account to credit bucket (Bucket): Bucket to load data from Returns: None """ from Acquire.Accounting import DebitNote as _DebitNote from Acquire.Accounting import Refund as _Refund from Acquire.Accounting import TransactionRecord as _TransactionRecord from Acquire.Accounting import TransactionState as _TransactionState from Acquire.Accounting import Account as _Account from Acquire.Accounting import Receipt as _Receipt if not isinstance(debit_note, _DebitNote): raise TypeError("You can only create a CreditNote " "with a DebitNote") if not isinstance(receipt, _Receipt): raise TypeError("You can only receipt a Receipt object: %s" % str(receipt.__class__)) # get the transaction behind this receipt and ensure it is in the # receipting state... transaction = _TransactionRecord.load_test_and_set( receipt.transaction_uid(), _TransactionState.RECEIPTING, _TransactionState.RECEIPTING, bucket=bucket) # ensure that the receipt matches the transaction... transaction.assert_matching_receipt(receipt) if account is None: account = _Account(transaction.credit_account_uid(), bucket) elif account.uid() != receipt.credit_account_uid(): raise ValueError("The accounts do not match when crediting " "the receipt: %s versus %s" % (account.uid(), receipt.credit_account_uid())) (uid, datetime) = account._credit_receipt(debit_note, receipt, bucket) self._account_uid = account.uid() self._debit_account_uid = debit_note.account_uid() self._datetime = datetime self._uid = uid self._debit_note_uid = debit_note.uid() self._value = debit_note.value() self._is_provisional = debit_note.is_provisional() if debit_note.is_provisional(): self._receipt_by = debit_note.receipt_by() # finally(!) move the transaction into the receipted state _TransactionRecord.load_test_and_set(receipt.transaction_uid(), _TransactionState.RECEIPTING, _TransactionState.RECEIPTED, bucket=bucket)
def receipt(receipt, bucket=None): """Create and record a new transaction from the passed receipt. This applies the receipt, thereby actually transferring value from the debit account to the credit account of the corresponding transaction. Note that you can only receipt a transaction once! This returns the (already recorded) TransactionRecord for the receipt Args: receipt (Receipt): Receipt to use for transaction bucket (default=None): Bucket to load data from Returns: list: List of TransactionRecords """ from Acquire.Accounting import Receipt as _Receipt from Acquire.Accounting import Account as _Account from Acquire.Accounting import DebitNote as _DebitNote from Acquire.Accounting import CreditNote as _CreditNote from Acquire.Accounting import TransactionRecord as _TransactionRecord from Acquire.Accounting import PairedNote as _PairedNote if not isinstance(receipt, _Receipt): raise TypeError("The Receipt must be of type Receipt") if receipt.is_null(): return _TransactionRecord() if bucket is None: from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket bucket = _get_service_account_bucket() # extract value into the debit note debit_account = _Account(uid=receipt.debit_account_uid(), bucket=bucket) credit_account = _Account(uid=receipt.credit_account_uid(), bucket=bucket) debit_note = _DebitNote(receipt=receipt, account=debit_account, bucket=bucket) # now create the credit note to put the value into the credit account try: credit_note = _CreditNote(debit_note=debit_note, receipt=receipt, account=credit_account, bucket=bucket) except Exception as e: # delete the debit note try: debit_account._delete_note(debit_note, bucket=bucket) except: pass # reset the transaction to the pending state try: _TransactionRecord.load_test_and_set( receipt.transaction_uid(), _TransactionState.RECEIPTING, _TransactionState.PENDING, bucket=bucket) except: pass raise e try: paired_notes = _PairedNote.create(debit_note, credit_note) except Exception as e: # delete all records...! try: debit_account._delete_note(debit_note, bucket=bucket) except: pass try: credit_account._delete_note(credit_note, bucket=bucket) except: pass # reset the transaction to the pending state try: _TransactionRecord.load_test_and_set( receipt.transaction_uid(), _TransactionState.RECEIPTING, _TransactionState.PENDING, bucket=bucket) except: pass raise e # now record the two entries to the ledger. The below function # is guaranteed not to raise an exception return Ledger._record_to_ledger(paired_notes, receipt=receipt, bucket=bucket)
def _create_from_receipt(self, receipt, account, bucket): """Function used to construct a debit note by extracting the value specified in the passed receipt from the specified account. This is authorised using the authorisation held in the receipt, based on the original authorisation given in the provisional transaction. Note that the receipt must match up with a prior existing provisional transaction, and this must not have already been receipted or refunded. This will actually take value out of the passed account, with that value residing in this debit note until it is credited to another account Args: receipt (Receipt): Receipt to create DebitNote from account (Account): Account to take value from bucket (dict): Bucket to read data from """ from Acquire.Accounting import Receipt as _Receipt if not isinstance(receipt, _Receipt): raise TypeError("You can only create a DebitNote with a " "Receipt") if receipt.is_null(): return if bucket is None: from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket bucket = _get_service_account_bucket() from Acquire.Accounting import TransactionRecord as _TransactionRecord from Acquire.Accounting import TransactionState as _TransactionState from Acquire.Accounting import Account as _Account # get the transaction behind this receipt and move it into # the "receipting" state transaction = _TransactionRecord.load_test_and_set( receipt.transaction_uid(), _TransactionState.PROVISIONAL, _TransactionState.RECEIPTING, bucket=bucket) try: # ensure that the receipt matches the transaction... transaction.assert_matching_receipt(receipt) if account is None: account = _Account(transaction.debit_account_uid(), bucket) elif account.uid() != receipt.debit_account_uid(): raise ValueError("The accounts do not match when debiting " "the receipt: %s versus %s" % (account.uid(), receipt.debit_account_uid())) # now move value from liability to debit, and then into this # debit note (uid, datetime) = account._debit_receipt(receipt, bucket) self._transaction = receipt.transaction() self._account_uid = receipt.debit_account_uid() self._authorisation = receipt.authorisation() self._is_provisional = False self._datetime = datetime self._uid = str(uid) except: # move the transaction back to its original state... _TransactionRecord.load_test_and_set( receipt.transaction_uid(), _TransactionState.RECEIPTING, _TransactionState.PROVISIONAL) raise