Feat: Convert data_models.py cloud/billing models
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Step definitions for domain models testing."""
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
from behave import given, then, when
|
||||
@@ -11,16 +12,55 @@ from cleveragents.domain.models.aimodelsdatamodels import AIModel, Provider
|
||||
from cleveragents.domain.models.core import (
|
||||
Change,
|
||||
ChangeSet,
|
||||
CloudBillingFields,
|
||||
Context,
|
||||
ContextType,
|
||||
ContextUpdateResult,
|
||||
CreditType,
|
||||
CreditsTransaction,
|
||||
CreditsTransactionType,
|
||||
Invite,
|
||||
MaxContextCount,
|
||||
OperationType,
|
||||
Org,
|
||||
OrgRole,
|
||||
OrgUser,
|
||||
Plan,
|
||||
PlanStatus,
|
||||
Project,
|
||||
ProjectSettings,
|
||||
SummaryForUpdateContextParams,
|
||||
User,
|
||||
)
|
||||
from cleveragents.domain.models.core.enums import ModelProvider
|
||||
from cleveragents.domain.models.orguserconfig import OrgUserConfig
|
||||
from cleveragents.domain.models.planconfig import PlanConfig
|
||||
|
||||
|
||||
def _sample_plan_config() -> PlanConfig:
|
||||
"""Create a reusable PlanConfig instance for tests."""
|
||||
|
||||
return PlanConfig(
|
||||
auto_mode="manual",
|
||||
editor="vim",
|
||||
editor_command="vim",
|
||||
editor_args=[],
|
||||
editor_open_manually=False,
|
||||
auto_continue=False,
|
||||
auto_build=False,
|
||||
auto_update_context=False,
|
||||
auto_context=False,
|
||||
smart_context=False,
|
||||
auto_apply=False,
|
||||
auto_commit=False,
|
||||
skip_commit=False,
|
||||
can_exec=False,
|
||||
auto_exec=False,
|
||||
auto_debug=False,
|
||||
auto_debug_tries=0,
|
||||
auto_revert_on_rewind=False,
|
||||
skip_changes_menu=False,
|
||||
)
|
||||
|
||||
|
||||
@given("I have valid project data")
|
||||
@@ -381,6 +421,255 @@ def step_stats_count_operations(context):
|
||||
assert "applied" in context.stats
|
||||
|
||||
|
||||
# Domain models from cloud/organization data
|
||||
|
||||
|
||||
def _sample_billing_payload() -> dict[str, object]:
|
||||
"""Provide representative camelCase billing payload."""
|
||||
|
||||
return {
|
||||
"creditsBalance": "125.5",
|
||||
"monthlyGrant": "200.0",
|
||||
"autoRebuyEnabled": True,
|
||||
"autoRebuyMinThreshold": "5.0",
|
||||
"autoRebuyToBalance": "50.0",
|
||||
"notifyThreshold": "10.0",
|
||||
"maxThresholdPerMonth": "500.0",
|
||||
"billingCycleStartedAt": "2025-01-01T00:00:00Z",
|
||||
"changedBillingMode": False,
|
||||
"trialPaid": True,
|
||||
"stripeSubscriptionId": "sub-123",
|
||||
"subscriptionStatus": "active",
|
||||
"subscriptionPausedAt": "2025-01-10T00:00:00Z",
|
||||
"stripePaymentMethod": "pm_abc",
|
||||
"subscriptionActionRequired": False,
|
||||
"subscriptionActionRequiredInvoiceUrl": None,
|
||||
}
|
||||
|
||||
|
||||
@given("I have sample cloud billing data")
|
||||
def step_sample_cloud_billing(context):
|
||||
"""Prepare representative cloud billing data."""
|
||||
|
||||
context.cloud_billing_data = _sample_billing_payload()
|
||||
|
||||
|
||||
@when("I create a CloudBillingFields model")
|
||||
def step_create_billing_fields(context):
|
||||
"""Instantiate CloudBillingFields from camelCase payload."""
|
||||
|
||||
context.billing_fields = CloudBillingFields(**context.cloud_billing_data)
|
||||
|
||||
|
||||
@then("the billing fields should expose decimal values")
|
||||
def step_verify_billing_fields(context):
|
||||
"""Validate decimal conversion for billing fields."""
|
||||
|
||||
billing = context.billing_fields
|
||||
assert billing.credits_balance == Decimal("125.5")
|
||||
assert billing.monthly_grant == Decimal("200.0")
|
||||
assert billing.subscription_action_required is False
|
||||
|
||||
|
||||
@given("I have organization data with billing")
|
||||
def step_org_with_billing(context):
|
||||
"""Prepare organization payload referencing billing fields."""
|
||||
|
||||
context.org_payload = {
|
||||
"id": "org-1",
|
||||
"name": "Example Org",
|
||||
"isTrial": True,
|
||||
"autoAddDomainUsers": True,
|
||||
"integratedModelsMode": False,
|
||||
}
|
||||
context.org_billing_payload = _sample_billing_payload()
|
||||
|
||||
|
||||
@when("I create an Org domain model")
|
||||
def step_create_org_model(context):
|
||||
"""Instantiate Org with nested billing fields."""
|
||||
|
||||
billing = CloudBillingFields(**context.org_billing_payload)
|
||||
context.org_model = Org(cloud_billing_fields=billing, **context.org_payload)
|
||||
|
||||
|
||||
@then("the org should include billing configuration")
|
||||
def step_verify_org_model(context):
|
||||
"""Ensure the org retains billing configuration."""
|
||||
|
||||
org = context.org_model
|
||||
assert org.cloud_billing_fields is not None
|
||||
assert org.cloud_billing_fields.notify_threshold == Decimal("10.0")
|
||||
|
||||
|
||||
@given("I have an org role definition")
|
||||
def step_org_role_definition(context):
|
||||
"""Set up org role payload."""
|
||||
|
||||
context.org_role_data = {
|
||||
"id": "role-1",
|
||||
"isDefault": True,
|
||||
"label": "Owner",
|
||||
"description": "Full access",
|
||||
}
|
||||
|
||||
|
||||
@when("I create an OrgRole model")
|
||||
def step_create_org_role(context):
|
||||
"""Instantiate OrgRole."""
|
||||
|
||||
context.org_role = OrgRole(**context.org_role_data)
|
||||
|
||||
|
||||
@then("the org role should retain its label")
|
||||
def step_verify_org_role(context):
|
||||
"""Ensure org role values persist."""
|
||||
|
||||
assert context.org_role.label == "Owner"
|
||||
assert context.org_role.is_default is True
|
||||
|
||||
|
||||
@given("I have user data referencing a default plan config")
|
||||
def step_user_with_plan_config(context):
|
||||
"""Prepare user payload referencing plan config."""
|
||||
|
||||
context.user_plan_config = _sample_plan_config()
|
||||
context.user_data = {
|
||||
"id": "user-1",
|
||||
"name": "Casey",
|
||||
"email": "casey@example.com",
|
||||
"isTrial": False,
|
||||
"numNonDraftPlans": 3,
|
||||
}
|
||||
|
||||
|
||||
@when("I create a User model")
|
||||
def step_create_user_model(context):
|
||||
"""Instantiate User with nested plan config."""
|
||||
|
||||
context.user_model = User(
|
||||
default_plan_config=context.user_plan_config, **context.user_data
|
||||
)
|
||||
|
||||
|
||||
@then("the user should include the default plan config")
|
||||
def step_verify_user_model(context):
|
||||
"""Ensure user retains plan config."""
|
||||
|
||||
assert context.user_model.default_plan_config is not None
|
||||
assert context.user_model.default_plan_config.auto_mode == "manual"
|
||||
|
||||
|
||||
@given("I have an org user association")
|
||||
def step_org_user_association(context):
|
||||
"""Prepare OrgUser payload."""
|
||||
|
||||
context.org_user_config = OrgUserConfig(
|
||||
prompted_claude_max=False,
|
||||
use_claude_subscription=True,
|
||||
claude_subscription_cooldown_started_at=datetime(2025, 1, 1, 0, 0, 0),
|
||||
)
|
||||
context.org_user_data = {
|
||||
"orgId": "org-1",
|
||||
"userId": "user-1",
|
||||
"orgRoleId": "role-1",
|
||||
}
|
||||
|
||||
|
||||
@when("I create an OrgUser model")
|
||||
def step_create_org_user(context):
|
||||
"""Instantiate OrgUser."""
|
||||
|
||||
context.org_user_model = OrgUser(
|
||||
config=context.org_user_config, **context.org_user_data
|
||||
)
|
||||
|
||||
|
||||
@then("the org user config should be attached")
|
||||
def step_verify_org_user(context):
|
||||
"""Ensure OrgUser carries config payload."""
|
||||
|
||||
assert context.org_user_model.config is not None
|
||||
assert context.org_user_model.config.use_claude_subscription is True
|
||||
|
||||
|
||||
@given("I have invite metadata")
|
||||
def step_invite_metadata(context):
|
||||
"""Prepare Invite payload."""
|
||||
|
||||
context.invite_data = {
|
||||
"id": "invite-1",
|
||||
"orgId": "org-1",
|
||||
"email": "new@example.com",
|
||||
"name": "New User",
|
||||
"orgRoleId": "role-1",
|
||||
"inviterId": "user-1",
|
||||
"inviteeId": None,
|
||||
"acceptedAt": "2025-02-01T12:00:00Z",
|
||||
"createdAt": "2025-01-15T08:30:00Z",
|
||||
}
|
||||
|
||||
|
||||
@when("I create an Invite model")
|
||||
def step_create_invite(context):
|
||||
"""Instantiate Invite."""
|
||||
|
||||
context.invite_model = Invite(**context.invite_data)
|
||||
|
||||
|
||||
@then("the invite should track acceptance timestamps")
|
||||
def step_verify_invite(context):
|
||||
"""Ensure Invite datetimes parsed."""
|
||||
|
||||
assert isinstance(context.invite_model.accepted_at, datetime)
|
||||
assert context.invite_model.accepted_at.year == 2025
|
||||
|
||||
|
||||
@given("I have credits transaction data")
|
||||
def step_credits_transaction_data(context):
|
||||
"""Prepare CreditsTransaction payload."""
|
||||
|
||||
context.credits_transaction_data = {
|
||||
"id": "txn-1",
|
||||
"orgId": "org-1",
|
||||
"orgName": "Example Org",
|
||||
"userId": "user-1",
|
||||
"userEmail": "casey@example.com",
|
||||
"userName": "Casey",
|
||||
"transactionType": CreditsTransactionType.CREDIT,
|
||||
"amount": "42.0",
|
||||
"startBalance": "20.0",
|
||||
"endBalance": "62.0",
|
||||
"creditType": CreditType.TRIAL,
|
||||
"creditIsAutoRebuy": True,
|
||||
"creditAutoRebuyMinThreshold": "5.0",
|
||||
"creditAutoRebuyToBalance": "40.0",
|
||||
"debitModelProvider": ModelProvider.OPENAI,
|
||||
"debitModelRole": "ModelRolePlanner",
|
||||
"debitModelName": "gpt-4.1",
|
||||
"debitPlanId": "plan-1",
|
||||
"debitPlanName": "Core Plan",
|
||||
"createdAt": "2025-01-20T00:00:00Z",
|
||||
}
|
||||
|
||||
|
||||
@when("I create a CreditsTransaction model")
|
||||
def step_create_credits_transaction(context):
|
||||
"""Instantiate CreditsTransaction."""
|
||||
|
||||
context.credits_transaction = CreditsTransaction(**context.credits_transaction_data)
|
||||
|
||||
|
||||
@then("the credits transaction should track balances")
|
||||
def step_verify_credits_transaction(context):
|
||||
"""Ensure CreditsTransaction stores decimals and provider metadata."""
|
||||
|
||||
tx = context.credits_transaction
|
||||
assert tx.amount == Decimal("42.0")
|
||||
assert tx.debit_model_provider == ModelProvider.OPENAI
|
||||
assert tx.end_balance == Decimal("62.0")
|
||||
|
||||
|
||||
# Auto-generated models steps
|
||||
@when("I import the auto-generated models")
|
||||
def step_import_autogenerated(context):
|
||||
|
||||
Reference in New Issue
Block a user