def test_save_and_get_transactions(self):
     storage = SimpleTransactionStorage()
     ledger = Ledger()
     ledger.storage = storage
     transaction = self._create_transaction(CreditTransaction, self.client, self.service_provider, 100)
     ledger.add_transaction(transaction)
     self.assertEqual(1, len(storage.get_transactions_from(self.client)))
     self.assertEqual(1, len(storage.get_transactions_to(self.service_provider)))
 def setUp(self):
     self.client = LedgerClient("Azamat")
     self.service_provider = LedgerService("Dentist")
     self.ledger = Ledger()
     self.ledger.storage = SimpleTransactionStorage()
     self.account_manager = AccountManager()
     self.account_manager.ledger = self.ledger
class TestLedger(TestCase):
    client = None
    service_provider = None
    ledger = None

    def setUp(self):
        self.client = LedgerClient("Azamat")
        self.service_provider = LedgerService("Dentist")
        self.ledger = Ledger()
        self.ledger.storage = SimpleTransactionStorage()

    def test_add_empty_transaction(self):

        self.assertRaises(ValueError, self.ledger.add_transaction, transaction=None)
        self.assertRaisesMessage(ValueError, "Empty transaction is not allowed", self.ledger.add_transaction, transaction=None)

    def test_client_pays_advance_payment_to_provider(self):
        transaction = DepositTransaction()
        transaction.amount = 200
        transaction.agent_from = self.client
        transaction.agent_to = self.service_provider

        self.ledger.add_transaction(transaction)
        self.assertEqual(1, len(self.ledger.get_transactions_from(self.client)))
        self.assertEqual(1, len(self.ledger.get_transactions_to(self.service_provider)))

    def test_client_is_billed_and_pays_full(self):
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        self.ledger.add_transaction(credit_transaction)

        debit_transaction = DebitTransaction()
        debit_transaction.transaction = credit_transaction
        debit_transaction.amount = 1000
        debit_transaction.agent_from = self.client
        debit_transaction.agent_to = self.service_provider

        self.ledger.add_transaction(debit_transaction)
        self.assertEqual(2, len(self.ledger.get_transactions_from(self.client)))
        self.assertEqual(0, len(self.ledger.get_transactions_to(self.client)))
        self.assertEqual(2, len(self.ledger.get_transactions_to(self.service_provider)))

    def test_add_batch_transactions(self):
        transactions = list()
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        debit_transaction = DebitTransaction()
        debit_transaction.transaction = credit_transaction
        debit_transaction.amount = 1000
        debit_transaction.agent_from = self.client
        debit_transaction.agent_to = self.service_provider
        transactions.append(credit_transaction)
        transactions.append(debit_transaction)
        self.ledger.add_batch(transactions, 'helo')

        self.assertEqual(2, len(self.ledger.get_transactions_from(self.client)))
        self.assertEqual(0, len(self.ledger.get_transactions_to(self.client)))
        self.assertEqual(2, len(self.ledger.get_transactions_to(self.service_provider)))
        self.assertEqual('helo', self.ledger.get_transactions_to(self.service_provider)[0].batch_id)
class TestAccountManager(TestCase):
    client = None
    service_provider = None
    account_manager = None
    ledger = None

    def setUp(self):
        self.client = LedgerClient("Azamat")
        self.service_provider = LedgerService("Dentist")
        self.ledger = Ledger()
        self.ledger.storage = SimpleTransactionStorage()
        self.account_manager = AccountManager()
        self.account_manager.ledger = self.ledger

    def test_get_agent_from_balance(self):
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        self.ledger.add_transaction(credit_transaction)
        self.assertEqual(-1000, self.account_manager.get_agent_from_balance(self.client))

    def test_get_receivable_balance(self):
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        self.ledger.add_transaction(credit_transaction)

        self.assertEqual(1000, self.account_manager.get_receivable_balance(self.service_provider))

    def test_client_is_billed_and_pays_full(self):
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        self.ledger.add_transaction(credit_transaction)

        debit_transaction = DebitTransaction()
        debit_transaction.transaction = credit_transaction
        debit_transaction.amount = 1000
        debit_transaction.agent_from = self.client
        debit_transaction.agent_to = self.service_provider

        self.ledger.add_transaction(debit_transaction)

        self.assertEqual(1000, self.account_manager.get_agent_to_balance(self.service_provider))
        self.assertEqual(0, self.account_manager.get_agent_from_balance(self.client))

    def test_client_pays_by_parts(self):
        credit_transaction = CreditTransaction()
        credit_transaction.agent_from = self.client
        credit_transaction.agent_to = self.service_provider
        credit_transaction.amount = 1000

        self.ledger.add_transaction(credit_transaction)

        debit_transaction = DebitTransaction()
        debit_transaction.transaction = credit_transaction
        debit_transaction.amount = 200
        debit_transaction.agent_from = self.client
        debit_transaction.agent_to = self.service_provider

        self.ledger.add_transaction(debit_transaction)
        self.assertEqual(200, self.account_manager.get_agent_to_balance(self.service_provider))
        self.assertEqual(-800, self.account_manager.get_agent_from_balance(self.client))

        debit_transaction = DebitTransaction()
        debit_transaction.transaction = credit_transaction
        debit_transaction.amount = 800
        debit_transaction.agent_from = self.client
        debit_transaction.agent_to = self.service_provider

        self.ledger.add_transaction(debit_transaction)

        self.assertEqual(1000, self.account_manager.get_agent_to_balance(self.service_provider))
        self.assertEqual(0, self.account_manager.get_receivable_balance(self.service_provider))
        self.assertEqual(0, self.account_manager.get_agent_from_balance(self.client))

        self.assertEqual(0, self.account_manager.get_balance(self.client))
        self.assertEqual(1000, self.account_manager.get_balance(self.service_provider))

    def test_deposits_and_withdraw(self):
        deposit_transaction = DepositTransaction()
        deposit_transaction.amount = 200
        deposit_transaction.agent_from = self.client
        deposit_transaction.agent_to = self.service_provider
        self.ledger.add_transaction(deposit_transaction)
        withdraw_transaction = WithdrawTransaction()
        withdraw_transaction.agent_from = self.client
        withdraw_transaction.agent_to = self.service_provider
        withdraw_transaction.amount = 100
        self.ledger.add_transaction(withdraw_transaction)
        self.assertEqual(100, self.account_manager.get_agent_to_balance(self.service_provider))
        self.assertEqual(100, self.account_manager.get_agent_from_balance(self.client))

        self.assertEqual(100, self.account_manager.get_balance(self.client))
        self.assertEqual(100, self.account_manager.get_balance(self.service_provider))

    def test_get_total_deposit(self):
        deposit_transaction = DepositTransaction()
        deposit_transaction.amount = 200
        deposit_transaction.agent_from = self.client
        deposit_transaction.agent_to = self.service_provider
        self.ledger.add_transaction(deposit_transaction)
        self.assertEqual(200, self.account_manager.get_total_by(self.client, TRANSACTION_DEPOSIT))