aboutsummaryrefslogtreecommitdiff
path: root/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/managers/thl/test_ledger/test_thl_lm_accounts.py')
-rw-r--r--tests/managers/thl/test_ledger/test_thl_lm_accounts.py411
1 files changed, 411 insertions, 0 deletions
diff --git a/tests/managers/thl/test_ledger/test_thl_lm_accounts.py b/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
new file mode 100644
index 0000000..01d5fe1
--- /dev/null
+++ b/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
@@ -0,0 +1,411 @@
+from uuid import uuid4
+
+import pytest
+
+
+class TestThlLedgerManagerAccounts:
+
+ def test_get_account_or_create_user_wallet(self, user, thl_lm, lm):
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ Direction,
+ AccountType,
+ )
+
+ account = thl_lm.get_account_or_create_user_wallet(user=user)
+ assert isinstance(account, LedgerAccount)
+
+ assert user.uuid in account.qualified_name
+ assert account.display_name == f"User Wallet {user.uuid}"
+ assert account.account_type == AccountType.USER_WALLET
+ assert account.normal_balance == Direction.CREDIT
+ assert account.reference_type == "user"
+ assert account.reference_uuid == user.uuid
+ assert account.currency == LedgerCurrency.TEST
+
+ # Actually query for it to confirm
+ res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ assert res.model_dump_json() == account.model_dump_json()
+
+ def test_get_account_or_create_bp_wallet(self, product, thl_lm, lm):
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ Direction,
+ AccountType,
+ )
+
+ account = thl_lm.get_account_or_create_bp_wallet(product=product)
+ assert isinstance(account, LedgerAccount)
+
+ assert product.uuid in account.qualified_name
+ assert account.display_name == f"BP Wallet {product.uuid}"
+ assert account.account_type == AccountType.BP_WALLET
+ assert account.normal_balance == Direction.CREDIT
+ assert account.reference_type == "bp"
+ assert account.reference_uuid == product.uuid
+ assert account.currency == LedgerCurrency.TEST
+
+ # Actually query for it to confirm
+ res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ assert res.model_dump_json() == account.model_dump_json()
+
+ def test_get_account_or_create_bp_commission(self, product, thl_lm, lm):
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.models.thl.ledger import (
+ Direction,
+ AccountType,
+ )
+
+ account = thl_lm.get_account_or_create_bp_commission(product=product)
+
+ assert product.uuid in account.qualified_name
+ assert account.display_name == f"Revenue from commission {product.uuid}"
+ assert account.account_type == AccountType.REVENUE
+ assert account.normal_balance == Direction.CREDIT
+ assert account.reference_type == "bp"
+ assert account.reference_uuid == product.uuid
+ assert account.currency == LedgerCurrency.TEST
+
+ # Actually query for it to confirm
+ res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ assert res.model_dump_json() == account.model_dump_json()
+
+ @pytest.mark.parametrize("expense", ["tango", "paypal", "gift", "tremendous"])
+ def test_get_account_or_create_bp_expense(self, product, expense, thl_lm, lm):
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.models.thl.ledger import (
+ Direction,
+ AccountType,
+ )
+
+ account = thl_lm.get_account_or_create_bp_expense(
+ product=product, expense_name=expense
+ )
+ assert product.uuid in account.qualified_name
+ assert account.display_name == f"Expense {expense} {product.uuid}"
+ assert account.account_type == AccountType.EXPENSE
+ assert account.normal_balance == Direction.DEBIT
+ assert account.reference_type == "bp"
+ assert account.reference_uuid == product.uuid
+ assert account.currency == LedgerCurrency.TEST
+
+ # Actually query for it to confirm
+ res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ assert res.model_dump_json() == account.model_dump_json()
+
+ def test_get_or_create_bp_pending_payout_account(self, product, thl_lm, lm):
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.models.thl.ledger import (
+ Direction,
+ AccountType,
+ )
+
+ account = thl_lm.get_or_create_bp_pending_payout_account(product=product)
+
+ assert product.uuid in account.qualified_name
+ assert account.display_name == f"BP Wallet Pending {product.uuid}"
+ assert account.account_type == AccountType.BP_WALLET
+ assert account.normal_balance == Direction.CREDIT
+ assert account.reference_type == "bp"
+ assert account.reference_uuid == product.uuid
+ assert account.currency == LedgerCurrency.TEST
+
+ # Actually query for it to confirm
+ res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ assert res.model_dump_json() == account.model_dump_json()
+
+ def test_get_account_task_complete_revenue_raises(
+ self, delete_ledger_db, thl_lm, lm
+ ):
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+
+ delete_ledger_db()
+
+ with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
+ thl_lm.get_account_task_complete_revenue()
+
+ def test_get_account_task_complete_revenue(
+ self, account_cash, account_revenue_task_complete, thl_lm, lm
+ ):
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ AccountType,
+ )
+
+ res = thl_lm.get_account_task_complete_revenue()
+ assert isinstance(res, LedgerAccount)
+ assert res.reference_type is None
+ assert res.reference_uuid is None
+ assert res.account_type == AccountType.REVENUE
+ assert res.display_name == "Cash flow task complete"
+
+ def test_get_account_cash_raises(self, delete_ledger_db, thl_lm, lm):
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+
+ delete_ledger_db()
+
+ with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
+ thl_lm.get_account_cash()
+
+ def test_get_account_cash(self, account_cash, thl_lm, lm):
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ AccountType,
+ )
+
+ res = thl_lm.get_account_cash()
+ assert isinstance(res, LedgerAccount)
+ assert res.reference_type is None
+ assert res.reference_uuid is None
+ assert res.account_type == AccountType.CASH
+ assert res.display_name == "Operating Cash Account"
+
+ def test_get_accounts(self, setup_accounts, product, user_factory, thl_lm, lm, lam):
+ from generalresearch.models.thl.user import User
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+
+ user1: User = user_factory(product=product)
+ user2: User = user_factory(product=product)
+
+ account1 = thl_lm.get_account_or_create_bp_wallet(product=product)
+
+ # (1) known account and confirm it comes back
+ res = lm.get_account(qualified_name=account1.qualified_name)
+ assert account1.model_dump_json() == res.model_dump_json()
+
+ # (2) known accounts and confirm they both come back
+ res = lam.get_accounts(qualified_names=[account1.qualified_name])
+ assert isinstance(res, list)
+ assert len(res) == 1
+ assert account1 in res
+
+ # Get 2 known and 1 made up qualified names, and confirm it raises
+ # an error
+ with pytest.raises(LedgerAccountDoesntExistError):
+ lam.get_accounts(
+ qualified_names=[
+ account1.qualified_name,
+ f"test:bp_wall:{uuid4().hex}",
+ ]
+ )
+
+ def test_get_accounts_if_exists(self, product_factory, currency, thl_lm, lm):
+ from generalresearch.models.thl.product import Product
+
+ p1: Product = product_factory()
+ p2: Product = product_factory()
+
+ account1 = thl_lm.get_account_or_create_bp_wallet(product=p1)
+ account2 = thl_lm.get_account_or_create_bp_wallet(product=p2)
+
+ # (1) known account and confirm it comes back
+ res = lm.get_account(qualified_name=account1.qualified_name)
+ assert account1.model_dump_json() == res.model_dump_json()
+
+ # (2) known accounts and confirm they both come back
+ res = lm.get_accounts(
+ qualified_names=[account1.qualified_name, account2.qualified_name]
+ )
+ assert isinstance(res, list)
+ assert len(res) == 2
+ assert account1 in res
+ assert account2 in res
+
+ # Get 2 known and 1 made up qualified names, and confirm only 2
+ # come back
+ lm.get_accounts_if_exists(
+ qualified_names=[
+ account1.qualified_name,
+ account2.qualified_name,
+ f"{currency.value}:bp_wall:{uuid4().hex}",
+ ]
+ )
+
+ assert isinstance(res, list)
+ assert len(res) == 2
+
+ # Confirm an empty array comes back for all unknown qualified names
+ res = lm.get_accounts_if_exists(
+ qualified_names=[
+ f"{lm.currency.value}:bp_wall:{uuid4().hex}" for i in range(5)
+ ]
+ )
+ assert isinstance(res, list)
+ assert len(res) == 0
+
+ def test_get_accounts_for_products(self, product_factory, thl_lm, lm):
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ )
+
+ # Create 5 Products
+ product_uuids = []
+ for i in range(5):
+ _p = product_factory()
+ product_uuids.append(_p.uuid)
+
+ # Confirm that this fails.. because none of those accounts have been
+ # created yet
+ with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
+ thl_lm.get_accounts_bp_wallet_for_products(product_uuids=product_uuids)
+
+ # Create the bp_wallet accounts and then try again
+ for p_uuid in product_uuids:
+ thl_lm.get_account_or_create_bp_wallet_by_uuid(product_uuid=p_uuid)
+
+ res = thl_lm.get_accounts_bp_wallet_for_products(product_uuids=product_uuids)
+ assert len(res) == len(product_uuids)
+ assert all([isinstance(i, LedgerAccount) for i in res])
+
+
+class TestLedgerAccountManager:
+
+ def test_get_or_create(self, thl_lm, lm, lam):
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ Direction,
+ AccountType,
+ )
+
+ u = uuid4().hex
+ name = f"test-{u[:8]}"
+
+ account = LedgerAccount(
+ display_name=name,
+ qualified_name=f"test:bp_wallet:{u}",
+ normal_balance=Direction.DEBIT,
+ account_type=AccountType.BP_WALLET,
+ currency="test",
+ reference_type="bp",
+ reference_uuid=u,
+ )
+
+ # First we want to validate that using the get_account method raises
+ # an error for a random LedgerAccount which we know does not exist.
+ with pytest.raises(LedgerAccountDoesntExistError):
+ lam.get_account(qualified_name=account.qualified_name)
+
+ # Now that we know it doesn't exist, get_or_create for it
+ instance = lam.get_account_or_create(account=account)
+
+ # It should always return
+ assert isinstance(instance, LedgerAccount)
+ assert instance.reference_uuid == u
+
+ def test_get(self, user, thl_lm, lm, lam):
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ AccountType,
+ )
+
+ with pytest.raises(LedgerAccountDoesntExistError):
+ lam.get_account(qualified_name=f"test:bp_wallet:{user.product.id}")
+
+ thl_lm.get_account_or_create_bp_wallet(product=user.product)
+ account = lam.get_account(qualified_name=f"test:bp_wallet:{user.product.id}")
+
+ assert isinstance(account, LedgerAccount)
+ assert AccountType.BP_WALLET == account.account_type
+ assert user.product.uuid == account.reference_uuid
+
+ def test_get_many(self, product_factory, thl_lm, lm, lam, currency):
+ from generalresearch.models.thl.product import Product
+ from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+ )
+
+ p1: Product = product_factory()
+ p2: Product = product_factory()
+
+ account1 = thl_lm.get_account_or_create_bp_wallet(product=p1)
+ account2 = thl_lm.get_account_or_create_bp_wallet(product=p2)
+
+ # Get 1 known account and confirm it comes back
+ res = lam.get_account_many(
+ qualified_names=[account1.qualified_name, account2.qualified_name]
+ )
+ assert isinstance(res, list)
+ assert len(res) == 2
+ assert account1 in res
+
+ # Get 2 known accounts and confirm they both come back
+ res = lam.get_account_many(
+ qualified_names=[account1.qualified_name, account2.qualified_name]
+ )
+ assert isinstance(res, list)
+ assert len(res) == 2
+ assert account1 in res
+ assert account2 in res
+
+ # Get 2 known and 1 made up qualified names, and confirm only 2 come
+ # back. Don't raise on error, so we can confirm the array is "short"
+ res = lam.get_account_many(
+ qualified_names=[
+ account1.qualified_name,
+ account2.qualified_name,
+ f"test:bp_wall:{uuid4().hex}",
+ ],
+ raise_on_error=False,
+ )
+ assert isinstance(res, list)
+ assert len(res) == 2
+
+ # Same as above, but confirm the raise works on checking res length
+ with pytest.raises(LedgerAccountDoesntExistError):
+ lam.get_account_many(
+ qualified_names=[
+ account1.qualified_name,
+ account2.qualified_name,
+ f"test:bp_wall:{uuid4().hex}",
+ ],
+ raise_on_error=True,
+ )
+
+ # Confirm an empty array comes back for all unknown qualified names
+ res = lam.get_account_many(
+ qualified_names=[f"test:bp_wall:{uuid4().hex}" for i in range(5)],
+ raise_on_error=False,
+ )
+ assert isinstance(res, list)
+ assert len(res) == 0
+
+ def test_create_account(self, thl_lm, lm, lam):
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ Direction,
+ AccountType,
+ )
+
+ u = uuid4().hex
+ name = f"test-{u[:8]}"
+
+ account = LedgerAccount(
+ display_name=name,
+ qualified_name=f"test:bp_wallet:{u}",
+ normal_balance=Direction.DEBIT,
+ account_type=AccountType.BP_WALLET,
+ currency="test",
+ reference_type="bp",
+ reference_uuid=u,
+ )
+
+ lam.create_account(account=account)
+ assert lam.get_account(f"test:bp_wallet:{u}") == account
+ assert lam.get_account_or_create(account) == account