Skip to content

Commit 00a2382

Browse files
committed
MPT-16326 Refactor accounts seeding accounts
1 parent 2556f5f commit 00a2382

21 files changed

+246
-651
lines changed

seed/accounts/accounts.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
import logging
2+
import os
23

4+
from mpt_api_client.resources.accounts.account import Account
35
from seed.accounts.api_tokens import seed_api_token
46
from seed.accounts.buyer import seed_buyer
57
from seed.accounts.licensee import seed_licensee
68
from seed.accounts.module import seed_module
79
from seed.accounts.seller import seed_seller
810
from seed.accounts.user_group import seed_user_group
11+
from seed.helper import init_resource
912

1013
logger = logging.getLogger(__name__)
1114

1215

13-
async def seed_accounts() -> None: # noqa: WPS217
16+
async def get_account() -> Account: # noqa: RUF029 async for compatibility purposes with init_resource
17+
"""Get account ID from environment variable."""
18+
account_id = os.getenv("CLIENT_ACCOUNT_ID")
19+
if not account_id:
20+
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
21+
return Account({"id": account_id})
22+
23+
24+
async def seed_accounts() -> None: # noqa: WPS213 WPS217
1425
"""Seed accounts data including account."""
1526
logger.debug("Seeding accounts ...")
27+
await init_resource("accounts.account.id", get_account)
28+
1629
await seed_seller()
1730
await seed_buyer()
1831
await seed_module()

seed/accounts/api_tokens.py

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,23 @@
11
import logging
2-
import os
32

43
from dependency_injector.wiring import Provide, inject
54

65
from mpt_api_client import AsyncMPTClient
76
from mpt_api_client.resources.accounts.api_tokens import ApiToken
87
from seed.container import Container
98
from seed.context import Context
9+
from seed.helper import init_resource, require_context_id
1010

1111
logger = logging.getLogger(__name__)
1212

1313

14-
@inject
15-
async def get_api_token(
16-
context: Context = Provide[Container.context],
17-
mpt_ops: AsyncMPTClient = Provide[Container.mpt_operations],
18-
) -> ApiToken | None:
19-
"""Get API token from context or fetch from API."""
20-
api_token_id = context.get_string("accounts.api_token.id")
21-
if not api_token_id:
22-
return None
23-
try:
24-
api_token = context.get_resource("accounts.api_token", api_token_id)
25-
except ValueError:
26-
api_token = None
27-
if not isinstance(api_token, ApiToken):
28-
api_token = await mpt_ops.accounts.api_tokens.get(api_token_id)
29-
context.set_resource("accounts.api_token", api_token)
30-
context["accounts.api_token.id"] = api_token.id
31-
return api_token
32-
return api_token
33-
34-
3514
@inject
3615
def build_api_token_data(
3716
context: Context = Provide[Container.context],
3817
) -> dict[str, object]:
3918
"""Get API token data dictionary for creation."""
40-
account_id = os.getenv("CLIENT_ACCOUNT_ID")
41-
module_id = context.get_string("accounts.module.id")
19+
account_id = require_context_id(context, "accounts.account.id", "creating API token")
20+
module_id = require_context_id(context, "accounts.module.id", "creating API token")
4221
return {
4322
"account": {"id": account_id},
4423
"name": "E2E Seeded API Token",
@@ -49,27 +28,16 @@ def build_api_token_data(
4928

5029

5130
@inject
52-
async def init_api_token(
53-
context: Context = Provide[Container.context],
31+
async def create_api_token(
5432
mpt_ops: AsyncMPTClient = Provide[Container.mpt_operations],
5533
) -> ApiToken:
56-
"""Get or create API token."""
57-
api_token = await get_api_token(context=context, mpt_ops=mpt_ops)
58-
if api_token is None:
59-
logger.debug("Creating API token ...")
60-
api_token_data = build_api_token_data(context=context)
61-
api_token = await mpt_ops.accounts.api_tokens.create(api_token_data)
62-
context.set_resource("accounts.api_token", api_token)
63-
context["accounts.api_token.id"] = api_token.id
64-
logger.info("API token created: %s", api_token.id)
65-
else:
66-
logger.info("API token found: %s", api_token.id)
67-
return api_token
34+
"""Creates an API token."""
35+
api_token_data = build_api_token_data()
36+
return await mpt_ops.accounts.api_tokens.create(api_token_data)
6837

6938

70-
@inject
7139
async def seed_api_token() -> None:
7240
"""Seed API token."""
7341
logger.debug("Seeding API token ...")
74-
await init_api_token()
42+
await init_resource("accounts.api_token.id", create_api_token)
7543
logger.debug("Seeding API token completed.")

seed/accounts/buyer.py

Lines changed: 9 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,21 @@
11
import logging
2-
import os
32

43
from dependency_injector.wiring import Provide, inject
54

65
from mpt_api_client import AsyncMPTClient
76
from mpt_api_client.resources.accounts.buyers import Buyer
87
from seed.container import Container
98
from seed.context import Context
9+
from seed.helper import init_resource, require_context_id
1010
from seed.static.static import ICON
1111

1212
logger = logging.getLogger(__name__)
1313

1414

15-
@inject
16-
async def get_buyer(
17-
context: Context = Provide[Container.context],
18-
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
19-
) -> Buyer | None:
20-
"""Get buyer from context or fetch from API."""
21-
buyer_id = context.get_string("accounts.buyer.id")
22-
if not buyer_id:
23-
return None
24-
try:
25-
buyer = context.get_resource("accounts.buyer", buyer_id)
26-
except ValueError:
27-
buyer = None
28-
if not isinstance(buyer, Buyer):
29-
buyer = await mpt_operations.accounts.buyers.get(buyer_id)
30-
context.set_resource("accounts.buyer", buyer)
31-
context["accounts.buyer.id"] = buyer.id
32-
return buyer
33-
return buyer
34-
35-
36-
@inject
3715
def build_buyer_data(context: Context = Provide[Container.context]) -> dict[str, object]:
3816
"""Build buyer data dictionary for creation."""
39-
buyer_account_id = os.getenv("CLIENT_ACCOUNT_ID")
40-
if not buyer_account_id:
41-
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
42-
seller_id = context.get_string("accounts.seller.id")
43-
if not seller_id:
44-
raise ValueError("accounts.seller.id missing from context; seed seller before buyer.")
17+
buyer_account_id = require_context_id(context, "accounts.account.id", "creating buyer")
18+
seller_id = require_context_id(context, "accounts.seller.id", "creating buyer")
4519
return {
4620
"name": "E2E Seeded Buyer",
4721
"account": {"id": buyer_account_id},
@@ -62,31 +36,18 @@ def build_buyer_data(context: Context = Provide[Container.context]) -> dict[str,
6236

6337

6438
@inject
65-
async def init_buyer(
39+
async def create_buyer(
6640
context: Context = Provide[Container.context],
6741
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
6842
) -> Buyer:
69-
"""Get or create buyer."""
70-
buyer = await get_buyer(context=context, mpt_operations=mpt_operations)
71-
if buyer is None:
72-
buyer_data = build_buyer_data(context=context)
73-
logger.debug("Creating buyer ...")
74-
with ICON.open("rb") as icon_fd:
75-
created = await mpt_operations.accounts.buyers.create(buyer_data, file=icon_fd)
76-
if isinstance(created, Buyer):
77-
context.set_resource("accounts.buyer", created)
78-
context["accounts.buyer.id"] = created.id
79-
logger.info("Buyer created: %s", created.id)
80-
return created
81-
logger.warning("Buyer creation failed") # type: ignore[unreachable]
82-
raise ValueError("Buyer creation failed")
83-
logger.info("Buyer found: %s", buyer.id)
84-
return buyer
43+
"""Creates a buyer."""
44+
buyer_data = build_buyer_data(context=context)
45+
with ICON.open("rb") as icon_fd:
46+
return await mpt_operations.accounts.buyers.create(buyer_data, file=icon_fd)
8547

8648

87-
@inject
8849
async def seed_buyer() -> None:
8950
"""Seed buyer."""
9051
logger.debug("Seeding buyer ...")
91-
await init_buyer()
52+
await init_resource("accounts.buyer.id", create_buyer)
9253
logger.debug("Seeding buyer completed.")

seed/accounts/licensee.py

Lines changed: 13 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,27 @@
11
import logging
2-
import os
32

43
from dependency_injector.wiring import Provide, inject
54

65
from mpt_api_client import AsyncMPTClient
76
from mpt_api_client.resources.accounts.licensees import Licensee
87
from seed.container import Container
98
from seed.context import Context
9+
from seed.helper import init_resource, require_context_id
1010
from seed.static.static import ICON
1111

1212
logger = logging.getLogger(__name__)
1313

1414

15-
@inject
16-
async def get_licensee(
17-
context: Context = Provide[Container.context],
18-
mpt_client: AsyncMPTClient = Provide[Container.mpt_client],
19-
) -> Licensee | None:
20-
"""Get licensee from context or fetch from API."""
21-
licensee_id = context.get_string("accounts.licensee.id")
22-
if not licensee_id:
23-
return None
24-
try:
25-
licensee = context.get_resource("accounts.licensee", licensee_id)
26-
except ValueError:
27-
licensee = None
28-
if not isinstance(licensee, Licensee):
29-
licensee = await mpt_client.accounts.licensees.get(licensee_id)
30-
context.set_resource("accounts.licensee", licensee)
31-
context["accounts.licensee.id"] = licensee.id
32-
return licensee
33-
return licensee
34-
35-
3615
@inject
3716
def build_licensee_data( # noqa: WPS238
3817
context: Context = Provide[Container.context],
3918
) -> dict[str, object]:
4019
"""Get licensee data dictionary for creation."""
41-
account_id = os.getenv("CLIENT_ACCOUNT_ID")
42-
if not account_id:
43-
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
44-
seller_id = context.get_string("accounts.seller.id")
45-
if not seller_id:
46-
raise ValueError("Seller ID is required in context")
47-
buyer_id = context.get_string("accounts.buyer.id")
48-
if not buyer_id:
49-
raise ValueError("Buyer ID is required in context")
50-
group = context.get_resource("accounts.user_group")
51-
if group is None:
52-
raise ValueError("User group is required in context")
20+
account_id = require_context_id(context, "accounts.account.id", "creating licensee")
21+
seller_id = require_context_id(context, "accounts.seller.id", "create licensee")
22+
buyer_id = require_context_id(context, "accounts.buyer.id", "create licensee")
23+
user_group_id = require_context_id(context, "accounts.user_group.id", "create licensee")
24+
5325
licensee_type = "Client"
5426
return {
5527
"name": "E2E Seeded Licensee",
@@ -65,39 +37,23 @@ def build_licensee_data( # noqa: WPS238
6537
"buyer": {"id": buyer_id},
6638
"account": {"id": account_id},
6739
"eligibility": {"client": True, "partner": False},
68-
"groups": [{"id": group.id}],
40+
"groups": [{"id": user_group_id}],
6941
"type": licensee_type,
7042
"status": "Enabled",
7143
"defaultLanguage": "en-US",
7244
}
7345

7446

7547
@inject
76-
async def init_licensee(
77-
context: Context = Provide[Container.context],
78-
mpt_client: AsyncMPTClient = Provide[Container.mpt_client],
79-
) -> Licensee:
80-
"""Get or create licensee."""
81-
licensee = await get_licensee(context=context, mpt_client=mpt_client)
82-
if licensee is None:
83-
licensee_data = build_licensee_data(context=context)
84-
logger.debug("Creating licensee ...")
85-
with ICON.open("rb") as icon_file:
86-
created = await mpt_client.accounts.licensees.create(licensee_data, file=icon_file)
87-
if isinstance(created, Licensee):
88-
context.set_resource("accounts.licensee", created)
89-
context["accounts.licensee.id"] = created.id
90-
logger.info("Licensee created: %s", created.id)
91-
return created
92-
logger.warning("Licensee creation failed") # type: ignore[unreachable]
93-
raise ValueError("Licensee creation failed")
94-
logger.info("Licensee found: %s", licensee.id)
95-
return licensee
48+
async def create_licensee(mpt_client: AsyncMPTClient = Provide[Container.mpt_client]) -> Licensee:
49+
"""Create licensee."""
50+
licensee_data = build_licensee_data()
51+
with ICON.open("rb") as icon_fd:
52+
return await mpt_client.accounts.licensees.create(licensee_data, file=icon_fd)
9653

9754

98-
@inject
9955
async def seed_licensee() -> None:
10056
"""Seed licensee."""
10157
logger.debug("Seeding licensee ...")
102-
await init_licensee()
58+
await init_resource("accounts.licensee.id", create_licensee)
10359
logger.info("Seeding licensee completed.")

seed/accounts/module.py

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,67 +6,29 @@
66
from mpt_api_client.resources.accounts.modules import Module
77
from mpt_api_client.rql.query_builder import RQLQuery
88
from seed.container import Container
9-
from seed.context import Context
9+
from seed.helper import init_resource
1010

1111
logger = logging.getLogger(__name__)
1212

1313

1414
@inject
15-
async def get_module(
16-
context: Context = Provide[Container.context],
15+
async def find_module(
1716
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
18-
) -> Module | None:
19-
"""Get module from context or fetch from API."""
20-
module_id = context.get_string("accounts.module.id")
21-
if not module_id:
22-
return None
23-
try:
24-
module = context.get_resource("accounts.module", module_id)
25-
except ValueError:
26-
module = None
27-
if not isinstance(module, Module):
28-
module = await mpt_operations.accounts.modules.get(module_id)
29-
context.set_resource("accounts.module", module)
30-
context["accounts.module.id"] = module.id
31-
return module
32-
return module
17+
) -> Module:
18+
"""Selects an existing module to use for seeding purposes.
3319
20+
Currently selects the "Access Management" module from the marketplace.
21+
"""
22+
filtered = mpt_operations.accounts.modules.filter(RQLQuery(name="Access Management"))
23+
modules = [module async for module in filtered.iterate()]
3424

35-
@inject
36-
async def refresh_module(
37-
context: Context = Provide[Container.context],
38-
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
39-
) -> Module | None:
40-
"""Refresh module in context (always fetch)."""
41-
module = await get_module(context=context, mpt_operations=mpt_operations)
42-
if module is None:
43-
filtered_modules = mpt_operations.accounts.modules.filter(
44-
RQLQuery(name="Access Management")
45-
)
46-
modules = [mod async for mod in filtered_modules.iterate()]
47-
if modules:
48-
first_module = modules[0]
49-
if isinstance(first_module, Module):
50-
context["accounts.module.id"] = first_module.id
51-
context.set_resource("accounts.module", first_module)
52-
return first_module
53-
logger.warning("First module is not a Module instance.") # type: ignore[unreachable]
54-
return None
55-
logger.warning("Module 'Access Management' not found.")
56-
return None
57-
return module
25+
if not modules:
26+
raise ValueError("Module 'Access Management' not found.")
27+
return modules[0]
5828

5929

60-
@inject
61-
async def seed_module() -> Module:
30+
async def seed_module() -> None:
6231
"""Seed module."""
6332
logger.debug("Seeding module ...")
64-
existing_module = await get_module()
65-
if existing_module is None:
66-
refreshed = await refresh_module()
67-
logger.debug("Seeding module completed.")
68-
if refreshed is None:
69-
raise ValueError("Could not seed module: no valid Module found.")
70-
return refreshed
33+
await init_resource("accounts.module.id", find_module)
7134
logger.debug("Seeding module completed.")
72-
return existing_module

0 commit comments

Comments
 (0)