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_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_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,
            )
Ejemplo n.º 4
0
 def test_credit_and_debit_helper_functions(self):
     with mock.patch('capone.api.actions.settings') as mock_settings:
         mock_settings.DEBITS_ARE_NEGATIVE = True
         self.assertPositive(credit(self.AMOUNT))
         self.assertNegative(debit(self.AMOUNT))
     with mock.patch('capone.api.actions.settings') as mock_settings:
         mock_settings.DEBITS_ARE_NEGATIVE = False
         self.assertNegative(credit(self.AMOUNT))
         self.assertPositive(debit(self.AMOUNT))
    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}
            )
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
    def test_custom_ledger_entries(self):
        ledger = LedgerFactory()
        amount = Decimal('500')
        TransactionFactory(evidence=[self.credit_card_transaction],
                           ledger_entries=[
                               LedgerEntry(ledger=ledger,
                                           amount=credit(amount)),
                               LedgerEntry(ledger=ledger,
                                           amount=debit(amount)),
                           ])

        assert_transaction_in_ledgers_for_amounts_with_evidence(
            ledger_amount_pairs=[
                (ledger.name, credit(amount)),
                (ledger.name, debit(amount)),
            ],
            evidence=[self.credit_card_transaction],
        )
Ejemplo n.º 8
0
 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)),
                               ])
Ejemplo n.º 9
0
 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)),
         ],
     )
Ejemplo n.º 10
0
 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))),
         ],
     )
Ejemplo n.º 11
0
    def test_no_args(self):
        TransactionFactory(evidence=[self.credit_card_transaction])

        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=[self.credit_card_transaction],
        )
Ejemplo n.º 12
0
 def test_debits_not_equal_to_credits(self):
     with self.assertRaises(TransactionBalanceException):
         validate_transaction(
             self.user,
             ledger_entries=[
                 LedgerEntry(ledger=self.revenue,
                             amount=credit(self.AMOUNT)),
                 LedgerEntry(ledger=self.accounts_receivable,
                             amount=debit(self.AMOUNT + 2)),
             ],
         )
Ejemplo n.º 13
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],
        )
Ejemplo n.º 14
0
 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))
Ejemplo n.º 15
0
    def test_auto_timestamp(self):
        """
        If a posted_timestamp isn't specified we assume the posted_timestamp is
        the same as the transaction we're voiding.
        """
        amount = D(100)
        charge_txn = TransactionFactory(self.creation_user, ledger_entries=[
            LedgerEntry(amount=debit(amount), ledger=self.ar_ledger),
            LedgerEntry(amount=credit(amount), ledger=self.rev_ledger),
        ])

        void_txn = void_transaction(charge_txn, self.creation_user)
        self.assertEqual(
            charge_txn.posted_timestamp, void_txn.posted_timestamp)
Ejemplo n.º 16
0
    def test_given_timestamp(self):
        """
        If a posted_timestamp is given for the void, then use it
        """
        amount = D(100)
        charge_txn = TransactionFactory(self.creation_user, ledger_entries=[
            LedgerEntry(amount=debit(amount), ledger=self.ar_ledger),
            LedgerEntry(amount=credit(amount), ledger=self.rev_ledger),
        ])

        now = datetime.now()
        void_txn = void_transaction(
            charge_txn, self.creation_user,
            posted_timestamp=now)
        self.assertEqual(now, void_txn.posted_timestamp)
Ejemplo n.º 17
0
    def test_cant_void_twice(self):
        """
        Voiding a `Transaction` more than once is not permitted.
        """
        amount = D(100)
        txn = TransactionFactory(self.creation_user, ledger_entries=[
            LedgerEntry(amount=debit(amount), ledger=self.ar_ledger),
            LedgerEntry(amount=credit(amount), ledger=self.rev_ledger),
        ])

        void_transaction(txn, self.creation_user)

        self.assertRaises(
            UnvoidableTransactionException,
            void_transaction, txn, self.creation_user)
Ejemplo n.º 18
0
    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()),
            )
Ejemplo n.º 19
0
    def test_ledger_balance_update(self):
        self.add_transaction([self.order_1])
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount)),
            (self.order_1, self.cash_ledger, debit(self.amount)),
            (self.order_2, self.ar_ledger, None),
            (self.order_2, self.cash_ledger, None),
        )

        self.add_transaction([self.order_2])
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount)),
            (self.order_1, self.cash_ledger, debit(self.amount)),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )

        self.add_transaction([self.order_1])
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 2),
            (self.order_1, self.cash_ledger, debit(self.amount) * 2),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )

        transaction = self.add_transaction([self.order_1, self.order_2])
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 3),
            (self.order_1, self.cash_ledger, debit(self.amount) * 3),
            (self.order_2, self.ar_ledger, credit(self.amount) * 2),
            (self.order_2, self.cash_ledger, debit(self.amount) * 2),
        )

        void_transaction(transaction, self.user)
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 2),
            (self.order_1, self.cash_ledger, debit(self.amount) * 2),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )
Ejemplo n.º 20
0
    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)
Ejemplo n.º 21
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],
            )
Ejemplo n.º 23
0
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,
    )
Ejemplo n.º 24
0
    def test_can_void_void(self):
        """
        A void can be voided, thus restoring the original transaction.
        """
        amount = D(100)
        txn = TransactionFactory(self.creation_user, ledger_entries=[
            LedgerEntry(amount=debit(amount), ledger=self.ar_ledger),
            LedgerEntry(amount=credit(amount), ledger=self.rev_ledger),
        ])

        void_txn = void_transaction(txn, self.creation_user)

        self.assertEqual(void_txn.voids, txn)

        void_void_txn = (void_transaction(void_txn, self.creation_user))
        self.assertEqual(void_void_txn.voids, void_txn)

        self.assertEqual(self.ar_ledger.get_balance(), amount)
        self.assertEqual(self.rev_ledger.get_balance(), -amount)
Ejemplo n.º 25
0
    def test_void_with_non_default_type(self):
        """
        Test voiding a `Transaction` with a non-default `type`.
        """
        amount = D(100)
        txn = TransactionFactory(self.creation_user, ledger_entries=[
            LedgerEntry(amount=debit(amount), ledger=self.ar_ledger),
            LedgerEntry(amount=credit(amount), ledger=self.rev_ledger),
        ])

        new_ttype = TransactionTypeFactory()
        void_txn = void_transaction(txn, self.creation_user, type=new_ttype)

        self.assertEqual(void_txn.voids, txn)

        self.assertEqual(self.ar_ledger.get_balance(), D(0))
        self.assertEqual(self.rev_ledger.get_balance(), D(0))

        self.assertEqual(void_txn.type, new_ttype)
        self.assertNotEqual(void_txn.type, txn.type)
Ejemplo n.º 26
0
    def test_custom_fields(self):
        """
        Test setting fields `posted_timestamp`, `notes`, `type`, and `user`.
        """
        time = datetime.now()
        FIELDS_TO_VALUES = [
            ('posted_timestamp', time),
            ('notes', 'booga'),
            ('type', TransactionTypeFactory()),
            ('user', UserFactory()),
        ]

        for field_name, value in FIELDS_TO_VALUES:
            TransactionFactory(evidence=[self.credit_card_transaction],
                               **{field_name: 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=[self.credit_card_transaction],
                **{field_name: value})
Ejemplo n.º 27
0
    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,
            },
        )
Ejemplo n.º 28
0
    def test_rebuild_ledger_balance(self):
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, None),
            (self.order_1, self.cash_ledger, None),
            (self.order_2, self.ar_ledger, None),
            (self.order_2, self.cash_ledger, None),
        )

        self.add_transaction([self.order_1])
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount)),
            (self.order_1, self.cash_ledger, debit(self.amount)),
            (self.order_2, self.ar_ledger, None),
            (self.order_2, self.cash_ledger, None),
        )

        self.add_transaction([self.order_2])
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount)),
            (self.order_1, self.cash_ledger, debit(self.amount)),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )

        self.add_transaction([self.order_1])
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 2),
            (self.order_1, self.cash_ledger, debit(self.amount) * 2),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )

        transaction = self.add_transaction([self.order_1, self.order_2])
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 3),
            (self.order_1, self.cash_ledger, debit(self.amount) * 3),
            (self.order_2, self.ar_ledger, credit(self.amount) * 2),
            (self.order_2, self.cash_ledger, debit(self.amount) * 2),
        )

        void_transaction(transaction, self.user)
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 2),
            (self.order_1, self.cash_ledger, debit(self.amount) * 2),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )

        LedgerBalance.objects.update(balance=Decimal('1.00'))
        LedgerBalance.objects.first().delete()
        rebuild_ledger_balances()
        self.assert_objects_have_ledger_balances(
            (self.order_1, self.ar_ledger, credit(self.amount) * 2),
            (self.order_1, self.cash_ledger, debit(self.amount) * 2),
            (self.order_2, self.ar_ledger, credit(self.amount)),
            (self.order_2, self.cash_ledger, debit(self.amount)),
        )