aboutsummaryrefslogtreecommitdiff
path: root/tests/managers/thl
diff options
context:
space:
mode:
Diffstat (limited to 'tests/managers/thl')
-rw-r--r--tests/managers/thl/test_buyer.py16
-rw-r--r--tests/managers/thl/test_cashout_method.py76
-rw-r--r--tests/managers/thl/test_category.py112
-rw-r--r--tests/managers/thl/test_contest/test_leaderboard.py89
-rw-r--r--tests/managers/thl/test_contest/test_milestone.py136
-rw-r--r--tests/managers/thl/test_contest/test_raffle.py232
-rw-r--r--tests/managers/thl/test_harmonized_uqa.py21
-rw-r--r--tests/managers/thl/test_ipinfo.py85
-rw-r--r--tests/managers/thl/test_ledger/test_lm_accounts.py162
-rw-r--r--tests/managers/thl/test_ledger/test_lm_tx.py145
-rw-r--r--tests/managers/thl/test_ledger/test_lm_tx_entries.py30
-rw-r--r--tests/managers/thl/test_ledger/test_lm_tx_locks.py283
-rw-r--r--tests/managers/thl/test_ledger/test_lm_tx_metadata.py43
-rw-r--r--tests/managers/thl/test_ledger/test_thl_lm_accounts.py329
-rw-r--r--tests/managers/thl/test_ledger/test_thl_lm_bp_payout.py473
-rw-r--r--tests/managers/thl/test_ledger/test_thl_lm_tx.py1213
-rw-r--r--tests/managers/thl/test_ledger/test_thl_lm_tx__user_payouts.py404
-rw-r--r--tests/managers/thl/test_ledger/test_thl_pem.py139
-rw-r--r--tests/managers/thl/test_ledger/test_user_txs.py119
-rw-r--r--tests/managers/thl/test_ledger/test_wallet.py51
-rw-r--r--tests/managers/thl/test_maxmind.py500
-rw-r--r--tests/managers/thl/test_payout.py1073
-rw-r--r--tests/managers/thl/test_product.py119
-rw-r--r--tests/managers/thl/test_product_prod.py27
-rw-r--r--tests/managers/thl/test_profiling/test_question.py32
-rw-r--r--tests/managers/thl/test_profiling/test_schema.py18
-rw-r--r--tests/managers/thl/test_profiling/test_uqa.py1
-rw-r--r--tests/managers/thl/test_profiling/test_user_upk.py28
-rw-r--r--tests/managers/thl/test_session_manager.py94
-rw-r--r--tests/managers/thl/test_survey.py96
-rw-r--r--tests/managers/thl/test_survey_penalty.py27
-rw-r--r--tests/managers/thl/test_task_adjustment.py248
-rw-r--r--tests/managers/thl/test_task_status.py169
-rw-r--r--tests/managers/thl/test_user_manager/test_base.py76
-rw-r--r--tests/managers/thl/test_user_manager/test_mysql.py31
-rw-r--r--tests/managers/thl/test_user_manager/test_redis.py46
-rw-r--r--tests/managers/thl/test_user_manager/test_user_fetch.py19
-rw-r--r--tests/managers/thl/test_user_manager/test_user_metadata.py47
-rw-r--r--tests/managers/thl/test_user_streak.py73
-rw-r--r--tests/managers/thl/test_userhealth.py169
-rw-r--r--tests/managers/thl/test_wall_manager.py106
41 files changed, 4041 insertions, 3116 deletions
diff --git a/tests/managers/thl/test_buyer.py b/tests/managers/thl/test_buyer.py
index 69ea105..0ab2d52 100644
--- a/tests/managers/thl/test_buyer.py
+++ b/tests/managers/thl/test_buyer.py
@@ -1,14 +1,24 @@
-from generalresearch.models import Source
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
+
+from generalresearch.models.definitions import Source
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.buyer import BuyerManager
class TestBuyer:
def test(
self,
- delete_buyers_surveys,
- buyer_manager,
+ delete_buyers_surveys: Callable[..., None],
+ buyer_manager: BuyerManager,
):
+ delete_buyers_surveys()
+
bs = buyer_manager.bulk_get_or_create(source=Source.TESTING, codes=["a", "b"])
assert len(bs) == 2
buyer_a = bs[0]
diff --git a/tests/managers/thl/test_cashout_method.py b/tests/managers/thl/test_cashout_method.py
index ee52188..fc364f2 100644
--- a/tests/managers/thl/test_cashout_method.py
+++ b/tests/managers/thl/test_cashout_method.py
@@ -1,62 +1,75 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
+
import pytest
-from generalresearch.models.thl.wallet import PayoutType
from generalresearch.models.thl.wallet.cashout_method import (
CashMailCashoutMethodData,
PaypalCashoutMethodData,
USDeliveryAddress,
)
-from test_utils.managers.cashout_methods import (
- EXAMPLE_TANGO_CASHOUT_METHODS,
-)
+from generalresearch.models.thl.wallet.definitions import PayoutType
+
+if TYPE_CHECKING:
+ from generalresearch.config import GRLBaseSettings
+ from generalresearch.managers.thl.cashout_method import (
+ CashoutMethodManager,
+ )
+ from generalresearch.models.thl.user import User
+ from generalresearch.models.thl.wallet.cashout_method import (
+ CashoutMethod,
+ )
class TestTangoCashoutMethods:
- def test_create_and_get(self, cashout_method_manager, setup_cashoutmethod_db):
+ def test_create_and_get(
+ self,
+ cashout_method_manager: CashoutMethodManager,
+ setup_cashoutmethod_db: Callable[..., None],
+ example_tango_cashout_methods: list[CashoutMethod],
+ ):
+ setup_cashoutmethod_db()
+
res = cashout_method_manager.filter(payout_types=[PayoutType.TANGO])
assert len(res) == 2
- cm = [x for x in res if x.ext_id == "U025035"][0]
- assert EXAMPLE_TANGO_CASHOUT_METHODS[0] == cm
+ cm = next(x for x in res if x.ext_id == "U025035")
+ assert example_tango_cashout_methods[0] == cm
def test_user(
- self, cashout_method_manager, user_with_wallet, setup_cashoutmethod_db
+ self,
+ cashout_method_manager: CashoutMethodManager,
+ user_with_wallet: User,
+ setup_cashoutmethod_db: Callable[..., None],
):
+ setup_cashoutmethod_db()
+
res = cashout_method_manager.get_cashout_methods(user_with_wallet)
# This user ONLY has the two tango cashout methods, no AMT
assert len(res) == 2
-class TestAMTCashoutMethods:
-
- def test_create_and_get(self, cashout_method_manager, setup_cashoutmethod_db):
- res = cashout_method_manager.filter(payout_types=[PayoutType.AMT])
- assert len(res) == 2
-
- cm = [x for x in res if x.name == "AMT Assignment"][0]
- assert AMT_ASSIGNMENT_CASHOUT_METHOD == cm
-
- cm = [x for x in res if x.name == "AMT Bonus"][0]
- assert AMT_BONUS_CASHOUT_METHOD == cm
-
- def test_user(
- self, cashout_method_manager, user_with_wallet_amt, setup_cashoutmethod_db
- ):
- res = cashout_method_manager.get_cashout_methods(user_with_wallet_amt)
- # This user has the 2 tango, plus amt bonus & assignment
- assert len(res) == 4
-
class TestUserCashoutMethods:
- def test(self, cashout_method_manager, user_with_wallet, delete_cashoutmethod_db):
+ def test(
+ self,
+ cashout_method_manager: CashoutMethodManager,
+ user_with_wallet: User,
+ delete_cashoutmethod_db: Callable[..., None],
+ ):
delete_cashoutmethod_db()
res = cashout_method_manager.get_cashout_methods(user_with_wallet)
assert len(res) == 0
def test_cash_in_mail(
- self, cashout_method_manager, user_with_wallet, delete_cashoutmethod_db
+ self,
+ cashout_method_manager: CashoutMethodManager,
+ user_with_wallet: User,
+ delete_cashoutmethod_db: Callable[..., None],
):
delete_cashoutmethod_db()
@@ -95,7 +108,10 @@ class TestUserCashoutMethods:
assert len(res) == 2
def test_paypal(
- self, cashout_method_manager, user_with_wallet, delete_cashoutmethod_db
+ self,
+ cashout_method_manager: CashoutMethodManager,
+ user_with_wallet: User,
+ delete_cashoutmethod_db: Callable[..., None],
):
delete_cashoutmethod_db()
diff --git a/tests/managers/thl/test_category.py b/tests/managers/thl/test_category.py
index ad0f07b..a2805bc 100644
--- a/tests/managers/thl/test_category.py
+++ b/tests/managers/thl/test_category.py
@@ -1,12 +1,21 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
+
import pytest
from generalresearch.models.thl.category import Category
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.category import CategoryManager
+ from generalresearch.pg_helper import PostgresConfig
+
class TestCategory:
@pytest.fixture
- def beauty_fitness(self, thl_web_rw):
+ def beauty_fitness(self) -> Category:
return Category(
uuid="12c1e96be82c4642a07a12a90ce6f59e",
@@ -16,72 +25,83 @@ class TestCategory:
)
@pytest.fixture
- def hair_care(self, beauty_fitness):
+ def hair_care(self, beauty_fitness: Category) -> Category:
return Category(
uuid="dd76c4b565d34f198dad3687326503d6",
adwords_vertical_id="146",
label="Hair Care",
- path="/Beauty & Fitness/Hair Care",
+ path=f"{beauty_fitness.path}/Hair Care",
)
@pytest.fixture
- def hair_loss(self, hair_care):
+ def hair_loss(self, hair_care: Category) -> Category:
return Category(
uuid="aacff523c8e246888215611ec3b823c0",
adwords_vertical_id="235",
label="Hair Loss",
- path="/Beauty & Fitness/Hair Care/Hair Loss",
+ path=f"{hair_care.path}/Hair Loss",
)
@pytest.fixture
def category_data(
- self, category_manager, thl_web_rw, beauty_fitness, hair_care, hair_loss
- ):
- cats = [beauty_fitness, hair_care, hair_loss]
- data = [x.model_dump(mode="json") for x in cats]
- # We need the parent pk's to set the parent_id. So insert all without a parent,
- # then pull back all pks and map to the parents as parsed by the parent_path
- query = """
- INSERT INTO marketplace_category
- (uuid, adwords_vertical_id, label, path)
- VALUES
- (%(uuid)s, %(adwords_vertical_id)s, %(label)s, %(path)s)
- ON CONFLICT (uuid) DO NOTHING;
- """
- with thl_web_rw.make_connection() as conn:
- with conn.cursor() as c:
- c.executemany(query=query, params_seq=data)
- conn.commit()
-
- res = thl_web_rw.execute_sql_query("SELECT id, path FROM marketplace_category")
- path_id = {x["path"]: x["id"] for x in res}
- data = [
- {"id": path_id[c.path], "parent_id": path_id[c.parent_path]}
- for c in cats
- if c.parent_path
- ]
- query = """
- UPDATE marketplace_category
- SET parent_id = %(parent_id)s
- WHERE id = %(id)s;
- """
- with thl_web_rw.make_connection() as conn:
- with conn.cursor() as c:
- c.executemany(query=query, params_seq=data)
- conn.commit()
-
- category_manager.populate_caches()
+ self,
+ category_manager: CategoryManager,
+ thl_web_rw: PostgresConfig,
+ beauty_fitness: Category,
+ hair_care: Category,
+ hair_loss: Category,
+ ) -> Callable[..., None]:
+
+ def _inner():
+ cats = [beauty_fitness, hair_care, hair_loss]
+ data = [x.model_dump(mode="json") for x in cats]
+ # We need the parent pk's to set the parent_id. So insert all without a parent,
+ # then pull back all pks and map to the parents as parsed by the parent_path
+ query = """
+ INSERT INTO marketplace_category
+ (uuid, adwords_vertical_id, label, path)
+ VALUES
+ (%(uuid)s, %(adwords_vertical_id)s, %(label)s, %(path)s)
+ ON CONFLICT (uuid) DO NOTHING;
+ """
+ with thl_web_rw.make_connection() as conn:
+ with conn.cursor() as c:
+ c.executemany(query=query, params_seq=data)
+ conn.commit()
+
+ res = thl_web_rw.execute_sql_query(
+ "SELECT id, path FROM marketplace_category"
+ )
+ path_id = {x["path"]: x["id"] for x in res}
+ data = [
+ {"id": path_id[c.path], "parent_id": path_id[c.parent_path]}
+ for c in cats
+ if c.parent_path
+ ]
+ query = """
+ UPDATE marketplace_category
+ SET parent_id = %(parent_id)s
+ WHERE id = %(id)s;
+ """
+ with thl_web_rw.make_connection() as conn:
+ with conn.cursor() as c:
+ c.executemany(query=query, params_seq=data)
+ conn.commit()
+
+ category_manager.populate_caches()
+
+ return _inner
def test(
self,
- category_data,
- category_manager,
- beauty_fitness,
- hair_care,
- hair_loss,
+ category_data: Callable[..., None],
+ category_manager: CategoryManager,
+ beauty_fitness: Category,
):
+ category_data()
+
# category_manager on init caches the category info. This rarely/never changes so this is fine,
# but now that tests get run on a new db each time, the category_manager is inited before
# the fixtures run. so category_manager's cache needs to be rerun
diff --git a/tests/managers/thl/test_contest/test_leaderboard.py b/tests/managers/thl/test_contest/test_leaderboard.py
index 80a88a5..8aa0780 100644
--- a/tests/managers/thl/test_contest/test_leaderboard.py
+++ b/tests/managers/thl/test_contest/test_leaderboard.py
@@ -1,34 +1,41 @@
-from datetime import datetime, timezone, timedelta
+from __future__ import annotations
+
+from datetime import UTC, datetime, timedelta
+from typing import TYPE_CHECKING
from zoneinfo import ZoneInfo
from generalresearch.currency import USDCent
from generalresearch.models.thl.contest.definitions import (
- ContestStatus,
ContestEndReason,
+ ContestStatus,
)
from generalresearch.models.thl.contest.leaderboard import (
LeaderboardContest,
- LeaderboardContestCreate,
-)
-from generalresearch.models.thl.product import Product
-from generalresearch.models.thl.user import User
-from test_utils.managers.contest.conftest import (
- leaderboard_contest_in_db as contest_in_db,
- leaderboard_contest_create as contest_create,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.contest_manager import ContestManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.user_manager.user_manager import UserManager
+ from generalresearch.models.thl.contest.leaderboard import (
+ LeaderboardContestCreate,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
+ from generalresearch.redis_helper import RedisConfig
-class TestLeaderboardContestCRUD:
+class TestLeaderboardContestCRUD:
def test_create(
self,
- contest_create: LeaderboardContestCreate,
+ leaderboard_contest_create: LeaderboardContestCreate,
product_user_wallet_yes: Product,
- thl_lm,
- contest_manager,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=contest_create
+ product_id=product_user_wallet_yes.uuid,
+ contest_create=leaderboard_contest_create,
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -39,18 +46,19 @@ class TestLeaderboardContestCRUD:
# We have it set in the fixture as the daily contest for 2025-01-01
assert c.end_condition.ends_at == datetime(
2025, 1, 1, 23, 59, 59, 999999, tzinfo=ZoneInfo("America/New_York")
- ).astimezone(tz=timezone.utc) + timedelta(minutes=90)
+ ).astimezone(tz=UTC) + timedelta(minutes=90)
def test_enter(
self,
user_with_wallet: User,
- contest_in_db: LeaderboardContest,
- thl_lm,
- contest_manager,
- user_manager,
- thl_redis,
+ leaderboard_contest_in_db: LeaderboardContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
+ user_manager: UserManager,
+ thl_redis_config: RedisConfig,
):
- contest = contest_in_db
+ thl_redis = thl_redis_config.create_redis_client()
+ contest = leaderboard_contest_in_db
user = user_with_wallet
c: LeaderboardContest = contest_manager.get(contest_uuid=contest.uuid)
@@ -77,14 +85,15 @@ class TestLeaderboardContestCRUD:
def test_contest_ends(
self,
user_with_wallet: User,
- contest_in_db: LeaderboardContest,
- thl_lm,
- contest_manager,
- user_manager,
- thl_redis,
+ leaderboard_contest_in_db: LeaderboardContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
+ user_manager: UserManager,
+ thl_redis_config: RedisConfig,
):
+ thl_redis = thl_redis_config.create_redis_client()
# The contest should be over. We need to trigger it.
- contest = contest_in_db
+ contest = leaderboard_contest_in_db
contest._redis_client = thl_redis
contest._user_manager = user_manager
user = user_with_wallet
@@ -100,18 +109,22 @@ class TestLeaderboardContestCRUD:
)
assert c.user_rank == 1
- bp_wallet = thl_lm.get_account_or_create_bp_wallet_by_uuid(user.product_id)
- bp_wallet_balance = thl_lm.get_account_balance(account=bp_wallet)
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet_by_uuid(
+ user.product_id
+ )
+ bp_wallet_balance = thl_ledger_manager.get_account_balance(account=bp_wallet)
assert bp_wallet_balance == 0
- user_wallet = thl_lm.get_account_or_create_user_wallet(user=user)
- user_balance = thl_lm.get_account_balance(user_wallet)
+ user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
+ user_balance = thl_ledger_manager.get_account_balance(user_wallet)
assert user_balance == 0
decision, reason = contest.should_end()
assert decision
assert reason == ContestEndReason.ENDS_AT
- contest_manager.end_contest_if_over(contest=contest, ledger_manager=thl_lm)
+ contest_manager.end_contest_if_over(
+ contest=contest, ledger_manager=thl_ledger_manager
+ )
c: LeaderboardContest = contest_manager.get(contest_uuid=contest.uuid)
assert c.status == ContestStatus.COMPLETED
@@ -129,10 +142,12 @@ class TestLeaderboardContestCRUD:
assert w.prize.cash_amount == USDCent(15_00)
# The prize is $15.00, so the user should get $15, paid by the bp
- assert thl_lm.get_account_balance(account=user_wallet) == 15_00
+ assert thl_ledger_manager.get_account_balance(account=user_wallet) == 15_00
# contest wallet is 0, and the BP gets 20c
- contest_wallet = thl_lm.get_account_or_create_contest_wallet_by_uuid(
- contest_uuid=c.uuid
+ contest_wallet = (
+ thl_ledger_manager.get_account_or_create_contest_wallet_by_uuid(
+ contest_uuid=c.uuid
+ )
)
- assert thl_lm.get_account_balance(account=contest_wallet) == 0
- assert thl_lm.get_account_balance(account=bp_wallet) == -15_00
+ assert thl_ledger_manager.get_account_balance(account=contest_wallet) == 0
+ assert thl_ledger_manager.get_account_balance(account=bp_wallet) == -15_00
diff --git a/tests/managers/thl/test_contest/test_milestone.py b/tests/managers/thl/test_contest/test_milestone.py
index 7312a64..f26819b 100644
--- a/tests/managers/thl/test_contest/test_milestone.py
+++ b/tests/managers/thl/test_contest/test_milestone.py
@@ -1,34 +1,41 @@
-from datetime import datetime, timezone
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime
+from typing import TYPE_CHECKING
from generalresearch.models.thl.contest.definitions import (
- ContestStatus,
ContestEndReason,
+ ContestEntryTrigger,
+ ContestStatus,
)
from generalresearch.models.thl.contest.milestone import (
MilestoneContest,
- MilestoneContestCreate,
MilestoneUserView,
- ContestEntryTrigger,
-)
-from generalresearch.models.thl.product import Product
-from generalresearch.models.thl.user import User
-from test_utils.managers.contest.conftest import (
- milestone_contest as contest,
- milestone_contest_in_db as contest_in_db,
- milestone_contest_create as contest_create,
- milestone_contest_factory as contest_factory,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.contest_manager import ContestManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.models.thl.contest.milestone import (
+ MilestoneContestCreate,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
-class TestMilestoneContest:
- def test_should_end(self, contest: MilestoneContest, thl_lm, contest_manager):
+class TestMilestoneContest:
+ def test_should_end(
+ self,
+ milestone_contest: MilestoneContest,
+ ):
+ contest = milestone_contest
# contest is active and has no entries
should, msg = contest.should_end()
assert not should, msg
# Change so that the contest ends now
- contest.end_condition.ends_at = datetime.now(tz=timezone.utc)
+ contest.end_condition.ends_at = datetime.now(tz=UTC)
should, msg = contest.should_end()
assert should
assert msg == ContestEndReason.ENDS_AT
@@ -43,16 +50,15 @@ class TestMilestoneContest:
class TestMilestoneContestCRUD:
-
def test_create(
self,
- contest_create: MilestoneContestCreate,
+ milestone_contest_create: MilestoneContestCreate,
product_user_wallet_yes: Product,
- thl_lm,
- contest_manager,
+ contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=contest_create
+ product_id=product_user_wallet_yes.uuid,
+ contest_create=milestone_contest_create,
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -68,20 +74,20 @@ class TestMilestoneContestCRUD:
def test_enter(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
- thl_lm,
- contest_manager,
+ milestone_contest_in_db: MilestoneContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Users CANNOT directly enter a milestone contest through the api,
# but we'll call this manager method when a trigger is hit.
- contest = contest_in_db
+ contest = milestone_contest_in_db
user = user_with_wallet
contest_manager.enter_milestone_contest(
contest_uuid=contest.uuid,
user=user,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
incr=1,
)
@@ -96,17 +102,19 @@ class TestMilestoneContestCRUD:
assert c.user_amount == 1
# Contest wallet should have 0 bc there is no ledger
- contest_wallet = thl_lm.get_account_or_create_contest_wallet_by_uuid(
- contest_uuid=contest.uuid
+ contest_wallet = (
+ thl_ledger_manager.get_account_or_create_contest_wallet_by_uuid(
+ contest_uuid=contest.uuid
+ )
)
- assert thl_lm.get_account_balance(contest_wallet) == 0
+ assert thl_ledger_manager.get_account_balance(contest_wallet) == 0
# Enter again!
contest_manager.enter_milestone_contest(
contest_uuid=contest.uuid,
user=user,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
incr=1,
)
c: MilestoneUserView = contest_manager.get_milestone_user_view(
@@ -122,21 +130,21 @@ class TestMilestoneContestCRUD:
def test_enter_win(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
- thl_lm,
- contest_manager,
+ milestone_contest_in_db: MilestoneContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# User enters contest, which brings the USER'S total amount above the limit,
# and the user reaches the milestone
- contest = contest_in_db
+ contest = milestone_contest_in_db
user = user_with_wallet
- user_wallet = thl_lm.get_account_or_create_user_wallet(user=user)
- user_balance = thl_lm.get_account_balance(account=user_wallet)
- bp_wallet = thl_lm.get_account_or_create_bp_wallet_by_uuid(
+ user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
+ user_balance = thl_ledger_manager.get_account_balance(account=user_wallet)
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet_by_uuid(
product_uuid=user.product_id
)
- bp_wallet_balance = thl_lm.get_account_balance(account=bp_wallet)
+ bp_wallet_balance = thl_ledger_manager.get_account_balance(account=bp_wallet)
c: MilestoneUserView = contest_manager.get_milestone_user_view(
contest_uuid=contest.uuid, user=user_with_wallet
@@ -151,7 +159,7 @@ class TestMilestoneContestCRUD:
contest_uuid=contest.uuid,
user=user,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
incr=1,
)
@@ -171,9 +179,12 @@ class TestMilestoneContestCRUD:
assert c.win_count == 1
# The prize was awarded! User should have won $1.00
- assert thl_lm.get_account_balance(user_wallet) - user_balance == 100
+ assert thl_ledger_manager.get_account_balance(user_wallet) - user_balance == 100
# Which was paid from the BP's balance
- assert thl_lm.get_account_balance(bp_wallet) - bp_wallet_balance == -100
+ assert (
+ thl_ledger_manager.get_account_balance(bp_wallet) - bp_wallet_balance
+ == -100
+ )
# winnings = cm.get_winnings_by_user(user=user)
# assert len(winnings) == 1
@@ -182,22 +193,22 @@ class TestMilestoneContestCRUD:
def test_enter_ends(
self,
- user_factory,
+ user_factory: Callable[..., User],
product_user_wallet_yes: Product,
- contest_in_db: MilestoneContest,
- thl_lm,
- contest_manager,
+ milestone_contest_in_db: MilestoneContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Multiple users reach the milestone. Contest ends after 5 wins.
users = [user_factory(product=product_user_wallet_yes) for _ in range(5)]
- contest = contest_in_db
+ contest = milestone_contest_in_db
for u in users:
contest_manager.enter_milestone_contest(
contest_uuid=contest.uuid,
user=u,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
incr=3,
)
@@ -208,29 +219,33 @@ class TestMilestoneContestCRUD:
def test_trigger(
self,
user_with_wallet: User,
- contest_in_db: MilestoneContest,
- thl_lm,
- contest_manager,
+ milestone_contest_in_db: MilestoneContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Pretend user just got a complete
cnt = contest_manager.hit_milestone_triggers(
country_iso="us",
user=user_with_wallet,
event=ContestEntryTrigger.TASK_COMPLETE,
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert cnt == 1
# Assert this contest got entered
c: MilestoneUserView = contest_manager.get_milestone_user_view(
- contest_uuid=contest_in_db.uuid, user=user_with_wallet
+ contest_uuid=milestone_contest_in_db.uuid, user=user_with_wallet
)
assert c.user_amount == 1
class TestMilestoneContestUserViews:
def test_list_user_eligible_country(
- self, user_with_wallet: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_wallet: User,
+ milestone_contest_factory: Callable[..., MilestoneContest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# No contests exists
cs = contest_manager.get_many_by_user_eligible(
@@ -239,7 +254,7 @@ class TestMilestoneContestUserViews:
assert len(cs) == 0
# Create a contest. It'll be in the US/CA
- contest_factory(country_isos={"us", "ca"})
+ milestone_contest_factory(country_isos={"us", "ca"})
# Not eligible in mexico
cs = contest_manager.get_many_by_user_eligible(
@@ -252,7 +267,7 @@ class TestMilestoneContestUserViews:
assert len(cs) == 1
# Create another, any country
- contest_factory(country_isos=None)
+ milestone_contest_factory(country_isos=None)
cs = contest_manager.get_many_by_user_eligible(
user=user_with_wallet, country_iso="mx"
)
@@ -263,10 +278,14 @@ class TestMilestoneContestUserViews:
assert len(cs) == 2
def test_list_user_eligible(
- self, user_with_money: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_money: User,
+ milestone_contest_factory: Callable[..., MilestoneContest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# User reaches milestone after 1 complete
- c = contest_factory(target_amount=1)
+ c = milestone_contest_factory(target_amount=1)
user = user_with_money
cs = contest_manager.get_many_by_user_eligible(
@@ -275,7 +294,10 @@ class TestMilestoneContestUserViews:
assert len(cs) == 1
contest_manager.enter_milestone_contest(
- contest_uuid=c.uuid, user=user, country_iso="us", ledger_manager=thl_lm
+ contest_uuid=c.uuid,
+ user=user,
+ country_iso="us",
+ ledger_manager=thl_ledger_manager,
)
# User isn't eligible anymore
diff --git a/tests/managers/thl/test_contest/test_raffle.py b/tests/managers/thl/test_contest/test_raffle.py
index 060055a..7388991 100644
--- a/tests/managers/thl/test_contest/test_raffle.py
+++ b/tests/managers/thl/test_contest/test_raffle.py
@@ -1,4 +1,8 @@
-from datetime import datetime, timezone
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime
+from typing import TYPE_CHECKING
import pytest
from pydantic import ValidationError
@@ -9,44 +13,49 @@ from generalresearch.managers.thl.ledger_manager.exceptions import (
LedgerTransactionConditionFailedError,
)
from generalresearch.models.thl.contest import (
- ContestPrize,
- ContestEntryRule,
ContestEndCondition,
+ ContestEntryRule,
+ ContestPrize,
)
-from generalresearch.models.thl.contest.definitions import (
- ContestStatus,
- ContestPrizeKind,
- ContestEndReason,
-)
-from generalresearch.models.thl.contest.exceptions import ContestError
-from generalresearch.models.thl.contest.raffle import (
+from generalresearch.models.thl.contest.contest_entry import (
ContestEntry,
ContestEntryType,
)
-from generalresearch.models.thl.contest.raffle import (
- RaffleContest,
- RaffleContestCreate,
- RaffleUserView,
-)
-from generalresearch.models.thl.product import Product
-from generalresearch.models.thl.user import User
-from test_utils.managers.contest.conftest import (
- raffle_contest as contest,
- raffle_contest_in_db as contest_in_db,
- raffle_contest_create as contest_create,
- raffle_contest_factory as contest_factory,
+from generalresearch.models.thl.contest.definitions import (
+ ContestEndReason,
+ ContestPrizeKind,
+ ContestStatus,
)
+from generalresearch.models.thl.contest.exceptions import ContestError
+from generalresearch.models.thl.contest.raffle import RaffleContest
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.contest_manager import ContestManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.models.thl.contest import (
+ Contest,
+ )
+ from generalresearch.models.thl.contest.raffle import (
+ RaffleContestCreate,
+ RaffleUserView,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
class TestRaffleContest:
- def test_should_end(self, contest: RaffleContest, thl_lm, contest_manager):
+ def test_should_end(
+ self,
+ raffle_contest: RaffleContest,
+ ):
+ contest = raffle_contest
# contest is active and has no entries
should, msg = contest.should_end()
assert not should, msg
# Change so that the contest ends now
- contest.end_condition.ends_at = datetime.now(tz=timezone.utc)
+ contest.end_condition.ends_at = datetime.now(tz=UTC)
should, msg = contest.should_end()
assert should
assert msg == ContestEndReason.ENDS_AT
@@ -63,13 +72,12 @@ class TestRaffleContestCRUD:
def test_create(
self,
- contest_create: RaffleContestCreate,
+ raffle_contest_create: RaffleContestCreate,
product_user_wallet_yes: Product,
- thl_lm,
- contest_manager,
+ contest_manager: ContestManager,
):
c = contest_manager.create(
- product_id=product_user_wallet_yes.uuid, contest_create=contest_create
+ product_id=product_user_wallet_yes.uuid, contest_create=raffle_contest_create
)
c_out = contest_manager.get(c.uuid)
assert c == c_out
@@ -85,18 +93,20 @@ class TestRaffleContestCRUD:
def test_enter(
self,
user_with_money: User,
- contest_in_db: RaffleContest,
- thl_lm,
- contest_manager,
+ raffle_contest_in_db: RaffleContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Raffle ends at $1.00. User enters for $0.60
print(user_with_money.product_id)
- print(contest_in_db.product_id)
- print(contest_in_db.uuid)
- contest = contest_in_db
+ print(raffle_contest_in_db.product_id)
+ print(raffle_contest_in_db.uuid)
+ contest = raffle_contest_in_db
- user_wallet = thl_lm.get_account_or_create_user_wallet(user=user_with_money)
- user_balance = thl_lm.get_account_balance(account=user_wallet)
+ user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(
+ user=user_with_money
+ )
+ user_balance = thl_ledger_manager.get_account_balance(account=user_wallet)
entry = ContestEntry(
entry_type=ContestEntryType.CASH, user=user_with_money, amount=USDCent(60)
@@ -105,7 +115,7 @@ class TestRaffleContestCRUD:
contest_uuid=contest.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
c: RaffleContest = contest_manager.get(contest_uuid=contest.uuid)
assert c.current_amount == USDCent(60)
@@ -120,30 +130,35 @@ class TestRaffleContestCRUD:
assert c.projected_win_probability == approx(60 / 100, rel=0.01)
# Contest wallet should have $0.60
- contest_wallet = thl_lm.get_account_or_create_contest_wallet_by_uuid(
- contest_uuid=contest.uuid
+ contest_wallet = (
+ thl_ledger_manager.get_account_or_create_contest_wallet_by_uuid(
+ contest_uuid=contest.uuid
+ )
)
- assert thl_lm.get_account_balance(account=contest_wallet) == 60
+ assert thl_ledger_manager.get_account_balance(account=contest_wallet) == 60
# User spent 60c
- assert user_balance - thl_lm.get_account_balance(account=user_wallet) == 60
+ assert (
+ user_balance - thl_ledger_manager.get_account_balance(account=user_wallet)
+ == 60
+ )
@pytest.mark.parametrize("user_with_money", [{"min_balance": 120}], indirect=True)
def test_enter_ends(
self,
user_with_money: User,
- contest_in_db: RaffleContest,
- thl_lm,
- contest_manager,
+ raffle_contest_in_db: RaffleContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# User enters contest, which brings the total amount above the limit,
# and the contest should end, with a winner selected
- contest = contest_in_db
+ contest = raffle_contest_in_db
- bp_wallet = thl_lm.get_account_or_create_bp_wallet_by_uuid(
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet_by_uuid(
user_with_money.product_id
)
# I bribed the user, so the balance is not 0
- bp_wallet_balance = thl_lm.get_account_balance(account=bp_wallet)
+ bp_wallet_balance = thl_ledger_manager.get_account_balance(account=bp_wallet)
for _ in range(2):
entry = ContestEntry(
@@ -155,7 +170,7 @@ class TestRaffleContestCRUD:
contest_uuid=contest.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
c: RaffleContest = contest_manager.get(contest_uuid=contest.uuid)
assert c.status == ContestStatus.COMPLETED
@@ -175,25 +190,33 @@ class TestRaffleContestCRUD:
assert win.product_user_id == user_with_money.product_user_id
# Contest wallet should have gotten zeroed out
- contest_wallet = thl_lm.get_account_or_create_contest_wallet_by_uuid(
- contest_uuid=contest.uuid
+ contest_wallet = (
+ thl_ledger_manager.get_account_or_create_contest_wallet_by_uuid(
+ contest_uuid=contest.uuid
+ )
)
- assert thl_lm.get_account_balance(contest_wallet) == 0
+ assert thl_ledger_manager.get_account_balance(contest_wallet) == 0
# Expense wallet gets the $1.00 expense
- expense_wallet = thl_lm.get_account_or_create_bp_expense_by_uuid(
+ expense_wallet = thl_ledger_manager.get_account_or_create_bp_expense_by_uuid(
product_uuid=user_with_money.product_id, expense_name="Prize"
)
- assert thl_lm.get_account_balance(expense_wallet) == -100
+ assert thl_ledger_manager.get_account_balance(expense_wallet) == -100
# And the BP gets 20c
- assert thl_lm.get_account_balance(bp_wallet) - bp_wallet_balance == 20
+ assert (
+ thl_ledger_manager.get_account_balance(bp_wallet) - bp_wallet_balance == 20
+ )
@pytest.mark.parametrize("user_with_money", [{"min_balance": 120}], indirect=True)
def test_enter_ends_cash_prize(
- self, user_with_money: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_money: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Same as test_enter_ends, but the prize is cash. Just
# testing the ledger methods
- c = contest_factory(
+ c = raffle_contest_factory(
prizes=[
ContestPrize(
name="$1.00 bonus",
@@ -205,12 +228,14 @@ class TestRaffleContestCRUD:
)
assert c.prizes[0].kind == ContestPrizeKind.CASH
- user_wallet = thl_lm.get_account_or_create_user_wallet(user=user_with_money)
- user_balance = thl_lm.get_account_balance(user_wallet)
- bp_wallet = thl_lm.get_account_or_create_bp_wallet_by_uuid(
+ user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(
+ user=user_with_money
+ )
+ user_balance = thl_ledger_manager.get_account_balance(user_wallet)
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet_by_uuid(
user_with_money.product_id
)
- bp_wallet_balance = thl_lm.get_account_balance(bp_wallet)
+ bp_wallet_balance = thl_ledger_manager.get_account_balance(bp_wallet)
## Enter Contest
entry = ContestEntry(
@@ -220,28 +245,35 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
# The prize is $1.00, so the user spent $1.20 entering, won, then got $1.00 back
assert (
- thl_lm.get_account_balance(account=user_wallet) == user_balance + 100 - 120
+ thl_ledger_manager.get_account_balance(account=user_wallet)
+ == user_balance + 100 - 120
)
# contest wallet is 0, and the BP gets 20c
- contest_wallet = thl_lm.get_account_or_create_contest_wallet_by_uuid(
- contest_uuid=c.uuid
+ contest_wallet = (
+ thl_ledger_manager.get_account_or_create_contest_wallet_by_uuid(
+ contest_uuid=c.uuid
+ )
+ )
+ assert thl_ledger_manager.get_account_balance(account=contest_wallet) == 0
+ assert (
+ thl_ledger_manager.get_account_balance(account=bp_wallet)
+ - bp_wallet_balance
+ == 20
)
- assert thl_lm.get_account_balance(account=contest_wallet) == 0
- assert thl_lm.get_account_balance(account=bp_wallet) - bp_wallet_balance == 20
def test_enter_failure(
self,
user_with_wallet: User,
- contest_in_db: RaffleContest,
- thl_lm,
- contest_manager,
+ raffle_contest_in_db: RaffleContest,
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
- c = contest_in_db
+ c = raffle_contest_in_db
user = user_with_wallet
# Tries to enter $0
@@ -260,7 +292,7 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert e.value.args[0] == "insufficient balance"
@@ -271,16 +303,20 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert "incompatible entry type" in str(e.value)
@pytest.mark.parametrize("user_with_money", [{"min_balance": 100}], indirect=True)
def test_enter_not_eligible(
- self, user_with_money: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_money: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# Max entry amount per user $0.10. Contest still ends at $1.00
- c = contest_factory(
+ c = raffle_contest_factory(
entry_rule=ContestEntryRule(
max_entry_amount_per_user=USDCent(10),
max_daily_entries_per_user=USDCent(8),
@@ -299,7 +335,7 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert "Entry would exceed max amount per user." in str(e.value)
@@ -312,7 +348,7 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert "Entry would exceed max amount per user per day." in str(e.value)
@@ -324,7 +360,7 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
# Then can't anymore
@@ -336,14 +372,18 @@ class TestRaffleContestCRUD:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
assert "Entry would exceed max amount per user per day." in str(e.value)
class TestRaffleContestUserViews:
def test_list_user_eligible_country(
- self, user_with_wallet: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_wallet: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
# No contests exists
cs = contest_manager.get_many_by_user_eligible(
@@ -352,7 +392,7 @@ class TestRaffleContestUserViews:
assert len(cs) == 0
# Create a contest. It'll be in the US/CA
- contest_factory(country_isos={"us", "ca"})
+ raffle_contest_factory(country_isos={"us", "ca"})
# Not eligible in mexico
cs = contest_manager.get_many_by_user_eligible(
@@ -365,7 +405,7 @@ class TestRaffleContestUserViews:
assert len(cs) == 1
# Create another, any country
- contest_factory(country_isos=None)
+ raffle_contest_factory(country_isos=None)
cs = contest_manager.get_many_by_user_eligible(
user=user_with_wallet, country_iso="mx"
)
@@ -376,9 +416,13 @@ class TestRaffleContestUserViews:
assert len(cs) == 2
def test_list_user_eligible(
- self, user_with_money: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_money: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
- c = contest_factory(
+ c = raffle_contest_factory(
end_condition=ContestEndCondition(target_entry_amount=USDCent(10)),
entry_rule=ContestEntryRule(
max_entry_amount_per_user=USDCent(1),
@@ -398,7 +442,7 @@ class TestRaffleContestUserViews:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
# User isn't eligible anymore
@@ -422,9 +466,13 @@ class TestRaffleContestUserViews:
assert len(contest_manager.get_winnings_by_user(user_with_money)) == 0
def test_list_user_winnings(
- self, user_with_money: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_money: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
- c = contest_factory(
+ c = raffle_contest_factory(
end_condition=ContestEndCondition(target_entry_amount=USDCent(100)),
)
entry = ContestEntry(
@@ -436,7 +484,7 @@ class TestRaffleContestUserViews:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
# Contest ends after 100 entry, user enters 100 entry, user wins!
ws = contest_manager.get_winnings_by_user(user_with_money)
@@ -458,9 +506,13 @@ class TestRaffleContestCRUDCount:
# This is a COUNT contest. No cash moves. Not really fleshed out what we'd do with this.
@pytest.mark.skip
def test_enter(
- self, user_with_wallet: User, contest_factory, thl_lm, contest_manager
+ self,
+ user_with_wallet: User,
+ raffle_contest_factory: Callable[..., Contest],
+ thl_ledger_manager: ThlLedgerManager,
+ contest_manager: ContestManager,
):
- c = contest_factory(entry_type=ContestEntryType.COUNT)
+ c = raffle_contest_factory(entry_type=ContestEntryType.COUNT)
entry = ContestEntry(
entry_type=ContestEntryType.COUNT,
user=user_with_wallet,
@@ -470,5 +522,5 @@ class TestRaffleContestCRUDCount:
contest_uuid=c.uuid,
entry=entry,
country_iso="us",
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
)
diff --git a/tests/managers/thl/test_harmonized_uqa.py b/tests/managers/thl/test_harmonized_uqa.py
index 6bbbbe1..2fc0ff0 100644
--- a/tests/managers/thl/test_harmonized_uqa.py
+++ b/tests/managers/thl/test_harmonized_uqa.py
@@ -1,13 +1,18 @@
-from datetime import datetime, timezone
+from __future__ import annotations
+
+from datetime import UTC, datetime
+from typing import TYPE_CHECKING
import pytest
-from generalresearch.managers.thl.profiling.uqa import UQAManager
from generalresearch.models.thl.profiling.user_question_answer import (
- UserQuestionAnswer,
DUMMY_UQA,
+ UserQuestionAnswer,
)
-from generalresearch.models.thl.user import User
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.profiling.uqa import UQAManager
+ from generalresearch.models.thl.user import User
@pytest.mark.usefixtures("uqa_db_index", "upk_data", "uqa_manager_clear_cache")
@@ -18,7 +23,7 @@ class TestUQAManager:
assert len(uqas) == 0
def test_create(self, uqa_manager: UQAManager, user: User):
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
uqas = [
UserQuestionAnswer(
user_id=user.user_id,
@@ -38,7 +43,7 @@ class TestUQAManager:
assert res[0] == uqas[0]
# Same question, so this gets updated
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
uqas_update = [
UserQuestionAnswer(
user_id=user.user_id,
@@ -57,7 +62,7 @@ class TestUQAManager:
assert res[0] == uqas_update[0]
# Add a new answer
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
uqas_new = [
UserQuestionAnswer(
user_id=user.user_id,
@@ -103,7 +108,7 @@ class TestUQAManagerCache:
UserQuestionAnswer(
question_id="5d6d9f3c03bb40bf9d0a24f306387d7c",
answer=("1",),
- timestamp=datetime.now(tz=timezone.utc),
+ timestamp=datetime.now(tz=UTC),
country_iso="us",
language_iso="eng",
property_code="gr:gender",
diff --git a/tests/managers/thl/test_ipinfo.py b/tests/managers/thl/test_ipinfo.py
index 847b00c..c021eb9 100644
--- a/tests/managers/thl/test_ipinfo.py
+++ b/tests/managers/thl/test_ipinfo.py
@@ -1,51 +1,75 @@
+from collections.abc import Callable
+from typing import TYPE_CHECKING
+
import faker
from generalresearch.managers.thl.ipinfo import (
+ GeoIpInfoManager,
IPGeonameManager,
IPInformationManager,
- GeoIpInfoManager,
)
-from generalresearch.models.thl.ipinfo import IPGeoname, IPInformation
+from generalresearch.models.thl.ipinfo import (
+ GeoIPInformation,
+ IPGeoname,
+ IPInformation,
+)
+
+if TYPE_CHECKING:
+ from generalresearch.pg_helper import PostgresConfig
+ from generalresearch.redis_helper import RedisConfig
fake = faker.Faker()
class TestIPGeonameManager:
- def test_init(self, thl_web_rr, ip_geoname_manager: IPGeonameManager):
+ def test_init(
+ self, thl_web_rr: PostgresConfig, ip_geoname_manager: IPGeonameManager
+ ):
instance = IPGeonameManager(pg_config=thl_web_rr)
assert isinstance(instance, IPGeonameManager)
assert isinstance(ip_geoname_manager, IPGeonameManager)
- def test_create(self, ip_geoname_manager: IPGeonameManager):
-
- instance = ip_geoname_manager.create_dummy()
+ def test_create(
+ self,
+ ip_geoname_factory: Callable[..., IPGeoname],
+ ip_geoname_manager: IPGeonameManager,
+ ):
+ instance = ip_geoname_factory()
assert isinstance(instance, IPGeoname)
res = ip_geoname_manager.fetch_geoname_ids(filter_ids=[instance.geoname_id])
-
assert res[0].model_dump_json() == instance.model_dump_json()
class TestIPInformationManager:
- def test_init(self, thl_web_rr, ip_information_manager: IPInformationManager):
+ def test_init(
+ self, thl_web_rr: PostgresConfig, ip_information_manager: IPInformationManager
+ ):
instance = IPInformationManager(pg_config=thl_web_rr)
assert isinstance(instance, IPInformationManager)
assert isinstance(ip_information_manager, IPInformationManager)
- def test_create(self, ip_information_manager: IPInformationManager):
- instance = ip_information_manager.create_dummy()
-
+ def test_create(
+ self,
+ ip_information_factory: Callable[..., IPInformation],
+ ip_information_manager: IPInformationManager,
+ ):
+ instance = ip_information_factory()
assert isinstance(instance, IPInformation)
res = ip_information_manager.fetch_ip_information(filter_ips=[instance.ip])
-
assert res[0].model_dump_json() == instance.model_dump_json()
- def test_prefetch_geoname(self, ip_information, ip_geoname, thl_web_rr):
+ def test_prefetch_geoname(
+ self,
+ ip_information: IPInformation,
+ ip_geoname: IPGeoname,
+ thl_web_rr: PostgresConfig,
+ ):
assert isinstance(ip_information, IPInformation)
assert ip_information.geoname_id == ip_geoname.geoname_id
@@ -57,13 +81,21 @@ class TestIPInformationManager:
class TestGeoIpInfoManager:
def test_init(
- self, thl_web_rr, thl_redis_config, geoipinfo_manager: GeoIpInfoManager
+ self,
+ thl_web_rr: PostgresConfig,
+ thl_redis_config: RedisConfig,
+ geoipinfo_manager: GeoIpInfoManager,
):
instance = GeoIpInfoManager(pg_config=thl_web_rr, redis_config=thl_redis_config)
assert isinstance(instance, GeoIpInfoManager)
assert isinstance(geoipinfo_manager, GeoIpInfoManager)
- def test_multi(self, ip_information_factory, ip_geoname, geoipinfo_manager):
+ def test_multi(
+ self,
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
+ geoipinfo_manager: GeoIpInfoManager,
+ ):
ip = fake.ipv4_public()
ip_information_factory(ip=ip, geoname=ip_geoname)
ips = [ip]
@@ -90,7 +122,12 @@ class TestGeoIpInfoManager:
assert res[ip] is not None
assert res[ip2] is not None
- def test_multi_ipv6(self, ip_information_factory, ip_geoname, geoipinfo_manager):
+ def test_multi_ipv6(
+ self,
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
+ geoipinfo_manager: GeoIpInfoManager,
+ ):
ip = fake.ipv6()
# Make another IP that will be in the same /64 block.
ip2 = ip[:-1] + "a" if ip[-1] != "a" else ip[:-1] + "b"
@@ -105,13 +142,19 @@ class TestGeoIpInfoManager:
# Looks up in redis, if not exists, looks in mysql, then sets
# the caches that didn't exist.
res = geoipinfo_manager.get_multi(ip_addresses=ips)
- assert res[ip].ip == ip
- assert res[ip].lookup_prefix == "/64"
- assert res[ip2].ip == ip2
- assert res[ip2].lookup_prefix == "/64"
+
+ res1 = res[ip]
+ assert isinstance(res1, GeoIPInformation)
+ assert res1.ip == ip
+ assert res1.lookup_prefix == "/64"
+
+ res2 = res[ip2]
+ assert isinstance(res2, GeoIPInformation)
+ assert res2.ip == ip2
+ assert res2.lookup_prefix == "/64"
# they should be the same basically, except for the ip
- def test_doesnt_exist(self, geoipinfo_manager):
+ def test_doesnt_exist(self, geoipinfo_manager: GeoIpInfoManager):
ip = fake.ipv4_public()
res = geoipinfo_manager.get_multi(ip_addresses=[ip])
assert res == {ip: None}
diff --git a/tests/managers/thl/test_ledger/test_lm_accounts.py b/tests/managers/thl/test_ledger/test_lm_accounts.py
index 5cfaac1..3af10e7 100644
--- a/tests/managers/thl/test_ledger/test_lm_accounts.py
+++ b/tests/managers/thl/test_ledger/test_lm_accounts.py
@@ -1,9 +1,12 @@
+from __future__ import annotations
+
from itertools import product as iproduct
from random import randint
-from typing import TYPE_CHECKING, Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
+from pydantic import PositiveInt
from generalresearch.currency import LedgerCurrency
from generalresearch.managers.base import Permission
@@ -11,6 +14,7 @@ from generalresearch.managers.thl.ledger_manager.exceptions import (
LedgerAccountDoesntExistError,
)
from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+from generalresearch.models.custom_types import UUIDStr
from generalresearch.models.thl.ledger import (
AccountType,
Direction,
@@ -19,22 +23,10 @@ from generalresearch.models.thl.ledger import (
)
if TYPE_CHECKING:
- from pydantic import PositiveInt
- from generalresearch.config import GRLSettings
- from generalresearch.currency import LedgerCurrency
- from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
- from generalresearch.models.custom_types import AccountType, Direction, UUIDStr
- from generalresearch.models.thl import Direction
from generalresearch.models.thl.ledger import (
- AccountType,
- LedgerAccount,
LedgerTransaction,
)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.session import Session
- from generalresearch.models.thl.user import User
- from generalresearch.models.thl.wallet import PayoutType
@pytest.mark.parametrize(
@@ -51,53 +43,63 @@ class TestLedgerAccountManagerNoResults:
def test_get_account_no_results(
self,
- currency: "LedgerCurrency",
+ currency: LedgerCurrency,
kind: str,
- acct_id: "UUIDStr",
- lm: "LedgerManager",
+ acct_id: UUIDStr,
+ ledger_manager: LedgerManager,
):
"""Try to query for accounts that we know don't exist and confirm that
we either get the expected None result or it raises the correct
exception
"""
- qn = ":".join([currency, kind, acct_id])
+ qn = f"{currency}:{kind}:{acct_id}"
# (1) .get_account is just a wrapper for .get_account_many_ but
# call it either way
- assert lm.get_account(qualified_name=qn, raise_on_error=False) is None
+ assert (
+ ledger_manager.get_account(qualified_name=qn, raise_on_error=False) is None
+ )
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- lm.get_account(qualified_name=qn, raise_on_error=True)
+ ledger_manager.get_account(qualified_name=qn, raise_on_error=True)
# (2) .get_account_if_exists is another wrapper
- assert lm.get_account(qualified_name=qn, raise_on_error=False) is None
+ assert (
+ ledger_manager.get_account(qualified_name=qn, raise_on_error=False) is None
+ )
def test_get_account_no_results_many(
self,
- currency: "LedgerCurrency",
+ currency: LedgerCurrency,
kind: str,
- acct_id: "UUIDStr",
- lm: "LedgerManager",
+ acct_id: UUIDStr,
+ ledger_manager: LedgerManager,
):
- qn = ":".join([currency, kind, acct_id])
+ qn = f"{currency}:{kind}:{acct_id}"
# (1) .get_many_
- assert lm.get_account_many_(qualified_names=[qn], raise_on_error=False) == []
+ assert (
+ ledger_manager.get_account_many_(qualified_names=[qn], raise_on_error=False)
+ == []
+ )
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- lm.get_account_many_(qualified_names=[qn], raise_on_error=True)
+ ledger_manager.get_account_many_(qualified_names=[qn], raise_on_error=True)
# (2) .get_many
- assert lm.get_account_many(qualified_names=[qn], raise_on_error=False) == []
+ assert (
+ ledger_manager.get_account_many(qualified_names=[qn], raise_on_error=False)
+ == []
+ )
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- lm.get_account_many(qualified_names=[qn], raise_on_error=True)
+ ledger_manager.get_account_many(qualified_names=[qn], raise_on_error=True)
# (3) .get_accounts(..)
- assert lm.get_accounts_if_exists(qualified_names=[qn]) == []
+ assert ledger_manager.get_accounts_if_exists(qualified_names=[qn]) == []
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- lm.get_accounts(qualified_names=[qn])
+ ledger_manager.get_accounts(qualified_names=[qn])
@pytest.mark.parametrize(
@@ -114,10 +116,10 @@ class TestLedgerAccountManagerCreate:
def test_create_account_error_permission(
self,
- currency: "LedgerCurrency",
- account_type: "AccountType",
- direction: "Direction",
- lm: "LedgerManager",
+ currency: LedgerCurrency,
+ account_type: AccountType,
+ direction: Direction,
+ ledger_manager: LedgerManager,
):
"""Confirm that the Permission values that are set on the Ledger Manger
allow the Creation action to occur.
@@ -134,11 +136,11 @@ class TestLedgerAccountManagerCreate:
# (1) With no Permissions defined
test_lm = LedgerManager(
- pg_config=lm.pg_config,
+ pg_config=ledger_manager.pg_config,
permissions=[],
- redis_config=lm.redis_config,
- cache_prefix=lm.cache_prefix,
- testing=lm.testing,
+ redis_config=ledger_manager.redis_config,
+ cache_prefix=ledger_manager.cache_prefix,
+ testing=ledger_manager.testing,
)
with pytest.raises(expected_exception=AssertionError) as excinfo:
@@ -149,11 +151,11 @@ class TestLedgerAccountManagerCreate:
# (2) With Permissions defined, but not CREATE
test_lm = LedgerManager(
- pg_config=lm.pg_config,
+ pg_config=ledger_manager.pg_config,
permissions=[Permission.READ, Permission.UPDATE, Permission.DELETE],
- redis_config=lm.redis_config,
- cache_prefix=lm.cache_prefix,
- testing=lm.testing,
+ redis_config=ledger_manager.redis_config,
+ cache_prefix=ledger_manager.cache_prefix,
+ testing=ledger_manager.testing,
)
with pytest.raises(expected_exception=AssertionError) as excinfo:
@@ -164,10 +166,10 @@ class TestLedgerAccountManagerCreate:
def test_create(
self,
- currency: "LedgerCurrency",
- account_type: "AccountType",
- direction: "Direction",
- lm: "LedgerManager",
+ currency: LedgerCurrency,
+ account_type: AccountType,
+ direction: Direction,
+ ledger_manager: LedgerManager,
):
"""Confirm that the Permission values that are set on the Ledger Manger
allow the Creation action to occur.
@@ -184,20 +186,20 @@ class TestLedgerAccountManagerCreate:
account_type=account_type,
normal_balance=direction,
)
- account = lm.create_account(account=acct_model)
+ account = ledger_manager.create_account(account=acct_model)
assert isinstance(account, LedgerAccount)
# Query for, and make sure the Account was saved in the DB
- res = lm.get_account(qualified_name=qn, raise_on_error=True)
+ res = ledger_manager.get_account(qualified_name=qn, raise_on_error=True)
assert res is not None
assert account.uuid == res.uuid
def test_get_or_create(
self,
- currency: "LedgerCurrency",
- account_type: "AccountType",
- direction: "Direction",
- lm: "LedgerManager",
+ currency: LedgerCurrency,
+ account_type: AccountType,
+ direction: Direction,
+ ledger_manager: LedgerManager,
):
"""Confirm that the Permission values that are set on the Ledger Manger
allow the Creation action to occur.
@@ -214,27 +216,31 @@ class TestLedgerAccountManagerCreate:
account_type=account_type,
normal_balance=direction,
)
- account = lm.get_account_or_create(account=acct_model)
+ account = ledger_manager.get_account_or_create(account=acct_model)
assert isinstance(account, LedgerAccount)
# Query for, and make sure the Account was saved in the DB
- res = lm.get_account(qualified_name=qn, raise_on_error=True)
+ res = ledger_manager.get_account(qualified_name=qn, raise_on_error=True)
assert res is not None
assert account.uuid == res.uuid
class TestLedgerAccountManagerGet:
- def test_get(self, ledger_account: "LedgerAccount", lm: "LedgerManager"):
- res = lm.get_account(qualified_name=ledger_account.qualified_name)
+ def test_get(self, ledger_account: LedgerAccount, ledger_manager: LedgerManager):
+ res = ledger_manager.get_account(qualified_name=ledger_account.qualified_name)
assert res is not None
assert res.uuid == ledger_account.uuid
- res = lm.get_account_many(qualified_names=[ledger_account.qualified_name])
+ res = ledger_manager.get_account_many(
+ qualified_names=[ledger_account.qualified_name]
+ )
assert len(res) == 1
assert res[0].uuid == ledger_account.uuid
- res = lm.get_accounts(qualified_names=[ledger_account.qualified_name])
+ res = ledger_manager.get_accounts(
+ qualified_names=[ledger_account.qualified_name]
+ )
assert len(res) == 1
assert res[0].uuid == ledger_account.uuid
@@ -243,30 +249,30 @@ class TestLedgerAccountManagerGet:
def test_get_balance_empty(
self,
- ledger_account: "LedgerAccount",
- ledger_account_credit: "LedgerAccount",
- ledger_account_debit: "LedgerAccount",
- ledger_tx: "LedgerTransaction",
- lm: "LedgerManager",
+ ledger_account: LedgerAccount,
+ ledger_account_credit: LedgerAccount,
+ ledger_account_debit: LedgerAccount,
+ ledger_tx: LedgerTransaction,
+ ledger_manager: LedgerManager,
):
- res = lm.get_account_balance(account=ledger_account)
+ res = ledger_manager.get_account_balance(account=ledger_account)
assert res == 0
- res = lm.get_account_balance(account=ledger_account_credit)
+ res = ledger_manager.get_account_balance(account=ledger_account_credit)
assert res == 100
- res = lm.get_account_balance(account=ledger_account_debit)
+ res = ledger_manager.get_account_balance(account=ledger_account_debit)
assert res == 100
@pytest.mark.parametrize("n_times", range(5))
def test_get_account_filtered_balance(
self,
- ledger_account: "LedgerAccount",
- ledger_account_credit: "LedgerAccount",
- ledger_account_debit: "LedgerAccount",
- ledger_tx: "LedgerTransaction",
- n_times: "PositiveInt",
- lm: "LedgerManager",
+ ledger_account: LedgerAccount,
+ ledger_account_credit: LedgerAccount,
+ ledger_account_debit: LedgerAccount,
+ ledger_tx: LedgerTransaction,
+ n_times: PositiveInt,
+ ledger_manager: LedgerManager,
):
"""Try searching for random metadata and confirm it's always 0 because
Tx can be found.
@@ -275,7 +281,7 @@ class TestLedgerAccountManagerGet:
rand_value = uuid4().hex
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=ledger_account, metadata_key=rand_key, metadata_value=rand_value
)
== 0
@@ -285,7 +291,7 @@ class TestLedgerAccountManagerGet:
# and that we can filter it back
rand_amount = randint(10, 1_000)
- lm.create_tx(
+ ledger_manager.create_tx(
entries=[
LedgerEntry(
direction=Direction.CREDIT,
@@ -302,7 +308,7 @@ class TestLedgerAccountManagerGet:
)
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=ledger_account_credit,
metadata_key=rand_key,
metadata_value=rand_value,
@@ -311,7 +317,7 @@ class TestLedgerAccountManagerGet:
)
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=ledger_account_debit,
metadata_key=rand_key,
metadata_value=rand_value,
@@ -320,7 +326,7 @@ class TestLedgerAccountManagerGet:
)
def test_get_balance_timerange_empty(
- self, ledger_account: "LedgerAccount", lm: "LedgerManager"
+ self, ledger_account: LedgerAccount, ledger_manager: LedgerManager
):
- res = lm.get_account_balance_timerange(account=ledger_account)
+ res = ledger_manager.get_account_balance_timerange(account=ledger_account)
assert res == 0
diff --git a/tests/managers/thl/test_ledger/test_lm_tx.py b/tests/managers/thl/test_ledger/test_lm_tx.py
index 37b7ba3..025f6ac 100644
--- a/tests/managers/thl/test_ledger/test_lm_tx.py
+++ b/tests/managers/thl/test_ledger/test_lm_tx.py
@@ -1,33 +1,41 @@
+from __future__ import annotations
+
from decimal import Decimal
from random import randint
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.currency import LedgerCurrency
-from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+from generalresearch.managers.thl.ledger_manager.ledger import (
+ LedgerManager,
+)
from generalresearch.models.thl.ledger import (
Direction,
LedgerEntry,
LedgerTransaction,
)
+if TYPE_CHECKING:
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ )
+
class TestLedgerManagerCreateTx:
- def test_create_account_error_permission(self, lm):
+ def test_create_account_error_permission(self, ledger_manager: LedgerManager):
"""Confirm that the Permission values that are set on the Ledger Manger
allow the Creation action to occur.
"""
- acct_uuid = uuid4().hex
-
# (1) With no Permissions defined
test_lm = LedgerManager(
- pg_config=lm.pg_config,
+ pg_config=ledger_manager.pg_config,
permissions=[],
- redis_config=lm.redis_config,
- cache_prefix=lm.cache_prefix,
- testing=lm.testing,
+ redis_config=ledger_manager.redis_config,
+ cache_prefix=ledger_manager.cache_prefix,
+ testing=ledger_manager.testing,
)
with pytest.raises(expected_exception=AssertionError) as excinfo:
@@ -37,9 +45,12 @@ class TestLedgerManagerCreateTx:
== "LedgerTransactionManager has insufficient Permissions"
)
- def test_create_assertions(self, ledger_account_debit, ledger_account_credit, lm):
+ def test_create_assertions(
+ self,
+ ledger_manager: LedgerManager,
+ ):
with pytest.raises(expected_exception=ValueError) as excinfo:
- lm.create_tx(
+ ledger_manager.create_tx(
entries=[
{
"direction": Direction.CREDIT,
@@ -53,7 +64,12 @@ class TestLedgerManagerCreateTx:
in str(excinfo.value)
)
- def test_create(self, ledger_account_credit, ledger_account_debit, lm):
+ def test_create(
+ self,
+ ledger_account_credit: LedgerAccount,
+ ledger_account_debit: LedgerAccount,
+ ledger_manager: LedgerManager,
+ ):
amount = int(Decimal("1.00") * 100)
entries = [
@@ -70,15 +86,20 @@ class TestLedgerManagerCreateTx:
]
# Create a Transaction and validate the operation was successful
- tx = lm.create_tx(entries=entries)
+ tx = ledger_manager.create_tx(entries=entries)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert isinstance(res, LedgerTransaction)
assert len(res.entries) == 2
assert tx.id == res.id
- def test_create_and_reverse(self, ledger_account_credit, ledger_account_debit, lm):
+ def test_create_and_reverse(
+ self,
+ ledger_account_credit: LedgerAccount,
+ ledger_account_debit: LedgerAccount,
+ ledger_manager: LedgerManager,
+ ):
amount = int(Decimal("1.00") * 100)
entries = [
@@ -94,13 +115,13 @@ class TestLedgerManagerCreateTx:
),
]
- tx = lm.create_tx(entries=entries)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ tx = ledger_manager.create_tx(entries=entries)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.id == tx.id
- assert lm.get_account_balance(account=ledger_account_credit) == 100
- assert lm.get_account_balance(account=ledger_account_debit) == 100
- assert lm.check_ledger_balanced() is True
+ assert ledger_manager.get_account_balance(account=ledger_account_credit) == 100
+ assert ledger_manager.get_account_balance(account=ledger_account_debit) == 100
+ assert ledger_manager.check_ledger_balanced() is True
# Reverse it
entries = [
@@ -116,13 +137,13 @@ class TestLedgerManagerCreateTx:
),
]
- tx = lm.create_tx(entries=entries)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ tx = ledger_manager.create_tx(entries=entries)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.id == tx.id
- assert lm.get_account_balance(ledger_account_credit) == 0
- assert lm.get_account_balance(ledger_account_debit) == 0
- assert lm.check_ledger_balanced()
+ assert ledger_manager.get_account_balance(ledger_account_credit) == 0
+ assert ledger_manager.get_account_balance(ledger_account_debit) == 0
+ assert ledger_manager.check_ledger_balanced()
# subtract again
entries = [
@@ -137,52 +158,60 @@ class TestLedgerManagerCreateTx:
amount=amount,
),
]
- tx = lm.create_tx(entries=entries)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ tx = ledger_manager.create_tx(entries=entries)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.id == tx.id
- assert lm.get_account_balance(ledger_account_credit) == -100
- assert lm.get_account_balance(ledger_account_debit) == -100
- assert lm.check_ledger_balanced()
+ assert ledger_manager.get_account_balance(ledger_account_credit) == -100
+ assert ledger_manager.get_account_balance(ledger_account_debit) == -100
+ assert ledger_manager.check_ledger_balanced()
class TestLedgerManagerGetTx:
# @pytest.mark.parametrize("currency", [LedgerCurrency.TEST], indirect=True)
- def test_get_tx_by_id(self, ledger_tx, lm):
+ def test_get_tx_by_id(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
with pytest.raises(expected_exception=AssertionError):
- lm.get_tx_by_id(transaction_id=ledger_tx)
+ ledger_manager.get_tx_by_id(transaction_id=ledger_tx)
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert res.id == ledger_tx.id
# @pytest.mark.parametrize("currency", [LedgerCurrency.TEST], indirect=True)
- def test_get_tx_by_ids(self, ledger_tx, lm):
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ def test_get_tx_by_ids(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert res.id == ledger_tx.id
@pytest.mark.parametrize(
"tag", [f"{LedgerCurrency.TEST}:{uuid4().hex}"], indirect=True
)
- def test_get_tx_ids_by_tag(self, ledger_tx, tag, lm):
+ def test_get_tx_ids_by_tag(
+ self, ledger_tx: LedgerTransaction, tag: str, ledger_manager: LedgerManager
+ ):
# (1) search for a random tag
- res = lm.get_tx_ids_by_tag(tag="aaa:bbb")
+ res = ledger_manager.get_tx_ids_by_tag(tag="aaa:bbb")
assert isinstance(res, set)
assert len(res) == 0
# (2) search for the tag that was used during ledger_transaction creation
- res = lm.get_tx_ids_by_tag(tag=tag)
+ res = ledger_manager.get_tx_ids_by_tag(tag=tag)
assert isinstance(res, set)
assert len(res) == 1
- def test_get_tx_by_tag(self, ledger_tx, tag, lm):
+ def test_get_tx_by_tag(
+ self, ledger_tx: LedgerTransaction, tag: str, ledger_manager: LedgerManager
+ ):
# (1) search for a random tag
- res = lm.get_tx_by_tag(tag="aaa:bbb")
+ res = ledger_manager.get_tx_by_tag(tag="aaa:bbb")
assert isinstance(res, list)
assert len(res) == 0
# (2) search for the tag that was used during ledger_transaction creation
- res = lm.get_tx_by_tag(tag=tag)
+ res = ledger_manager.get_tx_by_tag(tag=tag)
assert isinstance(res, list)
assert len(res) == 1
@@ -190,42 +219,60 @@ class TestLedgerManagerGetTx:
assert ledger_tx.id == res[0].id
def test_get_tx_filtered_by_account(
- self, ledger_tx, ledger_account, ledger_account_debit, ledger_account_credit, lm
+ self,
+ ledger_tx: LedgerTransaction,
+ ledger_account: LedgerAccount,
+ ledger_account_debit: LedgerAccount,
+ ledger_account_credit: LedgerAccount,
+ ledger_manager: LedgerManager,
):
# (1) Do basic assertion checks first
with pytest.raises(expected_exception=AssertionError) as excinfo:
- lm.get_tx_filtered_by_account(account_uuid=ledger_account)
+ ledger_manager.get_tx_filtered_by_account(account_uuid=ledger_account)
assert str(excinfo.value) == "account_uuid must be a str"
# (2) This search doesn't return anything because this ledger account
# wasn't actually used in the entries for the ledger_transaction
- res = lm.get_tx_filtered_by_account(account_uuid=ledger_account.uuid)
+ res = ledger_manager.get_tx_filtered_by_account(
+ account_uuid=ledger_account.uuid
+ )
assert len(res) == 0
# (3) Either the credit or the debit example ledger_accounts wll work
# to find this transaction because they're both used in the entries
- res = lm.get_tx_filtered_by_account(account_uuid=ledger_account_debit.uuid)
+ res = ledger_manager.get_tx_filtered_by_account(
+ account_uuid=ledger_account_debit.uuid
+ )
assert len(res) == 1
assert res[0].id == ledger_tx.id
- res = lm.get_tx_filtered_by_account(account_uuid=ledger_account_credit.uuid)
+ res = ledger_manager.get_tx_filtered_by_account(
+ account_uuid=ledger_account_credit.uuid
+ )
assert len(res) == 1
assert ledger_tx.id == res[0].id
- res2 = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res2 = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert res2.model_dump_json() == res[0].model_dump_json()
- def test_filter_metadata(self, ledger_tx, tx_metadata, lm):
+ def test_filter_metadata(
+ self,
+ ledger_tx: LedgerTransaction,
+ tx_metadata: dict[str, str] | None,
+ ledger_manager: LedgerManager,
+ ):
key, value = next(iter(tx_metadata.items()))
# (1) Confirm a random key,value pair returns nothing
- res = lm.get_tx_filtered_by_metadata(
+ res = ledger_manager.get_tx_filtered_by_metadata(
metadata_key=f"key-{uuid4().hex[:10]}", metadata_value=uuid4().hex[:12]
)
assert len(res) == 0
# (2) confirm a key,value pair return the correct results
- res = lm.get_tx_filtered_by_metadata(metadata_key=key, metadata_value=value)
+ res = ledger_manager.get_tx_filtered_by_metadata(
+ metadata_key=key, metadata_value=value
+ )
assert len(res) == 1
# assert 0 == THL_lm.get_filtered_account_balance(account2, "thl_wall", "ccc")
diff --git a/tests/managers/thl/test_ledger/test_lm_tx_entries.py b/tests/managers/thl/test_ledger/test_lm_tx_entries.py
index 5bf1c48..03c6e02 100644
--- a/tests/managers/thl/test_ledger/test_lm_tx_entries.py
+++ b/tests/managers/thl/test_ledger/test_lm_tx_entries.py
@@ -1,25 +1,41 @@
-from generalresearch.models.thl.ledger import LedgerEntry
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from generalresearch.models.thl.ledger import (
+ LedgerEntry,
+)
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.models.thl.ledger import (
+ LedgerTransaction,
+ )
class TestLedgerEntryManager:
- def test_get_tx_entries_by_tx(self, ledger_tx, lm):
+ def test_get_tx_entries_by_tx(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
# First confirm the Ledger TX exists with 2 Entries
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert len(res.entries) == 2
- tx_entries = lm.get_tx_entries_by_tx(transaction=ledger_tx)
+ tx_entries = ledger_manager.get_tx_entries_by_tx(transaction=ledger_tx)
assert len(tx_entries) == 2
assert res.entries == tx_entries
assert isinstance(tx_entries[0], LedgerEntry)
- def test_get_tx_entries_by_txs(self, ledger_tx, lm):
+ def test_get_tx_entries_by_txs(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
# First confirm the Ledger TX exists with 2 Entries
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert len(res.entries) == 2
- tx_entries = lm.get_tx_entries_by_txs(transactions=[ledger_tx])
+ tx_entries = ledger_manager.get_tx_entries_by_txs(transactions=[ledger_tx])
assert len(tx_entries) == 2
assert res.entries == tx_entries
diff --git a/tests/managers/thl/test_ledger/test_lm_tx_locks.py b/tests/managers/thl/test_ledger/test_lm_tx_locks.py
index df2611b..166598e 100644
--- a/tests/managers/thl/test_ledger/test_lm_tx_locks.py
+++ b/tests/managers/thl/test_ledger/test_lm_tx_locks.py
@@ -1,29 +1,38 @@
+from __future__ import annotations
+
import logging
-from datetime import datetime, timezone, timedelta
+from collections.abc import Callable, Generator
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
-from typing import Callable
+from typing import TYPE_CHECKING
import pytest
+from pytest import LogCaptureFixture
from generalresearch.managers.thl.ledger_manager.conditions import (
generate_condition_mp_payment,
)
from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerTransactionCreateError,
LedgerTransactionCreateLockError,
LedgerTransactionFlagAlreadyExistsError,
- LedgerTransactionCreateError,
)
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.ledger import LedgerTransaction
from generalresearch.models.thl.session import (
- Wall,
+ Session,
Status,
StatusCode1,
- Session,
+ Wall,
WallAdjustedStatus,
)
-from generalresearch.models.thl.user import User
-from test_utils.models.conftest import user_factory, session, product_user_wallet_no
+
+if TYPE_CHECKING:
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
logger = logging.getLogger("LedgerManager")
@@ -32,17 +41,17 @@ class TestLedgerLocks:
def test_a(
self,
- user_factory,
- session_factory,
- product_user_wallet_no,
- create_main_accounts,
- caplog,
- thl_lm,
- lm,
- utc_hour_ago,
- currency,
- wall_factory,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ session_factory: Callable[..., Session],
+ product_user_wallet_no: Product,
+ create_main_accounts: Callable[..., None],
+ caplog: Generator[LogCaptureFixture],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ utc_hour_ago: datetime,
+ currency: LedgerCurrency,
+ wall_factory: Callable[..., Wall],
+ delete_ledger_db: Callable[..., None],
):
"""
TODO: This whole test is confusing a I don't really understand.
@@ -56,18 +65,22 @@ class TestLedgerLocks:
s1 = session_factory(
user=user,
wall_count=3,
- wall_req_cpis=[Decimal("1.23"), Decimal("3.21"), Decimal("4")],
+ wall_req_cpis=[Decimal("1.23"), Decimal("3.21"), Decimal(4)],
wall_statuses=[Status.COMPLETE, Status.COMPLETE, Status.COMPLETE],
)
# A User does a Wall Completion in Session=1
w1 = s1.wall_events[0]
- tx = thl_lm.create_tx_task_complete(wall=w1, user=user, created=w1.started)
+ tx = thl_ledger_manager.create_tx_task_complete(
+ wall=w1, user=user, created=w1.started
+ )
assert isinstance(tx, LedgerTransaction)
# A User does another Wall Completion in Session=1
w2 = s1.wall_events[1]
- tx = thl_lm.create_tx_task_complete(wall=w2, user=user, created=w2.started)
+ tx = thl_ledger_manager.create_tx_task_complete(
+ wall=w2, user=user, created=w2.started
+ )
assert isinstance(tx, LedgerTransaction)
# That first Wall Complete was "adjusted" to instead be marked
@@ -77,7 +90,7 @@ class TestLedgerLocks:
adjusted_cpi=0,
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
- tx = thl_lm.create_tx_task_adjustment(wall=w1, user=user)
+ tx = thl_ledger_manager.create_tx_task_adjustment(wall=w1, user=user)
assert isinstance(tx, LedgerTransaction)
# A User does another! Wall Completion in Session=1; however, we
@@ -86,60 +99,63 @@ class TestLedgerLocks:
# Make sure we clear any flags/locks first
lock_key = f"{currency.value}:thl_wall:{w3.uuid}"
- lock_name = f"{lm.cache_prefix}:transaction_lock:{lock_key}"
- flag_name = f"{lm.cache_prefix}:transaction_flag:{lock_key}"
- lm.redis_client.delete(lock_name)
- lm.redis_client.delete(flag_name)
+ lock_name = f"{ledger_manager.cache_prefix}:transaction_lock:{lock_key}"
+ flag_name = f"{ledger_manager.cache_prefix}:transaction_flag:{lock_key}"
+ ledger_manager.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(flag_name)
# Despite the
f1 = generate_condition_mp_payment(wall=w1)
f2 = generate_condition_mp_payment(wall=w2)
f3 = generate_condition_mp_payment(wall=w3)
- assert f1(lm=lm) is False
- assert f2(lm=lm) is False
- assert f3(lm=lm) is True
+ assert f1(ledger_manager) is False
+ assert f2(lm=ledger_manager) is False
+ assert f3(lm=ledger_manager) is True
condition = f3
- create_tx_func = lambda: thl_lm.create_tx_task_complete_(wall=w3, user=user)
+ create_tx_func = lambda: thl_ledger_manager.create_tx_task_complete_(
+ wall=w3, user=user
+ )
assert isinstance(create_tx_func, Callable)
- assert f3(lm) is True
+ assert f3(ledger_manager) is True
- lm.redis_client.delete(flag_name)
- lm.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(flag_name)
+ ledger_manager.redis_client.delete(lock_name)
- tx = thl_lm.create_tx_protected(
+ tx = thl_ledger_manager.create_tx_protected(
lock_key=lock_key, condition=condition, create_tx_func=create_tx_func
)
- assert f3(lm) is False
+ assert f3(ledger_manager) is False
# purposely hold the lock open
tx = None
- lm.redis_client.set(lock_name, "1")
- with caplog.at_level(logging.ERROR):
- with pytest.raises(expected_exception=LedgerTransactionCreateLockError):
- tx = thl_lm.create_tx_protected(
- lock_key=lock_key,
- condition=condition,
- create_tx_func=create_tx_func,
- )
- assert tx is None
+ ledger_manager.redis_client.set(lock_name, "1")
+ with caplog.at_level(logging.ERROR), pytest.raises(
+ expected_exception=LedgerTransactionCreateLockError
+ ):
+ tx = thl_ledger_manager.create_tx_protected(
+ lock_key=lock_key,
+ condition=condition,
+ create_tx_func=create_tx_func,
+ )
+ assert tx is None
assert "Unable to acquire lock within the time specified" in caplog.text
- lm.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(lock_name)
def test_locking(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
- delete_ledger_db,
- caplog,
- thl_lm,
- lm,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ create_main_accounts: Callable[..., None],
+ delete_ledger_db: Callable[..., None],
+ caplog: Generator[LogCaptureFixture],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
delete_ledger_db()
create_main_accounts()
- now = datetime.now(timezone.utc) - timedelta(hours=1)
+ now = datetime.now(UTC) - timedelta(hours=1)
user: User = user_factory(product=product_user_wallet_no)
# A User does a Wall complete on Session.id=1 and the transaction is
@@ -155,7 +171,9 @@ class TestLedgerLocks:
started=now,
finished=now + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall=wall1, user=user, created=wall1.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall1, user=user, created=wall1.started
+ )
# A User does a Wall complete on Session.id=1 and the transaction is
# logged to the ledger
@@ -170,7 +188,9 @@ class TestLedgerLocks:
started=now,
finished=now + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall=wall2, user=user, created=wall2.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall2, user=user, created=wall2.started
+ )
# An hour later, the first wall complete is adjusted to a Failure and
# it's tracked in the ledger
@@ -179,7 +199,7 @@ class TestLedgerLocks:
adjusted_cpi=0,
adjusted_timestamp=now + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall=wall1, user=user)
+ thl_ledger_manager.create_tx_task_adjustment(wall=wall1, user=user)
# A User does a Wall complete on Session.id=1 and the transaction
# IS NOT logged to the ledger
@@ -187,7 +207,7 @@ class TestLedgerLocks:
user_id=user.user_id,
source=Source.DYNATA,
req_survey_id="xxx",
- req_cpi=Decimal("4"),
+ req_cpi=Decimal(4),
session_id=1,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
@@ -196,52 +216,53 @@ class TestLedgerLocks:
uuid="867a282d8b4d40d2a2093d75b802b629",
)
- revenue_account = thl_lm.get_account_task_complete_revenue()
- assert 0 == thl_lm.get_account_filtered_balance(
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ assert 0 == thl_ledger_manager.get_account_filtered_balance(
account=revenue_account,
metadata_key="thl_wall",
metadata_value=wall3.uuid,
)
# Make sure we clear any flags/locks first
lock_key = f"test:thl_wall:{wall3.uuid}"
- lock_name = f"{lm.cache_prefix}:transaction_lock:{lock_key}"
- flag_name = f"{lm.cache_prefix}:transaction_flag:{lock_key}"
- lm.redis_client.delete(lock_name)
- lm.redis_client.delete(flag_name)
+ lock_name = f"{ledger_manager.cache_prefix}:transaction_lock:{lock_key}"
+ flag_name = f"{ledger_manager.cache_prefix}:transaction_flag:{lock_key}"
+ ledger_manager.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(flag_name)
# Purposely hold the lock open
- lm.redis_client.set(name=lock_name, value="1")
- with caplog.at_level(logging.DEBUG):
- with pytest.raises(expected_exception=LedgerTransactionCreateLockError):
- tx = thl_lm.create_tx_task_complete(
- wall=wall3, user=user, created=wall3.started
- )
- assert isinstance(tx, LedgerTransaction)
+ ledger_manager.redis_client.set(name=lock_name, value="1")
+ with caplog.at_level(logging.DEBUG), pytest.raises(
+ expected_exception=LedgerTransactionCreateLockError
+ ):
+ tx = thl_ledger_manager.create_tx_task_complete(
+ wall=wall3, user=user, created=wall3.started
+ )
+ assert isinstance(tx, LedgerTransaction)
assert "Unable to acquire lock within the time specified" in caplog.text
# Release the lock
- lm.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(lock_name)
# Set the redis flag to indicate it has been run
- lm.redis_client.set(flag_name, "1")
+ ledger_manager.redis_client.set(flag_name, "1")
# with self.assertLogs(logger=logger, level=logging.DEBUG) as cm2:
with pytest.raises(expected_exception=LedgerTransactionFlagAlreadyExistsError):
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall3, user=user, created=wall3.started
)
# self.assertIn("entered_lock: True, flag_set: True", cm2.output[0])
# Unset the flag
- lm.redis_client.delete(flag_name)
+ ledger_manager.redis_client.delete(flag_name)
- assert 0 == lm.get_account_filtered_balance(
+ assert 0 == ledger_manager.get_account_filtered_balance(
account=revenue_account,
metadata_key="thl_wall",
metadata_value=wall3.uuid,
)
# Now actually run it
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall3, user=user, created=wall3.started
)
assert tx is not None
@@ -250,29 +271,34 @@ class TestLedgerLocks:
# Confirm the Exception inheritance works
tx = None
with pytest.raises(expected_exception=LedgerTransactionCreateError):
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall3, user=user, created=wall3.started
)
assert tx is None
# clear the redis flag, it should query the db
- assert lm.redis_client.get(flag_name) is not None
- lm.redis_client.delete(flag_name)
- assert lm.redis_client.get(flag_name) is None
+ assert ledger_manager.redis_client.get(flag_name) is not None
+ ledger_manager.redis_client.delete(flag_name)
+ assert ledger_manager.redis_client.get(flag_name) is None
with pytest.raises(expected_exception=LedgerTransactionCreateError):
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall3, user=user, created=wall3.started
)
- assert 400 == thl_lm.get_account_filtered_balance(
+ assert 400 == thl_ledger_manager.get_account_filtered_balance(
account=revenue_account,
metadata_key="thl_wall",
metadata_value=wall3.uuid,
)
def test_bp_payment_without_locks(
- self, user_factory, product_user_wallet_no, create_main_accounts, thl_lm, lm
+ self,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
user: User = user_factory(product=product_user_wallet_no)
wall1 = Wall(
@@ -283,39 +309,46 @@ class TestLedgerLocks:
session_id=3,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall=wall1, user=user, created=wall1.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall1, user=user, created=wall1.started
+ )
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": session.started + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=session.started + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
print(thl_net, commission_amount, bp_pay, user_pay)
# Run it 3 times without any checks, and it gets made three times!
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
- thl_lm.create_tx_bp_payment_(session=session, created=wall1.started)
- thl_lm.create_tx_bp_payment_(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment_(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment_(session=session, created=wall1.started)
- bp_wallet = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- assert 48 * 3 == lm.get_account_balance(account=bp_wallet)
- assert 48 * 3 == thl_lm.get_account_filtered_balance(
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
+ assert 48 * 3 == ledger_manager.get_account_balance(account=bp_wallet)
+ assert 48 * 3 == thl_ledger_manager.get_account_filtered_balance(
account=bp_wallet, metadata_key="thl_session", metadata_value=session.uuid
)
- assert lm.check_ledger_balanced()
+ assert ledger_manager.check_ledger_balanced()
def test_bp_payment_with_locks(
- self, user_factory, product_user_wallet_no, create_main_accounts, thl_lm, lm
+ self,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
user: User = user_factory(product=product_user_wallet_no)
@@ -327,45 +360,49 @@ class TestLedgerLocks:
session_id=3,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall1, user, created=wall1.started)
+ thl_ledger_manager.create_tx_task_complete(wall1, user, created=wall1.started)
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": session.started + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=session.started + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
print(thl_net, commission_amount, bp_pay, user_pay)
# Make sure we clear any flags/locks first
lock_key = f"test:thl_wall:{wall1.uuid}"
- lock_name = f"{lm.cache_prefix}:transaction_lock:{lock_key}"
- flag_name = f"{lm.cache_prefix}:transaction_flag:{lock_key}"
- lm.redis_client.delete(lock_name)
- lm.redis_client.delete(flag_name)
+ lock_name = f"{ledger_manager.cache_prefix}:transaction_lock:{lock_key}"
+ flag_name = f"{ledger_manager.cache_prefix}:transaction_flag:{lock_key}"
+ ledger_manager.redis_client.delete(lock_name)
+ ledger_manager.redis_client.delete(flag_name)
# Run it 3 times with check, and it gets made once!
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=session, created=wall1.started)
with pytest.raises(expected_exception=LedgerTransactionCreateError):
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(
+ session=session, created=wall1.started
+ )
with pytest.raises(expected_exception=LedgerTransactionCreateError):
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(
+ session=session, created=wall1.started
+ )
- bp_wallet = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- assert 48 == thl_lm.get_account_balance(bp_wallet)
- assert 48 == thl_lm.get_account_filtered_balance(
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
+ assert 48 == thl_ledger_manager.get_account_balance(bp_wallet)
+ assert 48 == thl_ledger_manager.get_account_filtered_balance(
account=bp_wallet,
metadata_key="thl_session",
metadata_value=session.uuid,
)
- assert lm.check_ledger_balanced()
+ assert ledger_manager.check_ledger_balanced()
diff --git a/tests/managers/thl/test_ledger/test_lm_tx_metadata.py b/tests/managers/thl/test_ledger/test_lm_tx_metadata.py
index 5d12633..3d8cf89 100644
--- a/tests/managers/thl/test_ledger/test_lm_tx_metadata.py
+++ b/tests/managers/thl/test_ledger/test_lm_tx_metadata.py
@@ -1,34 +1,55 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.ledger import (
+ LedgerManager,
+ LedgerTransaction,
+ )
+
+
class TestLedgerMetadataManager:
- def test_get_tx_metadata_by_txs(self, ledger_tx, lm):
+ def test_get_tx_metadata_by_txs(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
# First confirm the Ledger TX exists with 2 Entries
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
assert isinstance(res.metadata, dict)
- tx_metadatas = lm.get_tx_metadata_by_txs(transactions=[ledger_tx])
+ tx_metadatas = ledger_manager.get_tx_metadata_by_txs(transactions=[ledger_tx])
assert isinstance(tx_metadatas, dict)
assert isinstance(tx_metadatas[ledger_tx.id], dict)
assert res.metadata == tx_metadatas[ledger_tx.id]
- def test_get_tx_metadata_ids_by_tx(self, ledger_tx, lm):
+ def test_get_tx_metadata_ids_by_tx(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
# First confirm the Ledger TX exists with 2 Entries
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
tx_metadata_cnt = len(res.metadata.keys())
- tx_metadata_ids = lm.get_tx_metadata_ids_by_tx(transaction=ledger_tx)
+ tx_metadata_ids = ledger_manager.get_tx_metadata_ids_by_tx(
+ transaction=ledger_tx
+ )
assert isinstance(tx_metadata_ids, set)
- assert isinstance(list(tx_metadata_ids)[0], int)
+ assert isinstance(next(iter(tx_metadata_ids)), int)
assert tx_metadata_cnt == len(tx_metadata_ids)
- def test_get_tx_metadata_ids_by_txs(self, ledger_tx, lm):
+ def test_get_tx_metadata_ids_by_txs(
+ self, ledger_tx: LedgerTransaction, ledger_manager: LedgerManager
+ ):
# First confirm the Ledger TX exists with 2 Entries
- res = lm.get_tx_by_id(transaction_id=ledger_tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=ledger_tx.id)
tx_metadata_cnt = len(res.metadata.keys())
- tx_metadata_ids = lm.get_tx_metadata_ids_by_txs(transactions=[ledger_tx])
+ tx_metadata_ids = ledger_manager.get_tx_metadata_ids_by_txs(
+ transactions=[ledger_tx]
+ )
assert isinstance(tx_metadata_ids, set)
- assert isinstance(list(tx_metadata_ids)[0], int)
+ assert isinstance(next(iter(tx_metadata_ids)), int)
assert tx_metadata_cnt == len(tx_metadata_ids)
diff --git a/tests/managers/thl/test_ledger/test_thl_lm_accounts.py b/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
index 01d5fe1..107ff00 100644
--- a/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
+++ b/tests/managers/thl/test_ledger/test_thl_lm_accounts.py
@@ -1,19 +1,41 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
+from generalresearch.currency import LedgerCurrency
+from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerAccountDoesntExistError,
+)
+from generalresearch.models.thl.ledger import (
+ AccountType,
+ Direction,
+ LedgerAccount,
+)
+from generalresearch.models.thl.product import Product
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.ledger import (
+ LedgerAccountManager,
+ LedgerManager,
+ )
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.models.thl.user import User
+
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,
- )
+ def test_get_account_or_create_user_wallet(
+ self,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
- account = thl_lm.get_account_or_create_user_wallet(user=user)
+ account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
assert isinstance(account, LedgerAccount)
assert user.uuid in account.qualified_name
@@ -25,18 +47,20 @@ class TestThlLedgerManagerAccounts:
assert account.currency == LedgerCurrency.TEST
# Actually query for it to confirm
- res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ res = ledger_manager.get_account(
+ qualified_name=account.qualified_name, raise_on_error=True
+ )
+ assert isinstance(res, LedgerAccount)
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,
- )
+ def test_get_account_or_create_bp_wallet(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
- account = thl_lm.get_account_or_create_bp_wallet(product=product)
+ account = thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
assert isinstance(account, LedgerAccount)
assert product.uuid in account.qualified_name
@@ -48,17 +72,22 @@ class TestThlLedgerManagerAccounts:
assert account.currency == LedgerCurrency.TEST
# Actually query for it to confirm
- res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ res = ledger_manager.get_account(
+ qualified_name=account.qualified_name, raise_on_error=True
+ )
+ assert isinstance(res, LedgerAccount)
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,
- )
+ def test_get_account_or_create_bp_commission(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
- account = thl_lm.get_account_or_create_bp_commission(product=product)
+ account = thl_ledger_manager.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}"
@@ -69,18 +98,21 @@ class TestThlLedgerManagerAccounts:
assert account.currency == LedgerCurrency.TEST
# Actually query for it to confirm
- res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ res = ledger_manager.get_account(
+ qualified_name=account.qualified_name, raise_on_error=True
+ )
+ assert isinstance(res, LedgerAccount)
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(
+ def test_get_account_or_create_bp_expense(
+ self,
+ product: Product,
+ expense,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
+ account = thl_ledger_manager.get_account_or_create_bp_expense(
product=product, expense_name=expense
)
assert product.uuid in account.qualified_name
@@ -92,17 +124,22 @@ class TestThlLedgerManagerAccounts:
assert account.currency == LedgerCurrency.TEST
# Actually query for it to confirm
- res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ res = ledger_manager.get_account(
+ qualified_name=account.qualified_name, raise_on_error=True
+ )
+ assert isinstance(res, LedgerAccount)
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,
- )
+ def test_get_or_create_bp_pending_payout_account(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
- account = thl_lm.get_or_create_bp_pending_payout_account(product=product)
+ account = thl_ledger_manager.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}"
@@ -113,11 +150,17 @@ class TestThlLedgerManagerAccounts:
assert account.currency == LedgerCurrency.TEST
# Actually query for it to confirm
- res = lm.get_account(qualified_name=account.qualified_name, raise_on_error=True)
+ res = ledger_manager.get_account(
+ qualified_name=account.qualified_name, raise_on_error=True
+ )
+ assert isinstance(res, LedgerAccount)
assert res.model_dump_json() == account.model_dump_json()
def test_get_account_task_complete_revenue_raises(
- self, delete_ledger_db, thl_lm, lm
+ self,
+ delete_ledger_db: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
from generalresearch.managers.thl.ledger_manager.exceptions import (
LedgerAccountDoesntExistError,
@@ -126,63 +169,79 @@ class TestThlLedgerManagerAccounts:
delete_ledger_db()
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- thl_lm.get_account_task_complete_revenue()
+ thl_ledger_manager.get_account_task_complete_revenue()
def test_get_account_task_complete_revenue(
- self, account_cash, account_revenue_task_complete, thl_lm, lm
+ self, thl_ledger_manager: ThlLedgerManager, create_main_accounts
):
from generalresearch.models.thl.ledger import (
- LedgerAccount,
AccountType,
+ LedgerAccount,
)
- res = thl_lm.get_account_task_complete_revenue()
+ create_main_accounts()
+
+ res = thl_ledger_manager.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,
- )
+ def test_get_account_cash_raises(
+ self,
+ delete_ledger_db: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ):
delete_ledger_db()
with pytest.raises(expected_exception=LedgerAccountDoesntExistError):
- thl_lm.get_account_cash()
+ thl_ledger_manager.get_account_cash()
- def test_get_account_cash(self, account_cash, thl_lm, lm):
+ def test_get_account_cash(
+ self,
+ thl_ledger_manager: ThlLedgerManager,
+ create_main_accounts
+ ):
+ create_main_accounts()
from generalresearch.models.thl.ledger import (
- LedgerAccount,
AccountType,
+ LedgerAccount,
)
- res = thl_lm.get_account_cash()
+ res = thl_ledger_manager.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,
- )
+ def test_get_accounts(
+ self,
+ setup_accounts: Callable[..., None],
+ product: Product,
+ user_factory: Callable[..., User],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ledger_account_manager: LedgerAccountManager,
+ ):
+ setup_accounts()
- user1: User = user_factory(product=product)
- user2: User = user_factory(product=product)
+ _: User = user_factory(product=product)
+ _: User = user_factory(product=product)
- account1 = thl_lm.get_account_or_create_bp_wallet(product=product)
+ account1 = thl_ledger_manager.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)
+ res = ledger_manager.get_account(qualified_name=account1.qualified_name)
+ assert isinstance(res, LedgerAccount)
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])
+ res = ledger_account_manager.get_accounts(
+ qualified_names=[account1.qualified_name]
+ )
assert isinstance(res, list)
assert len(res) == 1
assert account1 in res
@@ -190,28 +249,34 @@ class TestThlLedgerManagerAccounts:
# Get 2 known and 1 made up qualified names, and confirm it raises
# an error
with pytest.raises(LedgerAccountDoesntExistError):
- lam.get_accounts(
+ ledger_account_manager.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
+ def test_get_accounts_if_exists(
+ self,
+ product_factory: Callable[..., Product],
+ currency: LedgerCurrency,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
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)
+ account1 = thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ account2 = thl_ledger_manager.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)
+ res = ledger_manager.get_account(qualified_name=account1.qualified_name)
+ assert isinstance(res, LedgerAccount)
assert account1.model_dump_json() == res.model_dump_json()
# (2) known accounts and confirm they both come back
- res = lm.get_accounts(
+ res = ledger_manager.get_accounts(
qualified_names=[account1.qualified_name, account2.qualified_name]
)
assert isinstance(res, list)
@@ -221,7 +286,7 @@ class TestThlLedgerManagerAccounts:
# Get 2 known and 1 made up qualified names, and confirm only 2
# come back
- lm.get_accounts_if_exists(
+ ledger_manager.get_accounts_if_exists(
qualified_names=[
account1.qualified_name,
account2.qualified_name,
@@ -233,53 +298,50 @@ class TestThlLedgerManagerAccounts:
assert len(res) == 2
# Confirm an empty array comes back for all unknown qualified names
- res = lm.get_accounts_if_exists(
+ assert isinstance(ledger_manager.currency, LedgerCurrency)
+ res = ledger_manager.get_accounts_if_exists(
qualified_names=[
- f"{lm.currency.value}:bp_wall:{uuid4().hex}" for i in range(5)
+ f"{ledger_manager.currency.value}:bp_wall:{uuid4().hex}"
+ for _ 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,
- )
-
+ def test_get_accounts_for_products(
+ self,
+ product_factory: Callable[..., Product],
+ thl_ledger_manager: ThlLedgerManager,
+ ):
# Create 5 Products
product_uuids = []
- for i in range(5):
+ for _ 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)
+ thl_ledger_manager.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)
+ thl_ledger_manager.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)
+ res = thl_ledger_manager.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])
+ 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,
- )
+ def test_get_or_create(self, ledger_account_manager: LedgerAccountManager):
u = uuid4().hex
name = f"test-{u[:8]}"
@@ -297,48 +359,52 @@ class TestLedgerAccountManager:
# 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)
+ ledger_account_manager.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)
+ instance = ledger_account_manager.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,
- )
+ def test_get(
+ self,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_account_manager: LedgerAccountManager,
+ ):
+
+ assert isinstance(user.product, Product)
with pytest.raises(LedgerAccountDoesntExistError):
- lam.get_account(qualified_name=f"test:bp_wallet:{user.product.id}")
+ ledger_account_manager.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}")
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=user.product)
+ account = ledger_account_manager.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,
- )
-
+ def test_get_many(
+ self,
+ product_factory: Callable[..., Product],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_account_manager: LedgerAccountManager,
+ ):
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)
+ account1 = thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ account2 = thl_ledger_manager.get_account_or_create_bp_wallet(product=p2)
# Get 1 known account and confirm it comes back
- res = lam.get_account_many(
+ res = ledger_account_manager.get_account_many(
qualified_names=[account1.qualified_name, account2.qualified_name]
)
assert isinstance(res, list)
@@ -346,7 +412,7 @@ class TestLedgerAccountManager:
assert account1 in res
# Get 2 known accounts and confirm they both come back
- res = lam.get_account_many(
+ res = ledger_account_manager.get_account_many(
qualified_names=[account1.qualified_name, account2.qualified_name]
)
assert isinstance(res, list)
@@ -356,7 +422,7 @@ class TestLedgerAccountManager:
# 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(
+ res = ledger_account_manager.get_account_many(
qualified_names=[
account1.qualified_name,
account2.qualified_name,
@@ -369,7 +435,7 @@ class TestLedgerAccountManager:
# Same as above, but confirm the raise works on checking res length
with pytest.raises(LedgerAccountDoesntExistError):
- lam.get_account_many(
+ ledger_account_manager.get_account_many(
qualified_names=[
account1.qualified_name,
account2.qualified_name,
@@ -379,19 +445,14 @@ class TestLedgerAccountManager:
)
# 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)],
+ res = ledger_account_manager.get_account_many(
+ qualified_names=[f"test:bp_wall:{uuid4().hex}" for _ 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,
- )
+ def test_create_account(self, ledger_account_manager: LedgerAccountManager):
u = uuid4().hex
name = f"test-{u[:8]}"
@@ -406,6 +467,6 @@ class TestLedgerAccountManager:
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
+ ledger_account_manager.create_account(account=account)
+ assert ledger_account_manager.get_account(f"test:bp_wallet:{u}") == account
+ assert ledger_account_manager.get_account_or_create(account) == account
diff --git a/tests/managers/thl/test_ledger/test_thl_lm_bp_payout.py b/tests/managers/thl/test_ledger/test_thl_lm_bp_payout.py
index 294d092..27ddc29 100644
--- a/tests/managers/thl/test_ledger/test_thl_lm_bp_payout.py
+++ b/tests/managers/thl/test_ledger/test_thl_lm_bp_payout.py
@@ -1,7 +1,11 @@
+from __future__ import annotations
+
import logging
-from datetime import datetime, timezone, timedelta
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
from random import randint
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
@@ -11,27 +15,35 @@ from redis.lock import Lock
from generalresearch.currency import USDCent
from generalresearch.managers.base import Permission
-from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
from generalresearch.managers.thl.ledger_manager.exceptions import (
- LedgerTransactionFlagAlreadyExistsError,
LedgerTransactionConditionFailedError,
- LedgerTransactionReleaseLockError,
LedgerTransactionCreateError,
+ LedgerTransactionFlagAlreadyExistsError,
+ LedgerTransactionReleaseLockError,
)
from generalresearch.managers.thl.ledger_manager.ledger import LedgerTransaction
-from generalresearch.models import Source
+from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.definitions import PayoutStatus
from generalresearch.models.thl.ledger import Direction, TransactionType
from generalresearch.models.thl.session import (
- Wall,
+ Session,
Status,
StatusCode1,
- Session,
+ Wall,
)
-from generalresearch.models.thl.user import User
-from generalresearch.models.thl.wallet import PayoutType
from generalresearch.redis_helper import RedisConfig
+if TYPE_CHECKING:
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.managers.thl.payout import (
+ BrokerageProductPayoutEventManager,
+ BusinessPayoutEventManager,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
+ from generalresearch.pg_helper import PostgresConfig
+
def broken_acquire(self, *args, **kwargs):
raise redis.exceptions.TimeoutError("Simulated timeout during acquire")
@@ -42,20 +54,18 @@ def broken_release(self, *args, **kwargs):
class TestThlLedgerManagerBPPayout:
+ @pytest.fixture(autouse=True)
+ def setup(self, create_main_accounts):
+ create_main_accounts()
def test_create_tx_with_bp_payment(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
caplog,
- thl_lm,
- delete_ledger_db,
+ thl_ledger_manager: ThlLedgerManager,
):
- delete_ledger_db()
- create_main_accounts()
-
- now = datetime.now(timezone.utc) - timedelta(hours=1)
+ now = datetime.now(UTC) - timedelta(hours=1)
user: User = user_factory(product=product_user_wallet_no)
wall1 = Wall(
@@ -69,31 +79,29 @@ class TestThlLedgerManagerBPPayout:
started=now,
finished=now + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
assert isinstance(tx, LedgerTransaction)
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
+ _, _, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": now + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=now + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=session, created=wall1.started)
lock_key = f"test:bp_payout:{user.product.id}"
- flag_name = f"{thl_lm.cache_prefix}:transaction_flag:{lock_key}"
- thl_lm.redis_client.delete(flag_name)
+ flag_name = f"{thl_ledger_manager.cache_prefix}:transaction_flag:{lock_key}"
+ thl_ledger_manager.redis_client.delete(flag_name)
payoutevent_uuid = uuid4().hex
- thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=user.product,
amount=USDCent(200),
created=now,
@@ -101,7 +109,7 @@ class TestThlLedgerManagerBPPayout:
)
payoutevent_uuid = uuid4().hex
- thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=user.product,
amount=USDCent(200),
created=now + timedelta(minutes=2),
@@ -109,13 +117,15 @@ class TestThlLedgerManagerBPPayout:
payoutevent_uuid=payoutevent_uuid,
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- assert 170 == thl_lm.get_account_balance(bp_wallet_account)
- assert 200 == thl_lm.get_account_balance(cash)
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ assert 170 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 200 == thl_ledger_manager.get_account_balance(cash)
with pytest.raises(expected_exception=LedgerTransactionFlagAlreadyExistsError):
- thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
user.product,
amount=USDCent(200),
created=now + timedelta(minutes=2),
@@ -125,19 +135,21 @@ class TestThlLedgerManagerBPPayout:
)
payoutevent_uuid = uuid4().hex
- with caplog.at_level(logging.INFO):
- with pytest.raises(LedgerTransactionConditionFailedError):
- thl_lm.create_tx_bp_payout(
- user.product,
- amount=USDCent(10_000),
- created=now + timedelta(minutes=2),
- skip_one_per_day_check=True,
- skip_wallet_balance_check=False,
- payoutevent_uuid=payoutevent_uuid,
- )
+ with (
+ caplog.at_level(logging.INFO),
+ pytest.raises(LedgerTransactionConditionFailedError),
+ ):
+ thl_ledger_manager.create_tx_bp_payout(
+ user.product,
+ amount=USDCent(10_000),
+ created=now + timedelta(minutes=2),
+ skip_one_per_day_check=True,
+ skip_wallet_balance_check=False,
+ payoutevent_uuid=payoutevent_uuid,
+ )
assert "failed condition check balance:" in caplog.text
- thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=user.product,
amount=USDCent(10_00),
created=now + timedelta(minutes=2),
@@ -145,20 +157,26 @@ class TestThlLedgerManagerBPPayout:
skip_wallet_balance_check=True,
payoutevent_uuid=payoutevent_uuid,
)
- assert 170 - 1000 == thl_lm.get_account_balance(bp_wallet_account)
+ assert 170 - 1000 == thl_ledger_manager.get_account_balance(bp_wallet_account)
- def test_create_tx(self, product, caplog, thl_lm, currency):
+ def test_create_tx(
+ self,
+ product: Product,
+ caplog,
+ thl_ledger_manager: ThlLedgerManager,
+ currency: LedgerCurrency,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
# Create a BP Payout for a Product without any activity. By issuing,
# the skip_* checks, we should be able to force it to work, and will
# then ultimately result in a negative balance
- tx = thl_lm.create_tx_bp_payout(
+ tx = thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
skip_wallet_balance_check=True,
skip_one_per_day_check=True,
skip_flag_check=True,
@@ -177,31 +195,38 @@ class TestThlLedgerManagerBPPayout:
# Check the Product's balance, it should be negative the amount that was
# paid out. That's because the Product earned nothing.. and then was
# sent something.
- balance = thl_lm.get_account_balance(
- account=thl_lm.get_account_or_create_bp_wallet(product=product)
+ balance = thl_ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
)
assert balance == int(rand_amount) * -1
# Test some basic assertions
- with caplog.at_level(logging.INFO):
- with pytest.raises(expected_exception=Exception):
- thl_lm.create_tx_bp_payout(
- product=product,
- amount=rand_amount,
- payoutevent_uuid=uuid4().hex,
- created=datetime.now(tz=timezone.utc),
- skip_wallet_balance_check=False,
- skip_one_per_day_check=False,
- skip_flag_check=False,
- )
+ with (
+ caplog.at_level(logging.INFO),
+ pytest.raises(expected_exception=LedgerTransactionConditionFailedError),
+ ):
+ thl_ledger_manager.create_tx_bp_payout(
+ product=product,
+ amount=rand_amount,
+ payoutevent_uuid=uuid4().hex,
+ created=datetime.now(tz=UTC),
+ skip_wallet_balance_check=False,
+ skip_one_per_day_check=False,
+ skip_flag_check=False,
+ )
assert "failed condition check >1 tx per day" in caplog.text
- def test_create_tx_redis_failure(self, product, thl_web_rw, thl_lm):
+ def test_create_tx_redis_failure(
+ self,
+ product: Product,
+ thl_web_rw: PostgresConfig,
+ thl_ledger_manager: ThlLedgerManager,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
- thl_lm.create_tx_plug_bp_wallet(
+ thl_ledger_manager.create_tx_plug_bp_wallet(
product, rand_amount, now, direction=Direction.CREDIT
)
@@ -222,43 +247,49 @@ class TestThlLedgerManagerBPPayout:
)
with pytest.raises(expected_exception=Exception) as e:
- tx = thl_lm_redis_0.create_tx_bp_payout(
+ thl_lm_redis_0.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
)
assert e.type is redis.exceptions.TimeoutError
# No txs were created
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=product)
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 0
- def test_create_tx_multiple_per_day(self, product, thl_lm):
+ def test_create_tx_multiple_per_day(
+ self, product: Product, thl_ledger_manager: ThlLedgerManager
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
- thl_lm.create_tx_plug_bp_wallet(
+ thl_ledger_manager.create_tx_plug_bp_wallet(
product, rand_amount * USDCent(2), now, direction=Direction.CREDIT
)
- tx = thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
)
# Try to create another
# Will fail b/c it has the same payout event uuid
with pytest.raises(expected_exception=Exception) as e:
- tx = thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
)
assert e.type is LedgerTransactionFlagAlreadyExistsError
@@ -266,251 +297,261 @@ class TestThlLedgerManagerBPPayout:
# Will fail due to multiple per day
payoutevent_uuid2 = uuid4().hex
with pytest.raises(expected_exception=Exception) as e:
- tx = thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid2,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
)
assert e.type is LedgerTransactionConditionFailedError
assert str(e.value) == ">1 tx per day"
# Make it run by skipping one per day check
- tx = thl_lm.create_tx_bp_payout(
+ thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid2,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
skip_one_per_day_check=True,
)
- def test_create_tx_redis_lock_release_error(self, product, thl_lm):
+ def test_create_tx_redis_lock_release_error(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ monkeypatch: pytest.MonkeyPatch,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
- now = datetime.now(tz=timezone.utc)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=product)
+ now = datetime.now(tz=UTC)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
- thl_lm.create_tx_plug_bp_wallet(
+ thl_ledger_manager.create_tx_plug_bp_wallet(
product, rand_amount * USDCent(2), now, direction=Direction.CREDIT
)
- original_acquire = Lock.acquire
- original_release = Lock.release
- Lock.acquire = broken_acquire
-
# Create TX will fail on lock enter, no tx will actually get created
- with pytest.raises(expected_exception=Exception) as e:
- tx = thl_lm.create_tx_bp_payout(
- product=product,
- amount=rand_amount,
- payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
- )
+ with monkeypatch.context() as m:
+ m.setattr(Lock, "acquire", broken_acquire)
+ with pytest.raises(expected_exception=Exception) as e:
+ thl_ledger_manager.create_tx_bp_payout(
+ product=product,
+ amount=rand_amount,
+ payoutevent_uuid=payoutevent_uuid,
+ created=datetime.now(tz=UTC),
+ )
assert e.type is LedgerTransactionCreateError
assert str(e.value) == "Redis error: Simulated timeout during acquire"
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 0
- Lock.acquire = original_acquire
- Lock.release = broken_release
-
# Create TX will fail on lock exit, after the tx was created!
- with pytest.raises(expected_exception=Exception) as e:
- tx = thl_lm.create_tx_bp_payout(
- product=product,
- amount=rand_amount,
- payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
- )
- assert e.type is LedgerTransactionReleaseLockError
+ with monkeypatch.context() as m:
+ m.setattr(Lock, "release", broken_release)
+ with pytest.raises(LedgerTransactionReleaseLockError) as e:
+ thl_ledger_manager.create_tx_bp_payout(
+ product=product,
+ amount=rand_amount,
+ payoutevent_uuid=payoutevent_uuid,
+ created=datetime.now(tz=UTC),
+ )
assert str(e.value) == "Redis error: Simulated timeout during release"
# Transaction was still created!
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 1
- Lock.release = original_release
class TestPayoutEventManagerBPPayout:
+ @pytest.fixture(autouse=True)
+ def setup(self, create_main_accounts):
+ create_main_accounts()
- def test_create(self, product, thl_lm, brokerage_product_payout_event_manager):
+ def test_create(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
- now = datetime.now(tz=timezone.utc)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=product)
- assert thl_lm.get_account_balance(bp_wallet_account) == 0
- thl_lm.create_tx_plug_bp_wallet(
+ now = datetime.now(tz=UTC)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == 0
+ thl_ledger_manager.create_tx_plug_bp_wallet(
product, rand_amount, now, direction=Direction.CREDIT
)
- assert thl_lm.get_account_balance(bp_wallet_account) == rand_amount
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == rand_amount
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ bpe = business_payout_event_manager.create_bp_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
product=product,
created=now,
amount=rand_amount,
- payout_type=PayoutType.ACH,
+ ext_ref_id=uuid4().hex,
)
+ bp_pe = bpe.bp_payouts[0]
assert brokerage_product_payout_event_manager.check_for_ledger_tx(
- thl_ledger_manager=thl_lm,
- product_id=product.id,
- amount=rand_amount,
- payout_event=pe,
+ thl_ledger_manager=thl_ledger_manager,
+ payout_event=bp_pe,
)
- assert thl_lm.get_account_balance(bp_wallet_account) == 0
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == 0
def test_create_with_redis_error(
- self, product, caplog, thl_lm, brokerage_product_payout_event_manager
+ self,
+ product: Product,
+ caplog,
+ thl_ledger_manager: ThlLedgerManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ monkeypatch: pytest.MonkeyPatch,
):
caplog.set_level("WARNING")
- original_acquire = Lock.acquire
- original_release = Lock.release
+ ext_ref_id = uuid4().hex
rand_amount: USDCent = USDCent(randint(100, 1_000))
- now = datetime.now(tz=timezone.utc)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=product)
- assert thl_lm.get_account_balance(bp_wallet_account) == 0
- thl_lm.create_tx_plug_bp_wallet(
- product, rand_amount, now, direction=Direction.CREDIT
+ now = datetime.now(tz=UTC)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == 0
+ thl_ledger_manager.create_tx_plug_bp_wallet(
+ product=product, amount=rand_amount, created=now, direction=Direction.CREDIT
)
- assert thl_lm.get_account_balance(bp_wallet_account) == rand_amount
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == rand_amount
# Will fail on lock enter, no tx will actually get created
- Lock.acquire = broken_acquire
- with pytest.raises(expected_exception=Exception) as e:
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- created=now,
- amount=rand_amount,
- payout_type=PayoutType.ACH,
- )
- assert e.type is LedgerTransactionCreateError
+ with monkeypatch.context() as m:
+ m.setattr(Lock, "acquire", broken_acquire)
+ with pytest.raises(LedgerTransactionCreateError) as e:
+ business_payout_event_manager.create_bp_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
+ product=product,
+ created=now,
+ amount=rand_amount,
+ ext_ref_id=ext_ref_id,
+ )
assert str(e.value) == "Redis error: Simulated timeout during acquire"
- assert any(
- "Simulated timeout during acquire. No ledger tx was created" in m
- for m in caplog.messages
- )
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
# One payout event is created, status is failed, and no ledger txs exist
assert len(txs) == 0
pes = (
brokerage_product_payout_event_manager.get_bp_bp_payout_events_for_products(
- thl_ledger_manager=thl_lm, product_uuids=[product.id]
+ product_uuids=[product.id]
)
)
assert len(pes) == 1
assert pes[0].status == PayoutStatus.FAILED
pe = pes[0]
- # Fix the redis method
- Lock.acquire = original_acquire
-
# Try to fix the failed payout, by trying ledger tx again
brokerage_product_payout_event_manager.retry_create_bp_payout_event_tx(
- product=product, thl_ledger_manager=thl_lm, payout_event_uuid=pe.uuid
+ product=product,
+ thl_ledger_manager=thl_ledger_manager,
+ bp_pe=pe,
+ )
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
)
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 1
- assert thl_lm.get_account_balance(bp_wallet_account) == 0
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == 0
# And then try to run it again, it'll fail because a payout event with the same info exists
- with pytest.raises(expected_exception=Exception) as e:
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ with pytest.raises(expected_exception=ValueError) as e:
+ pe = business_payout_event_manager.create_bp_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
product=product,
created=now,
amount=rand_amount,
- payout_type=PayoutType.ACH,
+ ext_ref_id=ext_ref_id,
)
- assert e.type is ValueError
- assert "Payout event already exists!" in str(e.value)
+ assert (
+ "Cannot create a BusinessPayoutEvent with an existing transaction_id"
+ in str(e.value)
+ )
# We wouldn't do this in practice, because this is paying out the BP again, but
# we can if want to.
- # Change the timestamp so it'll create a new payout event
- now = datetime.now(tz=timezone.utc)
- with pytest.raises(LedgerTransactionConditionFailedError) as e:
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- created=now,
- amount=rand_amount,
- payout_type=PayoutType.ACH,
- )
- # But it will fail due to 1 per day check
- assert str(e.value) == ">1 tx per day"
- pe = brokerage_product_payout_event_manager.get_by_uuid(e.value.pe_uuid)
- assert pe.status == PayoutStatus.FAILED
-
- # And if we really want to, we can make it again
- now = datetime.now(tz=timezone.utc)
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ # Change the ext_ref_id so it'll create a new payout event
+ pe = business_payout_event_manager.create_bp_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
product=product,
created=now,
amount=rand_amount,
- payout_type=PayoutType.ACH,
- skip_one_per_day_check=True,
- skip_wallet_balance_check=True,
+ ext_ref_id=uuid4().hex,
)
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 2
# since they were paid twice
- assert thl_lm.get_account_balance(bp_wallet_account) == 0 - rand_amount
-
- Lock.release = original_release
- Lock.acquire = original_acquire
+ assert (
+ thl_ledger_manager.get_account_balance(bp_wallet_account) == 0 - rand_amount
+ )
def test_create_with_redis_error_release(
- self, product, caplog, thl_lm, brokerage_product_payout_event_manager
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ monkeypatch: pytest.MonkeyPatch,
+ caplog: pytest.LogCaptureFixture,
):
caplog.set_level("WARNING")
- original_release = Lock.release
-
rand_amount: USDCent = USDCent(randint(100, 1_000))
- now = datetime.now(tz=timezone.utc)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ now = datetime.now(tz=UTC)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
- assert thl_lm.get_account_balance(bp_wallet_account) == 0
- thl_lm.create_tx_plug_bp_wallet(
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == 0
+ thl_ledger_manager.create_tx_plug_bp_wallet(
product, rand_amount, now, direction=Direction.CREDIT
)
- assert thl_lm.get_account_balance(bp_wallet_account) == rand_amount
+ assert thl_ledger_manager.get_account_balance(bp_wallet_account) == rand_amount
# Will fail on lock exit, after the tx was created!
# But it'll see that the tx was created and so everything will be fine
- Lock.release = broken_release
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- created=now,
- amount=rand_amount,
- payout_type=PayoutType.ACH,
- )
- assert any(
- "Simulated timeout during release but ledger tx exists" in m
- for m in caplog.messages
- )
+ caplog.clear()
+ with monkeypatch.context() as m, caplog.at_level("WARNING"):
+ m.setattr(Lock, "release", broken_release)
+ business_payout_event_manager.create_bp_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
+ product=product,
+ created=now,
+ amount=rand_amount,
+ ext_ref_id=uuid4().hex,
+ )
+ assert "Redis error: Simulated timeout during release" in caplog.messages
- txs = thl_lm.get_tx_filtered_by_account(account_uuid=bp_wallet_account.uuid)
+ txs = thl_ledger_manager.get_tx_filtered_by_account(
+ account_uuid=bp_wallet_account.uuid
+ )
txs = [tx for tx in txs if tx.metadata["tx_type"] != "plug"]
assert len(txs) == 1
pes = (
brokerage_product_payout_event_manager.get_bp_bp_payout_events_for_products(
- thl_ledger_manager=thl_lm, product_uuids=[product.uuid]
+ product_uuids=[product.uuid]
)
)
assert len(pes) == 1
assert pes[0].status == PayoutStatus.COMPLETE
- Lock.release = original_release
diff --git a/tests/managers/thl/test_ledger/test_thl_lm_tx.py b/tests/managers/thl/test_ledger/test_thl_lm_tx.py
index 31c7107..aa3b378 100644
--- a/tests/managers/thl/test_ledger/test_thl_lm_tx.py
+++ b/tests/managers/thl/test_ledger/test_thl_lm_tx.py
@@ -1,112 +1,137 @@
+from __future__ import annotations
+
import logging
-from datetime import datetime, timezone, timedelta
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
from random import randint
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.currency import USDCent
+from generalresearch.managers.thl.ledger_manager.exceptions import (
+ LedgerTransactionConditionFailedError,
+)
from generalresearch.managers.thl.ledger_manager.ledger import (
LedgerTransaction,
)
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.definitions import (
WALL_ALLOWED_STATUS_STATUS_CODE,
)
-from generalresearch.models.thl.ledger import Direction
-from generalresearch.models.thl.ledger import TransactionType
+from generalresearch.models.thl.ledger import (
+ Direction,
+ TransactionType,
+)
+from generalresearch.models.thl.payout import UserPayoutEvent
from generalresearch.models.thl.product import (
PayoutConfig,
PayoutTransformation,
+ Product,
UserWalletConfig,
)
from generalresearch.models.thl.session import (
- Wall,
+ Session,
Status,
StatusCode1,
- Session,
+ Wall,
WallAdjustedStatus,
)
-from generalresearch.models.thl.user import User
-from generalresearch.models.thl.wallet import PayoutType
-from generalresearch.models.thl.payout import UserPayoutEvent
+from generalresearch.models.thl.wallet.definitions import PayoutType
+
+if TYPE_CHECKING:
+ from generalresearch.currency import LedgerCurrency
+ from generalresearch.managers.thl.ledger_manager.ledger import (
+ LedgerManager,
+ )
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.managers.thl.wall import WallManager
+ from generalresearch.models.thl.ledger import (
+ LedgerAccount,
+ )
+ from generalresearch.models.thl.user import User
logger = logging.getLogger("LedgerManager")
class TestThlLedgerTxManager:
+ @pytest.fixture(autouse=True)
+ def setup(self, delete_ledger_db, create_main_accounts):
+ delete_ledger_db()
+ create_main_accounts()
def test_create_tx_task_complete(
self,
- wall,
- user,
- account_revenue_task_complete,
- create_main_accounts,
- thl_lm,
- lm,
+ wall: Wall,
+ user: User,
+ account_revenue_task_complete: LedgerAccount,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
- create_main_accounts()
- tx = thl_lm.create_tx_task_complete(wall=wall, user=user)
+ tx = thl_ledger_manager.create_tx_task_complete(wall=wall, user=user)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.created == tx.created
def test_create_tx_task_complete_(
- self, wall, user, account_revenue_task_complete, thl_lm, lm
+ self,
+ wall: Wall,
+ user: User,
+ account_revenue_task_complete: LedgerAccount,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
- tx = thl_lm.create_tx_task_complete_(wall=wall, user=user)
+ tx = thl_ledger_manager.create_tx_task_complete_(wall=wall, user=user)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.created == tx.created
def test_create_tx_bp_payment(
self,
- session_factory,
- user,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- lm,
- session_manager,
+ session_factory: Callable[..., Session],
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ session_manager: SessionManager,
):
- delete_ledger_db()
- create_main_accounts()
+
s1 = session_factory(user=user)
- status, status_code_1 = s1.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments()
+ _, status_code_1 = s1.determine_session_status()
+ _, _, bp_pay, user_pay = s1.determine_payments()
session_manager.finish_with_status(
session=s1,
status=Status.COMPLETE,
status_code_1=status_code_1,
- finished=datetime.now(tz=timezone.utc) + timedelta(minutes=10),
+ finished=datetime.now(tz=UTC) + timedelta(minutes=10),
payout=bp_pay,
user_payout=user_pay,
)
- tx = thl_lm.create_tx_bp_payment(session=s1)
+ tx = thl_ledger_manager.create_tx_bp_payment(session=s1)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.created == tx.created
def test_create_tx_bp_payment_amt(
self,
- session_factory,
- user_factory,
- product_manager,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- lm,
- session_manager,
+ session_factory: Callable[..., Session],
+ user_factory: Callable[..., User],
+ product_manager: ProductManager,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ session_manager: SessionManager,
+ product_factory: Callable[..., Product],
):
- delete_ledger_db()
- create_main_accounts()
- product = product_manager.create_dummy(
+
+ product = product_factory(
payout_config=PayoutConfig(
payout_transformation=PayoutTransformation(
f="payout_transformation_amt"
@@ -115,42 +140,41 @@ class TestThlLedgerTxManager:
user_wallet_config=UserWalletConfig(amt=True, enabled=True),
)
user = user_factory(product=product)
- s1 = session_factory(user=user, wall_req_cpi=Decimal("1"))
+ s1 = session_factory(user=user, wall_req_cpi=Decimal(1))
status, status_code_1 = s1.determine_session_status()
assert status == Status.COMPLETE
thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments(
- thl_ledger_manager=thl_lm
+ thl_ledger_manager=thl_ledger_manager
)
print(thl_net, commission_amount, bp_pay, user_pay)
session_manager.finish_with_status(
session=s1,
status=Status.COMPLETE,
status_code_1=status_code_1,
- finished=datetime.now(tz=timezone.utc) + timedelta(minutes=10),
+ finished=datetime.now(tz=UTC) + timedelta(minutes=10),
payout=bp_pay,
user_payout=user_pay,
)
- tx = thl_lm.create_tx_bp_payment(session=s1)
+ tx = thl_ledger_manager.create_tx_bp_payment(session=s1)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.created == tx.created
def test_create_tx_bp_payment_(
self,
- session_factory,
- user,
- create_main_accounts,
- thl_lm,
- lm,
- session_manager,
- utc_hour_ago,
+ session_factory: Callable[..., Session],
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ session_manager: SessionManager,
+ utc_hour_ago: datetime,
):
s1 = session_factory(user=user)
status, status_code_1 = s1.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments()
+ _, _, bp_pay, user_pay = s1.determine_payments()
session_manager.finish_with_status(
session=s1,
status=status,
@@ -161,14 +185,19 @@ class TestThlLedgerTxManager:
)
s1.determine_payments()
- tx = thl_lm.create_tx_bp_payment_(session=s1)
+ tx = thl_ledger_manager.create_tx_bp_payment_(session=s1)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.created == tx.created
def test_create_tx_task_adjustment(
- self, wall_factory, session, user, create_main_accounts, thl_lm, lm
+ self,
+ wall_factory: Callable[..., Wall],
+ bare_session: Session,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
"""Create Wall event Complete, and Create a Tx Task Adjustment
@@ -176,29 +205,34 @@ class TestThlLedgerTxManager:
the transaction comes back with balanced amounts, and that
the name of the Source is in the Tx description
"""
-
wall_status = Status.COMPLETE
- wall: Wall = wall_factory(session=session, wall_status=wall_status)
+ wall: Wall = wall_factory(session=bare_session, wall_status=wall_status)
- tx = thl_lm.create_tx_task_adjustment(wall=wall, user=user)
+ tx = thl_ledger_manager.create_tx_task_adjustment(wall=wall, user=user)
assert isinstance(tx, LedgerTransaction)
- res = lm.get_tx_by_id(transaction_id=tx.id)
+ res = ledger_manager.get_tx_by_id(transaction_id=tx.id)
assert res.entries[0].amount == int(wall.cpi * 100)
assert res.entries[1].amount == int(wall.cpi * 100)
assert wall.source.name in res.ext_description
assert res.created == tx.created
- def test_create_tx_bp_adjustment(self, session, user, caplog, thl_lm, lm):
+ def test_create_tx_bp_adjustment(
+ self,
+ session: Session,
+ user: User,
+ caplog,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ ):
status, status_code_1 = session.determine_session_status()
thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
- # The default session fixture is just an unfinished wall event
assert len(session.wall_events) == 1
assert session.finished is None
- assert status == Status.TIMEOUT
+ assert status == Status.FAIL
assert status_code_1 in list(
- WALL_ALLOWED_STATUS_STATUS_CODE.get(Status.TIMEOUT, {})
+ WALL_ALLOWED_STATUS_STATUS_CODE.get(Status.FAIL, {})
)
assert thl_net == Decimal(0)
assert commission_amount == Decimal(0)
@@ -208,28 +242,32 @@ class TestThlLedgerTxManager:
# Update the finished timestamp, but nothing else. This means that
# there is no financial changes needed
session.update(
- **{
- "finished": datetime.now(tz=timezone.utc) + timedelta(minutes=10),
- }
+ finished=datetime.now(tz=UTC) + timedelta(minutes=10), status=Status.FAIL
)
assert session.finished
with caplog.at_level(logging.INFO):
- tx = thl_lm.create_tx_bp_adjustment(session=session)
+ tx = thl_ledger_manager.create_tx_bp_adjustment(session=session)
assert tx is None
assert "No transactions needed." in caplog.text
- def test_create_tx_bp_payout(self, product, caplog, thl_lm, currency):
+ def test_create_tx_bp_payout(
+ self,
+ product: Product,
+ caplog,
+ thl_ledger_manager: ThlLedgerManager,
+ currency: LedgerCurrency,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
# Create a BP Payout for a Product without any activity. By issuing,
# the skip_* checks, we should be able to force it to work, and will
# then ultimately result in a negative balance
- tx = thl_lm.create_tx_bp_payout(
+ tx = thl_ledger_manager.create_tx_bp_payout(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
skip_wallet_balance_check=True,
skip_one_per_day_check=True,
skip_flag_check=True,
@@ -240,7 +278,7 @@ class TestThlLedgerTxManager:
assert tx.ext_description == "BP Payout"
assert (
tx.tag
- == f"{thl_lm.currency.value}:{TransactionType.BP_PAYOUT.value}:{payoutevent_uuid}"
+ == f"{thl_ledger_manager.currency.value}:{TransactionType.BP_PAYOUT.value}:{payoutevent_uuid}"
)
assert tx.entries[0].amount == rand_amount
assert tx.entries[1].amount == rand_amount
@@ -248,35 +286,42 @@ class TestThlLedgerTxManager:
# Check the Product's balance, it should be negative the amount that was
# paid out. That's because the Product earned nothing.. and then was
# sent something.
- balance = thl_lm.get_account_balance(
- account=thl_lm.get_account_or_create_bp_wallet(product=product)
+ balance = thl_ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
)
assert balance == int(rand_amount) * -1
# Test some basic assertions
- with caplog.at_level(logging.INFO):
- with pytest.raises(expected_exception=Exception):
- thl_lm.create_tx_bp_payout(
- product=product,
- amount=rand_amount,
- payoutevent_uuid=uuid4().hex,
- created=datetime.now(tz=timezone.utc),
- skip_wallet_balance_check=False,
- skip_one_per_day_check=False,
- skip_flag_check=False,
- )
+ with (
+ caplog.at_level(logging.INFO),
+ pytest.raises(expected_exception=LedgerTransactionConditionFailedError),
+ ):
+ thl_ledger_manager.create_tx_bp_payout(
+ product=product,
+ amount=rand_amount,
+ payoutevent_uuid=uuid4().hex,
+ created=datetime.now(tz=UTC),
+ skip_wallet_balance_check=False,
+ skip_one_per_day_check=False,
+ skip_flag_check=False,
+ )
assert "failed condition check >1 tx per day" in caplog.text
- def test_create_tx_bp_payout_(self, product, thl_lm, lm, currency):
+ def test_create_tx_bp_payout_(
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ currency: LedgerCurrency,
+ ):
rand_amount: USDCent = USDCent(randint(100, 1_000))
payoutevent_uuid = uuid4().hex
# Create a BP Payout for a Product without any activity.
- tx = thl_lm.create_tx_bp_payout_(
+ tx = thl_ledger_manager.create_tx_bp_payout_(
product=product,
amount=rand_amount,
payoutevent_uuid=payoutevent_uuid,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
)
# Check the basic attributes
@@ -290,17 +335,21 @@ class TestThlLedgerTxManager:
assert tx.entries[1].amount == rand_amount
def test_create_tx_plug_bp_wallet(
- self, product, create_main_accounts, thl_lm, lm, currency
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
"""A BP Wallet "plug" is a way to makeup discrepancies and simply
add or remove money
"""
rand_amount: USDCent = USDCent(randint(100, 1_000))
- tx = thl_lm.create_tx_plug_bp_wallet(
+ tx = thl_ledger_manager.create_tx_plug_bp_wallet(
product=product,
amount=rand_amount,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
direction=Direction.DEBIT,
skip_flag_check=False,
)
@@ -309,13 +358,17 @@ class TestThlLedgerTxManager:
# We issued the BP money they didn't earn, so now they have a
# negative balance
- balance = thl_lm.get_account_balance(
- account=thl_lm.get_account_or_create_bp_wallet(product=product)
+ balance = thl_ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
)
assert balance == int(rand_amount) * -1
def test_create_tx_plug_bp_wallet_(
- self, product, create_main_accounts, thl_lm, lm, currency
+ self,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
"""A BP Wallet "plug" is a way to fix discrepancies and simply
add or remove money.
@@ -325,10 +378,10 @@ class TestThlLedgerTxManager:
"""
rand_amount: USDCent = USDCent(randint(100, 1_000))
- tx = thl_lm.create_tx_plug_bp_wallet_(
+ tx = thl_ledger_manager.create_tx_plug_bp_wallet_(
product=product,
amount=rand_amount,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
direction=Direction.DEBIT,
)
@@ -336,32 +389,32 @@ class TestThlLedgerTxManager:
# We issued the BP money they didn't earn, so now they have a
# negative balance
- balance = thl_lm.get_account_balance(
- account=thl_lm.get_account_or_create_bp_wallet(product=product)
+ balance = thl_ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
)
assert balance == int(rand_amount) * -1
# Issue a positive one now, and confirm the balance goes positive
- thl_lm.create_tx_plug_bp_wallet_(
+ thl_ledger_manager.create_tx_plug_bp_wallet_(
product=product,
amount=rand_amount + rand_amount,
- created=datetime.now(tz=timezone.utc),
+ created=datetime.now(tz=UTC),
direction=Direction.CREDIT,
)
- balance = thl_lm.get_account_balance(
- account=thl_lm.get_account_or_create_bp_wallet(product=product)
+ balance = thl_ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
)
assert balance == int(rand_amount)
def test_create_tx_user_payout_request(
self,
- user,
- product_user_wallet_yes,
- user_factory,
- delete_df_collection,
- thl_lm,
- lm,
- currency,
+ user: User,
+ product_user_wallet_yes: Product,
+ user_factory: Callable[..., User],
+ delete_df_collection: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
pe = UserPayoutEvent(
uuid=uuid4().hex,
@@ -374,7 +427,7 @@ class TestThlLedgerTxManager:
# The default user fixture uses a product that doesn't have wallet
# mode enabled
with pytest.raises(expected_exception=AssertionError):
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
skip_flag_check=True,
@@ -385,12 +438,12 @@ class TestThlLedgerTxManager:
u2 = user_factory(product=product_user_wallet_yes)
# User's pre-balance is 0 because no activity has occurred yet
- pre_balance = lm.get_account_balance(
- account=thl_lm.get_account_or_create_user_wallet(user=u2)
+ pre_balance = ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_user_wallet(user=u2)
)
assert pre_balance == 0
- tx = thl_lm.create_tx_user_payout_request(
+ tx = thl_ledger_manager.create_tx_user_payout_request(
user=u2,
payout_event=pe,
skip_flag_check=True,
@@ -411,21 +464,19 @@ class TestThlLedgerTxManager:
# Post balance is -$5.00 because it comes out of the wallet before
# it's Approved or Completed
- post_balance = lm.get_account_balance(
- account=thl_lm.get_account_or_create_user_wallet(user=u2)
+ post_balance = ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_user_wallet(user=u2)
)
assert post_balance == -500
def test_create_tx_user_payout_request_(
self,
- user,
- product_user_wallet_yes,
- user_factory,
- delete_ledger_db,
- thl_lm,
- lm,
+ user: User,
+ product_user_wallet_yes: Product,
+ user_factory: Callable[..., User],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
- delete_ledger_db()
pe = UserPayoutEvent(
uuid=uuid4().hex,
@@ -436,36 +487,32 @@ class TestThlLedgerTxManager:
)
rand_description = uuid4().hex
- tx = thl_lm.create_tx_user_payout_request_(
+ tx = thl_ledger_manager.create_tx_user_payout_request_(
user=user, payout_event=pe, description=rand_description
)
assert tx.ext_description == rand_description
- post_balance = lm.get_account_balance(
- account=thl_lm.get_account_or_create_user_wallet(user=user)
+ post_balance = ledger_manager.get_account_balance(
+ account=thl_ledger_manager.get_account_or_create_user_wallet(user=user)
)
assert post_balance == -500
def test_create_tx_user_payout_complete(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
# Ensure the user starts out with nothing...
- assert lm.get_account_balance(account=user_account) == 0
+ assert ledger_manager.get_account_balance(account=user_account) == 0
pe = UserPayoutEvent(
uuid=uuid4().hex,
@@ -477,7 +524,7 @@ class TestThlLedgerTxManager:
# Confirm it's not possible unless a request occurred happen
with pytest.raises(expected_exception=ValueError):
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user=user,
payout_event=pe,
fee_amount=None,
@@ -485,17 +532,19 @@ class TestThlLedgerTxManager:
)
# (1) Make a request first
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
skip_flag_check=True,
skip_wallet_balance_check=True,
)
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == rand_amount * -1
+ assert (
+ ledger_manager.get_account_balance(account=user_account) == rand_amount * -1
+ )
# (2) Complete the request
- tx = thl_lm.create_tx_user_payout_complete(
+ tx = thl_ledger_manager.create_tx_user_payout_complete(
user=user,
payout_event=pe,
fee_amount=Decimal(0),
@@ -508,18 +557,19 @@ class TestThlLedgerTxManager:
# The amount that comes out of the user wallet doesn't change after
# it's approved becuase it's already been withdrawn
- assert lm.get_account_balance(account=user_account) == rand_amount * -1
+ assert (
+ ledger_manager.get_account_balance(account=user_account) == rand_amount * -1
+ )
def test_create_tx_user_payout_complete_(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
):
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
pe = UserPayoutEvent(
@@ -531,7 +581,7 @@ class TestThlLedgerTxManager:
)
# (1) Make a request first
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
skip_flag_check=True,
@@ -541,12 +591,14 @@ class TestThlLedgerTxManager:
# (2) Complete the request
rand_desc = uuid4().hex
- bp_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
product=user.product, expense_name="paypal"
)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=user.product)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
- tx = thl_lm.create_tx_user_payout_complete_(
+ tx = thl_ledger_manager.create_tx_user_payout_complete_(
user=user,
payout_event=pe,
fee_amount=Decimal("0.00"),
@@ -555,19 +607,20 @@ class TestThlLedgerTxManager:
description=rand_desc,
)
assert tx.ext_description == rand_desc
- assert lm.get_account_balance(account=user_account) == rand_amount * -1
+ assert (
+ ledger_manager.get_account_balance(account=user_account) == rand_amount * -1
+ )
def test_create_tx_user_payout_cancelled(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
pe = UserPayoutEvent(
@@ -579,17 +632,19 @@ class TestThlLedgerTxManager:
)
# (1) Make a request first
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
skip_flag_check=True,
skip_wallet_balance_check=True,
)
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == rand_amount * -1
+ assert (
+ ledger_manager.get_account_balance(account=user_account) == rand_amount * -1
+ )
# (2) Cancel the request
- tx = thl_lm.create_tx_user_payout_cancelled(
+ tx = thl_ledger_manager.create_tx_user_payout_cancelled(
user=user,
payout_event=pe,
skip_flag_check=False,
@@ -600,19 +655,18 @@ class TestThlLedgerTxManager:
assert isinstance(tx, LedgerTransaction)
# Assert the balance comes back to 0 after it was cancelled
- assert lm.get_account_balance(account=user_account) == 0
+ assert ledger_manager.get_account_balance(account=user_account) == 0
def test_create_tx_user_payout_cancelled_(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
pe = UserPayoutEvent(
@@ -624,43 +678,44 @@ class TestThlLedgerTxManager:
)
# (1) Make a request first
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
skip_flag_check=True,
skip_wallet_balance_check=True,
)
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == rand_amount * -1
+ assert (
+ ledger_manager.get_account_balance(account=user_account) == rand_amount * -1
+ )
# (2) Cancel the request
rand_desc = uuid4().hex
- tx = thl_lm.create_tx_user_payout_cancelled_(
+ tx = thl_ledger_manager.create_tx_user_payout_cancelled_(
user=user, payout_event=pe, description=rand_desc
)
assert isinstance(tx, LedgerTransaction)
assert tx.ext_description == rand_desc
- assert lm.get_account_balance(account=user_account) == 0
+ assert ledger_manager.get_account_balance(account=user_account) == 0
def test_create_tx_user_bonus(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
rand_ref_uuid = uuid4().hex
rand_desc = uuid4().hex
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == 0
+ assert ledger_manager.get_account_balance(account=user_account) == 0
- tx = thl_lm.create_tx_user_bonus(
+ tx = thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(rand_amount / 100),
ref_uuid=rand_ref_uuid,
@@ -668,44 +723,47 @@ class TestThlLedgerTxManager:
skip_flag_check=True,
)
assert tx.ext_description == rand_desc
- assert tx.tag == f"{thl_lm.currency.value}:user_bonus:{rand_ref_uuid}"
+ assert (
+ tx.tag == f"{thl_ledger_manager.currency.value}:user_bonus:{rand_ref_uuid}"
+ )
assert tx.entries[0].amount == rand_amount
assert tx.entries[1].amount == rand_amount
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == rand_amount
+ assert ledger_manager.get_account_balance(account=user_account) == rand_amount
def test_create_tx_user_bonus_(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
user: User = user_factory(product=product_user_wallet_yes)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
rand_amount = randint(100, 1_000)
rand_ref_uuid = uuid4().hex
rand_desc = uuid4().hex
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == 0
+ assert ledger_manager.get_account_balance(account=user_account) == 0
- tx = thl_lm.create_tx_user_bonus_(
+ tx = thl_ledger_manager.create_tx_user_bonus_(
user=user,
amount=Decimal(rand_amount / 100),
ref_uuid=rand_ref_uuid,
description=rand_desc,
)
assert tx.ext_description == rand_desc
- assert tx.tag == f"{thl_lm.currency.value}:user_bonus:{rand_ref_uuid}"
+ assert (
+ tx.tag == f"{thl_ledger_manager.currency.value}:user_bonus:{rand_ref_uuid}"
+ )
assert tx.entries[0].amount == rand_amount
assert tx.entries[1].amount == rand_amount
# Assert the balance came out of their user wallet
- assert lm.get_account_balance(account=user_account) == rand_amount
+ assert ledger_manager.get_account_balance(account=user_account) == rand_amount
class TestThlLedgerTxManagerFlows:
@@ -713,12 +771,19 @@ class TestThlLedgerTxManagerFlows:
examples
"""
- def test_create_tx_task_complete(
- self, user, create_main_accounts, thl_lm, lm, currency, delete_ledger_db
- ):
+ @pytest.fixture(autouse=True)
+ def setup(self, delete_ledger_db, create_main_accounts):
delete_ledger_db()
create_main_accounts()
+ def test_create_tx_task_complete(
+ self,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
+ ):
+
wall1 = Wall(
user_id=1,
source=Source.DYNATA,
@@ -727,10 +792,12 @@ class TestThlLedgerTxManagerFlows:
session_id=1,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
+ )
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall1, user=user, created=wall1.started
)
- thl_lm.create_tx_task_complete(wall=wall1, user=user, created=wall1.started)
wall2 = Wall(
user_id=1,
@@ -740,41 +807,43 @@ class TestThlLedgerTxManagerFlows:
session_id=1,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
+ )
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall2, user=user, created=wall2.started
)
- thl_lm.create_tx_task_complete(wall=wall2, user=user, created=wall2.started)
- cash = thl_lm.get_account_cash()
- revenue = thl_lm.get_account_task_complete_revenue()
+ cash = thl_ledger_manager.get_account_cash()
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
- assert lm.get_account_balance(cash) == 123 + 321
- assert lm.get_account_balance(revenue) == 123 + 321
- assert lm.check_ledger_balanced()
+ assert ledger_manager.get_account_balance(cash) == 123 + 321
+ assert ledger_manager.get_account_balance(revenue) == 123 + 321
+ assert ledger_manager.check_ledger_balanced()
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="d"
)
== 123
)
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="f"
)
== 321
)
assert (
- lm.get_account_filtered_balance(
+ ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="x"
)
== 0
)
assert (
- thl_lm.get_account_filtered_balance(
+ thl_ledger_manager.get_account_filtered_balance(
account=revenue,
metadata_key="thl_wall",
metadata_value=wall1.uuid,
@@ -783,7 +852,11 @@ class TestThlLedgerTxManagerFlows:
)
def test_create_transaction_task_complete_1_cent(
- self, user, create_main_accounts, thl_lm, lm, currency
+ self,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
wall1 = Wall(
user_id=1,
@@ -793,10 +866,10 @@ class TestThlLedgerTxManagerFlows:
session_id=1,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
@@ -804,17 +877,13 @@ class TestThlLedgerTxManagerFlows:
def test_create_transaction_bp_payment(
self,
- user,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
- delete_ledger_db,
- session_factory,
- utc_hour_ago,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
+ session_factory: Callable[..., Session],
+ utc_hour_ago: datetime,
):
- delete_ledger_db()
- create_main_accounts()
s1: Session = session_factory(
user=user,
@@ -824,50 +893,53 @@ class TestThlLedgerTxManagerFlows:
)
w1: Wall = s1.wall_events[0]
- tx = thl_lm.create_tx_task_complete(wall=w1, user=user, created=w1.started)
+ tx = thl_ledger_manager.create_tx_task_complete(
+ wall=w1, user=user, created=w1.started
+ )
assert isinstance(tx, LedgerTransaction)
status, status_code_1 = s1.determine_session_status()
thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments()
s1.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": s1.started + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=s1.started + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
print(thl_net, commission_amount, bp_pay, user_pay)
- thl_lm.create_tx_bp_payment(session=s1, created=w1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=s1, created=w1.started)
- revenue = thl_lm.get_account_task_complete_revenue()
- bp_wallet = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- bp_commission = thl_lm.get_account_or_create_bp_commission(product=user.product)
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
+ bp_commission = thl_ledger_manager.get_account_or_create_bp_commission(
+ product=user.product
+ )
- assert 0 == lm.get_account_balance(account=revenue)
- assert 50 == lm.get_account_filtered_balance(
+ assert 0 == ledger_manager.get_account_balance(account=revenue)
+ assert 50 == ledger_manager.get_account_filtered_balance(
account=revenue,
metadata_key="source",
metadata_value=Source.TESTING,
)
- assert 48 == lm.get_account_balance(account=bp_wallet)
- assert 48 == lm.get_account_filtered_balance(
+ assert 48 == ledger_manager.get_account_balance(account=bp_wallet)
+ assert 48 == ledger_manager.get_account_filtered_balance(
account=bp_wallet,
metadata_key="thl_session",
metadata_value=s1.uuid,
)
- assert 2 == thl_lm.get_account_balance(account=bp_commission)
- assert thl_lm.check_ledger_balanced()
+ assert 2 == thl_ledger_manager.get_account_balance(account=bp_commission)
+ assert thl_ledger_manager.check_ledger_balanced()
def test_create_transaction_bp_payment_round(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
product_user_wallet_no.commission_pct = Decimal("0.085")
user: User = user_factory(product=product_user_wallet_no)
@@ -880,11 +952,11 @@ class TestThlLedgerTxManagerFlows:
session_id=3,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
assert isinstance(tx, LedgerTransaction)
@@ -893,24 +965,27 @@ class TestThlLedgerTxManagerFlows:
status, status_code_1 = session.determine_session_status()
thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": session.started + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=session.started + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
print(thl_net, commission_amount, bp_pay, user_pay)
- tx = thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ tx = thl_ledger_manager.create_tx_bp_payment(
+ session=session, created=wall1.started
+ )
assert isinstance(tx, LedgerTransaction)
def test_create_transaction_bp_payment_round2(
- self, delete_ledger_db, user, create_main_accounts, thl_lm, lm, currency
+ self,
+ user: User,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
+
# user must be no user wallet
# e.g. session 869b5bfa47f44b4f81cd095ed01df2ff this fails if you dont round properly
@@ -922,34 +997,33 @@ class TestThlLedgerTxManagerFlows:
session_id=3,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall=wall1, user=user, created=wall1.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall1, user=user, created=wall1.started
+ )
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
# thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": session.started + timedelta(minutes=10),
- "payout": Decimal("1.53"),
- "user_payout": Decimal("1.53"),
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=session.started + timedelta(minutes=10),
+ payout=Decimal("1.53"),
+ user_payout=Decimal("1.53"),
)
- thl_lm.create_tx_bp_payment(session=session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=session, created=wall1.started)
def test_create_transaction_bp_payment_round3(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
# e.g. session ___ fails b/c we rounded incorrectly
# before, and now we are off by a penny...
@@ -963,22 +1037,22 @@ class TestThlLedgerTxManagerFlows:
session_id=3,
status=Status.COMPLETE,
status_code_1=StatusCode1.COMPLETE,
- started=datetime.now(timezone.utc),
- finished=datetime.now(timezone.utc) + timedelta(seconds=1),
+ started=datetime.now(UTC),
+ finished=datetime.now(UTC) + timedelta(seconds=1),
+ )
+ thl_ledger_manager.create_tx_task_complete(
+ wall=wall1, user=user, created=wall1.started
)
- thl_lm.create_tx_task_complete(wall=wall1, user=user, created=wall1.started)
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
# thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": session.started + timedelta(minutes=10),
- "payout": Decimal("0.39"),
- "user_payout": Decimal("0.26"),
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=session.started + timedelta(minutes=10),
+ payout=Decimal("0.39"),
+ user_payout=Decimal("0.26"),
)
# with pytest.logs(logger, level=logging.WARNING) as cm:
# tx = thl_lm.create_transaction_bp_payment(session, created=wall1.started)
@@ -986,22 +1060,19 @@ class TestThlLedgerTxManagerFlows:
def test_create_transaction_bp_payment_user_wallet(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- session_manager,
- wall_manager,
- lm,
- session_factory,
- currency,
- utc_hour_ago,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ session_manager: SessionManager,
+ wall_manager: WallManager,
+ ledger_manager: LedgerManager,
+ session_factory: Callable[..., Session],
+ currency: LedgerCurrency,
+ utc_hour_ago: datetime,
):
- delete_ledger_db()
- create_main_accounts()
user: User = user_factory(product=product_user_wallet_yes)
+ assert isinstance(user.product, Product)
assert user.product.user_wallet_enabled
s1: Session = session_factory(
@@ -1013,10 +1084,12 @@ class TestThlLedgerTxManagerFlows:
)
w1: Wall = s1.wall_events[0]
- thl_lm.create_tx_task_complete(wall=w1, user=user, created=w1.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=w1, user=user, created=w1.started
+ )
status, status_code_1 = s1.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments()
+ _, _, bp_pay, user_pay = s1.determine_payments()
session_manager.finish_with_status(
session=s1,
status=status,
@@ -1025,55 +1098,59 @@ class TestThlLedgerTxManagerFlows:
payout=bp_pay,
user_payout=user_pay,
)
- thl_lm.create_tx_bp_payment(session=s1, created=w1.started)
+ thl_ledger_manager.create_tx_bp_payment(session=s1, created=w1.started)
- revenue = thl_lm.get_account_task_complete_revenue()
- bp_wallet = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- bp_commission = thl_lm.get_account_or_create_bp_commission(product=user.product)
- user_wallet = thl_lm.get_account_or_create_user_wallet(user=user)
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
+ bp_commission = thl_ledger_manager.get_account_or_create_bp_commission(
+ product=user.product
+ )
+ user_wallet = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
- assert 0 == thl_lm.get_account_balance(account=revenue)
- assert 50 == thl_lm.get_account_filtered_balance(
+ assert 0 == thl_ledger_manager.get_account_balance(account=revenue)
+ assert 50 == thl_ledger_manager.get_account_filtered_balance(
account=revenue,
metadata_key="source",
metadata_value=Source.TESTING,
)
- assert 48 - 19 == thl_lm.get_account_balance(account=bp_wallet)
- assert 48 - 19 == thl_lm.get_account_filtered_balance(
+ assert 48 - 19 == thl_ledger_manager.get_account_balance(account=bp_wallet)
+ assert 48 - 19 == thl_ledger_manager.get_account_filtered_balance(
account=bp_wallet,
metadata_key="thl_session",
metadata_value=s1.uuid,
)
- assert 2 == thl_lm.get_account_balance(bp_commission)
- assert 19 == thl_lm.get_account_balance(user_wallet)
- assert 19 == thl_lm.get_account_filtered_balance(
+ assert 2 == thl_ledger_manager.get_account_balance(bp_commission)
+ assert 19 == thl_ledger_manager.get_account_balance(user_wallet)
+ assert 19 == thl_ledger_manager.get_account_filtered_balance(
account=user_wallet,
metadata_key="thl_session",
metadata_value=s1.uuid,
)
- assert 0 == thl_lm.get_account_filtered_balance(
+ assert 0 == thl_ledger_manager.get_account_filtered_balance(
account=user_wallet, metadata_key="thl_session", metadata_value="x"
)
- assert thl_lm.check_ledger_balanced()
+ assert thl_ledger_manager.check_ledger_balanced()
class TestThlLedgerManagerAdj:
+ @pytest.fixture(autouse=True)
+ def setup(self, delete_ledger_db, create_main_accounts):
+ delete_ledger_db()
+ create_main_accounts()
def test_create_tx_task_adjustment(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- lm,
- utc_hour_ago,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ utc_hour_ago: datetime,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
user: User = user_factory(product=product_user_wallet_no)
@@ -1089,7 +1166,7 @@ class TestThlLedgerManagerAdj:
finished=utc_hour_ago + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall1, user, created=wall1.started)
+ thl_ledger_manager.create_tx_task_complete(wall1, user, created=wall1.started)
wall2 = Wall(
user_id=1,
@@ -1102,7 +1179,7 @@ class TestThlLedgerManagerAdj:
started=utc_hour_ago,
finished=utc_hour_ago + timedelta(seconds=1),
)
- thl_lm.create_tx_task_complete(wall2, user, created=wall2.started)
+ thl_ledger_manager.create_tx_task_complete(wall2, user, created=wall2.started)
wall1.update(
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
@@ -1110,24 +1187,26 @@ class TestThlLedgerManagerAdj:
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
print(wall1.get_cpi_after_adjustment())
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
- cash = thl_lm.get_account_cash()
- revenue = thl_lm.get_account_task_complete_revenue()
+ cash = thl_ledger_manager.get_account_cash()
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
- assert 123 + 321 - 123 == thl_lm.get_account_balance(account=cash)
- assert 123 + 321 - 123 == thl_lm.get_account_balance(account=revenue)
- assert thl_lm.check_ledger_balanced()
- assert 0 == thl_lm.get_account_filtered_balance(
+ assert 123 + 321 - 123 == thl_ledger_manager.get_account_balance(account=cash)
+ assert 123 + 321 - 123 == thl_ledger_manager.get_account_balance(
+ account=revenue
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
+ assert 0 == thl_ledger_manager.get_account_filtered_balance(
revenue, metadata_key="source", metadata_value="d"
)
- assert 321 == thl_lm.get_account_filtered_balance(
+ assert 321 == thl_ledger_manager.get_account_filtered_balance(
revenue, metadata_key="source", metadata_value="f"
)
- assert 0 == thl_lm.get_account_filtered_balance(
+ assert 0 == thl_ledger_manager.get_account_filtered_balance(
revenue, metadata_key="source", metadata_value="x"
)
- assert 123 - 123 == thl_lm.get_account_filtered_balance(
+ assert 123 - 123 == thl_ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="thl_wall", metadata_value=wall1.uuid
)
@@ -1138,46 +1217,42 @@ class TestThlLedgerManagerAdj:
adjusted_timestamp=utc_hour_ago + timedelta(minutes=45),
)
print(wall1.get_cpi_after_adjustment())
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
# and then run it again to make sure it does nothing
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
- cash = thl_lm.get_account_cash()
- revenue = thl_lm.get_account_task_complete_revenue()
+ cash = thl_ledger_manager.get_account_cash()
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
- assert 123 + 321 - 123 + 123 == thl_lm.get_account_balance(cash)
- assert 123 + 321 - 123 + 123 == thl_lm.get_account_balance(revenue)
- assert thl_lm.check_ledger_balanced()
- assert 123 == thl_lm.get_account_filtered_balance(
+ assert 123 + 321 - 123 + 123 == thl_ledger_manager.get_account_balance(cash)
+ assert 123 + 321 - 123 + 123 == thl_ledger_manager.get_account_balance(revenue)
+ assert thl_ledger_manager.check_ledger_balanced()
+ assert 123 == thl_ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="d"
)
- assert 321 == thl_lm.get_account_filtered_balance(
+ assert 321 == thl_ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="f"
)
- assert 0 == thl_lm.get_account_filtered_balance(
+ assert 0 == thl_ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="source", metadata_value="x"
)
- assert 123 - 123 + 123 == thl_lm.get_account_filtered_balance(
+ assert 123 - 123 + 123 == thl_ledger_manager.get_account_filtered_balance(
account=revenue, metadata_key="thl_wall", metadata_value=wall1.uuid
)
def test_create_tx_bp_adjustment(
self,
- user,
- product_user_wallet_no,
- create_main_accounts,
+ user: User,
+ product_user_wallet_no: Product,
caplog,
- thl_lm,
- lm,
- currency,
- session_manager,
- wall_manager,
- session_factory,
- utc_hour_ago,
- delete_ledger_db,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
+ session_manager: SessionManager,
+ wall_manager: WallManager,
+ session_factory: Callable[..., Session],
+ utc_hour_ago: datetime,
):
- delete_ledger_db()
- create_main_accounts()
s1 = session_factory(
user=user,
@@ -1190,11 +1265,15 @@ class TestThlLedgerManagerAdj:
w1: Wall = s1.wall_events[0]
w2: Wall = s1.wall_events[1]
- thl_lm.create_tx_task_complete(wall=w1, user=user, created=w1.started)
- thl_lm.create_tx_task_complete(wall=w2, user=user, created=w2.started)
+ thl_ledger_manager.create_tx_task_complete(
+ wall=w1, user=user, created=w1.started
+ )
+ thl_ledger_manager.create_tx_task_complete(
+ wall=w2, user=user, created=w2.started
+ )
status, status_code_1 = s1.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = s1.determine_payments()
+ _, _, bp_pay, user_pay = s1.determine_payments()
session_manager.finish_with_status(
session=s1,
status=status,
@@ -1203,21 +1282,25 @@ class TestThlLedgerManagerAdj:
payout=bp_pay,
user_payout=user_pay,
)
- thl_lm.create_tx_bp_payment(session=s1, created=w1.started)
- revenue = thl_lm.get_account_task_complete_revenue()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- bp_commission_account = thl_lm.get_account_or_create_bp_commission(
+ thl_ledger_manager.create_tx_bp_payment(session=s1, created=w1.started)
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
product=user.product
)
- assert 380 == thl_lm.get_account_balance(account=bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(account=revenue)
- assert 20 == thl_lm.get_account_balance(account=bp_commission_account)
- thl_lm.check_ledger_balanced()
+ bp_commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ product=user.product
+ )
+ assert 380 == thl_ledger_manager.get_account_balance(account=bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(account=revenue)
+ assert 20 == thl_ledger_manager.get_account_balance(
+ account=bp_commission_account
+ )
+ thl_ledger_manager.check_ledger_balanced()
# This should do nothing (since we haven't adjusted any wall events)
s1.adjust_status()
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
assert (
"create_transaction_bp_adjustment. No transactions needed." in caplog.text
@@ -1235,22 +1318,22 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=Decimal(0),
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall=w1, user=user)
+ thl_ledger_manager.create_tx_task_adjustment(wall=w1, user=user)
# -$1.00 b/c the MP took the $1 back, but we haven't yet taken the BP payment back
- assert -100 == thl_lm.get_account_balance(revenue)
+ assert -100 == thl_ledger_manager.get_account_balance(revenue)
s1.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
assert (
"create_transaction_bp_adjustment. No transactions needed." in caplog.text
)
- assert 380 - 95 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 - 5 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ assert 380 - 95 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 - 5 == thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
# unrecon the $1 survey
wall_manager.adjust_status(
@@ -1259,32 +1342,28 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=None,
adjusted_timestamp=utc_hour_ago + timedelta(minutes=45),
)
- thl_lm.create_tx_task_adjustment(
+ thl_ledger_manager.create_tx_task_adjustment(
wall=w1,
user=user,
created=utc_hour_ago + timedelta(minutes=45),
)
- new_status, new_payout, new_user_payout = s1.determine_new_status_and_payouts()
+ _, _, _ = s1.determine_new_status_and_payouts()
s1.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=s1)
- assert 380 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20, thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
+ assert 380 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20, thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
def test_create_tx_bp_adjustment_small(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
- delete_ledger_db,
- thl_lm,
- lm,
- utc_hour_ago,
- currency,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ utc_hour_ago: datetime,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
# This failed when I didn't check that `change_commission` > 0 in
# create_transaction_bp_adjustment
@@ -1302,51 +1381,46 @@ class TestThlLedgerManagerAdj:
finished=utc_hour_ago + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
assert isinstance(tx, LedgerTransaction)
session = Session(started=wall1.started, user=user, wall_events=[wall1])
status, status_code_1 = session.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
+ _, _, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": utc_hour_ago + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=utc_hour_ago + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
- thl_lm.create_tx_bp_payment(session, created=wall1.started)
+ thl_ledger_manager.create_tx_bp_payment(session, created=wall1.started)
wall1.update(
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
adjusted_cpi=0,
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
session.adjust_status()
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
def test_create_tx_bp_adjustment_abandon(
self,
- user_factory,
- product_user_wallet_no,
- delete_ledger_db,
- session_factory,
- create_main_accounts,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
+ session_factory: Callable[..., Session],
caplog,
- thl_lm,
- lm,
- currency,
- utc_hour_ago,
- session_manager,
- wall_manager,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
+ utc_hour_ago: datetime,
+ session_manager: SessionManager,
+ wall_manager: WallManager,
):
- delete_ledger_db()
- create_main_accounts()
+
user: User = user_factory(product=product_user_wallet_no)
s1: Session = session_factory(
user=user, final_status=Status.ABANDON, wall_req_cpi=Decimal(1)
@@ -1360,9 +1434,9 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=w1.cpi,
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall=w1, user=user)
+ thl_ledger_manager.create_tx_task_adjustment(wall=w1, user=user)
s1.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
# And then adjust it back (it was abandon before, but now it should be
# fail (?) or back to abandon?)
wall_manager.adjust_status(
@@ -1371,24 +1445,26 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=None,
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall=w1, user=user)
+ thl_ledger_manager.create_tx_task_adjustment(wall=w1, user=user)
s1.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
- revenue = thl_lm.get_account_task_complete_revenue()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- bp_commission_account = thl_lm.get_account_or_create_bp_commission(
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
product=user.product
)
- assert 0 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 0 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ bp_commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ product=user.product
+ )
+ assert 0 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 0 == thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
# This should do nothing
s1.adjust_status()
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session=s1)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
assert "No transactions needed" in caplog.text
# Now back to complete again
@@ -1399,24 +1475,20 @@ class TestThlLedgerManagerAdj:
adjusted_timestamp=utc_hour_ago + timedelta(hours=1),
)
s1.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=s1)
- assert 95 == thl_lm.get_account_balance(bp_wallet_account)
+ thl_ledger_manager.create_tx_bp_adjustment(session=s1)
+ assert 95 == thl_ledger_manager.get_account_balance(bp_wallet_account)
def test_create_tx_bp_adjustment_user_wallet(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
caplog,
- thl_lm,
- lm,
- currency,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
- now = datetime.now(timezone.utc) - timedelta(days=1)
+ now = datetime.now(UTC) - timedelta(days=1)
user: User = user_factory(product=product_user_wallet_yes)
# Create 2 Wall completes and create the respective transaction for
@@ -1447,7 +1519,7 @@ class TestThlLedgerManagerAdj:
started=now_w1,
finished=now_w1 + timedelta(minutes=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
assert isinstance(tx, LedgerTransaction)
@@ -1464,7 +1536,7 @@ class TestThlLedgerManagerAdj:
started=now_w2,
finished=now_w2 + timedelta(minutes=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall2, user=user, created=wall2.started
)
assert isinstance(tx, LedgerTransaction)
@@ -1485,34 +1557,38 @@ class TestThlLedgerManagerAdj:
assert user_pay == Decimal("1.52")
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": now + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
+ status=status,
+ status_code_1=status_code_1,
+ finished=now + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
)
- tx = thl_lm.create_tx_bp_adjustment(session=session, created=wall1.started)
+ tx = thl_ledger_manager.create_tx_bp_adjustment(
+ session=session, created=wall1.started
+ )
assert isinstance(tx, LedgerTransaction)
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(product=user.product)
- assert 228 == thl_lm.get_account_balance(account=bp_wallet_account)
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=user.product
+ )
+ assert 228 == thl_ledger_manager.get_account_balance(account=bp_wallet_account)
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
- assert 152 == thl_lm.get_account_balance(account=user_account)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
+ assert 152 == thl_ledger_manager.get_account_balance(account=user_account)
- revenue = thl_lm.get_account_task_complete_revenue()
- assert 0 == thl_lm.get_account_balance(account=revenue)
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ assert 0 == thl_ledger_manager.get_account_balance(account=revenue)
- bp_commission_account = thl_lm.get_account_or_create_bp_commission(
+ bp_commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
product=user.product
)
- assert 20 == thl_lm.get_account_balance(account=bp_commission_account)
+ assert 20 == thl_ledger_manager.get_account_balance(
+ account=bp_commission_account
+ )
# the total (4.00) = 2.28 + 1.52 + .20
- assert thl_lm.check_ledger_balanced()
+ assert thl_ledger_manager.check_ledger_balanced()
# This should do nothing (since we haven't adjusted any wall events)
session.adjust_status()
@@ -1522,7 +1598,7 @@ class TestThlLedgerManagerAdj:
session.get_user_payout_after_adjustment(),
)
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
assert (
"create_transaction_bp_adjustment. No transactions needed." in caplog.text
)
@@ -1533,16 +1609,16 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=0,
adjusted_timestamp=now + timedelta(hours=1),
)
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
# -$1.00 b/c the MP took the $1 back, but we haven't yet taken the BP payment back
- assert -100 == thl_lm.get_account_balance(revenue)
+ assert -100 == thl_ledger_manager.get_account_balance(revenue)
session.adjust_status()
print(
session.get_status_after_adjustment(),
session.get_payout_after_adjustment(),
session.get_user_payout_after_adjustment(),
)
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
# running this twice b/c it should do nothing the 2nd time
print(
@@ -1551,16 +1627,16 @@ class TestThlLedgerManagerAdj:
session.get_user_payout_after_adjustment(),
)
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
assert (
"create_transaction_bp_adjustment. No transactions needed." in caplog.text
)
- assert 228 - 57 == thl_lm.get_account_balance(bp_wallet_account)
- assert 152 - 38 == thl_lm.get_account_balance(user_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 - 5 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ assert 228 - 57 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 152 - 38 == thl_ledger_manager.get_account_balance(user_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 - 5 == thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
# unrecon the $1 survey
wall1.update(
@@ -1568,7 +1644,7 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=None,
adjusted_timestamp=now + timedelta(hours=2),
)
- tx = thl_lm.create_tx_task_adjustment(wall=wall1, user=user)
+ tx = thl_ledger_manager.create_tx_task_adjustment(wall=wall1, user=user)
assert isinstance(tx, LedgerTransaction)
new_status, new_payout, new_user_payout = (
@@ -1581,13 +1657,17 @@ class TestThlLedgerManagerAdj:
session.get_payout_after_adjustment(),
session.get_user_payout_after_adjustment(),
)
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
- assert 228 - 57 + 57 == thl_lm.get_account_balance(bp_wallet_account)
- assert 152 - 38 + 38 == thl_lm.get_account_balance(user_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 - 5 + 5 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ assert 228 - 57 + 57 == thl_ledger_manager.get_account_balance(
+ bp_wallet_account
+ )
+ assert 152 - 38 + 38 == thl_ledger_manager.get_account_balance(user_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 - 5 + 5 == thl_ledger_manager.get_account_balance(
+ bp_commission_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
# make the $2 failure into a complete also
wall3.update(
@@ -1595,7 +1675,7 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=wall3.cpi,
adjusted_timestamp=now + timedelta(hours=2),
)
- thl_lm.create_tx_task_adjustment(wall3, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall3, user)
new_status, new_payout, new_user_payout = (
session.determine_new_status_and_payouts()
)
@@ -1606,27 +1686,30 @@ class TestThlLedgerManagerAdj:
session.get_payout_after_adjustment(),
session.get_user_payout_after_adjustment(),
)
- thl_lm.create_tx_bp_adjustment(session)
- assert 228 - 57 + 57 + 114 == thl_lm.get_account_balance(bp_wallet_account)
- assert 152 - 38 + 38 + 76 == thl_lm.get_account_balance(user_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 - 5 + 5 + 10 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ thl_ledger_manager.create_tx_bp_adjustment(session)
+ assert 228 - 57 + 57 + 114 == thl_ledger_manager.get_account_balance(
+ bp_wallet_account
+ )
+ assert 152 - 38 + 38 + 76 == thl_ledger_manager.get_account_balance(
+ user_account
+ )
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 - 5 + 5 + 10 == thl_ledger_manager.get_account_balance(
+ bp_commission_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
def test_create_transaction_bp_adjustment_cpi_adjustment(
self,
- user_factory,
- product_user_wallet_no,
- create_main_accounts,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_user_wallet_no: Product,
caplog,
- thl_lm,
- lm,
- utc_hour_ago,
- currency,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ utc_hour_ago: datetime,
+ currency: LedgerCurrency,
):
- delete_ledger_db()
- create_main_accounts()
+
user: User = user_factory(product=product_user_wallet_no)
wall1 = Wall(
@@ -1640,7 +1723,7 @@ class TestThlLedgerManagerAdj:
started=utc_hour_ago,
finished=utc_hour_ago + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall1, user=user, created=wall1.started
)
assert isinstance(tx, LedgerTransaction)
@@ -1656,32 +1739,34 @@ class TestThlLedgerManagerAdj:
started=utc_hour_ago,
finished=utc_hour_ago + timedelta(seconds=1),
)
- tx = thl_lm.create_tx_task_complete(
+ tx = thl_ledger_manager.create_tx_task_complete(
wall=wall2, user=user, created=wall2.started
)
assert isinstance(tx, LedgerTransaction)
session = Session(started=wall1.started, user=user, wall_events=[wall1, wall2])
status, status_code_1 = session.determine_session_status()
- thl_net, commission_amount, bp_pay, user_pay = session.determine_payments()
+ _, _, bp_pay, user_pay = session.determine_payments()
session.update(
- **{
- "status": status,
- "status_code_1": status_code_1,
- "finished": utc_hour_ago + timedelta(minutes=10),
- "payout": bp_pay,
- "user_payout": user_pay,
- }
- )
- thl_lm.create_tx_bp_payment(session, created=wall1.started)
-
- revenue = thl_lm.get_account_task_complete_revenue()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_commission_account = thl_lm.get_account_or_create_bp_commission(user.product)
- assert 380 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ status=status,
+ status_code_1=status_code_1,
+ finished=utc_hour_ago + timedelta(minutes=10),
+ payout=bp_pay,
+ user_payout=user_pay,
+ )
+ thl_ledger_manager.create_tx_bp_payment(session, created=wall1.started)
+
+ revenue = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ user.product
+ )
+ assert 380 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 == thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
# cpi adjustment $1 -> $.60.
wall1.update(
@@ -1689,17 +1774,17 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=Decimal("0.60"),
adjusted_timestamp=utc_hour_ago + timedelta(minutes=30),
)
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
# -$0.40 b/c the MP took $0.40 back, but we haven't yet taken the BP payment back
- assert -40 == thl_lm.get_account_balance(revenue)
+ assert -40 == thl_ledger_manager.get_account_balance(revenue)
session.adjust_status()
print(
session.get_status_after_adjustment(),
session.get_payout_after_adjustment(),
session.get_user_payout_after_adjustment(),
)
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
# running this twice b/c it should do nothing the 2nd time
print(
@@ -1708,14 +1793,14 @@ class TestThlLedgerManagerAdj:
session.get_user_payout_after_adjustment(),
)
with caplog.at_level(logging.INFO):
- thl_lm.create_tx_bp_adjustment(session)
+ thl_ledger_manager.create_tx_bp_adjustment(session)
assert "create_transaction_bp_adjustment." in caplog.text
assert "No transactions needed." in caplog.text
- assert 380 - 38 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 20 - 2 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ assert 380 - 38 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 20 - 2 == thl_ledger_manager.get_account_balance(bp_commission_account)
+ assert thl_ledger_manager.check_ledger_balanced()
# adjust it to failure
wall1.update(
@@ -1723,13 +1808,17 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=0,
adjusted_timestamp=utc_hour_ago + timedelta(minutes=45),
)
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
session.adjust_status()
- thl_lm.create_tx_bp_adjustment(session)
- assert 300 - (300 * 0.05) == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 300 * 0.05 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ thl_ledger_manager.create_tx_bp_adjustment(session)
+ assert 300 - (300 * 0.05) == thl_ledger_manager.get_account_balance(
+ bp_wallet_account
+ )
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 300 * 0.05 == thl_ledger_manager.get_account_balance(
+ bp_commission_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
# and then back to cpi adj again, but this time for more than the orig amount
wall1.update(
@@ -1737,13 +1826,17 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=Decimal("2.00"),
adjusted_timestamp=utc_hour_ago + timedelta(minutes=45),
)
- thl_lm.create_tx_task_adjustment(wall1, user)
+ thl_ledger_manager.create_tx_task_adjustment(wall1, user)
session.adjust_status()
- thl_lm.create_tx_bp_adjustment(session)
- assert 500 - (500 * 0.05) == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(revenue)
- assert 500 * 0.05 == thl_lm.get_account_balance(bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ thl_ledger_manager.create_tx_bp_adjustment(session)
+ assert 500 - (500 * 0.05) == thl_ledger_manager.get_account_balance(
+ bp_wallet_account
+ )
+ assert 0 == thl_ledger_manager.get_account_balance(revenue)
+ assert 500 * 0.05 == thl_ledger_manager.get_account_balance(
+ bp_commission_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
# And adjust again
wall1.update(
@@ -1751,12 +1844,14 @@ class TestThlLedgerManagerAdj:
adjusted_cpi=Decimal("3.00"),
adjusted_timestamp=utc_hour_ago + timedelta(minutes=45),
)
- thl_lm.create_tx_task_adjustment(wall=wall1, user=user)
+ thl_ledger_manager.create_tx_task_adjustment(wall=wall1, user=user)
session.adjust_status()
- thl_lm.create_tx_bp_adjustment(session=session)
- assert 600 - (600 * 0.05) == thl_lm.get_account_balance(
+ thl_ledger_manager.create_tx_bp_adjustment(session=session)
+ assert 600 - (600 * 0.05) == thl_ledger_manager.get_account_balance(
account=bp_wallet_account
)
- assert 0 == thl_lm.get_account_balance(account=revenue)
- assert 600 * 0.05 == thl_lm.get_account_balance(account=bp_commission_account)
- assert thl_lm.check_ledger_balanced()
+ assert 0 == thl_ledger_manager.get_account_balance(account=revenue)
+ assert 600 * 0.05 == thl_ledger_manager.get_account_balance(
+ account=bp_commission_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
diff --git a/tests/managers/thl/test_ledger/test_thl_lm_tx__user_payouts.py b/tests/managers/thl/test_ledger/test_thl_lm_tx__user_payouts.py
index 1e7146a..3fd21dc 100644
--- a/tests/managers/thl/test_ledger/test_thl_lm_tx__user_payouts.py
+++ b/tests/managers/thl/test_ledger/test_thl_lm_tx__user_payouts.py
@@ -1,30 +1,37 @@
+from __future__ import annotations
+
import logging
-from datetime import datetime, timezone, timedelta
+from collections.abc import Callable
from decimal import Decimal
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.managers.thl.ledger_manager.exceptions import (
- LedgerTransactionFlagAlreadyExistsError,
LedgerTransactionConditionFailedError,
+ LedgerTransactionFlagAlreadyExistsError,
)
-from generalresearch.models.thl.user import User
-from generalresearch.models.thl.wallet import PayoutType
from generalresearch.models.thl.payout import UserPayoutEvent
-from test_utils.managers.ledger.conftest import create_main_accounts
+from generalresearch.models.thl.wallet.definitions import PayoutType
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
class TestLedgerManagerAMT:
def test_create_transaction_amt_ass_request(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
@@ -40,16 +47,16 @@ class TestLedgerManagerAMT:
)
flag_key = f"test:user_payout:{pe.uuid}:request"
flag_name = f"ledger-manager:transaction_flag:{flag_key}"
- lm.redis_client.delete(flag_name)
+ ledger_manager.redis_client.delete(flag_name)
# User has $0 in their wallet. They are allowed amt_assignment payouts until -$1.00
- thl_lm.create_tx_user_payout_request(user=user, payout_event=pe)
+ thl_ledger_manager.create_tx_user_payout_request(user=user, payout_event=pe)
with pytest.raises(expected_exception=LedgerTransactionFlagAlreadyExistsError):
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user, payout_event=pe, skip_flag_check=False
)
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user, payout_event=pe, skip_flag_check=True
)
pe2 = UserPayoutEvent(
@@ -62,36 +69,40 @@ class TestLedgerManagerAMT:
flag_key = f"test:user_payout:{pe2.uuid}:request"
flag_name = f"ledger-manager:transaction_flag:{flag_key}"
- lm.redis_client.delete(flag_name)
+ ledger_manager.redis_client.delete(flag_name)
# 96 cents would put them over the -$1.00 limit
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- thl_lm.create_tx_user_payout_request(user, payout_event=pe2)
+ thl_ledger_manager.create_tx_user_payout_request(user, payout_event=pe2)
# But they could do 0.95 cents
pe2.amount = 95
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe2, skip_flag_check=True
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
product=user.product
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(
+ user=user
+ )
- assert 0 == lm.get_account_balance(account=bp_wallet_account)
- assert 0 == lm.get_account_balance(account=cash)
- assert 100 == lm.get_account_balance(account=bp_pending_account)
- assert -100 == lm.get_account_balance(account=user_wallet_account)
- assert thl_lm.check_ledger_balanced()
- assert -5 == thl_lm.get_account_filtered_balance(
+ assert 0 == ledger_manager.get_account_balance(account=bp_wallet_account)
+ assert 0 == ledger_manager.get_account_balance(account=cash)
+ assert 100 == ledger_manager.get_account_balance(account=bp_pending_account)
+ assert -100 == ledger_manager.get_account_balance(account=user_wallet_account)
+ assert thl_ledger_manager.check_ledger_balanced()
+ assert -5 == thl_ledger_manager.get_account_filtered_balance(
account=user_wallet_account,
metadata_key="payoutevent",
metadata_value=pe.uuid,
)
- assert -95 == thl_lm.get_account_filtered_balance(
+ assert -95 == thl_ledger_manager.get_account_filtered_balance(
account=user_wallet_account,
metadata_key="payoutevent",
metadata_value=pe2.uuid,
@@ -99,12 +110,12 @@ class TestLedgerManagerAMT:
def test_create_transaction_amt_ass_complete(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
@@ -118,40 +129,42 @@ class TestLedgerManagerAMT:
debit_account_uuid=uuid4().hex,
)
flag = f"ledger-manager:transaction_flag:test:user_payout:{pe.uuid}:request"
- lm.redis_client.delete(flag)
+ ledger_manager.redis_client.delete(flag)
flag = f"ledger-manager:transaction_flag:test:user_payout:{pe.uuid}:complete"
- lm.redis_client.delete(flag)
+ ledger_manager.redis_client.delete(flag)
# User has $0 in their wallet. They are allowed amt_assignment payouts until -$1.00
- thl_lm.create_tx_user_payout_request(user, payout_event=pe)
- thl_lm.create_tx_user_payout_complete(user, payout_event=pe)
+ thl_ledger_manager.create_tx_user_payout_request(user, payout_event=pe)
+ thl_ledger_manager.create_tx_user_payout_complete(user, payout_event=pe)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
user.product
)
- bp_amt_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
+ user.product
+ )
+ bp_amt_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
user.product, expense_name="amt"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user)
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(user)
# BP wallet pays the 1cent fee
- assert -1 == thl_lm.get_account_balance(bp_wallet_account)
- assert -5 == thl_lm.get_account_balance(cash)
- assert -1 == thl_lm.get_account_balance(bp_amt_expense_account)
- assert 0 == thl_lm.get_account_balance(bp_pending_account)
- assert -5 == lm.get_account_balance(user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ assert -1 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert -5 == thl_ledger_manager.get_account_balance(cash)
+ assert -1 == thl_ledger_manager.get_account_balance(bp_amt_expense_account)
+ assert 0 == thl_ledger_manager.get_account_balance(bp_pending_account)
+ assert -5 == ledger_manager.get_account_balance(user_wallet_account)
+ assert thl_ledger_manager.check_ledger_balanced()
def test_create_transaction_amt_bonus(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
@@ -166,15 +179,15 @@ class TestLedgerManagerAMT:
debit_account_uuid=uuid4().hex,
)
flag = f"ledger-manager:transaction_flag:test:user_payout:{pe.uuid}:request"
- lm.redis_client.delete(flag)
+ ledger_manager.redis_client.delete(flag)
flag = f"ledger-manager:transaction_flag:test:user_payout:{pe.uuid}:complete"
- lm.redis_client.delete(flag)
+ ledger_manager.redis_client.delete(flag)
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
# User has $0 in their wallet. No amt bonus allowed
- thl_lm.create_tx_user_payout_request(user, payout_event=pe)
+ thl_ledger_manager.create_tx_user_payout_request(user, payout_event=pe)
- thl_lm.create_tx_user_bonus(
+ thl_ledger_manager.create_tx_user_bonus(
user,
amount=Decimal(5),
ref_uuid="e703830dec124f17abed2d697d8d7701",
@@ -182,68 +195,68 @@ class TestLedgerManagerAMT:
skip_flag_check=True,
)
pe.amount = 101
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe, skip_flag_check=False
)
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe, skip_flag_check=False
)
with pytest.raises(expected_exception=LedgerTransactionFlagAlreadyExistsError):
# duplicate, even if amount changed
pe.amount = 200
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe, skip_flag_check=False
)
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
# duplicate
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe, skip_flag_check=True
)
pe.uuid = "533364150de4451198e5774e221a2acb"
pe.amount = 9900
with pytest.raises(expected_exception=ValueError):
# Trying to complete payout with no pending tx
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe, skip_flag_check=True
)
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
# trying to payout $99 with only a $5 balance
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe, skip_flag_check=True
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
user.product
)
- bp_amt_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_amt_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
user.product, expense_name="amt"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user)
- assert -500 + round(-101 * 0.20) == thl_lm.get_account_balance(
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(user)
+ assert -500 + round(-101 * 0.20) == thl_ledger_manager.get_account_balance(
bp_wallet_account
)
- assert -101 == lm.get_account_balance(cash)
- assert -20 == lm.get_account_balance(bp_amt_expense_account)
- assert 0 == lm.get_account_balance(bp_pending_account)
- assert 500 - 101 == lm.get_account_balance(user_wallet_account)
- assert lm.check_ledger_balanced() is True
+ assert -101 == ledger_manager.get_account_balance(cash)
+ assert -20 == ledger_manager.get_account_balance(bp_amt_expense_account)
+ assert 0 == ledger_manager.get_account_balance(bp_pending_account)
+ assert 500 - 101 == ledger_manager.get_account_balance(user_wallet_account)
+ assert ledger_manager.check_ledger_balanced() is True
def test_create_transaction_amt_bonus_cancel(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
caplog,
- thl_lm,
- lm,
- delete_ledger_db,
+ thl_ledger_manager: ThlLedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
- now = datetime.now(timezone.utc) - timedelta(hours=1)
user: User = user_factory(product=product_amt_true)
pe = UserPayoutEvent(
@@ -254,41 +267,48 @@ class TestLedgerManagerAMT:
debit_account_uuid=uuid4().hex,
)
- thl_lm.create_tx_user_bonus(
+ thl_ledger_manager.create_tx_user_bonus(
user,
amount=Decimal(5),
ref_uuid="c44f4da2db1d421ebc6a5e5241ca4ce6",
description="Bribe",
skip_flag_check=True,
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe, skip_flag_check=True
)
- thl_lm.create_tx_user_payout_cancelled(
+ thl_ledger_manager.create_tx_user_payout_cancelled(
user, payout_event=pe, skip_flag_check=True
)
- with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- with caplog.at_level(logging.WARNING):
- thl_lm.create_tx_user_payout_complete(
- user, payout_event=pe, skip_flag_check=True
- )
+ with pytest.raises(
+ expected_exception=LedgerTransactionConditionFailedError
+ ), caplog.at_level(logging.WARNING):
+ thl_ledger_manager.create_tx_user_payout_complete(
+ user, payout_event=pe, skip_flag_check=True
+ )
assert "trying to complete payout that was already cancelled" in caplog.text
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
user.product
)
- bp_amt_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_amt_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
user.product, expense_name="amt"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user)
- assert -500 == thl_lm.get_account_balance(account=bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(account=cash)
- assert 0 == thl_lm.get_account_balance(account=bp_amt_expense_account)
- assert 0 == thl_lm.get_account_balance(account=bp_pending_account)
- assert 500 == thl_lm.get_account_balance(account=user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(user)
+ assert -500 == thl_ledger_manager.get_account_balance(account=bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(account=cash)
+ assert 0 == thl_ledger_manager.get_account_balance(
+ account=bp_amt_expense_account
+ )
+ assert 0 == thl_ledger_manager.get_account_balance(account=bp_pending_account)
+ assert 500 == thl_ledger_manager.get_account_balance(
+ account=user_wallet_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
pe2 = UserPayoutEvent(
uuid=uuid4().hex,
@@ -297,17 +317,18 @@ class TestLedgerManagerAMT:
cashout_method_uuid=uuid4().hex,
debit_account_uuid=uuid4().hex,
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe2, skip_flag_check=True
)
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe2, skip_flag_check=True
)
- with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- with caplog.at_level(logging.WARNING):
- thl_lm.create_tx_user_payout_cancelled(
- user, payout_event=pe2, skip_flag_check=True
- )
+ with pytest.raises(
+ expected_exception=LedgerTransactionConditionFailedError
+ ), caplog.at_level(logging.WARNING):
+ thl_ledger_manager.create_tx_user_payout_cancelled(
+ user, payout_event=pe2, skip_flag_check=True
+ )
assert "trying to cancel payout that was already completed" in caplog.text
@@ -315,12 +336,12 @@ class TestLedgerManagerTango:
def test_create_transaction_tango_request(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
@@ -337,64 +358,65 @@ class TestLedgerManagerTango:
)
flag_key = f"test:user_payout:{pe.uuid}:request"
flag_name = f"ledger-manager:transaction_flag:{flag_key}"
- lm.redis_client.delete(flag_name)
- thl_lm.create_tx_user_bonus(
+ ledger_manager.redis_client.delete(flag_name)
+ thl_ledger_manager.create_tx_user_bonus(
user,
amount=Decimal(6),
ref_uuid="e703830dec124f17abed2d697d8d7701",
description="Bribe",
skip_flag_check=True,
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe, skip_flag_check=True
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
user.product
)
- bp_tango_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_tango_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
user.product, expense_name="tango"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user)
- assert -600 == thl_lm.get_account_balance(bp_wallet_account)
- assert 0 == thl_lm.get_account_balance(cash)
- assert 0 == thl_lm.get_account_balance(bp_tango_expense_account)
- assert 500 == thl_lm.get_account_balance(bp_pending_account)
- assert 600 - 500 == thl_lm.get_account_balance(user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(user)
+ assert -600 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert 0 == thl_ledger_manager.get_account_balance(cash)
+ assert 0 == thl_ledger_manager.get_account_balance(bp_tango_expense_account)
+ assert 500 == thl_ledger_manager.get_account_balance(bp_pending_account)
+ assert 600 - 500 == thl_ledger_manager.get_account_balance(user_wallet_account)
+ assert thl_ledger_manager.check_ledger_balanced()
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user, payout_event=pe, skip_flag_check=True
)
- assert -600 - round(500 * 0.035) == thl_lm.get_account_balance(
+ assert -600 - round(500 * 0.035) == thl_ledger_manager.get_account_balance(
bp_wallet_account
)
- assert -500, thl_lm.get_account_balance(cash)
- assert round(-500 * 0.035) == thl_lm.get_account_balance(
+ assert -500, thl_ledger_manager.get_account_balance(cash)
+ assert round(-500 * 0.035) == thl_ledger_manager.get_account_balance(
bp_tango_expense_account
)
- assert 0 == lm.get_account_balance(bp_pending_account)
- assert 100 == lm.get_account_balance(user_wallet_account)
- assert lm.check_ledger_balanced()
+ assert 0 == ledger_manager.get_account_balance(bp_pending_account)
+ assert 100 == ledger_manager.get_account_balance(user_wallet_account)
+ assert ledger_manager.check_ledger_balanced()
class TestLedgerManagerPaypal:
def test_create_transaction_paypal_request(
self,
- user_factory,
- product_amt_true,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
- now = datetime.now(tz=timezone.utc) - timedelta(hours=1)
user: User = user_factory(product=product_amt_true)
# debit_account_uuid nothing checks they match the ledger ... todo?
@@ -407,8 +429,8 @@ class TestLedgerManagerPaypal:
)
flag_key = f"test:user_payout:{pe.uuid}:request"
flag_name = f"ledger-manager:transaction_flag:{flag_key}"
- lm.redis_client.delete(flag_name)
- thl_lm.create_tx_user_bonus(
+ ledger_manager.redis_client.delete(flag_name)
+ thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(6),
ref_uuid="e703830dec124f17abed2d697d8d7701",
@@ -416,79 +438,91 @@ class TestLedgerManagerPaypal:
skip_flag_check=True,
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user, payout_event=pe, skip_flag_check=True
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
product=user.product
)
- bp_paypal_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_paypal_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
product=user.product, expense_name="paypal"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user=user)
- assert -600 == lm.get_account_balance(account=bp_wallet_account)
- assert 0 == lm.get_account_balance(account=cash)
- assert 0 == lm.get_account_balance(account=bp_paypal_expense_account)
- assert 500 == lm.get_account_balance(account=bp_pending_account)
- assert 600 - 500 == lm.get_account_balance(account=user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(
+ user=user
+ )
+ assert -600 == ledger_manager.get_account_balance(account=bp_wallet_account)
+ assert 0 == ledger_manager.get_account_balance(account=cash)
+ assert 0 == ledger_manager.get_account_balance(
+ account=bp_paypal_expense_account
+ )
+ assert 500 == ledger_manager.get_account_balance(account=bp_pending_account)
+ assert 600 - 500 == ledger_manager.get_account_balance(
+ account=user_wallet_account
+ )
+ assert thl_ledger_manager.check_ledger_balanced()
- thl_lm.create_tx_user_payout_complete(
+ thl_ledger_manager.create_tx_user_payout_complete(
user=user, payout_event=pe, skip_flag_check=True, fee_amount=Decimal("0.50")
)
- assert -600 - 50 == thl_lm.get_account_balance(bp_wallet_account)
- assert -500 == thl_lm.get_account_balance(cash)
- assert -50 == thl_lm.get_account_balance(bp_paypal_expense_account)
- assert 0 == thl_lm.get_account_balance(bp_pending_account)
- assert 100 == thl_lm.get_account_balance(user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ assert -600 - 50 == thl_ledger_manager.get_account_balance(bp_wallet_account)
+ assert -500 == thl_ledger_manager.get_account_balance(cash)
+ assert -50 == thl_ledger_manager.get_account_balance(bp_paypal_expense_account)
+ assert 0 == thl_ledger_manager.get_account_balance(bp_pending_account)
+ assert 100 == thl_ledger_manager.get_account_balance(user_wallet_account)
+ assert thl_ledger_manager.check_ledger_balanced()
class TestLedgerManagerBonus:
def test_create_transaction_bonus(
self,
- user_factory,
- product_user_wallet_yes,
- create_main_accounts,
- thl_lm,
- lm,
- delete_ledger_db,
+ user_factory: Callable[..., User],
+ product_user_wallet_yes: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
+ delete_ledger_db: Callable[..., None],
):
delete_ledger_db()
create_main_accounts()
user: User = user_factory(product=product_user_wallet_yes)
- thl_lm.create_tx_user_bonus(
+ thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(5),
ref_uuid="8d0aaf612462448a9ebdd57fab0fc660",
description="Bribe",
skip_flag_check=True,
)
- cash = thl_lm.get_account_cash()
- bp_wallet_account = thl_lm.get_account_or_create_bp_wallet(user.product)
- bp_pending_account = thl_lm.get_or_create_bp_pending_payout_account(
+ cash = thl_ledger_manager.get_account_cash()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ user.product
+ )
+ bp_pending_account = thl_ledger_manager.get_or_create_bp_pending_payout_account(
product=user.product
)
- bp_amt_expense_account = thl_lm.get_account_or_create_bp_expense(
+ bp_amt_expense_account = thl_ledger_manager.get_account_or_create_bp_expense(
user.product, expense_name="amt"
)
- user_wallet_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(
+ user=user
+ )
- assert -500 == lm.get_account_balance(account=bp_wallet_account)
- assert 0 == lm.get_account_balance(account=cash)
- assert 0 == lm.get_account_balance(account=bp_amt_expense_account)
- assert 0 == lm.get_account_balance(account=bp_pending_account)
- assert 500 == lm.get_account_balance(account=user_wallet_account)
- assert thl_lm.check_ledger_balanced()
+ assert -500 == ledger_manager.get_account_balance(account=bp_wallet_account)
+ assert 0 == ledger_manager.get_account_balance(account=cash)
+ assert 0 == ledger_manager.get_account_balance(account=bp_amt_expense_account)
+ assert 0 == ledger_manager.get_account_balance(account=bp_pending_account)
+ assert 500 == ledger_manager.get_account_balance(account=user_wallet_account)
+ assert thl_ledger_manager.check_ledger_balanced()
with pytest.raises(expected_exception=LedgerTransactionFlagAlreadyExistsError):
- thl_lm.create_tx_user_bonus(
+ thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(5),
ref_uuid="8d0aaf612462448a9ebdd57fab0fc660",
@@ -496,7 +530,7 @@ class TestLedgerManagerBonus:
skip_flag_check=False,
)
with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- thl_lm.create_tx_user_bonus(
+ thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(5),
ref_uuid="8d0aaf612462448a9ebdd57fab0fc660",
diff --git a/tests/managers/thl/test_ledger/test_thl_pem.py b/tests/managers/thl/test_ledger/test_thl_pem.py
index 5fb9e7d..fb35aa4 100644
--- a/tests/managers/thl/test_ledger/test_thl_pem.py
+++ b/tests/managers/thl/test_ledger/test_thl_pem.py
@@ -1,21 +1,39 @@
-import uuid
+from __future__ import annotations
+
+from collections.abc import Callable
from random import randint
-from uuid import uuid4, UUID
+from typing import TYPE_CHECKING
+from uuid import UUID, uuid4
import pytest
from generalresearch.currency import USDCent
from generalresearch.models.thl.definitions import PayoutStatus
-from generalresearch.models.thl.payout import BrokerageProductPayoutEvent
-from generalresearch.models.thl.product import Product
+from generalresearch.models.thl.payout import (
+ BrokerageProductPayoutEvent,
+)
from generalresearch.models.thl.wallet.cashout_method import (
CashoutRequestInfo,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import (
+ ThlLedgerManager,
+ )
+ from generalresearch.managers.thl.payout import (
+ BrokerageProductPayoutEventManager,
+ UserPayoutEventManager,
+ )
+ from generalresearch.models.thl.payout import UserPayoutEvent
+ from generalresearch.models.thl.product import Product
+
class TestThlPayoutEventManager:
- def test_get_by_uuid(self, brokerage_product_payout_event_manager, thl_lm):
+ def test_get_by_uuid(
+ self, brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager
+ ):
"""This validates that the method raises an exception if it
fails. There are plenty of other tests that use this method so
it seems silly to duplicate it here again
@@ -27,35 +45,31 @@ class TestThlPayoutEventManager:
def test_filter_by(
self,
- product_factory,
- usd_cent,
- bp_payout_event_factory,
- thl_lm,
- brokerage_product_payout_event_manager,
+ product_factory: Callable[..., Product],
+ usd_cent: USDCent,
+ bp_payout_event_factory: Callable[..., BrokerageProductPayoutEvent],
+ thl_ledger_manager: ThlLedgerManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
):
- from generalresearch.models.thl.payout import UserPayoutEvent
N_PRODUCTS = randint(3, 10)
N_PAYOUT_EVENTS = randint(3, 10)
amounts = []
products = []
- for x_idx in range(N_PRODUCTS):
+ for _ in range(N_PRODUCTS):
product: Product = product_factory()
- thl_lm.get_account_or_create_bp_wallet(product=product)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
products.append(product)
- brokerage_product_payout_event_manager.set_account_lookup_table(
- thl_lm=thl_lm
- )
- for y_idx in range(N_PAYOUT_EVENTS):
+ for _ in range(N_PAYOUT_EVENTS):
pe = bp_payout_event_factory(product=product, usd_cent=usd_cent)
amounts.append(int(usd_cent))
assert isinstance(pe, BrokerageProductPayoutEvent)
# We just added Payout Events for Products, now go ahead and
# query for them
- accounts = thl_lm.get_accounts_bp_wallet_for_products(
+ accounts = thl_ledger_manager.get_accounts_bp_wallet_for_products(
product_uuids=[i.uuid for i in products]
)
res = brokerage_product_payout_event_manager.filter_by(
@@ -67,36 +81,32 @@ class TestThlPayoutEventManager:
def test_get_bp_payout_events_for_product(
self,
- product_factory,
- usd_cent,
- bp_payout_event_factory,
- brokerage_product_payout_event_manager,
- thl_lm,
+ product_factory: Callable[..., Product],
+ usd_cent: USDCent,
+ bp_payout_event_factory: Callable[..., BrokerageProductPayoutEvent],
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ thl_ledger_manager: ThlLedgerManager,
):
- from generalresearch.models.thl.payout import UserPayoutEvent
N_PRODUCTS = randint(3, 10)
N_PAYOUT_EVENTS = randint(3, 10)
amounts = []
products = []
- for x_idx in range(N_PRODUCTS):
+ for _ in range(N_PRODUCTS):
product: Product = product_factory()
products.append(product)
- thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(
- thl_lm=thl_lm
- )
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
- for y_idx in range(N_PAYOUT_EVENTS):
+ for _ in range(N_PAYOUT_EVENTS):
pe = bp_payout_event_factory(product=product, usd_cent=usd_cent)
amounts.append(usd_cent)
assert isinstance(pe, BrokerageProductPayoutEvent)
- # We just added 5 Payouts for a specific Product, now go
+ # We just added 5 Payouts for a specific product: Product, now go
# ahead and query for them
res = brokerage_product_payout_event_manager.get_bp_bp_payout_events_for_products(
- thl_ledger_manager=thl_lm, product_uuids=[product.id]
+ product_uuids=[product.id]
)
assert len(res) == N_PAYOUT_EVENTS
@@ -105,7 +115,7 @@ class TestThlPayoutEventManager:
# ahead and query for them
res = (
brokerage_product_payout_event_manager.get_bp_bp_payout_events_for_products(
- thl_ledger_manager=thl_lm, product_uuids=[i.uuid for i in products]
+ product_uuids=[i.uuid for i in products],
)
)
@@ -113,13 +123,12 @@ class TestThlPayoutEventManager:
assert sum([i.amount for i in res]) == sum(amounts)
@pytest.mark.skip
- def test_get_payout_detail(self, user_payout_event_manager):
+ def test_get_payout_detail(self, user_payout_event_manager: UserPayoutEventManager):
"""This fails because the description coming back is None, but then
it tries to return a PayoutEvent which validates that the
description can't be None
"""
from generalresearch.models.thl.payout import (
- UserPayoutEvent,
PayoutType,
)
@@ -145,11 +154,15 @@ class TestThlPayoutEventManager:
# def test_filter_by(self):
# raise NotImplementedError
- def test_create(self, user_payout_event_manager):
+ def test_create(
+ self,
+ user_payout_event_factory: Callable[..., UserPayoutEvent],
+ user_payout_event_manager: UserPayoutEventManager,
+ ):
from generalresearch.models.thl.payout import UserPayoutEvent
# Confirm the creation method returns back an instance.
- pe = user_payout_event_manager.create_dummy()
+ pe = user_payout_event_factory()
assert isinstance(pe, UserPayoutEvent)
# Now query the DB for that PayoutEvent to confirm it was actually
@@ -167,27 +180,26 @@ class TestThlPayoutEventManager:
def test_create_bp_payout(
self,
- product,
- delete_ledger_db,
- create_main_accounts,
- thl_lm,
- brokerage_product_payout_event_manager,
- lm,
+ product: Product,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ ledger_manager: LedgerManager,
):
- from generalresearch.models.thl.payout import UserPayoutEvent
delete_ledger_db()
create_main_accounts()
- account_bp_wallet = thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
-
+ account_bp_wallet = thl_ledger_manager.get_account_or_create_bp_wallet(
+ product=product
+ )
rand_amount = randint(a=99, b=999)
# Save a Brokerage Product Payout, so we have something in the
# Payout Event table and the respective ledger TX and Entry rows for it
pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ thl_ledger_manager=thl_ledger_manager,
product=product,
amount=USDCent(rand_amount),
skip_wallet_balance_check=True,
@@ -196,15 +208,17 @@ class TestThlPayoutEventManager:
assert isinstance(pe, BrokerageProductPayoutEvent)
# Now try to query for it!
- res = thl_lm.get_tx_bp_payouts(account_uuids=[account_bp_wallet.uuid])
+ res = thl_ledger_manager.get_tx_bp_payouts(
+ account_uuids=[account_bp_wallet.uuid]
+ )
assert len(res) == 1
- res = thl_lm.get_tx_bp_payouts(account_uuids=[uuid4().hex])
+ res = thl_ledger_manager.get_tx_bp_payouts(account_uuids=[uuid4().hex])
assert len(res) == 0
# Confirm it added to the users balance. The amount is negative because
- # money was sent to the Brokerage Product, but they didn't have
+ # money was sent to the Brokerage product: Product, but they didn't have
# any activity that earned them money
- bal = lm.get_account_balance(account=account_bp_wallet)
+ bal = ledger_manager.get_account_balance(account=account_bp_wallet)
assert rand_amount == bal * -1
@@ -212,13 +226,13 @@ class TestBPPayoutEvent:
def test_get_bp_bp_payout_events_for_products(
self,
- product_factory,
- bp_payout_event_factory,
- usd_cent,
- delete_ledger_db,
- create_main_accounts,
- brokerage_product_payout_event_manager,
- thl_lm,
+ product_factory: Callable[..., Product],
+ bp_payout_event_factory: Callable[..., BrokerageProductPayoutEvent],
+ usd_cent: USDCent,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ thl_ledger_manager: ThlLedgerManager,
):
delete_ledger_db()
create_main_accounts()
@@ -227,10 +241,9 @@ class TestBPPayoutEvent:
amounts = []
product: Product = product_factory()
- thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
- for y_idx in range(N_PAYOUT_EVENTS):
+ for _ in range(N_PAYOUT_EVENTS):
bp_payout_event_factory(product=product, usd_cent=usd_cent)
amounts.append(usd_cent)
@@ -238,7 +251,7 @@ class TestBPPayoutEvent:
# array of BPPayoutEvents
bp_bp_res = (
brokerage_product_payout_event_manager.get_bp_bp_payout_events_for_products(
- thl_ledger_manager=thl_lm, product_uuids=[product.uuid]
+ product_uuids=[product.uuid]
)
)
assert isinstance(bp_bp_res, list)
diff --git a/tests/managers/thl/test_ledger/test_user_txs.py b/tests/managers/thl/test_ledger/test_user_txs.py
index ecf146f..6b6ef5b 100644
--- a/tests/managers/thl/test_ledger/test_user_txs.py
+++ b/tests/managers/thl/test_ledger/test_user_txs.py
@@ -1,54 +1,58 @@
-from datetime import datetime, timedelta, timezone
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime
from decimal import Decimal
-from typing import TYPE_CHECKING, Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
-from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
from generalresearch.managers.thl.user_compensate import user_compensate
from generalresearch.models.thl.definitions import (
Status,
- WallAdjustedStatus,
)
from generalresearch.models.thl.ledger import (
TransactionType,
UserLedgerTransactionTypesSummary,
UserLedgerTransactionTypeSummary,
)
+from generalresearch.models.thl.wallet.definitions import PayoutType
if TYPE_CHECKING:
- from generalresearch.config import GRLSettings
+ from generalresearch.config import GRLBaseSettings
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.payout import UserPayoutEventManager
from generalresearch.models.thl.product import Product
from generalresearch.models.thl.session import Session
from generalresearch.models.thl.user import User
- from generalresearch.models.thl.wallet import PayoutType
def test_user_txs(
- user_factory: Callable[..., "User"],
- product_amt_true: "Product",
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
create_main_accounts: Callable[..., None],
- thl_lm: ThlLedgerManager,
- lm,
+ thl_ledger_manager: ThlLedgerManager,
+ ledger_manager: LedgerManager,
delete_ledger_db: Callable[..., None],
- session_with_tx_factory,
- adj_to_fail_with_tx_factory,
- adj_to_complete_with_tx_factory,
- session_factory,
- user_payout_event_manager,
+ session_with_tx_factory: Callable[..., Session],
+ adj_to_fail_with_tx_factory: Callable[..., None],
+ adj_to_complete_with_tx_factory: Callable[..., None],
+ session_factory: Callable[..., Session],
+ user_payout_event_manager: UserPayoutEventManager,
utc_now: datetime,
- settings: "GRLSettings",
+ settings: GRLBaseSettings,
):
delete_ledger_db()
create_main_accounts()
user: User = user_factory(product=product_amt_true)
- account = thl_lm.get_account_or_create_user_wallet(user)
+ account = thl_ledger_manager.get_account_or_create_user_wallet(user)
print(f"{account.uuid=}")
s: Session = session_with_tx_factory(user=user, wall_req_cpi=Decimal("1.00"))
- bribe_uuid = user_compensate(
- ledger_manager=thl_lm,
+ user_compensate(
+ ledger_manager=thl_ledger_manager,
user=user,
amount_int=100,
)
@@ -60,9 +64,9 @@ def test_user_txs(
amount=5,
created=utc_now,
payout_type=PayoutType.AMT_HIT,
- request_data=dict(),
+ request_data={},
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
)
@@ -73,9 +77,9 @@ def test_user_txs(
amount=127,
created=utc_now,
payout_type=PayoutType.AMT_BONUS,
- request_data=dict(),
+ request_data={},
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
)
@@ -92,16 +96,16 @@ def test_user_txs(
)
adj_to_complete_with_tx_factory(session=s_fail, created=utc_now)
- # txs = thl_lm.get_tx_filtered_by_account(account.uuid)
+ # txs = thl_ledger_manager.get_tx_filtered_by_account(account.uuid)
# print(len(txs), txs)
- txs = thl_lm.get_user_txs(user)
+ txs = thl_ledger_manager.get_user_txs(user)
assert len(txs.transactions) == 6
assert txs.total == 6
assert txs.page == 1
assert txs.size == 50
# print(len(txs.transactions), txs)
- d = txs.model_dump_json()
+ # d = txs.model_dump_json()
# print(d)
descriptions = {x.description for x in txs.transactions}
@@ -136,33 +140,29 @@ def test_user_txs(
def test_user_txs_pagination(
- user_factory: Callable[..., "User"],
- product_amt_true: "Product",
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
create_main_accounts: Callable[..., None],
- thl_lm: "ThlLedgerManager",
- lm: "LedgerManager",
+ ledger_manager: LedgerManager,
+ thl_ledger_manager: ThlLedgerManager,
delete_ledger_db: Callable[..., None],
- session_with_tx_factory: Callable[..., "Session"],
- adj_to_fail_with_tx_factory,
- user_payout_event_manager,
- utc_now: datetime,
):
delete_ledger_db()
create_main_accounts()
user: User = user_factory(product=product_amt_true)
- account = thl_lm.get_account_or_create_user_wallet(user)
+ account = thl_ledger_manager.get_account_or_create_user_wallet(user)
print(f"{account.uuid=}")
for _ in range(12):
user_compensate(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
user=user,
amount_int=100,
skip_flag_check=True,
)
- txs = thl_lm.get_user_txs(user, page=1, size=5)
+ txs = thl_ledger_manager.get_user_txs(user, page=1, size=5)
assert len(txs.transactions) == 5
assert txs.total == 12
assert txs.page == 1
@@ -171,7 +171,7 @@ def test_user_txs_pagination(
assert txs.summary.user_bonus.entry_count == 12
# Skip to the 3rd page. We made 12, so there are 2 left
- txs = thl_lm.get_user_txs(user, page=3, size=5)
+ txs = thl_ledger_manager.get_user_txs(user, page=3, size=5)
assert len(txs.transactions) == 2
assert txs.total == 12
assert txs.page == 3
@@ -179,7 +179,7 @@ def test_user_txs_pagination(
assert txs.summary.user_bonus.entry_count == 12
# Should be empty, not fail
- txs = thl_lm.get_user_txs(user, page=4, size=5)
+ txs = thl_ledger_manager.get_user_txs(user, page=4, size=5)
assert len(txs.transactions) == 0
assert txs.total == 12
assert txs.page == 4
@@ -187,14 +187,14 @@ def test_user_txs_pagination(
assert txs.summary.user_bonus.entry_count == 12
# Test filtering. We should pull back only this one
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
user_compensate(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
user=user,
amount_int=100,
skip_flag_check=True,
)
- txs = thl_lm.get_user_txs(user, page=1, size=5, time_start=now)
+ txs = thl_ledger_manager.get_user_txs(user, page=1, size=5, time_start=now)
assert len(txs.transactions) == 1
assert txs.total == 1
assert txs.page == 1
@@ -203,8 +203,8 @@ def test_user_txs_pagination(
assert txs.summary.user_bonus.entry_count == 1
# And filtering with 0 results
- now = datetime.now(tz=timezone.utc)
- txs = thl_lm.get_user_txs(user, page=1, size=5, time_start=now)
+ now = datetime.now(tz=UTC)
+ txs = thl_ledger_manager.get_user_txs(user, page=1, size=5, time_start=now)
assert len(txs.transactions) == 0
assert txs.total == 0
assert txs.page == 1
@@ -215,16 +215,13 @@ def test_user_txs_pagination(
def test_user_txs_rolling_balance(
- user_factory: Callable[..., "User"],
- product_amt_true: "Product",
- create_main_accounts,
- thl_lm,
- lm,
+ user_factory: Callable[..., User],
+ product_amt_true: Product,
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
delete_ledger_db: Callable[..., None],
- session_with_tx_factory,
- adj_to_fail_with_tx_factory,
- user_payout_event_manager,
- settings: "GRLSettings",
+ user_payout_event_manager: UserPayoutEventManager,
+ settings: GRLBaseSettings,
):
"""
Creates 3 $1.00 bonuses (postive),
@@ -237,11 +234,11 @@ def test_user_txs_rolling_balance(
create_main_accounts()
user: User = user_factory(product=product_amt_true)
- account = thl_lm.get_account_or_create_user_wallet(user)
+ account = thl_ledger_manager.get_account_or_create_user_wallet(user)
for _ in range(3):
user_compensate(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
user=user,
amount_int=100,
skip_flag_check=True,
@@ -253,21 +250,21 @@ def test_user_txs_rolling_balance(
cashout_method_uuid=settings.amt_bonus_cashout_method_id,
amount=150,
payout_type=PayoutType.AMT_BONUS,
- request_data=dict(),
+ request_data={},
)
- thl_lm.create_tx_user_payout_request(
+ thl_ledger_manager.create_tx_user_payout_request(
user=user,
payout_event=pe,
)
for _ in range(3):
user_compensate(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
user=user,
amount_int=100,
skip_flag_check=True,
)
- txs = thl_lm.get_user_txs(user, page=1, size=10)
+ txs = thl_ledger_manager.get_user_txs(user, page=1, size=10)
assert txs.transactions[0].balance_after == 100
assert txs.transactions[1].balance_after == 200
assert txs.transactions[2].balance_after == 300
@@ -278,7 +275,7 @@ def test_user_txs_rolling_balance(
# Ascending order, get 2nd page, make sure the balances include
# the previous txs. (will return last 3 txs)
- txs = thl_lm.get_user_txs(user, page=2, size=4)
+ txs = thl_ledger_manager.get_user_txs(user, page=2, size=4)
assert len(txs.transactions) == 3
assert txs.transactions[0].balance_after == 250
assert txs.transactions[1].balance_after == 350
@@ -286,7 +283,7 @@ def test_user_txs_rolling_balance(
# Descending order, get 1st page. Will
# return most recent 3 txs in desc order
- txs = thl_lm.get_user_txs(user, page=1, size=3, order_by="-created")
+ txs = thl_ledger_manager.get_user_txs(user, page=1, size=3, order_by="-created")
assert len(txs.transactions) == 3
assert txs.transactions[0].balance_after == 450
assert txs.transactions[1].balance_after == 350
diff --git a/tests/managers/thl/test_ledger/test_wallet.py b/tests/managers/thl/test_ledger/test_wallet.py
index a0abd7c..0a1da73 100644
--- a/tests/managers/thl/test_ledger/test_wallet.py
+++ b/tests/managers/thl/test_ledger/test_wallet.py
@@ -1,20 +1,31 @@
+from __future__ import annotations
+
+from collections.abc import Callable
from decimal import Decimal
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.models.thl.product import (
- UserWalletConfig,
PayoutConfig,
PayoutTransformation,
PayoutTransformationPercentArgs,
+ Product,
+ UserWalletConfig,
)
-from generalresearch.models.thl.user import User
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.models.thl.user import User
@pytest.fixture()
-def schrute_product(product_manager):
- return product_manager.create_dummy(
+def schrute_product(
+ product_factory: Callable[..., Product], product_manager: ProductManager
+) -> Product:
+ return product_factory(
user_wallet_config=UserWalletConfig(enabled=True, amt=False),
payout_config=PayoutConfig(
payout_transformation=PayoutTransformation(
@@ -27,25 +38,31 @@ def schrute_product(product_manager):
class TestGetUserWalletBalance:
- def test_get_user_wallet_balance_non_managed(self, user, thl_lm):
+ def test_get_user_wallet_balance_non_managed(
+ self, user: User, thl_ledger_manager: ThlLedgerManager
+ ):
with pytest.raises(
AssertionError,
match="Can't get wallet balance on non-managed account.",
):
- thl_lm.get_user_wallet_balance(user=user)
+ thl_ledger_manager.get_user_wallet_balance(user=user)
def test_get_user_wallet_balance_managed_0(
- self, schrute_product, user_factory, thl_lm
+ self,
+ schrute_product: Product,
+ user_factory: Callable[..., User],
+ thl_ledger_manager: ThlLedgerManager,
):
assert (
schrute_product.payout_config.payout_format == "{payout:,.0f} Schrute Bucks"
)
- user: User = user_factory(schrute_product)
- balance = thl_lm.get_user_wallet_balance(user=user)
+ user: User = user_factory(product=schrute_product)
+ balance = thl_ledger_manager.get_user_wallet_balance(user=user)
assert balance == 0
+ assert isinstance(user.product, Product)
balance_string = user.product.format_payout_format(Decimal(balance) / 100)
assert balance_string == "0 Schrute Bucks"
- redeemable_balance = thl_lm.get_user_redeemable_wallet_balance(
+ redeemable_balance = thl_ledger_manager.get_user_redeemable_wallet_balance(
user=user, user_wallet_balance=balance
)
assert redeemable_balance == 0
@@ -55,10 +72,14 @@ class TestGetUserWalletBalance:
assert redeemable_balance_string == "0 Schrute Bucks"
def test_get_user_wallet_balance_managed(
- self, schrute_product, user_factory, thl_lm, session_with_tx_factory
+ self,
+ schrute_product: Product,
+ user_factory: Callable[..., User],
+ thl_ledger_manager: ThlLedgerManager,
+ session_with_tx_factory: Callable[..., None],
):
- user: User = user_factory(schrute_product)
- thl_lm.create_tx_user_bonus(
+ user: User = user_factory(product=schrute_product)
+ thl_ledger_manager.create_tx_user_bonus(
user=user,
amount=Decimal(1),
ref_uuid=uuid4().hex,
@@ -69,10 +90,10 @@ class TestGetUserWalletBalance:
# This product has a payout xform of 40% and commission of 5%
# 1.23 * 0.05 = 0.06 of commission
# 1.17 of payout * 0.40 = 0.47 of user pay and (1.17-0.47) 0.70 bp pay
- balance = thl_lm.get_user_wallet_balance(user=user)
+ balance = thl_ledger_manager.get_user_wallet_balance(user=user)
assert balance == 47 + 100 # plus the $1 bribe
- redeemable_balance = thl_lm.get_user_redeemable_wallet_balance(
+ redeemable_balance = thl_ledger_manager.get_user_redeemable_wallet_balance(
user=user, user_wallet_balance=balance
)
assert redeemable_balance == 20 + 100
diff --git a/tests/managers/thl/test_maxmind.py b/tests/managers/thl/test_maxmind.py
index c588c58..e44fe49 100644
--- a/tests/managers/thl/test_maxmind.py
+++ b/tests/managers/thl/test_maxmind.py
@@ -1,23 +1,6 @@
-import json
-import logging
-from typing import Callable
-
-import geoip2.models
-import pytest
from faker import Faker
from faker.providers.address.en_US import Provider as USAddressProvider
-from generalresearch.managers.thl.ipinfo import GeoIpInfoManager
-from generalresearch.managers.thl.maxmind import MaxmindManager
-from generalresearch.managers.thl.maxmind.basic import (
- MaxmindBasicManager,
-)
-from generalresearch.models.thl.ipinfo import (
- GeoIPInformation,
- normalize_ip,
-)
-from generalresearch.models.thl.maxmind.definitions import UserType
-
fake = Faker()
US_STATES = {x.lower() for x in USAddressProvider.states}
@@ -29,245 +12,244 @@ IP_v6_US = "2600:1700:ece0:9410:55d:faf3:c15d:6e4"
IP_v6_US_SAME_64 = "2600:1700:ece0:9410:55d:faf3:c15d:aaaa"
-@pytest.fixture(scope="session")
-def delete_ipinfo(thl_web_rw) -> Callable:
- def _delete_ipinfo(ip):
- thl_web_rw.execute_write(
- query="DELETE FROM thl_geoname WHERE geoname_id IN (SELECT geoname_id FROM thl_ipinformation WHERE ip = %s);",
- params=[ip],
- )
- thl_web_rw.execute_write(
- query="DELETE FROM thl_ipinformation WHERE ip = %s;",
- params=[ip],
- )
-
- return _delete_ipinfo
-
-
-class TestMaxmindBasicManager:
-
- def test_init(self, maxmind_basic_manager):
-
- assert isinstance(maxmind_basic_manager, MaxmindBasicManager)
-
- def test_get_basic_ip_information(self, maxmind_basic_manager):
- ip = IP_v4_INDIA
- maxmind_basic_manager.run_update_geoip_db()
-
- res1 = maxmind_basic_manager.get_basic_ip_information(ip_address=ip)
- assert isinstance(res1, geoip2.models.Country)
- assert res1.country.iso_code == "IN"
- assert res1.country.name == "India"
-
- res2 = maxmind_basic_manager.get_basic_ip_information(
- ip_address=fake.ipv4_private()
- )
- assert res2 is None
-
- def test_get_country_iso_from_ip_geoip2db(self, maxmind_basic_manager):
- ip = IP_v4_INDIA
- maxmind_basic_manager.run_update_geoip_db()
-
- res1 = maxmind_basic_manager.get_country_iso_from_ip_geoip2db(ip=ip)
- assert res1 == "in"
-
- res2 = maxmind_basic_manager.get_country_iso_from_ip_geoip2db(
- ip=fake.ipv4_private()
- )
- assert res2 is None
-
- def test_get_basic_ip_information_ipv6(self, maxmind_basic_manager):
- ip = IP_v6_INDIA
- maxmind_basic_manager.run_update_geoip_db()
-
- res1 = maxmind_basic_manager.get_basic_ip_information(ip_address=ip)
- assert isinstance(res1, geoip2.models.Country)
- assert res1.country.iso_code == "IN"
- assert res1.country.name == "India"
-
-
-class TestMaxmindManager:
-
- def test_init(self, thl_web_rr, thl_redis_config, maxmind_manager: MaxmindManager):
- instance = MaxmindManager(pg_config=thl_web_rr, redis_config=thl_redis_config)
- assert isinstance(instance, MaxmindManager)
- assert isinstance(maxmind_manager, MaxmindManager)
-
- def test_create_basic(
- self,
- maxmind_manager: MaxmindManager,
- geoipinfo_manager: GeoIpInfoManager,
- delete_ipinfo,
- ):
- # This is (currently) an IP in India, and so it should only do the basic lookup
- ip = IP_v4_INDIA
- delete_ipinfo(ip)
- geoipinfo_manager.clear_cache(ip)
- assert geoipinfo_manager.get_cache(ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(ip) is None
-
- maxmind_manager.run_ip_information(ip, force_insights=False)
- # Check that it is in the cache and in mysql
- res = geoipinfo_manager.get_cache(ip)
- assert res.ip == ip
- assert res.basic
- res = geoipinfo_manager.get_mysql(ip)
- assert res.ip == ip
- assert res.basic
-
- def test_create_basic_ipv6(
- self,
- maxmind_manager: MaxmindManager,
- geoipinfo_manager: GeoIpInfoManager,
- delete_ipinfo,
- ):
- # This is (currently) an IP in India, and so it should only do the basic lookup
- ip = IP_v6_INDIA
- normalized_ip, lookup_prefix = normalize_ip(ip)
- delete_ipinfo(ip)
- geoipinfo_manager.clear_cache(ip)
- delete_ipinfo(normalized_ip)
- geoipinfo_manager.clear_cache(normalized_ip)
- assert geoipinfo_manager.get_cache(ip) is None
- assert geoipinfo_manager.get_cache(normalized_ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(normalized_ip) is None
-
- maxmind_manager.run_ip_information(ip, force_insights=False)
-
- # Check that it is in the cache
- res = geoipinfo_manager.get_cache(ip)
- # The looked up IP (/128) is returned,
- assert res.ip == ip
- assert res.lookup_prefix == "/64"
- assert res.basic
-
- # ... but the normalized version was stored (/64)
- assert geoipinfo_manager.get_cache_raw(ip) is None
- res = json.loads(geoipinfo_manager.get_cache_raw(normalized_ip))
- assert res["ip"] == normalized_ip
-
- # Check mysql
- res = geoipinfo_manager.get_mysql(ip)
- assert res.ip == ip
- assert res.lookup_prefix == "/64"
- assert res.basic
- with pytest.raises(AssertionError):
- geoipinfo_manager.get_mysql_raw(ip)
- res = geoipinfo_manager.get_mysql_raw(normalized_ip)
- assert res["ip"] == normalized_ip
-
- def test_create_insights(
- self,
- maxmind_manager: MaxmindManager,
- geoipinfo_manager: GeoIpInfoManager,
- delete_ipinfo,
- ):
- # This is (currently) an IP in the US, so it should do insights
- ip = IP_v4_US
- delete_ipinfo(ip)
- geoipinfo_manager.clear_cache(ip)
- assert geoipinfo_manager.get_cache(ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(ip) is None
-
- res1 = maxmind_manager.run_ip_information(ip, force_insights=False)
- assert isinstance(res1, GeoIPInformation)
-
- # Check that it is in the cache and in mysql
- res2 = geoipinfo_manager.get_cache(ip)
- assert isinstance(res2, GeoIPInformation)
- assert res2.ip == ip
- assert not res2.basic
-
- res3 = geoipinfo_manager.get_mysql(ip)
- assert isinstance(res3, GeoIPInformation)
- assert res3.ip == ip
- assert not res3.basic
- assert res3.is_anonymous is False
- assert res3.subdivision_1_name.lower() in US_STATES
- # this might change ...
- assert res3.user_type == UserType.CELLULAR
-
- assert res1 == res2 == res3, "runner, cache, mysql all return same instance"
-
- def test_create_insights_ipv6(
- self,
- maxmind_manager: MaxmindManager,
- geoipinfo_manager: GeoIpInfoManager,
- delete_ipinfo,
- ):
- # This is (currently) an IP in the US, so it should do insights
- ip = IP_v6_US
- normalized_ip, lookup_prefix = normalize_ip(ip)
- delete_ipinfo(ip)
- geoipinfo_manager.clear_cache(ip)
- delete_ipinfo(normalized_ip)
- geoipinfo_manager.clear_cache(normalized_ip)
- assert geoipinfo_manager.get_cache(ip) is None
- assert geoipinfo_manager.get_cache(normalized_ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(ip) is None
- assert geoipinfo_manager.get_mysql_if_exists(normalized_ip) is None
-
- res1 = maxmind_manager.run_ip_information(ip, force_insights=False)
- assert isinstance(res1, GeoIPInformation)
- assert res1.lookup_prefix == "/64"
-
- # Check that it is in the cache and in mysql
- res2 = geoipinfo_manager.get_cache(ip)
- assert isinstance(res2, GeoIPInformation)
- assert res2.ip == ip
- assert not res2.basic
-
- res3 = geoipinfo_manager.get_mysql(ip)
- assert isinstance(res3, GeoIPInformation)
- assert res3.ip == ip
- assert not res3.basic
- assert res3.is_anonymous is False
- assert res3.subdivision_1_name.lower() in US_STATES
- # this might change ...
- assert res3.user_type == UserType.RESIDENTIAL
-
- assert res1 == res2 == res3, "runner, cache, mysql all return same instance"
-
- def test_get_or_create_ip_information(self, maxmind_manager):
- ip = IP_v4_US
-
- res1 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
- assert isinstance(res1, GeoIPInformation)
-
- res2 = maxmind_manager.get_or_create_ip_information(
- ip_address=fake.ipv4_private()
- )
- assert res2 is None
-
- def test_get_or_create_ip_information_ipv6(
- self, maxmind_manager, delete_ipinfo, geoipinfo_manager, caplog
- ):
- ip = IP_v6_US
- normalized_ip, lookup_prefix = normalize_ip(ip)
- delete_ipinfo(normalized_ip)
- geoipinfo_manager.clear_cache(normalized_ip)
-
- with caplog.at_level(logging.INFO):
- res1 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
- assert isinstance(res1, GeoIPInformation)
- assert res1.ip == ip
- # It looks up in insight using the normalize IP!
- assert f"get_insights_ip_information: {normalized_ip}" in caplog.text
-
- # And it should NOT do the lookup again with an ipv6 in the same /64 block!
- ip = IP_v6_US_SAME_64
- caplog.clear()
- with caplog.at_level(logging.INFO):
- res2 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
- assert isinstance(res2, GeoIPInformation)
- assert res2.ip == ip
- assert "get_insights_ip_information" not in caplog.text
-
- def test_run_ip_information(self, maxmind_manager):
- ip = IP_v4_US
-
- res = maxmind_manager.run_ip_information(ip_address=ip)
- assert isinstance(res, GeoIPInformation)
- assert res.country_name == "United States"
- assert res.country_iso == "us"
+# @pytest.fixture(scope="session")
+# def delete_ipinfo(thl_web_rw) -> Callable:
+# def _delete_ipinfo(ip):
+# thl_web_rw.execute_write(
+# query="DELETE FROM thl_geoname WHERE geoname_id IN (SELECT geoname_id FROM thl_ipinformation WHERE ip = %s);",
+# params=[ip],
+# )
+# thl_web_rw.execute_write(
+# query="DELETE FROM thl_ipinformation WHERE ip = %s;",
+# params=[ip],
+# )
+
+# return _delete_ipinfo
+
+
+# @pytest.skip("TODO: Replace with GRIP Client")
+# class TestMaxmindBasicManager:
+
+# def test_init(self,):
+
+# def test_get_basic_ip_information(self, maxmind_basic_manager):
+# ip = IP_v4_INDIA
+# maxmind_basic_manager.run_update_geoip_db()
+
+# res1 = maxmind_basic_manager.get_basic_ip_information(ip_address=ip)
+# # assert isinstance(res1, geoip2.models.Country)
+# assert res1.country.iso_code == "IN"
+# assert res1.country.name == "India"
+
+# res2 = maxmind_basic_manager.get_basic_ip_information(
+# ip_address=fake.ipv4_private()
+# )
+# assert res2 is None
+
+# def test_get_country_iso_from_ip_geoip2db(self, maxmind_basic_manager):
+# ip = IP_v4_INDIA
+# maxmind_basic_manager.run_update_geoip_db()
+
+# res1 = maxmind_basic_manager.get_country_iso_from_ip_geoip2db(ip=ip)
+# assert res1 == "in"
+
+# res2 = maxmind_basic_manager.get_country_iso_from_ip_geoip2db(
+# ip=fake.ipv4_private()
+# )
+# assert res2 is None
+
+# def test_get_basic_ip_information_ipv6(self, maxmind_basic_manager):
+# ip = IP_v6_INDIA
+# maxmind_basic_manager.run_update_geoip_db()
+
+# res1 = maxmind_basic_manager.get_basic_ip_information(ip_address=ip)
+# assert isinstance(res1, geoip2.models.Country)
+# assert res1.country.iso_code == "IN"
+# assert res1.country.name == "India"
+
+
+# class TestMaxmindManager:
+
+# def test_init(self, thl_web_rr: PostgresConfig, thl_redis_config: RedisConfig, maxmind_manager: MaxmindManager):
+# instance = MaxmindManager(pg_config=thl_web_rr: PostgresConfig, redis_config=thl_redis_config)
+# assert isinstance(instance, MaxmindManager)
+# assert isinstance(maxmind_manager, MaxmindManager)
+
+# def test_create_basic(
+# self,
+# maxmind_manager: MaxmindManager,
+# geoipinfo_manager: GeoIpInfoManager,
+# delete_ipinfo,
+# ):
+# # This is (currently) an IP in India, and so it should only do the basic lookup
+# ip = IP_v4_INDIA
+# delete_ipinfo(ip)
+# geoipinfo_manager.clear_cache(ip)
+# assert geoipinfo_manager.get_cache(ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(ip) is None
+
+# maxmind_manager.run_ip_information(ip, force_insights=False)
+# # Check that it is in the cache and in mysql
+# res = geoipinfo_manager.get_cache(ip)
+# assert res.ip == ip
+# assert res.basic
+# res = geoipinfo_manager.get_mysql(ip)
+# assert res.ip == ip
+# assert res.basic
+
+# def test_create_basic_ipv6(
+# self,
+# maxmind_manager: MaxmindManager,
+# geoipinfo_manager: GeoIpInfoManager,
+# delete_ipinfo,
+# ):
+# # This is (currently) an IP in India, and so it should only do the basic lookup
+# ip = IP_v6_INDIA
+# normalized_ip, lookup_prefix = normalize_ip(ip)
+# delete_ipinfo(ip)
+# geoipinfo_manager.clear_cache(ip)
+# delete_ipinfo(normalized_ip)
+# geoipinfo_manager.clear_cache(normalized_ip)
+# assert geoipinfo_manager.get_cache(ip) is None
+# assert geoipinfo_manager.get_cache(normalized_ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(normalized_ip) is None
+
+# maxmind_manager.run_ip_information(ip, force_insights=False)
+
+# # Check that it is in the cache
+# res = geoipinfo_manager.get_cache(ip)
+# # The looked up IP (/128) is returned,
+# assert res.ip == ip
+# assert res.lookup_prefix == "/64"
+# assert res.basic
+
+# # ... but the normalized version was stored (/64)
+# assert geoipinfo_manager.get_cache_raw(ip) is None
+# res = json.loads(geoipinfo_manager.get_cache_raw(normalized_ip))
+# assert res["ip"] == normalized_ip
+
+# # Check mysql
+# res = geoipinfo_manager.get_mysql(ip)
+# assert res.ip == ip
+# assert res.lookup_prefix == "/64"
+# assert res.basic
+# with pytest.raises(AssertionError):
+# geoipinfo_manager.get_mysql_raw(ip)
+# res = geoipinfo_manager.get_mysql_raw(normalized_ip)
+# assert res["ip"] == normalized_ip
+
+# def test_create_insights(
+# self,
+# maxmind_manager: MaxmindManager,
+# geoipinfo_manager: GeoIpInfoManager,
+# delete_ipinfo,
+# ):
+# # This is (currently) an IP in the US, so it should do insights
+# ip = IP_v4_US
+# delete_ipinfo(ip)
+# geoipinfo_manager.clear_cache(ip)
+# assert geoipinfo_manager.get_cache(ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(ip) is None
+
+# res1 = maxmind_manager.run_ip_information(ip, force_insights=False)
+# assert isinstance(res1, GeoIPInformation)
+
+# # Check that it is in the cache and in mysql
+# res2 = geoipinfo_manager.get_cache(ip)
+# assert isinstance(res2, GeoIPInformation)
+# assert res2.ip == ip
+# assert not res2.basic
+
+# res3 = geoipinfo_manager.get_mysql(ip)
+# assert isinstance(res3, GeoIPInformation)
+# assert res3.ip == ip
+# assert not res3.basic
+# assert res3.is_anonymous is False
+# assert res3.subdivision_1_name.lower() in US_STATES
+# # this might change ...
+# assert res3.user_type == UserType.CELLULAR
+
+# assert res1 == res2 == res3, "runner, cache, mysql all return same instance"
+
+# def test_create_insights_ipv6(
+# self,
+# maxmind_manager: MaxmindManager,
+# geoipinfo_manager: GeoIpInfoManager,
+# delete_ipinfo,
+# ):
+# # This is (currently) an IP in the US, so it should do insights
+# ip = IP_v6_US
+# normalized_ip, lookup_prefix = normalize_ip(ip)
+# delete_ipinfo(ip)
+# geoipinfo_manager.clear_cache(ip)
+# delete_ipinfo(normalized_ip)
+# geoipinfo_manager.clear_cache(normalized_ip)
+# assert geoipinfo_manager.get_cache(ip) is None
+# assert geoipinfo_manager.get_cache(normalized_ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(ip) is None
+# assert geoipinfo_manager.get_mysql_if_exists(normalized_ip) is None
+
+# res1 = maxmind_manager.run_ip_information(ip, force_insights=False)
+# assert isinstance(res1, GeoIPInformation)
+# assert res1.lookup_prefix == "/64"
+
+# # Check that it is in the cache and in mysql
+# res2 = geoipinfo_manager.get_cache(ip)
+# assert isinstance(res2, GeoIPInformation)
+# assert res2.ip == ip
+# assert not res2.basic
+
+# res3 = geoipinfo_manager.get_mysql(ip)
+# assert isinstance(res3, GeoIPInformation)
+# assert res3.ip == ip
+# assert not res3.basic
+# assert res3.is_anonymous is False
+# assert res3.subdivision_1_name.lower() in US_STATES
+# # this might change ...
+# assert res3.user_type == UserType.RESIDENTIAL
+
+# assert res1 == res2 == res3, "runner, cache, mysql all return same instance"
+
+# def test_get_or_create_ip_information(self, maxmind_manager):
+# ip = IP_v4_US
+
+# res1 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
+# assert isinstance(res1, GeoIPInformation)
+
+# res2 = maxmind_manager.get_or_create_ip_information(
+# ip_address=fake.ipv4_private()
+# )
+# assert res2 is None
+
+# def test_get_or_create_ip_information_ipv6(
+# self, maxmind_manager, delete_ipinfo, geoipinfo_manager, caplog
+# ):
+# ip = IP_v6_US
+# normalized_ip, lookup_prefix = normalize_ip(ip)
+# delete_ipinfo(normalized_ip)
+# geoipinfo_manager.clear_cache(normalized_ip)
+
+# with caplog.at_level(logging.INFO):
+# res1 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
+# assert isinstance(res1, GeoIPInformation)
+# assert res1.ip == ip
+# # It looks up in insight using the normalize IP!
+# assert f"get_insights_ip_information: {normalized_ip}" in caplog.text
+
+# # And it should NOT do the lookup again with an ipv6 in the same /64 block!
+# ip = IP_v6_US_SAME_64
+# caplog.clear()
+# with caplog.at_level(logging.INFO):
+# res2 = maxmind_manager.get_or_create_ip_information(ip_address=ip)
+# assert isinstance(res2, GeoIPInformation)
+# assert res2.ip == ip
+# assert "get_insights_ip_information" not in caplog.text
+
+# def test_run_ip_information(self, maxmind_manager):
+# ip = IP_v4_US
+
+# res = maxmind_manager.run_ip_information(ip_address=ip)
+# assert isinstance(res, GeoIPInformation)
+# assert res.country_name == "United States"
+# assert res.country_iso == "us"
diff --git a/tests/managers/thl/test_payout.py b/tests/managers/thl/test_payout.py
index 31087b8..52bbbec 100644
--- a/tests/managers/thl/test_payout.py
+++ b/tests/managers/thl/test_payout.py
@@ -1,25 +1,52 @@
+import io
import logging
import os
-from datetime import datetime, timezone, timedelta
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
-from random import choice as rand_choice, randint
-from typing import Optional
+from random import choice as rand_choice
+from random import randint
+from typing import TYPE_CHECKING
from uuid import uuid4
import pandas as pd
import pytest
+from dask.distributed import Client as DaskClient
from generalresearch.currency import USDCent
-from generalresearch.managers.thl.ledger_manager.exceptions import (
- LedgerTransactionConditionFailedError,
-)
-from generalresearch.managers.thl.payout import UserPayoutEventManager
from generalresearch.models.thl.definitions import PayoutStatus
-from generalresearch.models.thl.ledger import LedgerEntry, Direction
-from generalresearch.models.thl.payout import BusinessPayoutEvent
-from generalresearch.models.thl.payout import UserPayoutEvent
-from generalresearch.models.thl.wallet import PayoutType
-from generalresearch.models.thl.ledger import LedgerAccount
+from generalresearch.models.thl.finance import BusinessBalances
+from generalresearch.models.thl.payout import (
+ BrokerageProductPayoutEvent,
+ BusinessPayoutEvent,
+)
+from generalresearch.models.thl.wallet.definitions import PayoutType
+
+if TYPE_CHECKING:
+ from generalresearch.incite.base import GRLDatasets
+ from generalresearch.incite.collections.thl_web import (
+ LedgerDFCollection,
+ )
+ from generalresearch.incite.mergers.pop_ledger import PopLedgerMerge
+ from generalresearch.managers.thl.ledger_manager.ledger import LedgerManager
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.payout import (
+ BrokerageProductPayoutEventManager,
+ BusinessPayoutEventManager,
+ PayoutEventManager,
+ UserPayoutEventManager,
+ )
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.models.gr.business import Business
+ from generalresearch.models.thl.ledger import LedgerAccount
+ from generalresearch.models.thl.payout import (
+ UserPayoutEvent,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.session import Session
+ from generalresearch.models.thl.user import User
+ from generalresearch.pg_helper import PostgresConfig
+ from generalresearch.redis_helper import RedisConfig
logger = logging.getLogger()
@@ -27,17 +54,15 @@ cashout_method_uuid = uuid4().hex
class TestPayout:
-
def test_get_by_uuid_and_create(
self,
- user,
+ user: User,
user_payout_event_manager: UserPayoutEventManager,
- thl_lm,
- utc_now,
+ thl_ledger_manager: ThlLedgerManager,
+ utc_now: datetime,
):
-
- user_account: LedgerAccount = thl_lm.get_account_or_create_user_wallet(
- user=user
+ user_account: LedgerAccount = (
+ thl_ledger_manager.get_account_or_create_user_wallet(user=user)
)
pe1: UserPayoutEvent = user_payout_event_manager.create(
@@ -57,11 +82,14 @@ class TestPayout:
assert pe1 == pe2
- def test_update(self, user, user_payout_event_manager, lm, thl_lm, utc_now):
- from generalresearch.models.thl.definitions import PayoutStatus
- from generalresearch.models.thl.wallet import PayoutType
-
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
+ def test_update(
+ self,
+ user: User,
+ user_payout_event_manager: UserPayoutEventManager,
+ thl_ledger_manager: ThlLedgerManager,
+ utc_now: datetime,
+ ):
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
pe1 = user_payout_event_manager.create(
status=PayoutStatus.PENDING,
@@ -89,142 +117,84 @@ class TestPayout:
def test_create_bp_payout(
self,
- user,
- thl_web_rr,
- user_payout_event_manager,
- lm,
- thl_lm,
- product,
- brokerage_product_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
):
- delete_ledger_db()
- create_main_accounts()
- from generalresearch.models.thl.ledger import LedgerAccount
-
- thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
-
- with pytest.raises(expected_exception=LedgerTransactionConditionFailedError):
- # wallet balance failure
- brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- amount=USDCent(100),
- skip_wallet_balance_check=False,
- skip_one_per_day_check=False,
- )
-
- # (we don't have a special method for this) Put money in the BP's account
- amount_cents = 100
- cash_account: LedgerAccount = thl_lm.get_account_cash()
- bp_wallet: LedgerAccount = thl_lm.get_account_or_create_bp_wallet(
- product=product
- )
-
- entries = [
- LedgerEntry(
- direction=Direction.DEBIT,
- account_uuid=cash_account.uuid,
- amount=amount_cents,
- ),
- LedgerEntry(
- direction=Direction.CREDIT,
- account_uuid=bp_wallet.uuid,
- amount=amount_cents,
- ),
- ]
-
- lm.create_tx(entries=entries)
- assert 100 == lm.get_account_balance(account=bp_wallet)
-
- # Then run it again for $1.00
- brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- amount=USDCent(100),
- skip_wallet_balance_check=False,
- skip_one_per_day_check=False,
- )
- assert 0 == lm.get_account_balance(account=bp_wallet)
-
- # Run again should without balance check, should still fail due to day check
- with pytest.raises(LedgerTransactionConditionFailedError):
- brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
- amount=USDCent(100),
- skip_wallet_balance_check=True,
- skip_one_per_day_check=False,
- )
+ # create_bp_payout_event does not get called directly. We have tests
+ # for the ledger methods already
+ pass
- # And then we can run again skip both checks
- pe = brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
- product=product,
+ @pytest.fixture
+ def pending_bp_pe(
+ self,
+ thl_web_rw: PostgresConfig,
+ product: Product,
+ thl_ledger_manager: ThlLedgerManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ utc_now: datetime,
+ ) -> BrokerageProductPayoutEvent:
+ account = thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
+ bp_pe = BrokerageProductPayoutEvent(
+ product_id=product.uuid,
amount=USDCent(100),
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
- )
- assert -100 == lm.get_account_balance(account=bp_wallet)
-
- pe = brokerage_product_payout_event_manager.get_by_uuid(pe.uuid)
- txs = lm.get_tx_filtered_by_metadata(
- metadata_key="event_payout", metadata_value=pe.uuid
+ payout_type=PayoutType.ACH,
+ debit_account_uuid=account.uuid,
+ cashout_method_uuid=brokerage_product_payout_event_manager.CASHOUT_METHOD_UUID,
+ created=utc_now,
)
-
- assert 1 == len(txs)
+ params = bp_pe.model_dump_postgres()
+ # This shouldn't exist. For testing only, so no supplier_payout
+ params["supplier_payout_id"] = None
+ thl_web_rw.execute_write(
+ """
+ INSERT INTO event_payout (uuid, debit_account_uuid, created, cashout_method_uuid,
+ amount, status, ext_ref_id, payout_type, order_data,
+ request_data, supplier_payout_id)
+ VALUES (%(uuid)s, %(debit_account_uuid)s, %(created)s, %(cashout_method_uuid)s,
+ %(amount)s, %(status)s, %(ext_ref_id)s, %(payout_type)s, %(order_data)s,
+ %(request_data)s, %(supplier_payout_id)s);
+ """,
+ params,
+ )
+ return bp_pe
def test_create_bp_payout_quick_dupe(
self,
- user,
- product,
- thl_web_rw,
- brokerage_product_payout_event_manager,
- thl_lm,
- lm,
- utc_now,
- create_main_accounts,
+ product: Product,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ thl_ledger_manager: ThlLedgerManager,
+ utc_now: datetime,
+ pending_bp_pe: BrokerageProductPayoutEvent,
):
- thl_lm.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
- brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ brokerage_product_payout_event_manager.create_tx_bp_payout_from_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
+ bp_pe=pending_bp_pe,
product=product,
- amount=USDCent(100),
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
created=utc_now,
)
with pytest.raises(ValueError) as cm:
- brokerage_product_payout_event_manager.create_bp_payout_event(
- thl_ledger_manager=thl_lm,
+ brokerage_product_payout_event_manager.create_tx_bp_payout_from_payout_event(
+ thl_ledger_manager=thl_ledger_manager,
product=product,
- amount=USDCent(100),
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
+ bp_pe=pending_bp_pe,
created=utc_now,
)
assert "Payout event already exists!" in str(cm.value)
def test_filter(
self,
- thl_web_rw,
- thl_lm,
- lm,
- product,
- user,
- user_payout_event_manager,
- utc_now,
+ thl_ledger_manager: ThlLedgerManager,
+ product: Product,
+ user: User,
+ user_payout_event_manager: UserPayoutEventManager,
+ utc_now: datetime,
):
from generalresearch.models.thl.definitions import PayoutStatus
- from generalresearch.models.thl.wallet import PayoutType
+ from generalresearch.models.thl.wallet.definitions import PayoutType
- user_account = thl_lm.get_account_or_create_user_wallet(user=user)
- bp_account = thl_lm.get_account_or_create_bp_wallet(product=product)
+ user_account = thl_ledger_manager.get_account_or_create_user_wallet(user=user)
+ bp_account = thl_ledger_manager.get_account_or_create_bp_wallet(product=product)
user_payout_event_manager.create(
status=PayoutStatus.PENDING,
@@ -289,166 +259,109 @@ class TestPayout:
class TestPayoutEventManager:
-
- def test_set_account_lookup_table(
- self, payout_event_manager, thl_redis_config, thl_lm, delete_ledger_db
- ):
- delete_ledger_db()
- rc = thl_redis_config.create_redis_client()
- rc.delete("pem:account_to_product")
- rc.delete("pem:product_to_account")
- N = 5
-
- for idx in range(N):
- thl_lm.get_account_or_create_bp_wallet_by_uuid(product_uuid=uuid4().hex)
-
- res = rc.hgetall(name="pem:account_to_product")
- assert len(res.items()) == 0
-
- res = rc.hgetall(name="pem:product_to_account")
- assert len(res.items()) == 0
-
- payout_event_manager.set_account_lookup_table(
- thl_lm=thl_lm,
- )
-
- res = rc.hgetall(name="pem:account_to_product")
- assert len(res.items()) == N
-
- res = rc.hgetall(name="pem:product_to_account")
- assert len(res.items()) == N
-
- thl_lm.get_account_or_create_bp_wallet_by_uuid(product_uuid=uuid4().hex)
- payout_event_manager.set_account_lookup_table(
- thl_lm=thl_lm,
- )
-
- res = rc.hgetall(name="pem:account_to_product")
- assert len(res.items()) == N + 1
-
- res = rc.hgetall(name="pem:product_to_account")
- assert len(res.items()) == N + 1
+ pass
class TestBusinessPayoutEventManager:
-
@pytest.fixture
- def start(self) -> "datetime":
- return datetime(year=2018, month=3, day=14, hour=0, tzinfo=timezone.utc)
+ def start(self) -> datetime:
+ return datetime(year=2018, month=3, day=14, hour=0, tzinfo=UTC)
@pytest.fixture
def offset(self) -> str:
return "5d"
@pytest.fixture
- def duration(self) -> Optional["timedelta"]:
+ def duration(self) -> timedelta | None:
return timedelta(days=10)
def test_base(
self,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- thl_lm,
- thl_web_rr,
- product_factory,
- bp_payout_factory,
- business,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ product_factory: Callable[..., Product],
+ brokerage_product_payout_event_factory: Callable[
+ ..., BrokerageProductPayoutEvent
+ ],
+ gr_business: Business,
):
delete_ledger_db()
create_main_accounts()
- from generalresearch.models.thl.product import Product
-
- p1: Product = product_factory(business=business)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- business_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ p1: Product = product_factory(business=gr_business)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
ach_id1 = uuid4().hex
ach_id2 = uuid4().hex
- bp_payout_factory(
- product=p1,
- amount=USDCent(1),
- ext_ref_id=None,
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
+ # ext_ref_id is required now
+ brokerage_product_payout_event_factory(
+ product=p1, amount=USDCent(1), ext_ref_id="none"
)
- bp_payout_factory(
- product=p1,
- amount=USDCent(1),
- ext_ref_id=ach_id1,
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
+ brokerage_product_payout_event_factory(
+ product=p1, amount=USDCent(1), ext_ref_id=ach_id1
)
+ with pytest.raises(
+ expected_exception=ValueError,
+ match="Cannot create a BusinessPayoutEvent with an existing transaction_id",
+ ):
+ brokerage_product_payout_event_factory(
+ product=p1, amount=USDCent(25), ext_ref_id=ach_id1
+ )
- bp_payout_factory(
- product=p1,
- amount=USDCent(25),
- ext_ref_id=ach_id1,
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
+ brokerage_product_payout_event_factory(
+ product=p1, amount=USDCent(50), ext_ref_id=ach_id2
)
- bp_payout_factory(
- product=p1,
- amount=USDCent(50),
- ext_ref_id=ach_id2,
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
+ gr_business.prebuild_payouts(
+ bpem=business_payout_event_manager,
)
- business.prebuild_payouts(
- thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
- bpem=business_payout_event_manager,
+ assert isinstance(gr_business.payouts, list)
+ assert len(gr_business.payouts) == 3
+ assert gr_business.payouts_total == sum(
+ [pe.amount for pe in gr_business.payouts]
)
+ assert gr_business.payouts[0].created > gr_business.payouts[1].created
+ assert len(gr_business.payouts[0].bp_payouts) == 1
- assert len(business.payouts) == 3
- assert business.payouts_total == sum([pe.amount for pe in business.payouts])
- assert business.payouts[0].created > business.payouts[1].created
- assert len(business.payouts[0].bp_payouts) == 1
- assert len(business.payouts[1].bp_payouts) == 2
+ # Cannot pay out the same product twice in the same business payout
+ # assert len(business.payouts[1].bp_payouts) == 2
+ assert len(gr_business.payouts[1].bp_payouts) == 1
- assert business.payouts[0].ext_ref_id == ach_id2
- assert business.payouts[1].ext_ref_id == ach_id1
- assert business.payouts[2].ext_ref_id is None
+ assert gr_business.payouts[0].ext_ref_id == ach_id2
+ assert gr_business.payouts[1].ext_ref_id == ach_id1
+ assert gr_business.payouts[2].ext_ref_id == "none"
def test_update_ext_reference_ids(
self,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- thl_lm,
- thl_web_rr,
- product_factory,
- bp_payout_factory,
- delete_df_collection,
- user_factory,
- ledger_collection,
- session_with_tx_factory,
- pop_ledger_merge,
- client_no_amm,
- mnt_filepath,
- lm,
- product_manager,
- start,
- business,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ thl_ledger_manager: ThlLedgerManager,
+ thl_web_rr: PostgresConfig,
+ product_factory: Callable[..., Product],
+ delete_df_collection: Callable[..., None],
+ user_factory: Callable[..., User],
+ ledger_collection: LedgerDFCollection,
+ session_with_tx_factory: Callable[..., Session],
+ pop_ledger_merge: PopLedgerMerge,
+ client_no_amm: DaskClient,
+ mnt_filepath: GRLDatasets,
+ product_manager: ProductManager,
+ start: datetime,
+ gr_business: Business,
):
delete_ledger_db()
create_main_accounts()
delete_df_collection(coll=ledger_collection)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
+ p1: Product = product_factory(business=gr_business)
u1: User = user_factory(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- business_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
# $250.00 to work with
for idx in range(1, 10):
@@ -461,32 +374,34 @@ class TestBusinessPayoutEventManager:
ach_id1 = uuid4().hex
ach_id2 = uuid4().hex
- with pytest.raises(expected_exception=Warning) as cm:
+ with pytest.raises(
+ expected_exception=AssertionError, match="No Business Payout found"
+ ):
business_payout_event_manager.update_ext_reference_ids(
new_value=ach_id2,
current_value=ach_id1,
)
- assert "No event_payouts found to UPDATE" in str(cm)
# We must build the balance to issue ACH/Wire
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=thl_ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
res = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(100_01),
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
transaction_id=ach_id1,
)
assert isinstance(res, BusinessPayoutEvent)
+ assert business_payout_event_manager.get_by_ext_ref_id(ext_ref_id=ach_id1)
# Okay, now that there is a payout_event, let's try to update the
# ext_reference_id
@@ -495,111 +410,17 @@ class TestBusinessPayoutEventManager:
current_value=ach_id1,
)
- res = business_payout_event_manager.filter_by(ext_ref_id=ach_id1)
- assert len(res) == 0
+ with pytest.raises(
+ expected_exception=AssertionError, match="No Business Payout found"
+ ):
+ business_payout_event_manager.get_by_ext_ref_id(ext_ref_id=ach_id1)
- res = business_payout_event_manager.filter_by(ext_ref_id=ach_id2)
- assert len(res) == 1
+ assert business_payout_event_manager.get_by_ext_ref_id(ext_ref_id=ach_id2)
- def test_delete_failed_business_payout(
- self,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- thl_lm,
- thl_web_rr,
- product_factory,
- bp_payout_factory,
- currency,
- delete_df_collection,
- user_factory,
- ledger_collection,
- session_with_tx_factory,
- pop_ledger_merge,
- client_no_amm,
- mnt_filepath,
- lm,
- product_manager,
- start,
- business,
+ def test_recoup_empty(
+ self, business_payout_event_manager: BusinessPayoutEventManager
):
- delete_ledger_db()
- create_main_accounts()
- delete_df_collection(coll=ledger_collection)
-
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
- u1: User = user_factory(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- business_payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
-
- # $250.00 to work with
- for idx in range(1, 10):
- session_with_tx_factory(
- user=u1,
- wall_req_cpi=Decimal("25.00"),
- started=start + timedelta(days=1, minutes=idx),
- )
-
- # We must build the balance to issue ACH/Wire
- ledger_collection.initial_load(client=None, sync=True)
- pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
- thl_pg_config=thl_web_rr,
- lm=lm,
- ds=mnt_filepath,
- client=client_no_amm,
- pop_ledger=pop_ledger_merge,
- )
-
- ach_id1 = uuid4().hex
-
- res = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
- amount=USDCent(100_01),
- pm=product_manager,
- thl_lm=thl_lm,
- transaction_id=ach_id1,
- )
- assert isinstance(res, BusinessPayoutEvent)
-
- # (1) Confirm the initial Event Payout, Tx, TxMeta, TxEntry all exist
- event_payouts = business_payout_event_manager.filter_by(ext_ref_id=ach_id1)
- event_payout_uuids = [i.uuid for i in event_payouts]
- assert len(event_payout_uuids) == 1
- tags = [f"{currency.value}:bp_payout:{x}" for x in event_payout_uuids]
- transactions = thl_lm.get_txs_by_tags(tags=tags)
- assert len(transactions) == 1
- tx_metadata_ids = thl_lm.get_tx_metadata_ids_by_txs(transactions=transactions)
- assert len(tx_metadata_ids) == 2
- tx_entries = thl_lm.get_tx_entries_by_txs(transactions=transactions)
- assert len(tx_entries) == 2
-
- # (2) Delete!
- business_payout_event_manager.delete_failed_business_payout(
- ext_ref_id=ach_id1, thl_lm=thl_lm
- )
-
- # (3) Confirm the initial Event Payout, Tx, TxMeta, TxEntry have
- # all been deleted
- res = business_payout_event_manager.filter_by(ext_ref_id=ach_id1)
- assert len(res) == 0
-
- # Note: b/c the event_payout shouldn't exist anymore, we are taking
- # the tag strings and transactions from when they did..
- res = thl_lm.get_txs_by_tags(tags=tags)
- assert len(res) == 0
-
- tx_metadata_ids = thl_lm.get_tx_metadata_ids_by_txs(transactions=transactions)
- assert len(tx_metadata_ids) == 0
- tx_entries = thl_lm.get_tx_entries_by_txs(transactions=transactions)
- assert len(tx_entries) == 0
-
- def test_recoup_empty(self, business_payout_event_manager):
- res = {uuid4().hex: USDCent(0) for i in range(100)}
+ res = {uuid4().hex: USDCent(0) for _ in range(100)}
df = pd.DataFrame.from_dict(res, orient="index").reset_index()
df.columns = ["product_id", "available_balance"]
@@ -609,10 +430,12 @@ class TestBusinessPayoutEventManager:
)
assert "Total available amount is empty, cannot recoup" in str(cm)
- def test_recoup_exceeds(self, business_payout_event_manager):
+ def test_recoup_exceeds(
+ self, business_payout_event_manager: BusinessPayoutEventManager
+ ):
from random import randint
- res = {uuid4().hex: USDCent(randint(a=0, b=1_000_00)) for i in range(100)}
+ res = {uuid4().hex: USDCent(randint(a=0, b=1_000_00)) for _ in range(100)}
df = pd.DataFrame.from_dict(res, orient="index").reset_index()
df.columns = ["product_id", "available_balance"]
@@ -624,10 +447,10 @@ class TestBusinessPayoutEventManager:
)
assert " exceeds total available " in str(cm)
- def test_recoup(self, business_payout_event_manager):
+ def test_recoup(self, business_payout_event_manager: BusinessPayoutEventManager):
from random import randint, random
- res = {uuid4().hex: USDCent(randint(a=0, b=1_000_00)) for i in range(100)}
+ res = {uuid4().hex: USDCent(randint(a=0, b=1_000_00)) for _ in range(100)}
df = pd.DataFrame.from_dict(res, orient="index").reset_index()
df.columns = ["product_id", "available_balance"]
@@ -643,7 +466,9 @@ class TestBusinessPayoutEventManager:
assert res.deduction.sum() == random_recoup_amount
assert res.remaining_balance.sum() == avail_balance - random_recoup_amount
- def test_recoup_loop(self, business_payout_event_manager, request):
+ def test_recoup_loop(
+ self, business_payout_event_manager: BusinessPayoutEventManager, request
+ ):
# TODO: Generate this file at random
fp = os.path.join(
request.config.rootpath, "data/pytest_recoup_proportional.csv"
@@ -657,9 +482,11 @@ class TestBusinessPayoutEventManager:
assert int(res.deduction.sum()) == 1416089
- def test_recoup_loop_single_profitable_account(self, business_payout_event_manager):
- res = [{"product_id": uuid4().hex, "available_balance": 0} for i in range(1000)]
- for x in range(100):
+ def test_recoup_loop_single_profitable_account(
+ self, business_payout_event_manager: BusinessPayoutEventManager
+ ):
+ res = [{"product_id": uuid4().hex, "available_balance": 0} for _ in range(1000)]
+ for _ in range(100):
item = rand_choice(res)
item["available_balance"] = randint(8, 12)
@@ -670,14 +497,16 @@ class TestBusinessPayoutEventManager:
# res = res[res["remaining_balance"] > 0]
assert int(res.deduction.sum()) == 500
- def test_recoup_loop_assertions(self, business_payout_event_manager):
+ def test_recoup_loop_assertions(
+ self, business_payout_event_manager: BusinessPayoutEventManager
+ ):
df = pd.DataFrame(
[
{
"product_id": uuid4().hex,
"available_balance": randint(0, 999_999),
}
- for i in range(10_000)
+ for _ in range(10_000)
]
)
available_balance = int(df.available_balance.sum())
@@ -697,7 +526,7 @@ class TestBusinessPayoutEventManager:
assert int(res.deduction.sum()) == available_balance - 1
# Slightly less
- with pytest.raises(expected_exception=Exception) as cm:
+ with pytest.raises(expected_exception=ValueError):
res = business_payout_event_manager.recoup_proportional(
df=df, target_amount=available_balance + 1
)
@@ -707,8 +536,9 @@ class TestBusinessPayoutEventManager:
assert res.remaining_balance.sum() == available_balance
assert int(res.deduction.sum()) == 0
- def test_distribute_amount(self, business_payout_event_manager):
- import io
+ def test_distribute_amount(
+ self, business_payout_event_manager: BusinessPayoutEventManager
+ ):
df = pd.read_csv(
io.StringIO(
@@ -724,31 +554,31 @@ class TestBusinessPayoutEventManager:
def test_ach_payment_min_amount(
self,
- product,
- mnt_filepath,
- thl_lm,
- client_no_amm,
- thl_redis_config,
- payout_event_manager,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- delete_df_collection,
- ledger_collection,
- business,
- user_factory,
- product_factory,
- session_with_tx_factory,
- pop_ledger_merge,
- start,
- bp_payout_factory,
- adj_to_fail_with_tx_factory,
- thl_web_rr,
- lm,
- product_manager,
+ product: Product,
+ mnt_filepath: GRLDatasets,
+ thl_ledger_manager: ThlLedgerManager,
+ client_no_amm: DaskClient,
+ thl_redis_config: RedisConfig,
+ payout_event_manager: PayoutEventManager,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ delete_df_collection: Callable[..., None],
+ ledger_collection: LedgerDFCollection,
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ session_with_tx_factory: Callable[..., Session],
+ pop_ledger_merge: PopLedgerMerge,
+ start: datetime,
+ brokerage_product_payout_event_factory: Callable[
+ ..., BrokerageProductPayoutEvent
+ ],
+ ledger_manager: LedgerManager,
+ product_manager: ProductManager,
):
- """Test having a Business with three products.. one that lost money
+ """Test having a Business with three products. One that lost money
and two that gained money. Ensure that the Business balance
reflects that to compensate for the Product in the negative and only
assigns Brokerage Product payments from the 2 accounts that have
@@ -759,12 +589,9 @@ class TestBusinessPayoutEventManager:
create_main_accounts()
delete_df_collection(coll=ledger_collection)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
+ p1: Product = product_factory(business=gr_business)
u1: User = user_factory(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
session_with_tx_factory(
user=u1,
@@ -776,8 +603,7 @@ class TestBusinessPayoutEventManager:
wall_req_cpi=Decimal("5.00"),
started=start + timedelta(days=6),
)
- payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
- bp_payout_factory(
+ brokerage_product_payout_event_factory(
product=u1.product,
amount=USDCent(475), # 95% of $5.00
created=start + timedelta(days=1, minutes=1),
@@ -785,9 +611,9 @@ class TestBusinessPayoutEventManager:
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
- thl_pg_config=thl_web_rr,
- lm=lm,
+ gr_business.prebuild_balance(
+ product_manager=product_manager,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
@@ -795,40 +621,151 @@ class TestBusinessPayoutEventManager:
with pytest.raises(expected_exception=AssertionError) as cm:
business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(500),
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
+ transaction_id=uuid4().hex,
)
assert "Must issue Supplier Payouts at least $100 minimum." in str(cm)
+ def test_create_from_ach_or_wire(
+ self,
+ mnt_filepath: GRLDatasets,
+ thl_ledger_manager: ThlLedgerManager,
+ client_no_amm: DaskClient,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ delete_df_collection: Callable[..., None],
+ ledger_collection: LedgerDFCollection,
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ session_with_tx_factory: Callable[..., None],
+ pop_ledger_merge: PopLedgerMerge,
+ start: datetime,
+ thl_web_rr: PostgresConfig,
+ ledger_manager: LedgerManager,
+ product_manager: ProductManager,
+ caplog,
+ ):
+ """Test having a Business with three products"""
+ # Now let's load it up and actually test some things
+ delete_ledger_db()
+ create_main_accounts()
+ delete_df_collection(coll=ledger_collection)
+
+ p1: Product = product_factory(business=gr_business)
+ p2: Product = product_factory(business=gr_business)
+ p3: Product = product_factory(business=gr_business)
+ _: User = user_factory(product=p1)
+ u2: User = user_factory(product=p2)
+ u3: User = user_factory(product=p3)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p2)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p3)
+
+ ach_id1 = uuid4().hex
+ ach_id2 = uuid4().hex
+
+ # Product 1: Complete $10 x 20
+ for idx in range(20):
+ session_with_tx_factory(
+ user=u2,
+ wall_req_cpi=Decimal("10.00"),
+ started=start + timedelta(days=1, hours=2, minutes=1 + idx),
+ )
+
+ # Product 2: Complete $10 x 30
+ for idx in range(30):
+ session_with_tx_factory(
+ user=u3,
+ wall_req_cpi=Decimal("10.00"),
+ started=start + timedelta(days=1, hours=3, minutes=1 + idx),
+ )
+
+ ledger_collection.initial_load(client=None, sync=True)
+ pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
+ gr_business.prebuild_balance(
+ thl_pg_config=thl_web_rr,
+ lm=ledger_manager,
+ ds=mnt_filepath,
+ client=client_no_amm,
+ pop_ledger=pop_ledger_merge,
+ )
+
+ bb = gr_business.balance
+ assert isinstance(bb, BusinessBalances)
+ assert bb.payout == 475_00 # $500 * .95% = $475
+ assert bb.net == 475_00
+
+ bp1 = business_payout_event_manager.create_from_ach_or_wire(
+ business=gr_business,
+ amount=USDCent(100_00),
+ pm=product_manager,
+ thl_lm=thl_ledger_manager,
+ created=start + timedelta(days=1, hours=5),
+ transaction_id=ach_id1,
+ )
+ print(f"{bp1=}")
+ assert isinstance(bp1, BusinessPayoutEvent)
+ assert len(bp1.bp_payouts) == 2
+
+ bp2 = business_payout_event_manager.create_from_ach_or_wire(
+ business=gr_business,
+ amount=USDCent(bb.available_balance),
+ pm=product_manager,
+ thl_lm=thl_ledger_manager,
+ created=start + timedelta(days=2, hours=5),
+ transaction_id=ach_id2,
+ )
+ print(f"{bp2=}")
+ assert isinstance(bp2, BusinessPayoutEvent)
+ assert len(bp2.bp_payouts) == 2
+
+ with caplog.at_level(logging.WARNING):
+ business_payout_event_manager.resume_failed_business_payout(
+ ext_ref_id=ach_id1, thl_lm=thl_ledger_manager, pm=product_manager
+ )
+ assert "Nothing to do!" in caplog.text
+
+ # bpe = business_payout_event_manager.get_by_ext_ref_id(ext_ref_id=ach_id1)
+ # bp_pe = bpe.bp_payouts[0]
+ # thl_web_rr.execute_write(
+ # """
+ # UPDATE event_payout
+ # SET status = %(status)s
+ # WHERE uuid = %(uuid)s""",
+ # {"uuid": bp_pe.uuid, "status": PayoutStatus.FAILED},
+ # )
+
def test_ach_payment(
self,
- product,
- mnt_filepath,
- thl_lm,
- client_no_amm,
- thl_redis_config,
- payout_event_manager,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- delete_df_collection,
- ledger_collection,
- business,
- user_factory,
- product_factory,
- session_with_tx_factory,
- pop_ledger_merge,
- start,
- bp_payout_factory,
- adj_to_fail_with_tx_factory,
- thl_web_rr,
- lm,
- product_manager,
- rm_ledger_collection,
- rm_pop_ledger_merge,
+ mnt_filepath: GRLDatasets,
+ thl_ledger_manager: ThlLedgerManager,
+ client_no_amm: DaskClient,
+ brokerage_product_payout_event_manager: BrokerageProductPayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ delete_df_collection: Callable[..., None],
+ ledger_collection: LedgerDFCollection,
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ session_with_tx_factory: Callable[..., None],
+ pop_ledger_merge: PopLedgerMerge,
+ start: datetime,
+ brokerage_product_payout_event_factory: Callable[
+ ..., BrokerageProductPayoutEvent
+ ],
+ adj_to_fail_with_tx_factory: Callable[..., None],
+ thl_web_rr: PostgresConfig,
+ ledger_manager: LedgerManager,
+ product_manager: ProductManager,
+ rm_ledger_collection: Callable[..., None],
+ rm_pop_ledger_merge: Callable[..., None],
):
"""Test having a Business with three products.. one that lost money
and two that gained money. Ensure that the Business balance
@@ -841,21 +778,17 @@ class TestBusinessPayoutEventManager:
create_main_accounts()
delete_df_collection(coll=ledger_collection)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
- p2: Product = product_factory(business=business)
- p3: Product = product_factory(business=business)
+ p1: Product = product_factory(business=gr_business)
+ p2: Product = product_factory(business=gr_business)
+ p3: Product = product_factory(business=gr_business)
u1: User = user_factory(product=p1)
u2: User = user_factory(product=p2)
u3: User = user_factory(product=p3)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p2)
- thl_lm.get_account_or_create_bp_wallet(product=p3)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p2)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p3)
ach_id1 = uuid4().hex
- ach_id2 = uuid4().hex
# Product 1: Complete, Payout, Recon..
s1 = session_with_tx_factory(
@@ -863,14 +796,11 @@ class TestBusinessPayoutEventManager:
wall_req_cpi=Decimal("5.00"),
started=start + timedelta(days=1),
)
- payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
- bp_payout_factory(
+ brokerage_product_payout_event_factory(
product=u1.product,
amount=USDCent(475), # 95% of $5.00
ext_ref_id=ach_id1,
created=start + timedelta(days=1, minutes=1),
- skip_wallet_balance_check=True,
- skip_one_per_day_check=True,
)
adj_to_fail_with_tx_factory(
session=s1,
@@ -893,18 +823,19 @@ class TestBusinessPayoutEventManager:
started=start + timedelta(days=1, hours=3, minutes=1 + idx),
)
- # Now that we paid out the business, let's confirm the updated balances
+ # Now that we paid out the gr_business: Business, let's confirm the updated balances
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
- thl_pg_config=thl_web_rr,
- lm=lm,
+ gr_business.prebuild_balance(
+ product_manager=product_manager,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
- bb1 = business.balance
+ bb1 = gr_business.balance
+ assert isinstance(bb1, BusinessBalances)
pb1 = bb1.product_balances[0]
pb2 = bb1.product_balances[1]
pb3 = bb1.product_balances[2]
@@ -927,20 +858,21 @@ class TestBusinessPayoutEventManager:
assert pb2.recoup_usd_str == "$0.00"
assert pb3.recoup_usd_str == "$0.00"
- assert business.payouts is None
- business.prebuild_payouts(
+ assert gr_business.payouts is None
+ gr_business.prebuild_payouts(
thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
bpem=business_payout_event_manager,
)
- assert len(business.payouts) == 1
- assert business.payouts[0].ext_ref_id == ach_id1
+ assert isinstance(gr_business.payouts, list)
+ assert len(gr_business.payouts) == 1
+ assert gr_business.payouts[0].ext_ref_id == ach_id1
bp1 = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(bb1.available_balance),
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
created=start + timedelta(days=1, hours=5),
)
assert isinstance(bp1, BusinessPayoutEvent)
@@ -948,7 +880,7 @@ class TestBusinessPayoutEventManager:
assert bp1.bp_payouts[0].status == PayoutStatus.COMPLETE
assert bp1.bp_payouts[1].status == PayoutStatus.COMPLETE
bp1_tx = brokerage_product_payout_event_manager.check_for_ledger_tx(
- thl_ledger_manager=thl_lm,
+ thl_ledger_manager=thl_ledger_manager,
payout_event=bp1.bp_payouts[0],
product_id=bp1.bp_payouts[0].product_id,
amount=bp1.bp_payouts[0].amount,
@@ -956,14 +888,14 @@ class TestBusinessPayoutEventManager:
assert bp1_tx
bp2_tx = brokerage_product_payout_event_manager.check_for_ledger_tx(
- thl_ledger_manager=thl_lm,
+ thl_ledger_manager=thl_ledger_manager,
payout_event=bp1.bp_payouts[1],
product_id=bp1.bp_payouts[1].product_id,
amount=bp1.bp_payouts[1].amount,
)
assert bp2_tx
- # Now that we paid out the business, let's confirm the updated balances
+ # Now that we paid out the business: Business, let's confirm the updated balances
rm_ledger_collection()
rm_pop_ledger_merge()
ledger_collection.initial_load(client=None, sync=True)
@@ -971,16 +903,15 @@ class TestBusinessPayoutEventManager:
business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
business.prebuild_payouts(
- thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
bpem=business_payout_event_manager,
)
+ assert isinstance(business.payouts, list)
assert len(business.payouts) == 2
assert len(business.payouts[0].bp_payouts) == 2
assert len(business.payouts[1].bp_payouts) == 1
@@ -989,6 +920,8 @@ class TestBusinessPayoutEventManager:
# Okay os we have the balance before, and after the Business Payout
# of bb1.available_balance worth..
+ assert isinstance(bb1, BusinessBalances)
+ assert isinstance(bb2, BusinessBalances)
assert bb1.payout == bb2.payout
assert bb1.adjustment == bb2.adjustment
assert bb1.net == bb2.net
@@ -1005,34 +938,29 @@ class TestBusinessPayoutEventManager:
def test_ach_payment_partial_amount(
self,
- product,
- mnt_filepath,
- thl_lm,
- client_no_amm,
- thl_redis_config,
- payout_event_manager,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- delete_df_collection,
- ledger_collection,
- business,
- user_factory,
- product_factory,
- session_with_tx_factory,
- pop_ledger_merge,
- start,
- bp_payout_factory,
- adj_to_fail_with_tx_factory,
- thl_web_rr,
- lm,
- product_manager,
- rm_ledger_collection,
- rm_pop_ledger_merge,
+ mnt_filepath: GRLDatasets,
+ thl_ledger_manager: ThlLedgerManager,
+ client_no_amm: DaskClient,
+ payout_event_manager: PayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ delete_df_collection: Callable[..., None],
+ ledger_collection: LedgerDFCollection,
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ session_with_tx_factory: Callable[..., None],
+ pop_ledger_merge: PopLedgerMerge,
+ start: datetime,
+ thl_web_rr: PostgresConfig,
+ ledger_manager: LedgerManager,
+ product_manager: ProductManager,
+ rm_ledger_collection: Callable[..., None],
+ rm_pop_ledger_merge: Callable[..., None],
):
"""There are valid instances when we want issue a ACH or Wire to a
- Business, but not for the full Available Balance amount in their
+ gr_business: Business, but not for the full Available Balance amount in their
account.
To test this, we'll create a Business with multiple Products, and
@@ -1047,18 +975,15 @@ class TestBusinessPayoutEventManager:
create_main_accounts()
delete_df_collection(coll=ledger_collection)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
- p2: Product = product_factory(business=business)
- p3: Product = product_factory(business=business)
+ p1: Product = product_factory(business=gr_business)
+ p2: Product = product_factory(business=gr_business)
+ p3: Product = product_factory(business=gr_business)
u1: User = user_factory(product=p1)
u2: User = user_factory(product=p2)
u3: User = user_factory(product=p3)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p2)
- thl_lm.get_account_or_create_bp_wallet(product=p3)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p2)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p3)
# Product 1, 2, 3: Complete, and Payout multiple times.
for idx in range(5):
@@ -1068,27 +993,27 @@ class TestBusinessPayoutEventManager:
wall_req_cpi=Decimal("50.00"),
started=start + timedelta(days=1, hours=2, minutes=1 + idx),
)
- payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ payout_event_manager.set_account_lookup_table(thl_lm=thl_ledger_manager)
- # Now that we paid out the business, let's confirm the updated balances
+ # Now that we paid out the business: Business, let's confirm the updated balances
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
- business.prebuild_payouts(
- thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
+ gr_business.prebuild_payouts(
bpem=business_payout_event_manager,
)
# Confirm the initial amounts.
- assert len(business.payouts) == 0
- bb1 = business.balance
+ assert len(gr_business.payouts) == 0
+ bb1 = gr_business.balance
+
+ assert isinstance(bb1, BusinessBalances)
assert bb1.payout == 3 * 5 * 4750
assert bb1.adjustment == 0
assert bb1.payout == bb1.net
@@ -1100,24 +1025,25 @@ class TestBusinessPayoutEventManager:
assert bb1.product_balances[x].balance == 5 * 4750
assert bb1.product_balances[x].available_balance_usd_str == "$178.13"
- assert business.payouts_total_str == "$0.00"
- assert business.balance.payment_usd_str == "$0.00"
- assert business.balance.available_balance_usd_str == "$534.39"
+ assert gr_business.payouts_total_str == "$0.00"
+ assert isinstance(gr_business.balance, BusinessBalances)
+ assert gr_business.balance.payment_usd_str == "$0.00"
+ assert gr_business.balance.available_balance_usd_str == "$534.39"
# This is the important part, even those the Business has $534.39
# available to it, we are only trying to issue out a $250.00 ACH or
# Wire to the Business
bp1 = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(250_00),
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
created=start + timedelta(days=1, hours=3),
)
assert isinstance(bp1, BusinessPayoutEvent)
assert len(bp1.bp_payouts) == 3
- # Now that we paid out the business, let's confirm the updated
+ # Now that we paid out the gr_business: Business, let's confirm the updated
# balances. Clear and rebuild the parquet files.
rm_ledger_collection()
rm_pop_ledger_merge()
@@ -1127,51 +1053,46 @@ class TestBusinessPayoutEventManager:
# Now rebuild and confirm the payouts, balance.payment, and the
# balance.available_balance are reflective of having a $250 ACH/Wire
# sent to the Business
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
- business.prebuild_payouts(
- thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
+ gr_business.prebuild_payouts(
bpem=business_payout_event_manager,
)
- assert len(business.payouts) == 1
- assert len(business.payouts[0].bp_payouts) == 3
- assert business.payouts_total_str == "$250.00"
- assert business.balance.payment_usd_str == "$250.00"
- assert business.balance.available_balance_usd_str == "$346.88"
+ assert isinstance(gr_business.payouts, list)
+ assert len(gr_business.payouts) == 1
+ assert len(gr_business.payouts[0].bp_payouts) == 3
+ assert gr_business.payouts_total_str == "$250.00"
+ assert isinstance(gr_business.balance, BusinessBalances)
+ assert gr_business.balance.payment_usd_str == "$250.00"
+ assert gr_business.balance.available_balance_usd_str == "$346.88"
def test_ach_tx_id_reference(
self,
- product,
- mnt_filepath,
- thl_lm,
- client_no_amm,
- thl_redis_config,
- payout_event_manager,
- brokerage_product_payout_event_manager,
- business_payout_event_manager,
- delete_ledger_db,
- create_main_accounts,
- delete_df_collection,
- ledger_collection,
- business,
- user_factory,
- product_factory,
- session_with_tx_factory,
- pop_ledger_merge,
- start,
- bp_payout_factory,
- adj_to_fail_with_tx_factory,
- thl_web_rr,
- lm,
- product_manager,
- rm_ledger_collection,
- rm_pop_ledger_merge,
+ mnt_filepath: GRLDatasets,
+ thl_ledger_manager: ThlLedgerManager,
+ client_no_amm: DaskClient,
+ payout_event_manager: PayoutEventManager,
+ business_payout_event_manager: BusinessPayoutEventManager,
+ delete_ledger_db: Callable[..., None],
+ create_main_accounts: Callable[..., None],
+ delete_df_collection: Callable[..., None],
+ ledger_collection: LedgerDFCollection,
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ session_with_tx_factory: Callable[..., Session],
+ pop_ledger_merge: PopLedgerMerge,
+ start: datetime,
+ thl_web_rr: PostgresConfig,
+ ledger_manager: LedgerManager,
+ product_manager: ProductManager,
+ rm_ledger_collection: Callable[..., None],
+ rm_pop_ledger_merge: Callable[..., None],
):
# Now let's load it up and actually test some things
@@ -1179,18 +1100,15 @@ class TestBusinessPayoutEventManager:
create_main_accounts()
delete_df_collection(coll=ledger_collection)
- from generalresearch.models.thl.product import Product
- from generalresearch.models.thl.user import User
-
- p1: Product = product_factory(business=business)
- p2: Product = product_factory(business=business)
- p3: Product = product_factory(business=business)
+ p1: Product = product_factory(business=gr_business)
+ p2: Product = product_factory(business=gr_business)
+ p3: Product = product_factory(business=gr_business)
u1: User = user_factory(product=p1)
u2: User = user_factory(product=p2)
u3: User = user_factory(product=p3)
- thl_lm.get_account_or_create_bp_wallet(product=p1)
- thl_lm.get_account_or_create_bp_wallet(product=p2)
- thl_lm.get_account_or_create_bp_wallet(product=p3)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p1)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p2)
+ thl_ledger_manager.get_account_or_create_bp_wallet(product=p3)
ach_id1 = uuid4().hex
ach_id2 = uuid4().hex
@@ -1202,26 +1120,26 @@ class TestBusinessPayoutEventManager:
wall_req_cpi=Decimal("7.50"),
started=start + timedelta(days=1, hours=1 + iidx, minutes=1 + idx),
)
- payout_event_manager.set_account_lookup_table(thl_lm=thl_lm)
+ payout_event_manager.set_account_lookup_table(thl_lm=thl_ledger_manager)
rm_ledger_collection()
rm_pop_ledger_merge()
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
bp1 = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(100_01),
transaction_id=ach_id1,
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
created=start + timedelta(days=2, hours=1),
)
@@ -1229,20 +1147,20 @@ class TestBusinessPayoutEventManager:
rm_pop_ledger_merge()
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
bp2 = business_payout_event_manager.create_from_ach_or_wire(
- business=business,
+ business=gr_business,
amount=USDCent(100_02),
transaction_id=ach_id2,
pm=product_manager,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
created=start + timedelta(days=4, hours=1),
)
@@ -1253,17 +1171,18 @@ class TestBusinessPayoutEventManager:
rm_pop_ledger_merge()
ledger_collection.initial_load(client=None, sync=True)
pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection)
- business.prebuild_payouts(
+ gr_business.prebuild_payouts(
thl_pg_config=thl_web_rr,
- thl_lm=thl_lm,
+ thl_lm=thl_ledger_manager,
bpem=business_payout_event_manager,
)
- business.prebuild_balance(
+ gr_business.prebuild_balance(
thl_pg_config=thl_web_rr,
- lm=lm,
+ lm=ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
pop_ledger=pop_ledger_merge,
)
- assert business.payouts[0].ext_ref_id == ach_id2
- assert business.payouts[1].ext_ref_id == ach_id1
+ assert isinstance(gr_business.payouts, list)
+ assert gr_business.payouts[0].ext_ref_id == ach_id2
+ assert gr_business.payouts[1].ext_ref_id == ach_id1
diff --git a/tests/managers/thl/test_product.py b/tests/managers/thl/test_product.py
index 78d5dde..8d72fa5 100644
--- a/tests/managers/thl/test_product.py
+++ b/tests/managers/thl/test_product.py
@@ -1,24 +1,35 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.product import (
Product,
+ ProfilingConfig,
SourceConfig,
- UserCreateConfig,
SourcesConfig,
- UserHealthConfig,
- ProfilingConfig,
- SupplyPolicy,
SupplyConfig,
+ SupplyPolicy,
+ UserCreateConfig,
+ UserHealthConfig,
)
-from test_utils.models.conftest import product_factory
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.models.gr.team import Team
class TestProductManagerGetMethods:
- def test_get_by_uuid(self, product_manager):
- product: Product = product_manager.create_dummy(
+ def test_get_by_uuid(
+ self,
+ product_manager: ProductManager,
+ product_factory: Callable[..., Product],
+ ):
+ product: Product = product_factory(
product_id=uuid4().hex,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -37,12 +48,14 @@ class TestProductManagerGetMethods:
product_manager.get_by_uuid(product_uuid=uuid4().hex)
assert "product not found" in str(cm.value)
- def test_get_by_uuids(self, product_manager):
+ def test_get_by_uuids(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
cnt = 5
- product_uuids = [uuid4().hex for idx in range(cnt)]
+ product_uuids = [uuid4().hex for _ in range(cnt)]
for product_id in product_uuids:
- product_manager.create_dummy(
+ product_factory(
product_id=product_id,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -62,8 +75,10 @@ class TestProductManagerGetMethods:
product_manager.get_by_uuids(product_uuids=product_uuids + ["abc123"])
assert "invalid uuid" in str(cm.value)
- def test_get_by_uuid_if_exists(self, product_manager):
- product: Product = product_manager.create_dummy(
+ def test_get_by_uuid_if_exists(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ product: Product = product_factory(
product_id=uuid4().hex,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -74,10 +89,12 @@ class TestProductManagerGetMethods:
instance = product_manager.get_by_uuid_if_exists(product_uuid="abc123")
assert instance == None
- def test_get_by_uuids_if_exists(self, product_manager):
+ def test_get_by_uuids_if_exists(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
product_uuids = [uuid4().hex for _ in range(2)]
for product_id in product_uuids:
- product_manager.create_dummy(
+ product_factory(
product_id=product_id,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -106,13 +123,15 @@ class TestProductManagerGetMethods:
# for instance in res:
# assert isinstance(instance, Product)
- def test_get_by_business_ids(self, product_manager):
- business_ids = [uuid4().hex for i in range(5)]
+ def test_get_by_business_ids(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ business_ids = [uuid4().hex for _ in range(5)]
product_manager.fetch_uuids(business_uuids=business_ids)
for business_id in business_ids:
- product_manager.create(
+ product_factory(
product_id=uuid4().hex,
team_id=None,
business_id=business_id,
@@ -124,8 +143,10 @@ class TestProductManagerGetMethods:
class TestProductManagerCreation:
- def test_base(self, product_manager):
- instance = product_manager.create_dummy(
+ def test_base(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ instance = product_factory(
product_id=uuid4().hex,
team_id=uuid4().hex,
name=f"New Test Product {uuid4().hex[:6]}",
@@ -136,7 +157,7 @@ class TestProductManagerCreation:
class TestProductManagerCreate:
- def test_create_simple(self, product_manager):
+ def test_create_simple(self, product_manager: ProductManager):
# Always required: product_id, team_id, name, redirect_url
# Required internally - if not passed use default: harmonizer_domain,
# commission_pct, sources
@@ -179,20 +200,26 @@ class TestProductManager:
]
]
- def test_get_by_uuid1(self, product_manager, team, product, product_factory):
- p1 = product_factory(team=team)
+ def test_get_by_uuid1(
+ self,
+ product_manager: ProductManager,
+ gr_team: Team,
+ product: Product,
+ product_factory: Callable[..., Product],
+ ):
+ p1 = product_factory(team=gr_team)
instance = product_manager.get_by_uuid(product_uuid=p1.uuid)
assert instance.id == p1.id
# No Team and no user_create_config
- assert instance.team_id == team.uuid
+ assert instance.team_id == gr_team.uuid
# user_create_config can't be None, so ensure the default was set.
assert isinstance(instance.user_create_config, UserCreateConfig)
assert 0 == instance.user_create_config.min_hourly_create_limit
assert instance.user_create_config.max_hourly_create_limit is None
- def test_get_by_uuid2(self, product_manager, product_factory):
+ def test_get_by_uuid2(self, product_manager: ProductManager, product_factory):
p2 = product_factory()
instance = product_manager.get_by_uuid(p2.id)
assert instance.id, p2.id
@@ -204,7 +231,9 @@ class TestProductManager:
assert 0 == instance.user_create_config.min_hourly_create_limit
assert instance.user_create_config.max_hourly_create_limit is None
- def test_get_by_uuid3(self, product_manager, product_factory):
+ def test_get_by_uuid3(
+ self, product_manager: ProductManager, product_factory: Callable[..., Product]
+ ):
p3 = product_factory()
instance = product_manager.get_by_uuid(p3.id)
assert instance.id == p3.id
@@ -220,10 +249,12 @@ class TestProductManager:
assert instance.user_create_config.max_hourly_create_limit is None
assert not instance.user_wallet_config.enabled
- def test_sources(self, product_manager):
+ def test_sources(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
user_defined = [SourceConfig(name=Source.DYNATA, active=False)]
sources_config = SourcesConfig(user_defined=user_defined)
- p = product_manager.create_dummy(sources_config=sources_config)
+ p = product_factory(sources_config=sources_config)
p2 = product_manager.get_by_uuid(p.id)
@@ -235,7 +266,9 @@ class TestProductManager:
assert not dynata.active
assert all(x.active is True for x in p2.sources if x.name != Source.DYNATA)
- def test_global_sources(self, product_manager):
+ def test_global_sources(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
sources_config = SupplyConfig(
policies=[
SupplyPolicy(
@@ -246,7 +279,7 @@ class TestProductManager:
)
]
)
- p1 = product_manager.create_dummy(sources_config=sources_config)
+ p1 = product_factory(sources_config=sources_config)
p2 = product_manager.get_by_uuid(p1.id)
assert p1 == p2
@@ -262,8 +295,10 @@ class TestProductManager:
p2 = product_manager.get_by_uuid(p1.id)
assert p1 == p2
- def test_user_health_config(self, product_manager):
- p = product_manager.create_dummy(
+ def test_user_health_config(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ p = product_factory(
user_health_config=UserHealthConfig(banned_countries=["ng", "in"])
)
@@ -273,10 +308,10 @@ class TestProductManager:
assert p2.user_health_config.banned_countries == ["in", "ng"]
assert p2.user_health_config.allow_ban_iphist
- def test_profiling_config(self, product_manager):
- p = product_manager.create_dummy(
- profiling_config=ProfilingConfig(max_questions=1)
- )
+ def test_profiling_config(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ p = product_factory(profiling_config=ProfilingConfig(max_questions=1))
p2 = product_manager.get_by_uuid(p.id)
assert p == p2
@@ -320,8 +355,10 @@ class TestProductManager:
class TestProductManagerUpdate:
- def test_update(self, product_manager):
- p = product_manager.create_dummy()
+ def test_update(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ p = product_factory()
p.name = "new name"
p.enabled = False
p.user_create_config = UserCreateConfig(min_hourly_create_limit=200)
@@ -341,8 +378,10 @@ class TestProductManagerUpdate:
class TestProductManagerCacheClear:
- def test_cache_clear(self, product_manager):
- p = product_manager.create_dummy()
+ def test_cache_clear(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
+ p = product_factory()
product_manager.get_by_uuid(product_uuid=p.id)
product_manager.get_by_uuid(product_uuid=p.id)
product_manager.pg_config.execute_write(
diff --git a/tests/managers/thl/test_product_prod.py b/tests/managers/thl/test_product_prod.py
index 7b4f677..d584527 100644
--- a/tests/managers/thl/test_product_prod.py
+++ b/tests/managers/thl/test_product_prod.py
@@ -1,17 +1,25 @@
+from __future__ import annotations
+
import logging
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.models.thl.product import Product
-from test_utils.models.conftest import product_factory
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.product import ProductManager
logger = logging.getLogger()
class TestProductManagerGetMethods:
- def test_get_by_uuid(self, product_manager, product_factory):
+ def test_get_by_uuid(
+ self, product_manager: ProductManager, product_factory: Callable[..., Product]
+ ):
# Just test that we load properly
for p in [product_factory(), product_factory(), product_factory()]:
instance = product_manager.get_by_uuid(product_uuid=p.id)
@@ -23,7 +31,9 @@ class TestProductManagerGetMethods:
product_manager.get_by_uuid(product_uuid=uuid4().hex)
assert "product not found" in str(cm.value)
- def test_get_by_uuids(self, product_manager, product_factory):
+ def test_get_by_uuids(
+ self, product_manager: ProductManager, product_factory: Callable[..., Product]
+ ):
products = [product_factory(), product_factory(), product_factory()]
cnt = len(products)
res = product_manager.get_by_uuids(product_uuids=[p.id for p in products])
@@ -43,7 +53,9 @@ class TestProductManagerGetMethods:
)
assert "invalid uuid passed" in str(cm.value)
- def test_get_by_uuid_if_exists(self, product_factory, product_manager):
+ def test_get_by_uuid_if_exists(
+ self, product_factory: Callable[..., Product], product_manager: ProductManager
+ ):
products = [product_factory(), product_factory(), product_factory()]
instance = product_manager.get_by_uuid_if_exists(product_uuid=products[0].id)
@@ -52,7 +64,9 @@ class TestProductManagerGetMethods:
instance = product_manager.get_by_uuid_if_exists(product_uuid="abc123")
assert instance is None
- def test_get_by_uuids_if_exists(self, product_manager, product_factory):
+ def test_get_by_uuids_if_exists(
+ self, product_manager: ProductManager, product_factory: Callable[..., Product]
+ ):
products = [product_factory(), product_factory(), product_factory()]
res = product_manager.get_by_uuids_if_exists(
@@ -75,8 +89,7 @@ class TestProductManagerGetMethods:
class TestProductManagerGetAll:
@pytest.mark.skip(reason="TODO")
- def test_get_ALL_by_ids(self, product_manager):
+ def test_get_ALL_by_ids(self, product_manager: ProductManager):
products = product_manager.get_all(rand_limit=50)
logger.info(f"Fetching {len(products)} product uuids")
# todo: once timebucks stops spamming broken accounts, fetch more
- pass
diff --git a/tests/managers/thl/test_profiling/test_question.py b/tests/managers/thl/test_profiling/test_question.py
index 998466e..e4afb87 100644
--- a/tests/managers/thl/test_profiling/test_question.py
+++ b/tests/managers/thl/test_profiling/test_question.py
@@ -1,12 +1,20 @@
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
-from generalresearch.managers.thl.profiling.question import QuestionManager
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.profiling.question import QuestionManager
class TestQuestionManager:
- def test_get_multi_upk(self, question_manager: QuestionManager, upk_data):
+ def test_get_multi_upk(
+ self, question_manager: QuestionManager, upk_data: Callable[..., None]
+ ):
+ upk_data()
+
qs = question_manager.get_multi_upk(
question_ids=[
"8a22de34f985476aac85e15547100db8",
@@ -17,13 +25,21 @@ class TestQuestionManager:
)
assert len(qs) == 3
- def test_get_questions_ranked(self, question_manager: QuestionManager, upk_data):
+ def test_get_questions_ranked(
+ self, question_manager: QuestionManager, upk_data: Callable[..., None]
+ ):
+ upk_data()
+
qs = question_manager.get_questions_ranked(country_iso="mx", language_iso="spa")
assert len(qs) >= 40
assert qs[0].importance.task_score > qs[40].importance.task_score
assert all(q.country_iso == "mx" and q.language_iso == "spa" for q in qs)
- def test_lookup_by_property(self, question_manager: QuestionManager, upk_data):
+ def test_lookup_by_property(
+ self, question_manager: QuestionManager, upk_data: Callable[..., None]
+ ):
+ upk_data()
+
q = question_manager.lookup_by_property(
property_code="i:industry", country_iso="us", language_iso="eng"
)
@@ -38,7 +54,11 @@ class TestQuestionManager:
)
assert q.explanation_template
- def test_filter_by_property(self, question_manager: QuestionManager, upk_data):
+ def test_filter_by_property(
+ self, question_manager: QuestionManager, upk_data: Callable[..., None]
+ ):
+ upk_data()
+
lookup = [
("i:industry", "us", "eng"),
("i:industry", "mx", "eng"),
diff --git a/tests/managers/thl/test_profiling/test_schema.py b/tests/managers/thl/test_profiling/test_schema.py
index ae61527..feab902 100644
--- a/tests/managers/thl/test_profiling/test_schema.py
+++ b/tests/managers/thl/test_profiling/test_schema.py
@@ -1,9 +1,21 @@
+from collections.abc import Callable
+from typing import TYPE_CHECKING
+
from generalresearch.models.thl.profiling.upk_property import PropertyType
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.profiling.schema import (
+ UpkSchemaManager,
+ )
+
class TestUpkSchemaManager:
- def test_get_props_info(self, upk_schema_manager, upk_data):
+ def test_get_props_info(
+ self, upk_schema_manager: UpkSchemaManager, upk_data: Callable[..., None]
+ ):
+ upk_data()
+
props = upk_schema_manager.get_props_info()
assert (
len(props) == 16955
@@ -35,10 +47,10 @@ class TestUpkSchemaManager:
assert age.prop_type == PropertyType.UPK_NUMERICAL
assert age.gold_standard
- cars = [
+ cars = next(
x
for x in props
if x.country_iso == "us" and x.property_label == "household_auto_type"
- ][0]
+ )
assert not cars.gold_standard
assert cars.categories[0].label == "Autos & Vehicles"
diff --git a/tests/managers/thl/test_profiling/test_uqa.py b/tests/managers/thl/test_profiling/test_uqa.py
deleted file mode 100644
index 8b13789..0000000
--- a/tests/managers/thl/test_profiling/test_uqa.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tests/managers/thl/test_profiling/test_user_upk.py b/tests/managers/thl/test_profiling/test_user_upk.py
index 53bb8fe..0f3140c 100644
--- a/tests/managers/thl/test_profiling/test_user_upk.py
+++ b/tests/managers/thl/test_profiling/test_user_upk.py
@@ -1,8 +1,12 @@
-from datetime import datetime, timezone
+from collections.abc import Callable
+from datetime import UTC, datetime
+from typing import TYPE_CHECKING
-from generalresearch.managers.thl.profiling.user_upk import UserUpkManager
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.profiling.user_upk import UserUpkManager
+ from generalresearch.models.thl.user import User
-now = datetime.now(tz=timezone.utc)
+now = datetime.now(tz=UTC)
base = {
"country_iso": "us",
"language_iso": "eng",
@@ -21,11 +25,25 @@ for a in upk_ans_dict:
class TestUserUpkManager:
- def test_user_upk_empty(self, user_upk_manager: UserUpkManager, upk_data, user):
+ def test_user_upk_empty(
+ self,
+ user_upk_manager: UserUpkManager,
+ upk_data: Callable[..., None],
+ user: User,
+ ):
+ upk_data()
+
res = user_upk_manager.get_user_upk_mysql(user_id=user.user_id)
assert len(res) == 0
- def test_user_upk(self, user_upk_manager: UserUpkManager, upk_data, user):
+ def test_user_upk(
+ self,
+ user_upk_manager: UserUpkManager,
+ upk_data: Callable[..., None],
+ user: User,
+ ):
+ upk_data()
+
for x in upk_ans_dict:
x["user_id"] = user.user_id
user_upk = user_upk_manager.populate_user_upk_from_dict(upk_ans_dict)
diff --git a/tests/managers/thl/test_session_manager.py b/tests/managers/thl/test_session_manager.py
index 6bedc2b..60edcb9 100644
--- a/tests/managers/thl/test_session_manager.py
+++ b/tests/managers/thl/test_session_manager.py
@@ -1,28 +1,42 @@
-from datetime import timedelta
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import datetime, timedelta
from decimal import Decimal
+from typing import TYPE_CHECKING
from uuid import uuid4
from faker import Faker
-from generalresearch.models import DeviceType
+from generalresearch.models.definitions import DeviceType
from generalresearch.models.legacy.bucket import Bucket
from generalresearch.models.thl.definitions import (
+ SessionStatusCode2,
Status,
StatusCode1,
- SessionStatusCode2,
)
-from test_utils.models.conftest import user
+from generalresearch.models.thl.session import Session
+from generalresearch.models.thl.user import User
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.models.gr.business import Business
+ from generalresearch.models.gr.team import Team
+ from generalresearch.models.thl.product import Product
+ from generalresearch.pg_helper import PostgresConfig
fake = Faker()
class TestSessionManager:
- def test_create_session(self, session_manager, user, utc_hour_ago):
+ def test_create_session(
+ self, session_manager: SessionManager, user: User, utc_hour_ago: datetime
+ ):
bucket = Bucket(
loi_min=timedelta(seconds=60),
loi_max=timedelta(seconds=120),
- user_payout_min=Decimal("1"),
- user_payout_max=Decimal("2"),
+ user_payout_min=Decimal(1),
+ user_payout_max=Decimal(2),
)
s1 = session_manager.create(
@@ -40,7 +54,9 @@ class TestSessionManager:
s2 = session_manager.get_from_uuid(session_uuid=s1.uuid)
assert s1 == s2
- def test_finish_with_status(self, session_manager, user, utc_hour_ago):
+ def test_finish_with_status(
+ self, session_manager: SessionManager, user: User, utc_hour_ago: datetime
+ ):
uuid_1 = uuid4().hex
session = session_manager.create(
started=utc_hour_ago, user=user, uuid_id=uuid_1
@@ -60,7 +76,7 @@ class TestSessionManager:
class TestSessionManagerFilter:
- def test_base(self, session_manager, user, utc_now):
+ def test_base(self, session_manager: SessionManager, user: User, utc_now: datetime):
uuid_id = uuid4().hex
session_manager.create(started=utc_now, user=user, uuid_id=uuid_id)
res = session_manager.filter(limit=1)
@@ -68,7 +84,9 @@ class TestSessionManagerFilter:
assert isinstance(res, list)
assert res[0].uuid == uuid_id
- def test_user(self, session_manager, user, utc_hour_ago):
+ def test_user(
+ self, session_manager: SessionManager, user: User, utc_hour_ago: datetime
+ ):
session_manager.create(started=utc_hour_ago, user=user, uuid_id=uuid4().hex)
session_manager.create(started=utc_hour_ago, user=user, uuid_id=uuid4().hex)
@@ -76,14 +94,16 @@ class TestSessionManagerFilter:
assert len(res) == 2
def test_product(
- self, product_factory, user_factory, session_manager, user, utc_hour_ago
+ self,
+ product_factory: Callable[..., Product],
+ user_factory: Callable[..., User],
+ session_manager: SessionManager,
+ utc_hour_ago: datetime,
):
- from generalresearch.models.thl.session import Session
- from generalresearch.models.thl.user import User
p1 = product_factory()
- for n in range(5):
+ for _ in range(5):
u = user_factory(product=p1)
session_manager.create(started=utc_hour_ago, user=u, uuid_id=uuid4().hex)
@@ -96,42 +116,40 @@ class TestSessionManagerFilter:
def test_team(
self,
- product_factory,
- user_factory,
- team,
- session_manager,
- user,
- utc_hour_ago,
- thl_web_rr,
+ product_factory: Callable[..., Product],
+ user_factory: Callable[..., User],
+ gr_team: Team,
+ session_manager: SessionManager,
+ utc_hour_ago: datetime,
+ thl_web_rr: PostgresConfig,
):
- p1 = product_factory(team=team)
+ p1 = product_factory(team=gr_team)
- for n in range(5):
+ for _ in range(5):
u = user_factory(product=p1)
session_manager.create(started=utc_hour_ago, user=u, uuid_id=uuid4().hex)
- team.prefetch_products(thl_pg_config=thl_web_rr)
- assert len(team.product_uuids) == 1
- res = session_manager.filter(product_uuids=team.product_uuids)
+ gr_team.prefetch_products(thl_pg_config=thl_web_rr)
+ assert len(gr_team.product_uuids) == 1
+ res = session_manager.filter(product_uuids=gr_team.product_uuids)
assert len(res) == 5
def test_business(
self,
- product_factory,
- business,
- user_factory,
- session_manager,
- user,
- utc_hour_ago,
- thl_web_rr,
+ product_factory: Callable[..., Product],
+ gr_business: Business,
+ user_factory: Callable[..., User],
+ session_manager: SessionManager,
+ utc_hour_ago: datetime,
+ thl_web_rr: PostgresConfig,
):
- p1 = product_factory(business=business)
+ p1 = product_factory(business=gr_business)
- for n in range(5):
+ for _ in range(5):
u = user_factory(product=p1)
session_manager.create(started=utc_hour_ago, user=u, uuid_id=uuid4().hex)
- business.prefetch_products(thl_pg_config=thl_web_rr)
- assert len(business.product_uuids) == 1
- res = session_manager.filter(product_uuids=business.product_uuids)
+ gr_business.prefetch_products(thl_pg_config=thl_web_rr)
+ assert len(gr_business.product_uuids) == 1
+ res = session_manager.filter(product_uuids=gr_business.product_uuids)
assert len(res) == 5
diff --git a/tests/managers/thl/test_survey.py b/tests/managers/thl/test_survey.py
index 58c4577..e114b70 100644
--- a/tests/managers/thl/test_survey.py
+++ b/tests/managers/thl/test_survey.py
@@ -1,29 +1,41 @@
+from __future__ import annotations
+
import uuid
-from datetime import datetime, timezone
+from collections.abc import Callable
+from datetime import UTC, datetime
from decimal import Decimal
+from typing import TYPE_CHECKING
import pytest
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.legacy.bucket import (
- SurveyEligibilityCriterion,
- TopNPlusBucket,
DurationSummary,
PayoutSummary,
+ SurveyEligibilityCriterion,
+ TopNPlusBucket,
)
from generalresearch.models.thl.profiling.user_question_answer import (
UserQuestionAnswer,
)
from generalresearch.models.thl.survey.model import (
Survey,
- SurveyStat,
SurveyCategoryModel,
SurveyEligibilityDefinition,
+ SurveyStat,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.buyer import BuyerManager
+ from generalresearch.managers.thl.profiling.question import (
+ QuestionManager,
+ )
+ from generalresearch.managers.thl.profiling.uqa import UQAManager
+ from generalresearch.managers.thl.survey import SurveyManager, SurveyStatManager
+
@pytest.fixture(scope="session")
-def surveys_fixture():
+def surveys_fixture() -> list[Survey]:
return [
Survey(source=Source.TESTING, survey_id="a", buyer_code="buyer1"),
Survey(source=Source.TESTING, survey_id="b", buyer_code="buyer2"),
@@ -73,11 +85,13 @@ class TestSurvey:
def test(
self,
- delete_buyers_surveys,
- buyer_manager,
- survey_manager,
- surveys_fixture,
+ delete_buyers_surveys: Callable[..., None],
+ buyer_manager: BuyerManager,
+ survey_manager: SurveyManager,
+ surveys_fixture: list[Survey],
):
+ delete_buyers_surveys()
+
survey_manager.create_or_update(surveys_fixture)
survey_ids = {s.survey_id for s in surveys_fixture}
res = survey_manager.filter_by_natural_key(
@@ -98,7 +112,7 @@ class TestSurvey:
assert res2[0] == res[0]
assert len(res2) == len(surveys2)
- def test_category(self, survey_manager):
+ def test_category(self, survey_manager: SurveyManager):
survey1 = Survey(id=562289, survey_id="a", source=Source.TESTING)
survey2 = Survey(id=562290, survey_id="a", source=Source.TESTING)
categories = list(survey_manager.category_manager.categories.values())
@@ -110,8 +124,14 @@ class TestSurvey:
survey_manager.update_surveys_categories(surveys)
def test_survey_eligibility(
- self, survey_manager, upk_data, question_manager, uqa_manager
+ self,
+ survey_manager: SurveyManager,
+ upk_data: Callable[..., None],
+ question_manager: QuestionManager,
+ uqa_manager: UQAManager,
):
+ upk_data()
+
bucket = TopNPlusBucket(
id="c82cf98c578a43218334544ab376b00e",
contents=[],
@@ -161,9 +181,10 @@ class TestSurvey:
calc_answers={"i:adhoc_13126": ("3", "4")},
),
]
- uqad = dict()
+ uqad = {}
for uqa in uqas:
- for k, v in uqa.calc_answers.items():
+ assert uqa.calc_answers
+ for k in uqa.calc_answers:
if k in qualifying_questions:
uqad[k] = uqa
uqad[uqa.property_code] = uqa
@@ -174,9 +195,9 @@ class TestSurvey:
qs = sorted(qs, key=lambda x: x.importance.task_count if x.importance else 0)
# qd = {q.id: q for q in qs}
- q = [x for x in qs if x.ext_question_id == "i:adhoc_13126"][0]
+ q = next(x for x in qs if x.ext_question_id == "i:adhoc_13126")
q.explanation_template = "You have been diagnosed with: {answer}."
- q = [x for x in qs if x.ext_question_id == "gr:gender"][0]
+ q = next(x for x in qs if x.ext_question_id == "gr:gender")
q.explanation_template = "Your gender is {answer}."
ecs = []
@@ -205,10 +226,9 @@ class TestSurvey:
class TestSurveyStat:
def test(
self,
- delete_buyers_surveys,
surveystat_manager,
- survey_manager,
- surveys_fixture,
+ survey_manager: SurveyManager,
+ surveys_fixture: list[Survey],
):
survey_manager.create_or_update(surveys_fixture)
ss = [ssa, ssb]
@@ -234,7 +254,7 @@ class TestSurveyStat:
):
survey = surveys_fixture[0].model_copy()
surveys = []
- for idx in range(20_000):
+ for _ in range(20_000):
s = survey.model_copy()
s.survey_id = uuid.uuid4().hex
surveys.append(s)
@@ -251,14 +271,14 @@ class TestSurveyStat:
survey_stats.append(ss)
print(len(survey_stats))
print(survey_stats[12].natural_key, survey_stats[2000].natural_key)
- print(f"----a-----: {datetime.now().isoformat()}")
+ print(f"----a-----: {datetime.now(tz=UTC).isoformat()}")
res = surveystat_manager.update_or_create(survey_stats)
- print(f"----b-----: {datetime.now().isoformat()}")
+ print(f"----b-----: {datetime.now(tz=UTC).isoformat()}")
assert len(res) == 20_000
return
# 1,000 of the 20,000 are "new"
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
for s in ss[:1000]:
s.survey__survey_id = "b"
s.updated_at = now
@@ -269,22 +289,24 @@ class TestSurveyStat:
s.conv_beta = 20
s.updated_at = now
# and 1,000 don't change
- print(f"----c-----: {datetime.now().isoformat()}")
+ print(f"----c-----: {datetime.now(tz=UTC).isoformat()}")
res2 = surveystat_manager.update_or_create(ss)
- print(f"----d-----: {datetime.now().isoformat()}")
+ print(f"----d-----: {datetime.now(tz=UTC).isoformat()}")
assert len(res2) == 20_000
def test_ymsp(
self,
- delete_buyers_surveys,
- surveys_fixture,
- survey_manager,
- surveystat_manager,
+ delete_buyers_surveys: Callable[..., None],
+ surveys_fixture: list[Survey],
+ survey_manager: SurveyManager,
+ surveystat_manager: SurveyStatManager,
):
+ delete_buyers_surveys()
+
source = Source.TESTING
survey = surveys_fixture[0].model_copy()
surveys = []
- for idx in range(100):
+ for _ in range(100):
s = survey.model_copy()
s.survey_id = uuid.uuid4().hex
surveys.append(s)
@@ -298,14 +320,14 @@ class TestSurveyStat:
source=source, surveys=surveys, survey_stats=survey_stats
)
# UPDATE -------
- since = datetime.now(tz=timezone.utc)
+ since = datetime.now(tz=UTC)
print(f"{since=}")
# 10 survey disappear
surveys = surveys[10:]
# and 2 new ones are created
- for idx in range(2):
+ for _ in range(2):
s = survey.model_copy()
s.survey_id = uuid.uuid4().hex
surveys.append(s)
@@ -329,11 +351,13 @@ class TestSurveyStat:
def test_filter(
self,
- delete_buyers_surveys,
- surveys_fixture,
- survey_manager,
- surveystat_manager,
+ delete_buyers_surveys: Callable[..., None],
+ surveys_fixture: list[Survey],
+ survey_manager: SurveyManager,
+ surveystat_manager: SurveyStatManager,
):
+ delete_buyers_surveys()
+
surveys = []
survey = surveys_fixture[0].model_copy()
survey.source = Source.TESTING
diff --git a/tests/managers/thl/test_survey_penalty.py b/tests/managers/thl/test_survey_penalty.py
index 4c7dc08..04f69d2 100644
--- a/tests/managers/thl/test_survey_penalty.py
+++ b/tests/managers/thl/test_survey_penalty.py
@@ -1,14 +1,19 @@
+from __future__ import annotations
+
import uuid
+from typing import TYPE_CHECKING
import pytest
-from cachetools.keys import _HashedTuple
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.survey.penalty import (
BPSurveyPenalty,
TeamSurveyPenalty,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.survey_penalty import SurveyPenaltyManager
+
@pytest.fixture
def product_uuid() -> str:
@@ -23,7 +28,9 @@ def team_uuid() -> str:
@pytest.fixture
-def penalties(product_uuid, team_uuid):
+def penalties(
+ product_uuid: str, team_uuid: str
+) -> list[BPSurveyPenalty | TeamSurveyPenalty]:
return [
BPSurveyPenalty(
source=Source.TESTING, survey_id="a", penalty=0.1, product_id=product_uuid
@@ -49,7 +56,13 @@ def penalties(product_uuid, team_uuid):
class TestSurveyPenalty:
- def test(self, surveypenalty_manager, penalties, product_uuid, team_uuid):
+ def test(
+ self,
+ surveypenalty_manager: SurveyPenaltyManager,
+ penalties: list[BPSurveyPenalty | TeamSurveyPenalty],
+ product_uuid: str,
+ team_uuid: str,
+ ):
surveypenalty_manager.set_penalties(penalties)
res = surveypenalty_manager.get_penalties_for(
@@ -89,10 +102,8 @@ class TestSurveyPenalty:
)
assert res == {"t:a": 0.1, "t:b": 0.2, "u:b": 0.1}
assert surveypenalty_manager.cache.currsize == 1
- cached_key = tuple(list(list(surveypenalty_manager.cache.keys())[0])[1:])
- assert cached_key == tuple(
- ["product_id", product_uuid, "team_id", team_id_random]
- )
+ cached_key = tuple(list(next(iter(surveypenalty_manager.cache.keys())))[1:])
+ assert cached_key == ("product_id", product_uuid, "team_id", team_id_random)
# Both don't exist, return nothing
res = surveypenalty_manager.get_penalties_for(
diff --git a/tests/managers/thl/test_task_adjustment.py b/tests/managers/thl/test_task_adjustment.py
index 839bbe1..1e741fd 100644
--- a/tests/managers/thl/test_task_adjustment.py
+++ b/tests/managers/thl/test_task_adjustment.py
@@ -1,27 +1,43 @@
+from __future__ import annotations
+
import logging
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
+from decimal import Decimal
from random import randint
+from typing import TYPE_CHECKING
import pytest
-from datetime import datetime, timezone, timedelta
-from decimal import Decimal
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.definitions import (
Status,
StatusCode1,
WallAdjustedStatus,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.ledger_manager.thl_ledger import ThlLedgerManager
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.managers.thl.task_adjustment import (
+ TaskAdjustmentManager,
+ )
+ from generalresearch.managers.thl.wall import WallManager
+ from generalresearch.models.thl.session import Session, Wall
+ from generalresearch.models.thl.user import User
+
@pytest.fixture()
-def session_complete(session_with_tx_factory, user):
+def session_complete(session_with_tx_factory: Callable[..., Session], user: User):
return session_with_tx_factory(
user=user, final_status=Status.COMPLETE, wall_req_cpi=Decimal("1.23")
)
@pytest.fixture()
-def session_complete_with_wallet(session_with_tx_factory, user_with_wallet):
+def session_complete_with_wallet(
+ session_with_tx_factory: Callable[..., None], user_with_wallet: User
+):
return session_with_tx_factory(
user=user_with_wallet,
final_status=Status.COMPLETE,
@@ -30,17 +46,21 @@ def session_complete_with_wallet(session_with_tx_factory, user_with_wallet):
@pytest.fixture()
-def session_fail(user, session_manager, wall_manager):
- session = session_manager.create_dummy(
- started=datetime.now(timezone.utc), user=user
- )
- wall1 = wall_manager.create_dummy(
- session_id=session.id,
- user_id=user.user_id,
+def session_fail(
+ user: User,
+ session_manager: SessionManager,
+ wall_manager: WallManager,
+ session_factory: Callable[..., Session],
+ wall_factory: Callable[..., Wall],
+) -> Session:
+ session = session_manager.create(started=datetime.now(UTC), user=user)
+ wall1 = wall_factory(
+ session=session,
+ user=user,
source=Source.DYNATA,
req_survey_id="72723",
req_cpi=Decimal("3.22"),
- started=datetime.now(timezone.utc),
+ started=datetime.now(UTC),
)
wall_manager.finish(
wall=wall1,
@@ -48,46 +68,47 @@ def session_fail(user, session_manager, wall_manager):
status_code_1=StatusCode1.PS_FAIL,
finished=wall1.started + timedelta(seconds=randint(a=60 * 2, b=60 * 10)),
)
- session.wall_events.append(wall1)
return session
class TestHandleRecons:
+ @pytest.fixture(autouse=True)
+ def setup(self, create_main_accounts):
+ create_main_accounts()
def test_complete_to_recon(
self,
- session_complete,
- thl_lm,
- task_adjustment_manager,
- wall_manager,
- session_manager,
+ session_complete: Session,
+ thl_ledger_manager: ThlLedgerManager,
+ task_adjustment_manager: TaskAdjustmentManager,
+ wall_manager: WallManager,
+ session_manager: SessionManager,
caplog,
):
print(wall_manager.pg_config.dsn)
mid = session_complete.uuid
wall_uuid = session_complete.wall_events[-1].uuid
s = session_complete
- ledger_manager = thl_lm
- revenue_account = ledger_manager.get_account_task_complete_revenue()
- current_amount = ledger_manager.get_account_filtered_balance(
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
- assert (
- current_amount == 123
- ), "this is the amount of revenue from this task complete"
+ assert current_amount == 123, (
+ "this is the amount of revenue from this task complete"
+ )
- bp_wallet_account = ledger_manager.get_account_or_create_bp_wallet(
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
s.user.product
)
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 117, "this is the amount paid to the BP"
# Do the work here !! ----v
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
)
@@ -95,21 +116,21 @@ class TestHandleRecons:
len(task_adjustment_manager.filter_by_wall_uuid(wall_uuid=wall_uuid)) == 1
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 0, "after recon, it should be zeroed"
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 0, "this is the amount paid to the BP"
- commission_account = ledger_manager.get_account_or_create_bp_commission(
+ commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
s.user.product
)
- assert ledger_manager.get_account_balance(commission_account) == 0
+ assert thl_ledger_manager.get_account_balance(commission_account) == 0
# Now, say we get the exact same *adjust to incomplete* msg again. It should do nothing!
- adjusted_timestamp = datetime.now(tz=timezone.utc)
+ adjusted_timestamp = datetime.now(tz=UTC)
wall = wall_manager.get_from_uuid(wall_uuid=wall_uuid)
with pytest.raises(match=" is already "):
wall_manager.adjust_status(
@@ -122,7 +143,7 @@ class TestHandleRecons:
session = session_manager.get_from_id(wall.session_id)
user = session.user
with caplog.at_level(logging.INFO):
- ledger_manager.create_tx_task_adjustment(
+ thl_ledger_manager.create_tx_task_adjustment(
wall, user=user, created=adjusted_timestamp
)
assert "No transactions needed" in caplog.text
@@ -135,212 +156,219 @@ class TestHandleRecons:
assert "is already f" in caplog.text or "is already Status.FAIL" in caplog.text
with caplog.at_level(logging.INFO, logger="LedgerManager"):
- ledger_manager.create_tx_bp_adjustment(session, created=adjusted_timestamp)
+ thl_ledger_manager.create_tx_bp_adjustment(
+ session, created=adjusted_timestamp
+ )
assert "No transactions needed" in caplog.text
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 0, "after recon, it should be zeroed"
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 0, "this is the amount paid to the BP"
# And if we get an adj to fail, and handle it, it should do nothing at all
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
)
assert (
len(task_adjustment_manager.filter_by_wall_uuid(wall_uuid=wall_uuid)) == 1
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 0, "after recon, it should be zeroed"
- def test_fail_to_complete(self, session_fail, thl_lm, task_adjustment_manager):
- s = session_fail
+ def test_fail_to_complete(
+ self,
+ session_fail: Session,
+ thl_ledger_manager: ThlLedgerManager,
+ task_adjustment_manager: TaskAdjustmentManager,
+ ):
mid = session_fail.uuid
wall_uuid = session_fail.wall_events[-1].uuid
- ledger_manager = thl_lm
- revenue_account = ledger_manager.get_account_task_complete_revenue()
- current_amount = ledger_manager.get_account_filtered_balance(
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", mid
)
- assert (
- current_amount == 0
- ), "this is the amount of revenue from this task complete"
+ assert current_amount == 0, (
+ "this is the amount of revenue from this task complete"
+ )
- bp_wallet_account = ledger_manager.get_account_or_create_bp_wallet(
- s.user.product
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ session_fail.user.product
)
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 0, "this is the amount paid to the BP"
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_COMPLETE,
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 322, "after recon, we should be paid"
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 306, "this is the amount paid to the BP"
# Now reverse it back to fail
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 0
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 0
- commission_account = ledger_manager.get_account_or_create_bp_commission(
- s.user.product
+ commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ session_fail.user.product
)
- assert ledger_manager.get_account_balance(commission_account) == 0
+ assert thl_ledger_manager.get_account_balance(commission_account) == 0
def test_complete_already_complete(
- self, session_complete, thl_lm, task_adjustment_manager
+ self,
+ session_complete: Session,
+ thl_ledger_manager: ThlLedgerManager,
+ task_adjustment_manager: TaskAdjustmentManager,
):
- s = session_complete
mid = session_complete.uuid
wall_uuid = session_complete.wall_events[-1].uuid
- ledger_manager = thl_lm
for _ in range(4):
# just run it 4 times to make sure nothing happens 4 times
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_COMPLETE,
)
- revenue_account = ledger_manager.get_account_task_complete_revenue()
- bp_wallet_account = ledger_manager.get_account_or_create_bp_wallet(
- s.user.product
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ session_complete.user.product
)
- commission_account = ledger_manager.get_account_or_create_bp_commission(
- s.user.product
+ commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ session_complete.user.product
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert current_amount == 123
- assert ledger_manager.get_account_balance(commission_account) == 6
+ assert thl_ledger_manager.get_account_balance(commission_account) == 6
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 117
def test_incomplete_already_incomplete(
- self, session_fail, thl_lm, task_adjustment_manager
+ self,
+ session_fail: Session,
+ thl_ledger_manager: ThlLedgerManager,
+ task_adjustment_manager: TaskAdjustmentManager,
):
- s = session_fail
mid = session_fail.uuid
wall_uuid = session_fail.wall_events[-1].uuid
- ledger_manager = thl_lm
for _ in range(4):
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
)
- revenue_account = ledger_manager.get_account_task_complete_revenue()
- bp_wallet_account = ledger_manager.get_account_or_create_bp_wallet(
- s.user.product
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ session_fail.user.product
)
- commission_account = ledger_manager.get_account_or_create_bp_commission(
- s.user.product
+ commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ session_fail.user.product
)
- current_amount = ledger_manager.get_account_filtered_balance(
+ current_amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", mid
)
assert current_amount == 0
- assert ledger_manager.get_account_balance(commission_account) == 0
+ assert thl_ledger_manager.get_account_balance(commission_account) == 0
- current_bp_payout = ledger_manager.get_account_filtered_balance(
+ current_bp_payout = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert current_bp_payout == 0
def test_complete_to_recon_user_wallet(
self,
- session_complete_with_wallet,
- user_with_wallet,
- thl_lm,
- task_adjustment_manager,
+ session_complete_with_wallet: Session,
+ # user_with_wallet: User,
+ thl_ledger_manager: ThlLedgerManager,
+ task_adjustment_manager: TaskAdjustmentManager,
):
- s = session_complete_with_wallet
- mid = s.uuid
- wall_uuid = s.wall_events[-1].uuid
- ledger_manager = thl_lm
+ mid = session_complete_with_wallet.uuid
+ wall_uuid = session_complete_with_wallet.wall_events[-1].uuid
- revenue_account = ledger_manager.get_account_task_complete_revenue()
- amount = ledger_manager.get_account_filtered_balance(
+ revenue_account = thl_ledger_manager.get_account_task_complete_revenue()
+ amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert amount == 123, "this is the amount of revenue from this task complete"
- bp_wallet_account = ledger_manager.get_account_or_create_bp_wallet(
- s.user.product
+ bp_wallet_account = thl_ledger_manager.get_account_or_create_bp_wallet(
+ session_complete_with_wallet.user.product
)
- user_wallet_account = ledger_manager.get_account_or_create_user_wallet(s.user)
- commission_account = ledger_manager.get_account_or_create_bp_commission(
- s.user.product
+ user_wallet_account = thl_ledger_manager.get_account_or_create_user_wallet(
+ session_complete_with_wallet.user
)
- amount = ledger_manager.get_account_filtered_balance(
+ commission_account = thl_ledger_manager.get_account_or_create_bp_commission(
+ session_complete_with_wallet.user.product
+ )
+ amount = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert amount == 70, "this is the amount paid to the BP"
- amount = ledger_manager.get_account_filtered_balance(
+ amount = thl_ledger_manager.get_account_filtered_balance(
user_wallet_account, "thl_session", mid
)
assert amount == 47, "this is the amount paid to the user"
- assert (
- ledger_manager.get_account_balance(commission_account) == 6
- ), "earned commission"
+ assert thl_ledger_manager.get_account_balance(commission_account) == 6, (
+ "earned commission"
+ )
task_adjustment_manager.handle_single_recon(
- ledger_manager=thl_lm,
+ ledger_manager=thl_ledger_manager,
wall_uuid=wall_uuid,
adjusted_status=WallAdjustedStatus.ADJUSTED_TO_FAIL,
)
- amount = ledger_manager.get_account_filtered_balance(
+ amount = thl_ledger_manager.get_account_filtered_balance(
revenue_account, "thl_wall", wall_uuid
)
assert amount == 0
- amount = ledger_manager.get_account_filtered_balance(
+ amount = thl_ledger_manager.get_account_filtered_balance(
bp_wallet_account, "thl_session", mid
)
assert amount == 0
- amount = ledger_manager.get_account_filtered_balance(
+ amount = thl_ledger_manager.get_account_filtered_balance(
user_wallet_account, "thl_session", mid
)
assert amount == 0
- assert (
- ledger_manager.get_account_balance(commission_account) == 0
- ), "earned commission"
+ assert thl_ledger_manager.get_account_balance(commission_account) == 0, (
+ "earned commission"
+ )
diff --git a/tests/managers/thl/test_task_status.py b/tests/managers/thl/test_task_status.py
index 55c89c0..11edc99 100644
--- a/tests/managers/thl/test_task_status.py
+++ b/tests/managers/thl/test_task_status.py
@@ -1,47 +1,61 @@
-import pytest
-from datetime import datetime, timezone, timedelta
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
+from typing import TYPE_CHECKING
+
+import pytest
-from generalresearch.managers.thl.session import SessionManager
-from generalresearch.models import Source
+from generalresearch.models.definitions import Source
from generalresearch.models.thl.definitions import (
Status,
- WallAdjustedStatus,
StatusCode1,
+ WallAdjustedStatus,
)
from generalresearch.models.thl.product import (
PayoutConfig,
- UserWalletConfig,
PayoutTransformation,
PayoutTransformationPercentArgs,
+ UserWalletConfig,
)
-from generalresearch.models.thl.session import Session, WallOut
+from generalresearch.models.thl.session import WallOut
from generalresearch.models.thl.task_status import TaskStatusResponse
-from generalresearch.models.thl.user import User
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.managers.thl.wall import WallManager
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.session import Session
+ from generalresearch.models.thl.user import User
-start1 = datetime(2023, 2, 1, tzinfo=timezone.utc)
+start1 = datetime(2023, 2, 1, tzinfo=UTC)
finish1 = start1 + timedelta(minutes=5)
recon1 = start1 + timedelta(days=20)
-start2 = datetime(2023, 2, 2, tzinfo=timezone.utc)
+start2 = datetime(2023, 2, 2, tzinfo=UTC)
finish2 = start2 + timedelta(minutes=5)
-start3 = datetime(2023, 2, 3, tzinfo=timezone.utc)
+start3 = datetime(2023, 2, 3, tzinfo=UTC)
finish3 = start3 + timedelta(minutes=5)
-@pytest.fixture(scope="session")
-def bp1(product_manager):
+@pytest.fixture()
+def bp1(
+ product_factory: Callable[..., Product], product_manager: ProductManager
+) -> Product:
# user wallet disabled, payout xform NULL
- return product_manager.create_dummy(
+ return product_factory(
user_wallet_config=UserWalletConfig(enabled=False),
payout_config=PayoutConfig(),
)
-@pytest.fixture(scope="session")
-def bp2(product_manager):
+@pytest.fixture()
+def bp2(
+ product_factory: Callable[..., Product], product_manager: ProductManager
+) -> Product:
# user wallet disabled, payout xform 40%
- return product_manager.create_dummy(
+ return product_factory(
user_wallet_config=UserWalletConfig(enabled=False),
payout_config=PayoutConfig(
payout_transformation=PayoutTransformation(
@@ -52,10 +66,12 @@ def bp2(product_manager):
)
-@pytest.fixture(scope="session")
-def bp3(product_manager):
+@pytest.fixture()
+def bp3(
+ product_factory: Callable[..., Product], product_manager: ProductManager
+) -> Product:
# user wallet enabled, payout xform 50%
- return product_manager.create_dummy(
+ return product_factory(
user_wallet_config=UserWalletConfig(enabled=True),
payout_config=PayoutConfig(
payout_transformation=PayoutTransformation(
@@ -70,9 +86,9 @@ class TestTaskStatus:
def test_task_status_complete_1(
self,
- bp1,
- user_factory,
- finished_session_factory,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
session_manager: SessionManager,
):
# User Payout xform NULL
@@ -130,7 +146,11 @@ class TestTaskStatus:
assert tsr == expected_tsr
def test_task_status_complete_2(
- self, bp2, user_factory, finished_session_factory, session_manager
+ self,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# User Payout xform 40%
user2: User = user_factory(product=bp2)
@@ -197,7 +217,11 @@ class TestTaskStatus:
assert tsr == expected_tsr
def test_task_status_complete_3(
- self, bp3, user_factory, finished_session_factory, session_manager
+ self,
+ bp3: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# Wallet enabled User Payout xform 50% (the response is identical
# to the user wallet disabled w same xform)
@@ -227,12 +251,17 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s3.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_fail(
- self, bp1, user_factory, finished_session_factory, session_manager
+ self,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# User Payout xform NULL: user payout is None always
user1: User = user_factory(product=bp1)
@@ -263,12 +292,17 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s1.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_fail_xform(
- self, bp2, user_factory, finished_session_factory, session_manager
+ self,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# User Payout xform 40%: user_payout is 0 (not None)
@@ -298,12 +332,17 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_abandon(
- self, bp1, user_factory, session_factory, session_manager
+ self,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# User Payout xform NULL: all payout fields are None
user: User = user_factory(product=bp1)
@@ -332,12 +371,17 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_abandon_xform(
- self, bp2, user_factory, session_factory, session_manager
+ self,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ session_factory: Callable[..., Session],
+ session_manager: SessionManager,
):
# User Payout xform 40%: all payout fields are None (same as when payout xform is null)
user: User = user_factory(product=bp2)
@@ -369,17 +413,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_fail(
self,
- bp1,
- user_factory,
- finished_session_factory,
- wall_manager,
- session_manager,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# Complete -> Fail
# User Payout xform NULL: adjusted_user_* and user_* is still all None
@@ -418,17 +463,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_fail_xform(
self,
- bp2,
- user_factory,
- finished_session_factory,
- wall_manager,
- session_manager,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# Complete -> Fail
# User Payout xform 40%: adjusted_user_payout is 0 (not null)
@@ -470,17 +516,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_complete_from_abandon(
self,
- bp1,
- user_factory,
- session_factory,
- wall_manager,
- session_manager,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# User Payout xform NULL
user: User = user_factory(product=bp1)
@@ -524,17 +571,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_complete_from_abandon_xform(
self,
- bp2,
- user_factory,
- session_factory,
- wall_manager,
- session_manager,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# User Payout xform 40%
user: User = user_factory(product=bp2)
@@ -581,17 +629,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_complete_from_fail(
self,
- bp1,
- user_factory,
- finished_session_factory,
- wall_manager,
- session_manager,
+ bp1: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# User Payout xform NULL
user: User = user_factory(product=bp1)
@@ -635,17 +684,18 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
def test_task_status_adj_complete_from_fail_xform(
self,
- bp2,
- user_factory,
- finished_session_factory,
- wall_manager,
- session_manager,
+ bp2: Product,
+ user_factory: Callable[..., User],
+ finished_session_factory: Callable[..., Session],
+ wall_manager: WallManager,
+ session_manager: SessionManager,
):
# User Payout xform 40%
user: User = user_factory(product=bp2)
@@ -691,6 +741,7 @@ class TestTaskStatus:
}
)
tsr = session_manager.get_task_status_response(s.uuid)
+ assert isinstance(tsr, TaskStatusResponse)
# Not bothering with wall events ...
tsr.wall_events = None
assert tsr == expected_tsr
diff --git a/tests/managers/thl/test_user_manager/test_base.py b/tests/managers/thl/test_user_manager/test_base.py
index 0d7ffef..5d12052 100644
--- a/tests/managers/thl/test_user_manager/test_base.py
+++ b/tests/managers/thl/test_user_manager/test_base.py
@@ -1,23 +1,37 @@
import logging
-from datetime import datetime, timezone
+from collections.abc import Callable
+from datetime import UTC, datetime
from random import randint
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.managers.thl.user_manager import (
- UserCreateNotAllowedError,
get_bp_user_create_limit_hourly,
)
+from generalresearch.managers.thl.user_manager.exceptions import (
+ UserCreateNotAllowedError,
+)
+from generalresearch.managers.thl.user_manager.mysql_user_manager import (
+ MysqlUserManager,
+)
from generalresearch.managers.thl.user_manager.rate_limit import (
RateLimitItemPerHourConstantKey,
+ UserManagerLimiter,
)
-from generalresearch.managers.thl.user_manager.user_manager import (
- UserManager,
-)
-from generalresearch.models.thl.product import Product, UserCreateConfig
+from generalresearch.models.thl.product import UserCreateConfig
from generalresearch.models.thl.user import User
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.product import ProductManager
+ from generalresearch.managers.thl.user_manager.user_manager import (
+ UserManager,
+ )
+ from generalresearch.managers.thl.userhealth import AuditLogManager
+ from generalresearch.models.thl.product import Product
+ from generalresearch.pg_helper import PostgresConfig
+
logger = logging.getLogger()
@@ -83,10 +97,11 @@ class TestUserManager:
class TestBlockUserManager:
- def test_block_user(self, product, user_manager: UserManager):
+ def test_block_user(self, product: Product, user_manager: UserManager):
product_user_id = f"user-{uuid4().hex[:10]}"
# mysql_user_manager to skip user creation limit check
+ assert isinstance(user_manager.mysql_user_manager, MysqlUserManager)
user: User = user_manager.mysql_user_manager.create_user(
product_id=product.id, product_user_id=product_user_id
)
@@ -109,16 +124,19 @@ class TestBlockUserManager:
user = user_manager.get_user(user_id=user.user_id)
assert user.blocked
- def test_block_user_whitelist(self, product, user_manager, thl_web_rw):
+ def test_block_user_whitelist(
+ self, product: Product, user_manager: UserManager, thl_web_rw: PostgresConfig
+ ):
product_user_id = f"user-{uuid4().hex[:10]}"
# mysql_user_manager to skip user creation limit check
+ assert isinstance(user_manager.mysql_user_manager, MysqlUserManager)
user: User = user_manager.mysql_user_manager.create_user(
product_id=product.id, product_user_id=product_user_id
)
assert not user.blocked
- now = datetime.now(tz=timezone.utc)
+ now = datetime.now(tz=UTC)
# Adds user to whitelist
thl_web_rw.execute_write(
"""
@@ -135,8 +153,13 @@ class TestBlockUserManager:
class TestCreateUserManager:
- def test_create_user(self, product_manager, thl_web_rw, user_manager):
- product: Product = product_manager.create_dummy(
+ def test_create_user(
+ self,
+ product_factory: Callable[..., Product],
+ thl_web_rw: PostgresConfig,
+ user_manager: UserManager,
+ ):
+ product: Product = product_factory(
user_create_config=UserCreateConfig(
min_hourly_create_limit=10, max_hourly_create_limit=69
),
@@ -144,6 +167,7 @@ class TestCreateUserManager:
product_user_id = f"user-{uuid4().hex[:10]}"
+ assert isinstance(user_manager.mysql_user_manager, MysqlUserManager)
user: User = user_manager.mysql_user_manager.create_user(
product_id=product.id, product_user_id=product_user_id
)
@@ -156,7 +180,7 @@ class TestCreateUserManager:
# make sure thl_user row is created
res_thl_user = thl_web_rw.execute_sql_query(
- query=f"""
+ query="""
SELECT *
FROM thl_user AS u
WHERE u.id = %s
@@ -172,8 +196,13 @@ class TestCreateUserManager:
assert u2.user_id == user.user_id
assert u2.uuid == user.uuid
- def test_create_user_integrity_error(self, product_manager, user_manager, caplog):
- product: Product = product_manager.create_dummy(
+ def test_create_user_integrity_error(
+ self,
+ user_manager: UserManager,
+ product_factory: Callable[..., Product],
+ caplog,
+ ):
+ product: Product = product_factory(
product_id=uuid4().hex,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -185,6 +214,7 @@ class TestCreateUserManager:
product_user_id = f"user-{uuid4().hex[:10]}"
rand_msg = f"log-{uuid4().hex}"
+ assert isinstance(user_manager.mysql_user_manager, MysqlUserManager)
with caplog.at_level(logging.INFO):
logger.info(rand_msg)
user1 = user_manager.mysql_user_manager.create_user(
@@ -213,9 +243,14 @@ class TestCreateUserManager:
assert user1 == user2
- def test_raise_allow_user_create(self, product_manager, user_manager):
+ def test_raise_allow_user_create(
+ self,
+ product_manager: ProductManager,
+ user_manager: UserManager,
+ product_factory: Callable[..., Product],
+ ):
rand_num = randint(25, 200)
- product: Product = product_manager.create_dummy(
+ product: Product = product_factory(
product_id=uuid4().hex,
team_id=uuid4().hex,
name=f"Test Product ID #{uuid4().hex[:6]}",
@@ -247,10 +282,11 @@ class TestCreateUserManager:
assert key == f"LIMITER/thl-grpc/allow_user_create/{instance.id}"
# make sure we clear the key or subsequent tests will fail
+ assert isinstance(user_manager.user_manager_limiter, UserManagerLimiter)
user_manager.user_manager_limiter.storage.clear(key=key)
n = 0
- with pytest.raises(expected_exception=UserCreateNotAllowedError) as cm:
+ with pytest.raises(expected_exception=UserCreateNotAllowedError):
for n, _ in enumerate(range(rl_value + 5)):
user_manager.user_manager_limiter.raise_allow_user_create(
product=product
@@ -260,14 +296,16 @@ class TestCreateUserManager:
class TestUserManagerMethods:
- def test_audit_log(self, user_manager, user, audit_log_manager):
+ def test_audit_log(
+ self, user_manager: UserManager, user: User, audit_log_manager: AuditLogManager
+ ):
from generalresearch.models.thl.userhealth import AuditLog
res = audit_log_manager.filter_by_user_id(user_id=user.user_id)
assert len(res) == 0
msg = uuid4().hex
- user_manager.audit_log(user=user, level=30, event_type=msg)
+ user_manager.audit_log(audit_log_manager, user=user, level=30, event_type=msg)
res = audit_log_manager.filter_by_user_id(user_id=user.user_id)
assert len(res) == 1
diff --git a/tests/managers/thl/test_user_manager/test_mysql.py b/tests/managers/thl/test_user_manager/test_mysql.py
index 0313bbf..ed7d458 100644
--- a/tests/managers/thl/test_user_manager/test_mysql.py
+++ b/tests/managers/thl/test_user_manager/test_mysql.py
@@ -1,25 +1,28 @@
-from test_utils.models.conftest import user, user_manager
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.user_manager.mysql_user_manager import (
+ MysqlUserManager,
+ )
+ from generalresearch.models.thl.user import User
class TestUserManagerMysqlNew:
- def test_get_notset(self, user_manager):
- assert (
- user_manager.mysql_user_manager.get_user_from_mysql(user_id=-3105) is None
- )
+ def test_get_notset(self, mysql_user_manager: MysqlUserManager):
+ assert mysql_user_manager.get_user_from_mysql(user_id=-3105) is None
- def test_get_user_id(self, user, user_manager):
- assert (
- user_manager.mysql_user_manager.get_user_from_mysql(user_id=user.user_id)
- == user
- )
+ def test_get_user_id(self, user: User, mysql_user_manager: MysqlUserManager):
+ assert mysql_user_manager.get_user_from_mysql(user_id=user.user_id) == user
- def test_get_uuid(self, user, user_manager):
- u = user_manager.mysql_user_manager.get_user_from_mysql(user_uuid=user.uuid)
+ def test_get_uuid(self, user: User, mysql_user_manager: MysqlUserManager):
+ u = mysql_user_manager.get_user_from_mysql(user_uuid=user.uuid)
assert u == user
- def test_get_ubp(self, user, user_manager):
- u = user_manager.mysql_user_manager.get_user_from_mysql(
+ def test_get_ubp(self, user: User, mysql_user_manager: MysqlUserManager):
+ u = mysql_user_manager.get_user_from_mysql(
product_id=user.product_id, product_user_id=user.product_user_id
)
assert u == user
diff --git a/tests/managers/thl/test_user_manager/test_redis.py b/tests/managers/thl/test_user_manager/test_redis.py
index a69519e..f6b59c9 100644
--- a/tests/managers/thl/test_user_manager/test_redis.py
+++ b/tests/managers/thl/test_user_manager/test_redis.py
@@ -1,29 +1,41 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
import pytest
from generalresearch.managers.base import Permission
+from generalresearch.managers.thl.user_manager.redis_user_manager import (
+ RedisUserManager,
+)
+
+if TYPE_CHECKING:
+ from generalresearch.config import GRLBaseSettings
+ from generalresearch.models.thl.user import User
+ from generalresearch.pg_helper import PostgresConfig
class TestUserManagerRedis:
- def test_get_notset(self, user_manager, user):
- user_manager.clear_user_inmemory_cache(user=user)
- assert user_manager.redis_user_manager.get_user(user_id=user.user_id) is None
+ def test_get_notset(self, redis_user_manager: RedisUserManager, user: User):
+ redis_user_manager.clear_user(user=user)
+ assert redis_user_manager.get_user(user_id=user.user_id) is None
- def test_get_user_id(self, user_manager, user):
- user_manager.redis_user_manager.set_user(user=user)
+ def test_get_user_id(self, redis_user_manager: RedisUserManager, user: User):
+ redis_user_manager.set_user(user=user)
- assert user_manager.redis_user_manager.get_user(user_id=user.user_id) == user
+ assert redis_user_manager.get_user(user_id=user.user_id) == user
- def test_get_uuid(self, user_manager, user):
- user_manager.redis_user_manager.set_user(user=user)
+ def test_get_uuid(self, redis_user_manager: RedisUserManager, user: User):
+ redis_user_manager.set_user(user=user)
- assert user_manager.redis_user_manager.get_user(user_uuid=user.uuid) == user
+ assert redis_user_manager.get_user(user_uuid=user.uuid) == user
- def test_get_ubp(self, user_manager, user):
- user_manager.redis_user_manager.set_user(user=user)
+ def test_get_ubp(self, redis_user_manager: RedisUserManager, user: User):
+ redis_user_manager.set_user(user=user)
assert (
- user_manager.redis_user_manager.get_user(
+ redis_user_manager.get_user(
product_id=user.product_id, product_user_id=user.product_user_id
)
== user
@@ -34,7 +46,13 @@ class TestUserManagerRedis:
# I mean, the sets are implicitly tested by the get tests above. no point
pass
- def test_get_with_cache_prefix(self, settings, user, thl_web_rw, thl_web_rr):
+ def test_get_with_cache_prefix(
+ self,
+ settings: GRLBaseSettings,
+ user: User,
+ thl_web_rw: PostgresConfig,
+ thl_web_rr: PostgresConfig,
+ ):
"""
Confirm the prefix functionality is working; we do this so it
is easier to migrate between any potentially breaking versions
@@ -69,9 +87,11 @@ class TestUserManagerRedis:
product_id=user.product_id, product_user_id=user.product_user_id
)
+ assert isinstance(um1.redis_user_manager, RedisUserManager)
res1 = um1.redis_user_manager.client.get(f"user-lookup:user_id:{user.user_id}")
assert res1 is not None
+ assert isinstance(um2.redis_user_manager, RedisUserManager)
res2 = um2.redis_user_manager.client.get(
f"user-lookup-v2:user_id:{user.user_id}"
)
diff --git a/tests/managers/thl/test_user_manager/test_user_fetch.py b/tests/managers/thl/test_user_manager/test_user_fetch.py
index a4b3d57..9a279ed 100644
--- a/tests/managers/thl/test_user_manager/test_user_fetch.py
+++ b/tests/managers/thl/test_user_manager/test_user_fetch.py
@@ -1,14 +1,25 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
-from generalresearch.models.thl.user import User
-from test_utils.models.conftest import product, user_manager, user_factory
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.user_manager.user_manager import UserManager
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
class TestUserManagerFetch:
- def test_fetch(self, user_factory, product, user_manager):
+ def test_fetch(
+ self,
+ user_factory: Callable[..., User],
+ product: Product,
+ user_manager: UserManager,
+ ):
user1: User = user_factory(product=product)
user2: User = user_factory(product=product)
res = user_manager.fetch_by_bpuids(
@@ -30,7 +41,7 @@ class TestUserManagerFetch:
res = user_manager.fetch(user_uuids=[uuid4().hex])
assert len(res) == 0
- def test_fetch_invalid(self, user_manager):
+ def test_fetch_invalid(self, user_manager: UserManager):
with pytest.raises(AssertionError) as e:
user_manager.fetch(user_uuids=[], user_ids=None)
assert "Must pass ONE of user_ids, user_uuids" in str(e.value)
diff --git a/tests/managers/thl/test_user_manager/test_user_metadata.py b/tests/managers/thl/test_user_manager/test_user_metadata.py
index 91dc16a..eb6a272 100644
--- a/tests/managers/thl/test_user_manager/test_user_metadata.py
+++ b/tests/managers/thl/test_user_manager/test_user_metadata.py
@@ -1,20 +1,38 @@
+from __future__ import annotations
+
+from collections.abc import Callable
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from generalresearch.models.thl.user_profile import UserMetadata
-from test_utils.models.conftest import user, user_manager, user_factory
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.user_manager.user_metadata_manager import (
+ UserMetadataManager,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
class TestUserMetadataManager:
- def test_get_notset(self, user, user_manager, user_metadata_manager):
+ def test_get_notset(
+ self,
+ user: User,
+ user_metadata_manager: UserMetadataManager,
+ ):
# The row in the db won't exist. It just returns the default obj with everything None (except for the user_id)
um1 = user_metadata_manager.get(user_id=user.user_id)
assert um1 == UserMetadata(user_id=user.user_id)
- def test_create(self, user_factory, product, user_metadata_manager):
- from generalresearch.models.thl.user import User
+ def test_create(
+ self,
+ user_factory: Callable[..., User],
+ product: Product,
+ user_metadata_manager: UserMetadataManager,
+ ):
u1: User = user_factory(product=product)
@@ -27,8 +45,12 @@ class TestUserMetadataManager:
um2 = user_metadata_manager.get(email_address=email_address)
assert um == um2
- def test_create_no_email(self, product, user_factory, user_metadata_manager):
- from generalresearch.models.thl.user import User
+ def test_create_no_email(
+ self,
+ product: Product,
+ user_factory: Callable[..., User],
+ user_metadata_manager: UserMetadataManager,
+ ):
u1: User = user_factory(product=product)
um = UserMetadata(user_id=u1.user_id)
@@ -38,8 +60,12 @@ class TestUserMetadataManager:
um2 = user_metadata_manager.get(user_id=u1.user_id)
assert um == um2
- def test_update(self, product, user_factory, user_metadata_manager):
- from generalresearch.models.thl.user import User
+ def test_update(
+ self,
+ product: Product,
+ user_factory: Callable[..., User],
+ user_metadata_manager: UserMetadataManager,
+ ):
u: User = user_factory(product=product)
@@ -58,8 +84,9 @@ class TestUserMetadataManager:
email_address=email_address.replace("example1", "example2"),
)
- def test_filter(self, user_factory, product, user_metadata_manager):
- from generalresearch.models.thl.user import User
+ def test_filter(
+ self, user_factory: Callable[..., User], product: Product, user_metadata_manager
+ ):
user1: User = user_factory(product=product)
user2: User = user_factory(product=product)
diff --git a/tests/managers/thl/test_user_streak.py b/tests/managers/thl/test_user_streak.py
index 7728f9f..d99b2b8 100644
--- a/tests/managers/thl/test_user_streak.py
+++ b/tests/managers/thl/test_user_streak.py
@@ -1,19 +1,33 @@
+from __future__ import annotations
+
import copy
-from datetime import datetime, timezone, timedelta, date
+from collections.abc import Callable
+from datetime import UTC, date, datetime, timedelta
from decimal import Decimal
+from typing import TYPE_CHECKING
from zoneinfo import ZoneInfo
import pytest
-from generalresearch.managers.thl.user_streak import compute_streaks_from_days
-from generalresearch.models.thl.definitions import StatusCode1, Status
+from generalresearch.managers.thl.user_streak import (
+ compute_streaks_from_days,
+)
+from generalresearch.models.thl.definitions import Status, StatusCode1
from generalresearch.models.thl.user_streak import (
- UserStreak,
- StreakState,
- StreakPeriod,
StreakFulfillment,
+ StreakPeriod,
+ StreakState,
+ UserStreak,
)
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.managers.thl.user_streak import (
+ UserStreakManager,
+ )
+ from generalresearch.models.thl.session import Session, Wall
+ from generalresearch.models.thl.user import User
+
def test_compute_streaks_from_days():
days = [
@@ -59,7 +73,7 @@ def test_compute_streaks_from_days():
@pytest.fixture
-def broken_active_streak(user):
+def broken_active_streak(user: User) -> list[UserStreak]:
return [
UserStreak(
period=StreakPeriod.DAY,
@@ -94,8 +108,12 @@ def broken_active_streak(user):
]
-def create_session_fail(session_manager, start, user):
- session = session_manager.create_dummy(started=start, country_iso="us", user=user)
+def create_session_fail(
+ session_manager: SessionManager,
+ start: datetime,
+ user: User,
+):
+ session = session_manager.create(started=start, country_iso="us", user=user)
session_manager.finish_with_status(
session,
finished=start + timedelta(minutes=1),
@@ -104,8 +122,12 @@ def create_session_fail(session_manager, start, user):
)
-def create_session_complete(session_manager, start, user):
- session = session_manager.create_dummy(started=start, country_iso="us", user=user)
+def create_session_complete(
+ session_manager: SessionManager,
+ start: datetime,
+ user: User,
+):
+ session = session_manager.create(started=start, country_iso="us", user=user)
session_manager.finish_with_status(
session,
finished=start + timedelta(minutes=1),
@@ -115,7 +137,7 @@ def create_session_complete(session_manager, start, user):
)
-def test_user_streak_empty(user_streak_manager, user):
+def test_user_streak_empty(user_streak_manager: UserStreakManager, user: User):
streaks = user_streak_manager.get_user_streaks(
user_id=user.user_id, country_iso="us"
)
@@ -123,14 +145,19 @@ def test_user_streak_empty(user_streak_manager, user):
def test_user_streaks_active_broken(
- user_streak_manager, user, session_manager, broken_active_streak
+ user_streak_manager: UserStreakManager,
+ user: User,
+ session_manager: SessionManager,
+ broken_active_streak: list[UserStreak],
+ bare_session_factory: Callable[..., Session],
+ wall_factory: Callable[..., Wall],
):
# Testing active streak, but broken (not today or yesterday)
- start1 = datetime(2025, 2, 12, tzinfo=timezone.utc)
+ start1 = datetime(2025, 2, 12, tzinfo=UTC)
end1 = start1 + timedelta(minutes=1)
# abandon counts as inactive
- session = session_manager.create_dummy(started=start1, country_iso="us", user=user)
+ session = bare_session_factory(started=start1, country_iso="us", user=user)
streak = user_streak_manager.get_user_streaks(user_id=user.user_id)
assert streak == []
@@ -171,12 +198,14 @@ def test_user_streaks_active_broken(
assert streaks == expected_streaks
-def test_user_streak_complete_active(user_streak_manager, user, session_manager):
+def test_user_streak_complete_active(
+ user_streak_manager: UserStreakManager, user: User, session_manager: SessionManager
+):
"""Testing active streak that is today"""
# They completed yesterday NY time. Today isn't over so streak is pending
start1 = datetime.now(tz=ZoneInfo("America/New_York")) - timedelta(days=1)
- create_session_complete(session_manager, start1.astimezone(tz=timezone.utc), user)
+ create_session_complete(session_manager, start1.astimezone(tz=UTC), user)
last_complete_day = start1.date()
expected_streak = UserStreak(
@@ -192,16 +221,16 @@ def test_user_streak_complete_active(user_streak_manager, user, session_manager)
streaks = user_streak_manager.get_user_streaks(
user_id=user.user_id, country_iso="us"
)
- streak = [
+ streak = next(
s
for s in streaks
if s.fulfillment == StreakFulfillment.COMPLETE and s.period == StreakPeriod.DAY
- ][0]
+ )
assert streak == expected_streak
# And now they complete today
start2 = datetime.now(tz=ZoneInfo("America/New_York"))
- create_session_complete(session_manager, start2.astimezone(tz=timezone.utc), user)
+ create_session_complete(session_manager, start2.astimezone(tz=UTC), user)
last_complete_day = start2.date()
expected_streak = UserStreak(
longest_streak=2,
@@ -217,9 +246,9 @@ def test_user_streak_complete_active(user_streak_manager, user, session_manager)
streaks = user_streak_manager.get_user_streaks(
user_id=user.user_id, country_iso="us"
)
- streak = [
+ streak = next(
s
for s in streaks
if s.fulfillment == StreakFulfillment.COMPLETE and s.period == StreakPeriod.DAY
- ][0]
+ )
assert streak == expected_streak
diff --git a/tests/managers/thl/test_userhealth.py b/tests/managers/thl/test_userhealth.py
index 1cda8de..268b110 100644
--- a/tests/managers/thl/test_userhealth.py
+++ b/tests/managers/thl/test_userhealth.py
@@ -1,27 +1,43 @@
-from datetime import timezone, datetime
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime
+from typing import TYPE_CHECKING
from uuid import uuid4
import faker
import pytest
from generalresearch.managers.thl.userhealth import (
+ AuditLogManager,
IPRecordManager,
UserIpHistoryManager,
)
-from generalresearch.models.thl.ipinfo import GeoIPInformation
+from generalresearch.models.thl.ipinfo import (
+ GeoIPInformation,
+)
from generalresearch.models.thl.user_iphistory import (
IPRecord,
+ UserIPHistory,
)
-from generalresearch.models.thl.userhealth import AuditLogLevel, AuditLog
+from generalresearch.models.thl.userhealth import AuditLog, AuditLogLevel
+
+if TYPE_CHECKING:
+ from generalresearch.models.thl.ipinfo import (
+ IPGeoname,
+ IPInformation,
+ )
+ from generalresearch.models.thl.product import Product
+ from generalresearch.models.thl.user import User
+ from generalresearch.pg_helper import PostgresConfig
+ from generalresearch.redis_helper import RedisConfig
fake = faker.Faker()
class TestAuditLog:
- def test_init(self, thl_web_rr, audit_log_manager):
- from generalresearch.managers.thl.userhealth import AuditLogManager
-
+ def test_init(self, thl_web_rr: PostgresConfig, audit_log_manager: AuditLogManager):
alm = AuditLogManager(pg_config=thl_web_rr)
assert isinstance(alm, AuditLogManager)
@@ -33,15 +49,16 @@ class TestAuditLog:
argnames="level",
argvalues=list(AuditLogLevel),
)
- def test_create(self, audit_log_manager, user, level):
+ def test_create(
+ self, audit_log_manager: AuditLogManager, user: User, level: AuditLogLevel
+ ):
instance = audit_log_manager.create(
user_id=user.user_id, level=level, event_type=uuid4().hex
)
assert isinstance(instance, AuditLog)
assert instance.id != 1
- def test_get_by_id(self, audit_log, audit_log_manager):
- from generalresearch.models.thl.userhealth import AuditLog
+ def test_get_by_id(self, audit_log: AuditLog, audit_log_manager: AuditLogManager):
with pytest.raises(expected_exception=Exception) as cm:
audit_log_manager.get_by_id(auditlog_id=999_999_999_999)
@@ -51,14 +68,14 @@ class TestAuditLog:
res = audit_log_manager.get_by_id(auditlog_id=audit_log.id)
assert isinstance(res, AuditLog)
assert res.id == audit_log.id
- assert res.created.tzinfo == timezone.utc
+ assert res.created.tzinfo == UTC
def test_filter_by_product(
self,
- user_factory,
- product_factory,
- audit_log_factory,
- audit_log_manager,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ audit_log_factory: Callable[..., AuditLog],
+ audit_log_manager: AuditLogManager,
):
p1 = product_factory()
p2 = product_factory()
@@ -82,7 +99,11 @@ class TestAuditLog:
assert len(res) == 1
def test_filter_by_user_id(
- self, user_factory, product, audit_log_factory, audit_log_manager
+ self,
+ user_factory: Callable[..., User],
+ product: Product,
+ audit_log_factory: Callable[..., AuditLog],
+ audit_log_manager: AuditLogManager,
):
u1 = user_factory(product=product)
u2 = user_factory(product=product)
@@ -108,10 +129,10 @@ class TestAuditLog:
def test_filter(
self,
- user_factory,
- product_factory,
- audit_log_factory,
- audit_log_manager,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ audit_log_factory: Callable[..., AuditLog],
+ audit_log_manager: AuditLogManager,
):
p1 = product_factory()
p2 = product_factory()
@@ -142,10 +163,10 @@ class TestAuditLog:
def test_filter_count(
self,
- user_factory,
- product_factory,
- audit_log_factory,
- audit_log_manager,
+ user_factory: Callable[..., User],
+ product_factory: Callable[..., Product],
+ audit_log_factory: Callable[..., AuditLog],
+ audit_log_manager: AuditLogManager,
):
p1 = product_factory()
p2 = product_factory()
@@ -179,7 +200,7 @@ class TestAuditLog:
res = audit_log_manager.filter_count(
user_ids=[u1.user_id, u2.user_id, u3.user_id],
- created_after=datetime.now(tz=timezone.utc),
+ created_after=datetime.now(tz=UTC),
)
assert isinstance(res, int)
assert res == 0
@@ -205,18 +226,28 @@ class TestAuditLog:
class TestIPRecordManager:
- def test_init(self, thl_web_rr, thl_redis_config, ip_record_manager):
+ def test_init(
+ self,
+ thl_web_rr: PostgresConfig,
+ thl_redis_config: RedisConfig,
+ ip_record_manager: IPRecordManager,
+ ):
instance = IPRecordManager(pg_config=thl_web_rr, redis_config=thl_redis_config)
assert isinstance(instance, IPRecordManager)
assert isinstance(ip_record_manager, IPRecordManager)
- def test_create(self, ip_record_manager, user, ip_information):
- instance = ip_record_manager.create_dummy(
- user_id=user.user_id, ip=ip_information.ip
- )
+ def test_create(
+ self,
+ ip_record_manager: IPRecordManager,
+ user: User,
+ ip_information: IPInformation,
+ ip_record_factory: Callable[..., IPRecord],
+ ):
+ instance = ip_record_factory(user_id=user.user_id, ip=ip_information.ip)
assert isinstance(instance, IPRecord)
assert isinstance(instance.forwarded_ips, list)
+ assert isinstance(instance.forwarded_ip_records, list)
assert isinstance(instance.forwarded_ip_records[0], IPRecord)
assert isinstance(instance.forwarded_ips[0], str)
@@ -228,20 +259,22 @@ class TestIPRecordManager:
def test_prefetch_info(
self,
- ip_record_factory,
- ip_information_factory,
- ip_geoname,
- user,
- thl_web_rr,
- thl_redis_config,
+ ip_record_factory: Callable[..., IPRecord],
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
+ user: User,
+ thl_web_rr: PostgresConfig,
+ thl_redis_config: RedisConfig,
):
ip = fake.ipv4_public()
ip_information_factory(ip=ip, geoname=ip_geoname)
ipr: IPRecord = ip_record_factory(user_id=user.user_id, ip=ip)
+ assert isinstance(ipr, IPRecord)
assert ipr.information is None
assert len(ipr.forwarded_ip_records) >= 1
+ assert isinstance(ipr.forwarded_ip_records, list)
fipr = ipr.forwarded_ip_records[0]
assert fipr.information is None
@@ -265,7 +298,12 @@ class TestIPRecordManager:
@pytest.mark.usefixtures("user_iphistory_manager_clear_cache")
class TestUserIpHistoryManager:
- def test_init(self, thl_web_rr, thl_redis_config, user_iphistory_manager):
+ def test_init(
+ self,
+ thl_web_rr: PostgresConfig,
+ thl_redis_config: RedisConfig,
+ user_iphistory_manager: UserIpHistoryManager,
+ ):
instance = UserIpHistoryManager(
pg_config=thl_web_rr, redis_config=thl_redis_config
)
@@ -274,27 +312,31 @@ class TestUserIpHistoryManager:
def test_latest_record(
self,
- user_iphistory_manager,
- user,
- ip_record_factory,
- ip_information_factory,
- ip_geoname,
+ user_iphistory_manager: UserIpHistoryManager,
+ user: User,
+ ip_record_factory: Callable[..., IPRecord],
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
):
ip = fake.ipv4_public()
- ip_information_factory(ip=ip, geoname=ip_geoname, is_anonymous=True)
+ ip_information_factory(ip=ip, geoname_id=ip_geoname.geoname_id, is_anonymous=True)
ipr1: IPRecord = ip_record_factory(user_id=user.user_id, ip=ip)
ipr = user_iphistory_manager.get_user_latest_ip_record(user=user)
+ assert isinstance(ipr, IPRecord)
assert ipr.ip == ipr1.ip
assert ipr.is_anonymous
+ assert isinstance(ipr.information, GeoIPInformation)
assert ipr.information.lookup_prefix == "/32"
ip = fake.ipv6()
- ip_information_factory(ip=ip, geoname=ip_geoname)
+ ip_information_factory(ip=ip, geoname_id=ip_geoname.geoname_id)
ipr2: IPRecord = ip_record_factory(user_id=user.user_id, ip=ip)
ipr = user_iphistory_manager.get_user_latest_ip_record(user=user)
+ assert isinstance(ipr, IPRecord)
assert ipr.ip == ipr2.ip
+ assert isinstance(ipr.information, GeoIPInformation)
assert ipr.information.lookup_prefix == "/64"
assert ipr.information is not None
assert not ipr.is_anonymous
@@ -303,6 +345,8 @@ class TestUserIpHistoryManager:
assert country_iso == ip_geoname.country_iso
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
+ assert isinstance(iph, UserIPHistory)
+ assert isinstance(iph.ips, list)
assert iph.ips[0].information is not None
assert iph.ips[1].information is not None
assert iph.ips[0].country_iso == country_iso
@@ -310,7 +354,12 @@ class TestUserIpHistoryManager:
assert iph.ips[0].ip == ipr1.ip
assert iph.ips[1].ip == ipr2.ip
- def test_virgin(self, user, user_iphistory_manager, ip_record_factory):
+ def test_virgin(
+ self,
+ user: User,
+ user_iphistory_manager: UserIpHistoryManager,
+ ip_record_factory: Callable[..., IPRecord],
+ ):
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
assert len(iph.ips) == 0
@@ -320,23 +369,27 @@ class TestUserIpHistoryManager:
def test_out_of_order(
self,
- ip_record_factory,
- user,
- user_iphistory_manager,
- ip_information_factory,
- ip_geoname,
+ ip_record_factory: Callable[..., IPRecord],
+ user: User,
+ user_iphistory_manager: UserIpHistoryManager,
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
):
# Create the user-ip association BEFORE the ip even exists in the ipinfo table
ip = fake.ipv4_public()
ip_record_factory(user_id=user.user_id, ip=ip)
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
+ assert isinstance(iph, UserIPHistory)
+ assert isinstance(iph.ips, list)
assert len(iph.ips) == 1
ipr = iph.ips[0]
assert ipr.information is None
assert not ipr.is_anonymous
- ip_information_factory(ip=ip, geoname=ip_geoname, is_anonymous=True)
+ ip_information_factory(ip=ip, geoname_id=ip_geoname.geoname_id, is_anonymous=True)
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
+ assert isinstance(iph, UserIPHistory)
+ assert isinstance(iph.ips, list)
assert len(iph.ips) == 1
ipr = iph.ips[0]
assert ipr.information is not None
@@ -344,23 +397,27 @@ class TestUserIpHistoryManager:
def test_out_of_order_ipv6(
self,
- ip_record_factory,
- user,
- user_iphistory_manager,
- ip_information_factory,
- ip_geoname,
+ ip_record_factory: Callable[..., IPRecord],
+ user: User,
+ user_iphistory_manager: UserIpHistoryManager,
+ ip_information_factory: Callable[..., IPInformation],
+ ip_geoname: IPGeoname,
):
# Create the user-ip association BEFORE the ip even exists in the ipinfo table
ip = fake.ipv6()
ip_record_factory(user_id=user.user_id, ip=ip)
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
+ assert isinstance(iph, UserIPHistory)
+ assert isinstance(iph.ips, list)
assert len(iph.ips) == 1
ipr = iph.ips[0]
assert ipr.information is None
assert not ipr.is_anonymous
- ip_information_factory(ip=ip, geoname=ip_geoname, is_anonymous=True)
+ ip_information_factory(ip=ip, geoname_id=ip_geoname.geoname_id, is_anonymous=True)
iph = user_iphistory_manager.get_user_ip_history(user_id=user.user_id)
+ assert isinstance(iph, UserIPHistory)
+ assert isinstance(iph.ips, list)
assert len(iph.ips) == 1
ipr = iph.ips[0]
assert ipr.information is not None
diff --git a/tests/managers/thl/test_wall_manager.py b/tests/managers/thl/test_wall_manager.py
index ee44e23..777252f 100644
--- a/tests/managers/thl/test_wall_manager.py
+++ b/tests/managers/thl/test_wall_manager.py
@@ -1,25 +1,39 @@
-from datetime import datetime, timezone, timedelta
+from __future__ import annotations
+
+from collections.abc import Callable
+from datetime import UTC, datetime, timedelta
from decimal import Decimal
+from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
+from pydantic import PositiveInt
-from generalresearch.models import Source
-from generalresearch.models.thl.session import (
+from generalresearch.models.definitions import Source
+from generalresearch.models.thl.definitions import (
ReportValue,
Status,
StatusCode1,
)
-from test_utils.models.conftest import user, session
+
+if TYPE_CHECKING:
+ from generalresearch.managers.thl.session import SessionManager
+ from generalresearch.managers.thl.wall import WallCacheManager, WallManager
+ from generalresearch.models.thl.session import Session, Wall
+ from generalresearch.models.thl.user import User
class TestWallManager:
@pytest.mark.parametrize("wall_count", [1, 2, 5, 10, 50, 99])
def test_get_wall_events(
- self, wall_manager, session_factory, user, wall_count, utc_hour_ago
+ self,
+ wall_manager: WallManager,
+ session_factory: Callable[..., Session],
+ user: User,
+ wall_count: PositiveInt,
+ utc_hour_ago: datetime,
):
- from generalresearch.models.thl.session import Session
s1: Session = session_factory(
user=user, wall_count=wall_count, started=utc_hour_ago
@@ -63,12 +77,15 @@ class TestWallManager:
]
def test_get_wall_events_list_input(
- self, wall_manager, session_factory, user, utc_hour_ago
+ self,
+ wall_manager: WallManager,
+ session_factory: Callable[..., Session],
+ user: User,
+ utc_hour_ago: datetime,
):
- from generalresearch.models.thl.session import Session
session_ids = []
- for idx in range(10):
+ for _ in range(10):
s: Session = session_factory(user=user, wall_count=5, started=utc_hour_ago)
session_ids.append(s.id)
@@ -78,21 +95,21 @@ class TestWallManager:
assert isinstance(res, list)
assert len(res) == 50
- res1 = list(set([w.session_id for w in res]))
+ res1 = list({w.session_id for w in res})
res1.sort()
assert session_ids == res1
- def test_create_wall(self, wall_manager, session_manager, user, session):
+ def test_create_wall(self, wall_manager: WallManager, user: User, session: Session):
w = wall_manager.create(
session_id=session.id,
user_id=user.user_id,
uuid_id=uuid4().hex,
- started=datetime.now(tz=timezone.utc),
+ started=datetime.now(tz=UTC),
source=Source.DYNATA,
buyer_id="123",
req_survey_id="456",
- req_cpi=Decimal("1"),
+ req_cpi=Decimal(1),
)
assert w is not None
@@ -100,7 +117,11 @@ class TestWallManager:
assert w == w2
def test_report_wall_abandon(
- self, wall_manager, session_manager, user, session, utc_hour_ago
+ self,
+ wall_manager: WallManager,
+ user: User,
+ session: Session,
+ utc_hour_ago: datetime,
):
w1 = wall_manager.create(
session_id=session.id,
@@ -110,7 +131,7 @@ class TestWallManager:
source=Source.DYNATA,
buyer_id="123",
req_survey_id="456",
- req_cpi=Decimal("1"),
+ req_cpi=Decimal(1),
)
wall_manager.report(
wall=w1,
@@ -141,7 +162,12 @@ class TestWallManager:
# the status and finished get updated
def test_report_wall(
- self, wall_manager, session_manager, user, session, utc_hour_ago
+ self,
+ wall_manager: WallManager,
+ session_manager: SessionManager,
+ user: User,
+ session: Session,
+ utc_hour_ago: datetime,
):
w1 = wall_manager.create(
session_id=session.id,
@@ -151,7 +177,7 @@ class TestWallManager:
source=Source.DYNATA,
buyer_id="123",
req_survey_id="456",
- req_cpi=Decimal("1"),
+ req_cpi=Decimal(1),
)
finish_ts = utc_hour_ago + timedelta(minutes=10)
@@ -178,11 +204,15 @@ class TestWallManager:
assert "This survey blows!" == w2.report_notes
def test_filter_wall_attempts(
- self, wall_manager, session_manager, user, session, utc_hour_ago
+ self,
+ wall_manager: WallManager,
+ user: User,
+ session: Session,
+ utc_hour_ago: datetime,
):
res = wall_manager.filter_wall_attempts(user_id=user.user_id)
assert len(res) == 0
- w1 = wall_manager.create(
+ wall_manager.create(
session_id=session.id,
user_id=user.user_id,
uuid_id=uuid4().hex,
@@ -190,11 +220,11 @@ class TestWallManager:
source=Source.DYNATA,
buyer_id="123",
req_survey_id="456",
- req_cpi=Decimal("1"),
+ req_cpi=Decimal(1),
)
res = wall_manager.filter_wall_attempts(user_id=user.user_id)
assert len(res) == 1
- w2 = wall_manager.create(
+ wall_manager.create(
session_id=session.id,
user_id=user.user_id,
uuid_id=uuid4().hex,
@@ -202,7 +232,7 @@ class TestWallManager:
source=Source.DYNATA,
buyer_id="123",
req_survey_id="555",
- req_cpi=Decimal("1"),
+ req_cpi=Decimal(1),
)
res = wall_manager.filter_wall_attempts(user_id=user.user_id)
assert len(res) == 2
@@ -210,21 +240,25 @@ class TestWallManager:
class TestWallCacheManager:
- def test_get_attempts_none(self, wall_cache_manager, user):
+ def test_get_attempts_none(self, wall_cache_manager: WallCacheManager, user: User):
attempts = wall_cache_manager.get_attempts(user.user_id)
assert len(attempts) == 0
def test_get_wall_events(
- self, wall_cache_manager, wall_manager, session_manager, user
+ self,
+ wall_cache_manager: WallCacheManager,
+ user: User,
+ bare_session_factory: Callable[..., Session],
+ wall_factory: Callable[..., Wall],
):
- start1 = datetime.now(timezone.utc) - timedelta(hours=3)
- start2 = datetime.now(timezone.utc) - timedelta(hours=2)
- start3 = datetime.now(timezone.utc) - timedelta(hours=1)
+ start1 = datetime.now(UTC) - timedelta(hours=3)
+ start2 = datetime.now(UTC) - timedelta(hours=2)
+ start3 = datetime.now(UTC) - timedelta(hours=1)
- session = session_manager.create_dummy(started=start1, user=user)
- wall1 = wall_manager.create_dummy(
+ session = bare_session_factory(started=start1, user=user)
+ wall_factory(
session_id=session.id,
- user_id=session.user_id,
+ user=session.user,
started=start1,
req_cpi=Decimal("1.23"),
req_survey_id="11111",
@@ -238,9 +272,9 @@ class TestWallCacheManager:
attempts = wall_cache_manager.get_attempts(user_id=user.user_id)
assert len(attempts) == 1
- wall2 = wall_manager.create_dummy(
+ wall_factory(
session_id=session.id,
- user_id=session.user_id,
+ user=session.user,
started=start2,
req_cpi=Decimal("1.23"),
req_survey_id="22222",
@@ -264,10 +298,10 @@ class TestWallCacheManager:
attempts10000 = [attempts[0]] * 6000
wall_cache_manager.update_attempts_redis_(attempts10000, user_id=user.user_id)
- session = session_manager.create_dummy(started=start3, user=user)
- wall3 = wall_manager.create_dummy(
+ session = bare_session_factory(started=start3, user=user)
+ wall_factory(
session_id=session.id,
- user_id=session.user_id,
+ user=session.user,
started=start3,
req_cpi=Decimal("1.23"),
req_survey_id="33333",
@@ -279,5 +313,5 @@ class TestWallCacheManager:
redis_key = wall_cache_manager.get_cache_key_(user_id=user.user_id)
assert wall_cache_manager.redis_client.llen(redis_key) == 5000
- assert len(attempts) == 5000
+ assert len(attempts) == 5_000
assert attempts[0].req_survey_id == "33333"