def test_mismatch_on_evidence(self):
        """
        An otherwise matching Trans. will fail if its evidence is different.
        """
        credit_card_transaction = CreditCardTransactionFactory()
        amount = Decimal('100')
        ledger = LedgerFactory()

        TransactionFactory(
            UserFactory(),
            ledger_entries=[
                LedgerEntry(amount=debit(amount), ledger=ledger),
                LedgerEntry(amount=credit(amount), ledger=ledger),
            ],
            evidence=[credit_card_transaction],
        )

        ledger_amount_pairs = [
            (ledger.name, credit(amount)),
            (ledger.name, debit(amount)),
        ]

        with self.assertRaises(Transaction.DoesNotExist):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=ledger_amount_pairs,
                evidence=[
                    credit_card_transaction, CreditCardTransactionFactory()],
            )

        with self.assertRaises(Transaction.DoesNotExist):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=ledger_amount_pairs,
                evidence=[],
            )
    def test_multiple_matches(self):
        """
        Multiple matching transactions raises MultipleObjectsReturned.
        """
        credit_card_transaction = CreditCardTransactionFactory()
        amount = Decimal('100')
        ledger = LedgerFactory()
        for _ in range(2):
            TransactionFactory(
                UserFactory(),
                ledger_entries=[
                    LedgerEntry(amount=debit(amount), ledger=ledger),
                    LedgerEntry(amount=credit(amount), ledger=ledger),
                ],
                evidence=[credit_card_transaction],
            )

        self.assertEqual(Transaction.objects.count(), 2)

        with self.assertRaises(Transaction.MultipleObjectsReturned):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=[
                    (ledger.name, credit(amount)),
                    (ledger.name, debit(amount)),
                ],
                evidence=[credit_card_transaction],
            )
    def test_transaction_fields(self):
        """
        Test filtering by `posted_timestamp`, `notes`, `type`, and `user`.
        """
        time = datetime.now()
        wrong_time = datetime.now() - timedelta(days=1)
        user1 = UserFactory()
        user2 = UserFactory()
        credit_card_transaction = CreditCardTransactionFactory()
        ttype1 = TransactionTypeFactory(name='1')
        ttype2 = TransactionTypeFactory(name='2')

        FIELDS_TO_VALUES = [
            ('posted_timestamp', time, wrong_time),
            ('notes', 'foo', 'bar'),
            ('type', ttype1, ttype2),
            ('user', user1, user2),
        ]

        for field_name, right_value, wrong_value in FIELDS_TO_VALUES:
            TransactionFactory(
                evidence=[credit_card_transaction],
                **{field_name: right_value})
            ledger = Ledger.objects.last()
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=[
                    (ledger.name, credit(Decimal('100'))),
                    (ledger.name, debit(Decimal('100'))),
                ],
                evidence=[credit_card_transaction],
                **{field_name: right_value}
            )
    def test_mismatch_on_ledger_entries(self):
        """
        An otherwise matching Trans. will fail if its LedgerEntries mismatch.
        """
        credit_card_transaction = CreditCardTransactionFactory()
        amount = Decimal('100')
        ledger = LedgerFactory()
        evidence = [credit_card_transaction]

        TransactionFactory(
            UserFactory(),
            ledger_entries=[
                LedgerEntry(amount=debit(amount), ledger=ledger),
                LedgerEntry(amount=credit(amount), ledger=ledger),
            ],
            evidence=evidence,
        )

        with self.assertRaises(Transaction.DoesNotExist):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=[
                    (ledger.name + 'foo', credit(amount)),
                    (ledger.name + 'foo', debit(amount)),
                ],
                evidence=evidence,
            )

        with self.assertRaises(AssertionError):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=[
                    (ledger.name, credit(amount + Decimal('1'))),
                    (ledger.name, debit(amount + Decimal('1'))),
                ],
                evidence=evidence,
            )
Esempio n. 5
0
    def test_custom_evidence(self):
        ccx = CreditCardTransactionFactory()
        TransactionFactory(evidence=[ccx])

        ledger = Ledger.objects.last()
        assert_transaction_in_ledgers_for_amounts_with_evidence(
            ledger_amount_pairs=[
                (ledger.name, credit(Decimal('100'))),
                (ledger.name, debit(Decimal('100'))),
            ],
            evidence=[ccx],
        )
Esempio n. 6
0
    def test_transaction_summary(self):
        ledger = LedgerFactory()
        amount = Decimal('500')
        ccx = CreditCardTransactionFactory()
        le1 = LedgerEntry(ledger=ledger, amount=credit(amount))
        le2 = LedgerEntry(ledger=ledger, amount=debit(amount))
        txn = TransactionFactory(evidence=[ccx], ledger_entries=[le1, le2])

        self.assertEqual(
            txn.summary(),
            {
                'entries': [str(entry) for entry in txn.entries.all()],
                'related_objects': [
                    'TransactionRelatedObject: CreditCardTransaction(id=%s)' %
                    ccx.id,
                ],
            },
        )
    def test_no_matches(self):
        """
        No matching transaction raises DoesNotExist.
        """
        TransactionFactory()
        credit_card_transaction = CreditCardTransactionFactory()
        ledger = Ledger.objects.last()

        self.assertTrue(Transaction.objects.exists())

        with self.assertRaises(Transaction.DoesNotExist):
            assert_transaction_in_ledgers_for_amounts_with_evidence(
                ledger_amount_pairs=[
                    (ledger.name, credit(Decimal('100'))),
                    (ledger.name, debit(Decimal('100'))),
                ],
                evidence=[credit_card_transaction],
            )
Esempio n. 8
0
 def setUpTestData(cls):
     cls.credit_card_transaction = CreditCardTransactionFactory()
    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,
            },
        )