def _create_transaction_and_compare_to_amount( self, amount, comparison_amount=None): ledger1 = LedgerFactory() ledger2 = LedgerFactory() transaction = create_transaction( UserFactory(), ledger_entries=[ LedgerEntry( ledger=ledger1, amount=amount), LedgerEntry( ledger=ledger2, amount=-amount), ] ) entry1 = transaction.entries.get(ledger=ledger1) entry2 = transaction.entries.get(ledger=ledger2) if comparison_amount: self.assertNotEqual(entry1.amount, amount) self.assertEqual(entry1.amount, comparison_amount) self.assertNotEqual(entry2.amount, -amount) self.assertEqual(-entry2.amount, comparison_amount) else: self.assertEqual(entry1.amount, amount) self.assertEqual(entry2.amount, -amount)
def test_with_existing_ledger_entry(self): existing_transaction = create_transaction( self.user, ledger_entries=[ LedgerEntry(ledger=self.accounts_receivable, amount=credit(self.amount)), LedgerEntry(ledger=self.accounts_receivable, amount=debit(self.amount)), ], ) with self.assertRaises(ExistingLedgerEntriesException): create_transaction( self.user, ledger_entries=list(existing_transaction.entries.all()), )
def test_void_with_overridden_notes_and_type(self): """ Test voiding while setting notes and type. """ amount = D(100) evidence = UserFactory.create_batch(3) transaction = create_transaction( user=UserFactory(), evidence=evidence, ledger_entries=[ LedgerEntry( ledger=self.ar_ledger, amount=credit(amount), ), LedgerEntry( ledger=self.rev_ledger, amount=debit(amount), ), ], type=self.ttype, ) voiding_transaction = void_transaction( transaction, self.creation_user, notes='test notes', ) self.assertEqual(voiding_transaction.notes, 'test notes') self.assertEqual(voiding_transaction.type, transaction.type)
def _create_transaction_with_evidence(cls, evidence): return create_transaction(cls.create_user, evidence=evidence, ledger_entries=[ LedgerEntry(ledger=cls.ledger, amount=credit(cls.AMOUNT)), LedgerEntry(ledger=cls.ledger, amount=debit(cls.AMOUNT)), ])
def add_transaction(self): return create_transaction( self.user, evidence=[self.order], ledger_entries=[ LedgerEntry(ledger=self.ar_ledger, amount=credit(Decimal(50))), LedgerEntry(ledger=self.cash_ledger, amount=debit(Decimal(50))), ], )
def add_transaction(self, orders): return create_transaction( self.user, evidence=orders, ledger_entries=[ LedgerEntry(ledger=self.ar_ledger, amount=credit(self.amount)), LedgerEntry(ledger=self.cash_ledger, amount=debit(self.amount)), ], )
def test_setting_posted_timestamp(self): POSTED_DATETIME = datetime(2016, 2, 7, 11, 59) order = OrderFactory(amount=self.AMOUNT) txn_recognize = create_transaction( self.user, evidence=[order], ledger_entries=[ LedgerEntry(ledger=self.revenue, amount=credit(self.AMOUNT)), LedgerEntry(ledger=self.accounts_receivable, amount=debit(self.AMOUNT)), ], posted_timestamp=POSTED_DATETIME, ) self.assertEqual(txn_recognize.posted_timestamp, POSTED_DATETIME)
def TransactionFactory( user=None, evidence=None, ledger_entries=None, notes='', type=None, posted_timestamp=None, ): """ Factory for creating a Transaction Instead of inheriting from DjangoModelFactory, TransactionFactory is a method made to look like a factory call because the creation and validation of Transactions is handeled by `create_transaction`. """ if user is None: user = UserFactory() if evidence is None: evidence = [CreditCardTransactionFactory()] if ledger_entries is None: ledger = LedgerFactory() amount = Decimal('100') ledger_entries = [ LedgerEntry( ledger=ledger, amount=debit(amount), ), LedgerEntry( ledger=ledger, amount=credit(amount), ), ] return create_transaction( user, evidence=evidence, ledger_entries=ledger_entries, notes=notes, type=type or TransactionTypeFactory(), posted_timestamp=posted_timestamp, )
def test_simple_void(self): """ Test voiding a `Transaction`. """ amount = D(100) evidence = UserFactory.create_batch(3) transaction = create_transaction( user=UserFactory(), evidence=evidence, ledger_entries=[ LedgerEntry( ledger=self.ar_ledger, amount=credit(amount), ), LedgerEntry( ledger=self.rev_ledger, amount=debit(amount), ), ], ) self.assertEqual(self.ar_ledger.get_balance(), credit(amount)) self.assertEqual(self.rev_ledger.get_balance(), debit(amount)) voiding_transaction = void_transaction(transaction, self.creation_user) self.assertEqual( set(tro.related_object for tro in voiding_transaction.related_objects.all()), set(evidence), ) self.assertEqual(self.ar_ledger.get_balance(), D(0)) self.assertEqual(self.rev_ledger.get_balance(), D(0)) self.assertEqual(voiding_transaction.voids, transaction) self.assertEqual( voiding_transaction.posted_timestamp, transaction.posted_timestamp) self.assertEqual( voiding_transaction.type, transaction.type) self.assertEqual( voiding_transaction.notes, 'Voiding transaction {}'.format(transaction))
def test_using_ledgers_for_reconciliation(self): """ Test ledger behavior with a revenue reconciliation worked example. This test creates an Order and a CreditCardTransaction and, using the four Ledgers created in setUp, it makes all of the ledger entries that an Order and Transaction would be expected to have. There are three, specifically: Revenue Recognition (credit: Revenue, debit:A/R), recording incoming cash (credit: A/R, debit: Cash (unreconciled)) and Reconciliation (credit: Cash (reconciled), debit: Cash (unreconciled)). In table form: Event | Accounts Receivable (unreconciled) | Revenue | Cash (unreconciled) | Cash (reconciled) | Evidence Models ----------------------- | ---------------------------------- | ------- | ------------------- | ----------------- | -------------------------------------------------------------- Test is complete | -$500 | +$500 | | | `Order` Patient pays | +$500 | | -$500 | | `CreditCardTransaction` Payments are reconciled | | | +$500 | -$500 | both `Order` and `CreditCardTransaction` """ # noqa: E501 order = OrderFactory() credit_card_transaction = CreditCardTransactionFactory() # Assert that this Order looks "unrecognized". self.assertEqual( get_balances_for_object(order), {}, ) # Add an entry debiting AR and crediting Revenue: this entry should # reference the Order. create_transaction( self.user, evidence=[order], ledger_entries=[ LedgerEntry( ledger=self.revenue, amount=credit(self.AMOUNT)), LedgerEntry( ledger=self.accounts_receivable, amount=debit(self.AMOUNT)), ], ) # Assert that the correct entries were created. self.assertEqual(LedgerEntry.objects.count(), 2) self.assertEqual(Transaction.objects.count(), 1) # Assert that this Order looks "recognized". self.assertEqual( get_balances_for_object(order), { self.revenue: -self.AMOUNT, self.accounts_receivable: self.AMOUNT, }, ) # Add an entry crediting "A/R" and debiting "Cash (unreconciled)": this # entry should reference the CreditCardTransaction. create_transaction( self.user, evidence=[credit_card_transaction], ledger_entries=[ LedgerEntry( ledger=self.accounts_receivable, amount=credit(self.AMOUNT)), LedgerEntry( ledger=self.cash_unrecon, amount=debit(self.AMOUNT)) ], ) # Assert that the correct entries were created self.assertEqual(LedgerEntry.objects.count(), 4) self.assertEqual(Transaction.objects.count(), 2) # Assert the CreditCardTransaction is in "Cash (unreconciled)". self.assertEqual( get_balances_for_object(credit_card_transaction), { self.accounts_receivable: -self.AMOUNT, self.cash_unrecon: self.AMOUNT, }, ) # Add an entry crediting "Cash (Unreconciled)" and debiting "Cash # (Reconciled)": this entry should reference both an Order and # a CreditCardTransaction. create_transaction( self.user, evidence=[order, credit_card_transaction], ledger_entries=[ LedgerEntry( ledger=self.cash_unrecon, amount=credit(self.AMOUNT)), LedgerEntry( ledger=self.cash_recon, amount=debit(self.AMOUNT)) ], type=self.recon_ttype, ) # Assert that the correct entries were created. self.assertEqual(LedgerEntry.objects.count(), 6) self.assertEqual(Transaction.objects.count(), 3) # Assert that revenue is recognized and reconciled. self.assertEqual( get_balances_for_object(order), { self.accounts_receivable: self.AMOUNT, self.cash_unrecon: -self.AMOUNT, self.cash_recon: self.AMOUNT, self.revenue: -self.AMOUNT, }, )