import os from datetime import datetime, timedelta, timezone from decimal import Decimal from typing import Optional from uuid import uuid4 import pandas as pd import pytest # noinspection PyUnresolvedReferences from distributed.utils_test import ( gen_cluster, client_no_amm, loop, loop_in_thread, cleanup, cluster_fixture, client, ) from pytest import approx from generalresearch.currency import USDCent from generalresearch.models.thl.finance import ( ProductBalances, BusinessBalances, ) # from test_utils.incite.conftest import mnt_filepath from test_utils.managers.conftest import ( business_bank_account_manager, lm, thl_lm, ) class TestBusinessBankAccount: def test_init(self, business, business_bank_account_manager): from generalresearch.models.gr.business import ( BusinessBankAccount, TransferMethod, ) instance = business_bank_account_manager.create( business_id=business.id, uuid=uuid4().hex, transfer_method=TransferMethod.ACH, ) assert isinstance(instance, BusinessBankAccount) def test_business(self, business_bank_account, business, gr_db, gr_redis_config): from generalresearch.models.gr.business import Business assert business_bank_account.business is None business_bank_account.prefetch_business( pg_config=gr_db, redis_config=gr_redis_config ) assert isinstance(business_bank_account.business, Business) assert business_bank_account.business.uuid == business.uuid class TestBusinessAddress: def test_init(self, business_address): from generalresearch.models.gr.business import BusinessAddress assert isinstance(business_address, BusinessAddress) class TestBusinessContact: def test_init(self): from generalresearch.models.gr.business import BusinessContact bc = BusinessContact(name="abc", email="test@abc.com") assert isinstance(bc, BusinessContact) class TestBusiness: @pytest.fixture def start(self) -> "datetime": return datetime(year=2018, month=3, day=14, hour=0, tzinfo=timezone.utc) @pytest.fixture def offset(self) -> str: return "30d" @pytest.fixture def duration(self) -> Optional["timedelta"]: return None def test_init(self, business): from generalresearch.models.gr.business import Business assert isinstance(business, Business) assert isinstance(business.id, int) assert isinstance(business.uuid, str) def test_str_and_repr( self, business, product_factory, thl_web_rr, lm, thl_lm, business_payout_event_manager, bp_payout_factory, start, user_factory, session_with_tx_factory, pop_ledger_merge, client_no_amm, ledger_collection, mnt_filepath, create_main_accounts, ): create_main_accounts() p1 = product_factory(business=business) u1 = user_factory(product=p1) p2 = product_factory(business=business) thl_lm.get_account_or_create_bp_wallet(product=p1) thl_lm.get_account_or_create_bp_wallet(product=p2) res1 = repr(business) assert business.uuid in res1 assert " "datetime": return datetime(year=2018, month=3, day=14, hour=0, tzinfo=timezone.utc) @pytest.fixture def offset(self) -> str: return "30d" @pytest.fixture def duration(self) -> Optional["timedelta"]: return None @pytest.mark.skip def test_product_ordering(self): # Assert that the order of business.balance.product_balances is always # consistent and in the same order based off product.created ASC pass def test_single_product( self, business, product_factory, user_factory, mnt_filepath, bp_payout_factory, thl_lm, lm, duration, offset, start, thl_web_rr, payout_event_manager, session_with_tx_factory, delete_ledger_db, create_main_accounts, client_no_amm, ledger_collection, pop_ledger_merge, delete_df_collection, ): 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) u2: User = user_factory(product=p1) session_with_tx_factory( user=u1, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1), ) session_with_tx_factory( user=u2, wall_req_cpi=Decimal("1.25"), started=start + timedelta(days=2), ) 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, ) assert isinstance(business.balance, BusinessBalances) assert business.balance.payout == 190 assert business.balance.adjustment == 0 assert business.balance.net == 190 assert business.balance.retainer == 47 assert business.balance.available_balance == 143 assert len(business.balance.product_balances) == 1 pb = business.balance.product_balances[0] assert isinstance(pb, ProductBalances) assert pb.balance == business.balance.balance assert pb.available_balance == business.balance.available_balance assert pb.adjustment_percent == 0.0 def test_multi_product( self, business, product_factory, user_factory, mnt_filepath, bp_payout_factory, thl_lm, lm, duration, offset, start, thl_web_rr, payout_event_manager, session_with_tx_factory, delete_ledger_db, create_main_accounts, client_no_amm, ledger_collection, pop_ledger_merge, delete_df_collection, ): delete_ledger_db() create_main_accounts() delete_df_collection(coll=ledger_collection) from generalresearch.models.thl.user import User u1: User = user_factory(product=product_factory(business=business)) u2: User = user_factory(product=product_factory(business=business)) session_with_tx_factory( user=u1, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1), ) session_with_tx_factory( user=u2, wall_req_cpi=Decimal("1.25"), started=start + timedelta(days=2), ) 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, ) assert isinstance(business.balance, BusinessBalances) assert business.balance.payout == 190 assert business.balance.balance == 190 assert business.balance.adjustment == 0 assert business.balance.net == 190 assert business.balance.retainer == 46 assert business.balance.available_balance == 144 assert len(business.balance.product_balances) == 2 pb1 = business.balance.product_balances[0] pb2 = business.balance.product_balances[1] assert isinstance(pb1, ProductBalances) assert pb1.product_id == u1.product_id assert isinstance(pb2, ProductBalances) assert pb2.product_id == u2.product_id for pb in [pb1, pb2]: assert pb.balance != business.balance.balance assert pb.available_balance != business.balance.available_balance assert pb.adjustment_percent == 0.0 assert pb1.product_id in [u1.product_id, u2.product_id] assert pb1.payout == 71 assert pb1.adjustment == 0 assert pb1.expense == 0 assert pb1.net == 71 assert pb1.retainer == 17 assert pb1.available_balance == 54 assert pb2.product_id in [u1.product_id, u2.product_id] assert pb2.payout == 119 assert pb2.adjustment == 0 assert pb2.expense == 0 assert pb2.net == 119 assert pb2.retainer == 29 assert pb2.available_balance == 90 def test_multi_product_multi_payout( self, business, product_factory, user_factory, mnt_filepath, bp_payout_factory, thl_lm, lm, duration, offset, start, thl_web_rr, payout_event_manager, session_with_tx_factory, delete_ledger_db, create_main_accounts, client_no_amm, ledger_collection, pop_ledger_merge, delete_df_collection, ): delete_ledger_db() create_main_accounts() delete_df_collection(coll=ledger_collection) from generalresearch.models.thl.user import User u1: User = user_factory(product=product_factory(business=business)) u2: User = user_factory(product=product_factory(business=business)) session_with_tx_factory( user=u1, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1), ) session_with_tx_factory( user=u2, wall_req_cpi=Decimal("1.25"), started=start + timedelta(days=2), ) payout_event_manager.set_account_lookup_table(thl_lm=thl_lm) bp_payout_factory( product=u1.product, amount=USDCent(5), created=start + timedelta(days=4), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) bp_payout_factory( product=u2.product, amount=USDCent(50), created=start + timedelta(days=4), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) 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, ) assert business.balance.payout == 190 assert business.balance.net == 190 assert business.balance.balance == 135 def test_multi_product_multi_payout_adjustment( self, business, product_factory, user_factory, mnt_filepath, bp_payout_factory, thl_lm, lm, duration, offset, start, thl_web_rr, payout_event_manager, session_with_tx_factory, delete_ledger_db, create_main_accounts, client_no_amm, ledger_collection, task_adj_collection, pop_ledger_merge, wall_manager, session_manager, adj_to_fail_with_tx_factory, delete_df_collection, ): """ - Product 1 $2.50 Complete - Product 2 $2.50 Complete - $2.50 Payout on Product 1 - $0.50 Payout on Product 2 - Product 3 $2.50 Complete - Complete -> Failure $2.50 Adjustment on Product 1 ==== - Net: $7.50 * .95 = $7.125 - $2.50 = $2.375 = $2.38 - $2.50 = $2.375 = $2.38 - $2.50 = $2.375 = $2.38 ==== - $7.14 - Balance: $2 """ delete_ledger_db() create_main_accounts() delete_df_collection(coll=ledger_collection) delete_df_collection(coll=task_adj_collection) from generalresearch.models.thl.user import User u1: User = user_factory(product=product_factory(business=business)) u2: User = user_factory(product=product_factory(business=business)) u3: User = user_factory(product=product_factory(business=business)) s1 = session_with_tx_factory( user=u1, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=1), ) session_with_tx_factory( user=u2, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=2), ) payout_event_manager.set_account_lookup_table(thl_lm=thl_lm) bp_payout_factory( product=u1.product, amount=USDCent(250), created=start + timedelta(days=3), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) bp_payout_factory( product=u2.product, amount=USDCent(50), created=start + timedelta(days=4), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) adj_to_fail_with_tx_factory(session=s1, created=start + timedelta(days=5)) session_with_tx_factory( user=u3, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=6), ) # Build and prepare the Business with the db transactions now in place # This isn't needed for Business Balance... but good to also check # task_adj_collection.initial_load(client=None, sync=True) # These are the only two that are needed for Business Balance ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) df = client_no_amm.compute(ledger_collection.ddf(), sync=True) assert df.shape == (24, 24) df = client_no_amm.compute(pop_ledger_merge.ddf(), sync=True) assert df.shape == (20, 28) business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, ) assert business.balance.payout == 714 assert business.balance.adjustment == -238 assert business.balance.product_balances[0].adjustment == -238 assert business.balance.product_balances[1].adjustment == 0 assert business.balance.product_balances[2].adjustment == 0 assert business.balance.expense == 0 assert business.balance.net == 714 - 238 assert business.balance.balance == business.balance.payout - (250 + 50 + 238) predicted_retainer = sum( [ pb.balance * 0.25 for pb in business.balance.product_balances if pb.balance > 0 ] ) assert business.balance.retainer == approx(predicted_retainer, rel=0.01) def test_neg_balance_cache( self, product, mnt_filepath, thl_lm, client_no_amm, thl_redis_config, brokerage_product_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, payout_event_manager, adj_to_fail_with_tx_factory, thl_web_rr, lm, ): """Test having a Business with two products.. one that lost money and one that gained money. Ensure that the Business balance reflects that to compensate for the Product in the negative. """ # Now let's load it up and actually test some things 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) p2: Product = product_factory(business=business) u1: User = user_factory(product=p1) u2: User = user_factory(product=p2) thl_lm.get_account_or_create_bp_wallet(product=p1) thl_lm.get_account_or_create_bp_wallet(product=p2) # Product 1: Complete, Payout, Recon.. s1 = session_with_tx_factory( user=u1, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1), ) payout_event_manager.set_account_lookup_table(thl_lm=thl_lm) bp_payout_factory( product=u1.product, amount=USDCent(71), ext_ref_id=uuid4().hex, 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, created=start + timedelta(days=1, minutes=2), ) # Product 2: Complete, Complete. s2 = session_with_tx_factory( user=u2, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1, minutes=3), ) s3 = session_with_tx_factory( user=u2, wall_req_cpi=Decimal(".75"), started=start + timedelta(days=1, minutes=4), ) # Finally, process everything: 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, ) # Check Product 1 pb1 = business.balance.product_balances[0] assert pb1.product_id == p1.uuid assert pb1.payout == 71 assert pb1.adjustment == -71 assert pb1.net == 0 assert pb1.balance == 71 - (71 * 2) assert pb1.retainer == 0 assert pb1.available_balance == 0 # Check Product 2 pb2 = business.balance.product_balances[1] assert pb2.product_id == p2.uuid assert pb2.payout == 71 * 2 assert pb2.adjustment == 0 assert pb2.net == 71 * 2 assert pb2.balance == (71 * 2) assert pb2.retainer == pytest.approx((71 * 2) * 0.25, rel=1) assert pb2.available_balance == 107 # Check Business bb1 = business.balance assert bb1.payout == (71 * 3) # Raw total of completes assert bb1.adjustment == -71 # 1 Complete >> Failure assert bb1.expense == 0 assert bb1.net == (71 * 3) - 71 # How much the Business actually earned assert ( bb1.balance == (71 * 3) - 71 - 71 ) # 3 completes, but 1 payout and 1 recon leaves only one complete # worth of activity on the account assert bb1.retainer == pytest.approx((71 * 2) * 0.25, rel=1) assert bb1.available_balance_usd_str == "$0.36" # Confirm that the debt from the pb1 in the red is covered when # calculating the Business balance by the profit of pb2 assert pb2.available_balance + pb1.balance == bb1.available_balance def test_multi_product_multi_payout_adjustment_at_timestamp( self, business, product_factory, user_factory, mnt_filepath, bp_payout_factory, thl_lm, lm, duration, offset, start, thl_web_rr, payout_event_manager, session_with_tx_factory, delete_ledger_db, create_main_accounts, client_no_amm, ledger_collection, task_adj_collection, pop_ledger_merge, wall_manager, session_manager, adj_to_fail_with_tx_factory, delete_df_collection, ): """ This test measures a complex Business situation, but then makes various assertions based off the query which uses an at_timestamp. The goal here is a feature that allows us to look back and see what the balance was of an account at any specific point in time. - Day 1: Product 1 $2.50 Complete - Total Payout: $2.38 - Smart Retainer: $0.59 - Available Balance: $1.79 - Day 2: Product 2 $2.50 Complete - Total Payout: $4.76 - Smart Retainer: $1.18 - Available Balance: $3.58 - Day 3: $2.50 Payout on Product 1 - Total Payout: $4.76 - Smart Retainer: $0.59 - Available Balance: $1.67 - Day 4: $0.50 Payout on Product 2 - Total Payout: $4.76 - Smart Retainer: $0.47 - Available Balance: $1.29 - Day 5: Product 3 $2.50 Complete - Total Payout: $7.14 - Smart Retainer: $1.06 - Available Balance: $3.08 - Day 6: Complete -> Failure $2.50 Adjustment on Product 1 - Total Payout: $7.18 - Smart Retainer: $1.06 - Available Balance: $0.70 """ delete_ledger_db() create_main_accounts() delete_df_collection(coll=ledger_collection) delete_df_collection(coll=task_adj_collection) from generalresearch.models.thl.user import User u1: User = user_factory(product=product_factory(business=business)) u2: User = user_factory(product=product_factory(business=business)) u3: User = user_factory(product=product_factory(business=business)) s1 = session_with_tx_factory( user=u1, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=1), ) session_with_tx_factory( user=u2, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=2), ) payout_event_manager.set_account_lookup_table(thl_lm=thl_lm) bp_payout_factory( product=u1.product, amount=USDCent(250), created=start + timedelta(days=3), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) bp_payout_factory( product=u2.product, amount=USDCent(50), created=start + timedelta(days=4), skip_wallet_balance_check=True, skip_one_per_day_check=True, ) session_with_tx_factory( user=u3, wall_req_cpi=Decimal("2.50"), started=start + timedelta(days=5), ) adj_to_fail_with_tx_factory(session=s1, created=start + timedelta(days=6)) # Build and prepare the Business with the db transactions now in place # This isn't needed for Business Balance... but good to also check # task_adj_collection.initial_load(client=None, sync=True) # These are the only two that are needed for Business Balance ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) df = client_no_amm.compute(ledger_collection.ddf(), sync=True) assert df.shape == (24, 24) df = client_no_amm.compute(pop_ledger_merge.ddf(), sync=True) assert df.shape == (20, 28) business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, ) business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=1, hours=1), ) day1_bal = business.balance business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=2, hours=1), ) day2_bal = business.balance business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=3, hours=1), ) day3_bal = business.balance business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=4, hours=1), ) day4_bal = business.balance business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=5, hours=1), ) day5_bal = business.balance business.prebuild_balance( thl_pg_config=thl_web_rr, lm=lm, ds=mnt_filepath, client=client_no_amm, pop_ledger=pop_ledger_merge, at_timestamp=start + timedelta(days=6, hours=1), ) day6_bal = business.balance assert day1_bal.payout == 238 assert day1_bal.retainer == 59 assert day1_bal.available_balance == 179 assert day2_bal.payout == 476 assert day2_bal.retainer == 118 assert day2_bal.available_balance == 358 assert day3_bal.payout == 476 assert day3_bal.retainer == 59 assert day3_bal.available_balance == 167 assert day4_bal.payout == 476 assert day4_bal.retainer == 47 assert day4_bal.available_balance == 129 assert day5_bal.payout == 714 assert day5_bal.retainer == 106 assert day5_bal.available_balance == 308 assert day6_bal.payout == 714 assert day6_bal.retainer == 106 assert day6_bal.available_balance == 70 class TestBusinessMethods: @pytest.fixture(scope="function") def start(self, utc_90days_ago) -> "datetime": s = utc_90days_ago.replace(microsecond=0) return s @pytest.fixture(scope="function") def offset(self) -> str: return "15d" @pytest.fixture(scope="function") def duration( self, ) -> Optional["timedelta"]: return None def test_cache_key(self, business, gr_redis): assert isinstance(business.cache_key, str) assert ":" in business.cache_key assert str(business.uuid) in business.cache_key def test_set_cache( self, business, gr_redis, gr_db, thl_web_rr, client_no_amm, mnt_filepath, lm, thl_lm, business_payout_event_manager, product_factory, membership_factory, team, session_with_tx_factory, user_factory, ledger_collection, pop_ledger_merge, utc_60days_ago, delete_ledger_db, create_main_accounts, gr_redis_config, mnt_gr_api_dir, ): assert gr_redis.get(name=business.cache_key) is None p1 = product_factory(team=team, business=business) u1 = user_factory(product=p1) # Business needs tx & incite to build balance delete_ledger_db() create_main_accounts() thl_lm.get_account_or_create_bp_wallet(product=p1) session_with_tx_factory(user=u1, started=utc_60days_ago) ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) business.set_cache( pg_config=gr_db, thl_web_rr=thl_web_rr, redis_config=gr_redis_config, client=client_no_amm, ds=mnt_filepath, lm=lm, thl_lm=thl_lm, bpem=business_payout_event_manager, pop_ledger=pop_ledger_merge, mnt_gr_api=mnt_gr_api_dir, ) assert gr_redis.hgetall(name=business.cache_key) is not None from generalresearch.models.gr.business import Business # We're going to pull only a specific year, but make sure that # it's being assigned to the field regardless year = datetime.now(tz=timezone.utc).year res = Business.from_redis( uuid=business.uuid, fields=[f"pop_financial:{year}"], gr_redis_config=gr_redis_config, ) assert len(res.pop_financial) > 0 def test_set_cache_business( self, gr_user, business, gr_user_token, gr_redis, gr_db, thl_web_rr, product_factory, team, membership_factory, client_no_amm, mnt_filepath, lm, thl_lm, business_payout_event_manager, user_factory, delete_ledger_db, create_main_accounts, session_with_tx_factory, ledger_collection, team_manager, pop_ledger_merge, gr_redis_config, utc_60days_ago, mnt_gr_api_dir, ): from generalresearch.models.gr.business import Business p1 = product_factory(team=team, business=business) u1 = user_factory(product=p1) team_manager.add_business(team=team, business=business) # Business needs tx & incite to build balance delete_ledger_db() create_main_accounts() thl_lm.get_account_or_create_bp_wallet(product=p1) session_with_tx_factory(user=u1, started=utc_60days_ago) ledger_collection.initial_load(client=None, sync=True) pop_ledger_merge.build(client=client_no_amm, ledger_coll=ledger_collection) business.set_cache( pg_config=gr_db, thl_web_rr=thl_web_rr, redis_config=gr_redis_config, client=client_no_amm, ds=mnt_filepath, lm=lm, thl_lm=thl_lm, bpem=business_payout_event_manager, pop_ledger=pop_ledger_merge, mnt_gr_api=mnt_gr_api_dir, ) # keys: List = Business.required_fields() + ["products", "bp_accounts"] business2 = Business.from_redis( uuid=business.uuid, fields=[ "id", "tax_number", "contact", "addresses", "teams", "products", "bank_accounts", "balance", "payouts_total_str", "payouts_total", "payouts", "pop_financial", "bp_accounts", ], gr_redis_config=gr_redis_config, ) assert business.model_dump_json() == business2.model_dump_json() assert p1.uuid in [p.uuid for p in business2.products] assert len(business2.teams) == 1 assert team.uuid in [t.uuid for t in business2.teams] assert business2.balance.payout == 48 assert business2.balance.balance == 48 assert business2.balance.net == 48 assert business2.balance.retainer == 12 assert business2.balance.available_balance == 36 assert len(business2.balance.product_balances) == 1 assert len(business2.payouts) == 0 assert len(business2.bp_accounts) == 1 assert len(business2.bp_accounts) == len(business2.product_uuids) assert len(business2.pop_financial) == 1 assert business2.pop_financial[0].payout == business2.balance.payout assert business2.pop_financial[0].net == business2.balance.net def test_prebuild_enriched_session_parquet( self, event_report_request, enriched_session_merge, client_no_amm, wall_collection, session_collection, thl_web_rr, session_report_request, user_factory, start, session_factory, product_factory, delete_df_collection, business, mnt_filepath, mnt_gr_api_dir, ): delete_df_collection(coll=wall_collection) delete_df_collection(coll=session_collection) p1 = product_factory(business=business) p2 = product_factory(business=business) for p in [p1, p2]: u = user_factory(product=p) for i in range(50): s = session_factory( user=u, wall_count=1, wall_req_cpi=Decimal("1.00"), started=start + timedelta(minutes=i, seconds=1), ) wall_collection.initial_load(client=None, sync=True) session_collection.initial_load(client=None, sync=True) enriched_session_merge.build( client=client_no_amm, session_coll=session_collection, wall_coll=wall_collection, pg_config=thl_web_rr, ) business.prebuild_enriched_session_parquet( thl_pg_config=thl_web_rr, ds=mnt_filepath, client=client_no_amm, mnt_gr_api=mnt_gr_api_dir, enriched_session=enriched_session_merge, ) # Now try to read from path df = pd.read_parquet( os.path.join(mnt_gr_api_dir, "pop_session", f"{business.file_key}.parquet") ) assert isinstance(df, pd.DataFrame) def test_prebuild_enriched_wall_parquet( self, event_report_request, enriched_session_merge, enriched_wall_merge, client_no_amm, wall_collection, session_collection, thl_web_rr, session_report_request, user_factory, start, session_factory, product_factory, delete_df_collection, business, mnt_filepath, mnt_gr_api_dir, ): delete_df_collection(coll=wall_collection) delete_df_collection(coll=session_collection) p1 = product_factory(business=business) p2 = product_factory(business=business) for p in [p1, p2]: u = user_factory(product=p) for i in range(50): s = session_factory( user=u, wall_count=1, wall_req_cpi=Decimal("1.00"), started=start + timedelta(minutes=i, seconds=1), ) wall_collection.initial_load(client=None, sync=True) session_collection.initial_load(client=None, sync=True) enriched_wall_merge.build( client=client_no_amm, session_coll=session_collection, wall_coll=wall_collection, pg_config=thl_web_rr, ) business.prebuild_enriched_wall_parquet( thl_pg_config=thl_web_rr, ds=mnt_filepath, client=client_no_amm, mnt_gr_api=mnt_gr_api_dir, enriched_wall=enriched_wall_merge, ) # Now try to read from path df = pd.read_parquet( os.path.join(mnt_gr_api_dir, "pop_event", f"{business.file_key}.parquet") ) assert isinstance(df, pd.DataFrame)