aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Nanis2026-09-01 16:58:01 -0700
committerMax Nanis2026-09-01 16:58:01 -0700
commit4e9e08718884b1c4394d16055ba3f30c790ef8d0 (patch)
treea8c0c40ac5ac92d90c7cdfdda31c34ddf1e62d79
parentfdfd6dbd2b71b0cf11741915620dca181fdc7bb0 (diff)
downloadgeneralresearch-4e9e08718884b1c4394d16055ba3f30c790ef8d0.tar.gz
generalresearch-4e9e08718884b1c4394d16055ba3f30c790ef8d0.zip
Latest state for Django Migrations / Discussion
-rw-r--r--generalresearch/grliq/managers/forensic_results.py6
-rw-r--r--generalresearch/models/gr/business.py4
-rw-r--r--generalresearch/thl_django/migrations/0010_supplierpayout_payout_supplier_payout.py51
-rw-r--r--test_utils/conftest.py51
-rw-r--r--test_utils/managers/gr/conftest.py2
-rw-r--r--test_utils/managers/thl/conftest.py34
-rw-r--r--test_utils/models/gr/conftest.py55
-rw-r--r--tests/managers/gr/test_business.py10
-rw-r--r--tests/models/gr/test_business.py23
-rw-r--r--tests/test_postgres.py13
10 files changed, 171 insertions, 78 deletions
diff --git a/generalresearch/grliq/managers/forensic_results.py b/generalresearch/grliq/managers/forensic_results.py
index 587b768..158e582 100644
--- a/generalresearch/grliq/managers/forensic_results.py
+++ b/generalresearch/grliq/managers/forensic_results.py
@@ -1,17 +1,15 @@
from collections.abc import Collection
from datetime import datetime
-from typing import TYPE_CHECKING, Any
+from typing import Any
from generalresearch.grliq.models.forensic_result import (
GrlIqForensicCategoryResult,
Phase,
)
from generalresearch.grliq.models.useragents import GrlUserAgent
+from generalresearch.models.thl.user import User
from generalresearch.pg_helper import PostgresConfig
-if TYPE_CHECKING:
- from generalresearch.models.thl.user import User
-
class GrlIqCategoryResultsReader:
def __init__(self, postgres_config: PostgresConfig):
diff --git a/generalresearch/models/gr/business.py b/generalresearch/models/gr/business.py
index b01c902..73a2f27 100644
--- a/generalresearch/models/gr/business.py
+++ b/generalresearch/models/gr/business.py
@@ -449,7 +449,7 @@ class Business(BaseModel):
def prebuild_pop_financial(
self,
- thl_pg_config: PostgresConfig,
+ product_manager: ProductManager,
thl_lm: ThlLedgerManager,
ds: GRLDatasets,
client: DaskClient,
@@ -461,7 +461,7 @@ class Business(BaseModel):
financial activity within that time window.
"""
if self.bp_accounts is None:
- self.prefetch_bp_accounts(thl_lm=thl_lm, thl_pg_config=thl_pg_config)
+ self.prefetch_bp_accounts(thl_lm=thl_lm, product_manager=product_manager)
from generalresearch.models.admin.request import (
ReportRequest,
diff --git a/generalresearch/thl_django/migrations/0010_supplierpayout_payout_supplier_payout.py b/generalresearch/thl_django/migrations/0010_supplierpayout_payout_supplier_payout.py
new file mode 100644
index 0000000..5c3319c
--- /dev/null
+++ b/generalresearch/thl_django/migrations/0010_supplierpayout_payout_supplier_payout.py
@@ -0,0 +1,51 @@
+# Generated by Django 6.1 on 2026-09-01 23:15
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ (
+ "thl_django",
+ "0009_toolrun_mtrhop_portscanport_iplabel_mtr_portscan_and_more",
+ ),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="SupplierPayout",
+ fields=[
+ ("id", models.BigAutoField(primary_key=True, serialize=False)),
+ ("ext_ref_id", models.CharField(max_length=64, unique=True)),
+ ("business_id", models.UUIDField(null=True)),
+ ("created", models.DateTimeField(auto_now_add=True)),
+ ("amount", models.BigIntegerField()),
+ ("status", models.CharField(max_length=20, null=True)),
+ ("payout_type", models.CharField(max_length=14)),
+ ("request_data", models.JSONField(null=True)),
+ ("order_data", models.JSONField(null=True)),
+ ],
+ options={
+ "db_table": "supplier_payout",
+ "indexes": [
+ models.Index(
+ fields=["created"], name="supplier_pa_created_336236_idx"
+ ),
+ models.Index(
+ fields=["business_id"], name="supplier_pa_busines_2c7a4e_idx"
+ ),
+ ],
+ },
+ ),
+ migrations.AddField(
+ model_name="payout",
+ name="supplier_payout",
+ field=models.ForeignKey(
+ null=True,
+ on_delete=django.db.models.deletion.DO_NOTHING,
+ to="thl_django.supplierpayout",
+ ),
+ ),
+ ]
diff --git a/test_utils/conftest.py b/test_utils/conftest.py
index daf6b43..44e36a6 100644
--- a/test_utils/conftest.py
+++ b/test_utils/conftest.py
@@ -225,8 +225,10 @@ def django_db_factory(
_ran = {}
import django
+ from django.apps import apps
from django.conf import settings as django_settings
from django.core.management import call_command
+ from django.utils.functional import empty
def _inner(
django_project: str = "generalresearch.thl_django",
@@ -242,34 +244,43 @@ def django_db_factory(
# We need model files that are NOT in this repo.
gr_path = gr_repo()
sys.path.insert(0, str(gr_path))
+ print("DJANGO_PROJECT_PATH", str(gr_path), sys.path)
# 1. Bootstrapping Django settings
- if not django_settings.configured:
- django_settings.configure(
- DATABASES={
- "default": {
- "ENGINE": "django.db.backends.postgresql",
- "NAME": postgres_instance_dict["name"],
- "USER": postgres_instance_dict["username"],
- "PASSWORD": postgres_instance_dict["password"],
- "HOST": postgres_instance_dict["host"],
- "PORT": postgres_instance_dict["port"],
- }
- },
- INSTALLED_APPS=[
- "django.contrib.postgres",
- "django.contrib.contenttypes",
- django_project,
- ],
- )
+ # if not django_settings.configured:
+ # 1. Reset the lazy wrapper back to an empty state
+ # if not django_settings.configured:
+
+ django_settings._wrapped = empty
+
+ django_settings.configure(
+ DATABASES={
+ "default": {
+ "ENGINE": "django.db.backends.postgresql",
+ "NAME": postgres_instance_dict["name"],
+ "USER": postgres_instance_dict["username"],
+ "PASSWORD": postgres_instance_dict["password"],
+ "HOST": postgres_instance_dict["host"],
+ "PORT": postgres_instance_dict["port"],
+ }
+ },
+ INSTALLED_APPS=[
+ "django.contrib.postgres",
+ "django.contrib.contenttypes",
+ django_project,
+ ],
+ )
django.setup()
- # for model in apps.get_models():
- # print(f"Discovered model: {model._meta.label}")
+ for model in apps.get_models():
+ print(f"Discovered model: {model._meta.label}")
# 2. Run migrations directly during fixture activation
+ print("DJANGO_PROJECT", django_project)
if "gr" in django_project:
call_command("makemigrations", "common", interactive=False)
+ else:
+ call_command("makemigrations", interactive=False)
call_command("migrate")
diff --git a/test_utils/managers/gr/conftest.py b/test_utils/managers/gr/conftest.py
index a7fa9e9..b5db2a5 100644
--- a/test_utils/managers/gr/conftest.py
+++ b/test_utils/managers/gr/conftest.py
@@ -24,6 +24,8 @@ if TYPE_CHECKING:
# === Msc ===
+
+
@pytest.fixture(scope="session")
def gr_redis_config_db() -> str:
return str(randint(99, 1_023))
diff --git a/test_utils/managers/thl/conftest.py b/test_utils/managers/thl/conftest.py
index 391b74c..6e19bef 100644
--- a/test_utils/managers/thl/conftest.py
+++ b/test_utils/managers/thl/conftest.py
@@ -45,20 +45,7 @@ if TYPE_CHECKING:
WallManager,
)
-
-@pytest.fixture(scope="session")
-def thl_web_rr(django_db_factory: Callable[..., PostgresDsn]) -> PostgresConfig:
-
- return PostgresConfig(
- dsn=django_db_factory("generalresearch.thl_django"),
- connect_timeout=1,
- statement_timeout=5,
- )
-
-
-@pytest.fixture(scope="session")
-def thl_web_rw(thl_web_rr: PostgresConfig) -> PostgresConfig:
- return thl_web_rr
+# === Msc ===
@pytest.fixture(scope="session")
@@ -98,6 +85,25 @@ def thl_redis_config(
@pytest.fixture(scope="session")
+def thl_web_rr(django_db_factory: Callable[..., PostgresDsn]) -> PostgresConfig:
+ _dsn = django_db_factory("generalresearch.thl_django")
+
+ return PostgresConfig(
+ dsn=_dsn,
+ connect_timeout=1,
+ statement_timeout=5,
+ )
+
+
+@pytest.fixture(scope="session")
+def thl_web_rw(thl_web_rr: PostgresConfig) -> PostgresConfig:
+ return thl_web_rr
+
+
+# === Managers ===
+
+
+@pytest.fixture(scope="session")
def payout_event_manager(
thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig
) -> PayoutEventManager:
diff --git a/test_utils/models/gr/conftest.py b/test_utils/models/gr/conftest.py
index b87f3bb..a73dd70 100644
--- a/test_utils/models/gr/conftest.py
+++ b/test_utils/models/gr/conftest.py
@@ -66,36 +66,59 @@ def gr_user_cache(
return gr_user
+# --- Business Bank Account ---
+
+
@pytest.fixture
def gr_business_bank_account_factory(
- gr_bbam: BusinessBankAccountManager,
+ gr_business_bank_account_manager: BusinessBankAccountManager,
) -> Callable[..., BusinessBankAccount]:
def _inner(
business_id: PositiveInt,
+ save: bool = True,
uuid: UUIDStr | None = None,
transfer_method: TransferMethod | None = None,
account_number: str | None = None,
routing_number: str | None = None,
iban: str | None = None,
swift: str | None = None,
- ):
- from generalresearch.models.gr.business import TransferMethod
+ **kwargs,
+ ) -> BusinessBankAccount:
- return gr_bbam.create(
- business_id=business_id,
- uuid=uuid or uuid4().hex,
- transfer_method=transfer_method or TransferMethod.ACH,
- account_number=account_number or uuid4().hex[:6],
- routing_number=routing_number or uuid4().hex[:6],
- iban=iban or uuid4().hex[:6],
- swift=swift or uuid4().hex[:6],
- )
+ if save:
+ return gr_business_bank_account_manager.create(
+ business_id=business_id,
+ uuid=uuid or uuid4().hex,
+ transfer_method=transfer_method or TransferMethod.ACH,
+ account_number=account_number or uuid4().hex[:6],
+ routing_number=routing_number or uuid4().hex[:6],
+ iban=iban or uuid4().hex[:6],
+ swift=swift or uuid4().hex[:6],
+ **kwargs,
+ )
+ else:
+ raise ValueError("BusinessBankAccount Business not supported yet")
return _inner
@pytest.fixture
+def gr_business_bank_account(gr_business_factory: Callable[..., Business]) -> Business:
+ return gr_business_factory(save=True)
+
+
+@pytest.fixture
+def unsaved_gr_business_bank_account(
+ gr_business_factory: Callable[..., Business],
+) -> Business:
+ return gr_business_factory(save=False)
+
+
+# -----------------
+
+
+@pytest.fixture
def gr_business_address_factory(
gr_bam: BusinessAddressManager,
) -> Callable[..., BusinessAddress]:
@@ -204,14 +227,6 @@ def business_address(
return business_address_manager.create_dummy(business_id=gr_business.id)
-@pytest.fixture
-def business_bank_account(
- gr_business: Business,
- business_bank_account_manager: BusinessBankAccountManager,
-) -> BusinessBankAccount:
- return business_bank_account_manager.create_dummy(business_id=gr_business.id)
-
-
@pytest.fixture()
def gr_user_token_header(gr_user_token: GRToken) -> dict[str, str]:
return gr_user_token.auth_header
diff --git a/tests/managers/gr/test_business.py b/tests/managers/gr/test_business.py
index 35c471e..3513af5 100644
--- a/tests/managers/gr/test_business.py
+++ b/tests/managers/gr/test_business.py
@@ -25,18 +25,18 @@ class TestBusinessBankAccountManager:
def test_init(
self,
- business_bank_account_manager: BusinessBankAccountManager,
+ gr_business_bank_account_manager: BusinessBankAccountManager,
gr_db: PostgresConfig,
):
- assert business_bank_account_manager.pg_config == gr_db
+ assert gr_business_bank_account_manager.pg_config == gr_db
def test_create(
self,
gr_business: Business,
- business_bank_account_manager: BusinessBankAccountManager,
+ gr_business_bank_account_manager: BusinessBankAccountManager,
):
- instance = business_bank_account_manager.create(
+ instance = gr_business_bank_account_manager.create(
business_id=gr_business.id,
uuid=uuid4().hex,
transfer_method=TransferMethod.ACH,
@@ -44,7 +44,7 @@ class TestBusinessBankAccountManager:
assert isinstance(instance, BusinessBankAccount)
assert isinstance(instance.id, int)
- res = business_bank_account_manager.get_by_business_id(
+ res = gr_business_bank_account_manager.get_by_business_id(
business_id=instance.business_id
)
assert isinstance(res, list)
diff --git a/tests/models/gr/test_business.py b/tests/models/gr/test_business.py
index 90e69db..57f31f3 100644
--- a/tests/models/gr/test_business.py
+++ b/tests/models/gr/test_business.py
@@ -62,12 +62,12 @@ class TestBusinessBankAccount:
def test_init(
self,
gr_business: Business,
- business_bank_account_manager: BusinessBankAccountManager,
+ gr_business_bank_account_manager: BusinessBankAccountManager,
):
from generalresearch.models.gr.business import BusinessBankAccount
from generalresearch.models.gr.definitions import TransferMethod
- instance = business_bank_account_manager.create(
+ instance = gr_business_bank_account_manager.create(
business_id=gr_business.id,
uuid=uuid4().hex,
transfer_method=TransferMethod.ACH,
@@ -76,20 +76,20 @@ class TestBusinessBankAccount:
def test_business(
self,
- business_bank_account: BusinessBankAccount,
+ gr_business_bank_account: BusinessBankAccount,
gr_business: Business,
gr_db: PostgresConfig,
gr_redis_config: RedisConfig,
):
from generalresearch.models.gr.business import Business
- assert business_bank_account.business is None
+ assert gr_business_bank_account.business is None
- business_bank_account.prefetch_business(
+ gr_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 == gr_business.uuid
+ assert isinstance(gr_business_bank_account.business, Business)
+ assert gr_business_bank_account.business.uuid == gr_business.uuid
class TestBusinessAddress:
@@ -264,13 +264,13 @@ class TestBusiness:
def test_bank_accounts(
self,
gr_business: Business,
- business_bank_account_manager: BusinessBankAccountManager,
+ gr_business_bank_account_manager: BusinessBankAccountManager,
):
assert gr_business.products is None
# It's an empty list after prefetch
gr_business.prefetch_bank_accounts(
- business_bank_account_manager=business_bank_account_manager
+ business_bank_account_manager=gr_business_bank_account_manager
)
assert isinstance(gr_business.bank_accounts, list)
assert len(gr_business.bank_accounts) == 1
@@ -423,7 +423,7 @@ class TestBusiness:
def test_pop_financial(
self,
gr_business: Business,
- thl_web_rr: PostgresConfig,
+ product_manager: ProductManager,
thl_ledger_manager: ThlLedgerManager,
mnt_filepath: GRLDatasets,
client_no_amm: DaskClient,
@@ -431,7 +431,7 @@ class TestBusiness:
):
assert gr_business.pop_financial is None
gr_business.prebuild_pop_financial(
- thl_pg_config=thl_web_rr,
+ product_manager=product_manager,
thl_lm=thl_ledger_manager,
ds=mnt_filepath,
client=client_no_amm,
@@ -442,7 +442,6 @@ class TestBusiness:
def test_bp_accounts(
self,
gr_business: Business,
- thl_web_rr: PostgresConfig,
product_factory: Callable[..., Product],
thl_ledger_manager: ThlLedgerManager,
product_manager: ProductManager,
diff --git a/tests/test_postgres.py b/tests/test_postgres.py
index c53f644..9794321 100644
--- a/tests/test_postgres.py
+++ b/tests/test_postgres.py
@@ -68,4 +68,15 @@ class TestPostgresDjangoCreation:
WHERE table_schema = 'public';
""")
assert len(res) == 1
- assert res[0]["count"] == 56
+ assert res[0]["count"] == 57
+
+ def test_django_tables_with_gr(
+ self, thl_web_rw: PostgresConfig, gr_db: PostgresConfig
+ ):
+ res = thl_web_rw.execute_sql_query(query="""
+ SELECT COUNT(*)
+ FROM information_schema.tables
+ WHERE table_schema = 'public';
+ """)
+ assert len(res) == 1
+ assert res[0]["count"] > 57