678 lines
26 KiB
Python
678 lines
26 KiB
Python
"""
|
|
Commands for account-related operations.
|
|
"""
|
|
from typing import Any, Dict, List, Optional
|
|
from datetime import datetime
|
|
|
|
from backend.core.models.accounts.accounts import Account
|
|
from backend.core.repositories.accounts.accounts import AccountRepository
|
|
from backend.core.repositories.customers.customers import CustomerRepository
|
|
from backend.core.utils.validators import (
|
|
is_valid_uuid, is_valid_email, is_valid_phone, is_valid_date,
|
|
validate_required_fields, validate_model_exists
|
|
)
|
|
from backend.core.utils.helpers import generate_uuid, parse_date
|
|
from backend.core.commands.base import Command, CommandResult
|
|
|
|
|
|
class CreateAccountCommand(Command):
|
|
"""
|
|
Command to create a new account.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
account_repo: AccountRepository,
|
|
customer_repo: CustomerRepository,
|
|
customer_id: str,
|
|
name: str,
|
|
street_address: str,
|
|
city: str,
|
|
state: str,
|
|
zip_code: str,
|
|
start_date: str,
|
|
primary_contact_first_name: str, # Changed from contact_first_name
|
|
primary_contact_last_name: str, # Changed from contact_last_name
|
|
primary_contact_phone: str, # Changed from contact_phone
|
|
primary_contact_email: str, # Changed from contact_email
|
|
secondary_contact_first_name: Optional[str] = None, # Added
|
|
secondary_contact_last_name: Optional[str] = None, # Added
|
|
secondary_contact_phone: Optional[str] = None, # Added
|
|
secondary_contact_email: Optional[str] = None, # Added
|
|
end_date: Optional[str] = None
|
|
):
|
|
"""
|
|
Initialize the create account command.
|
|
|
|
Args:
|
|
account_repo: Repository for account operations.
|
|
customer_repo: Repository for customer operations.
|
|
customer_id: ID of the customer this account belongs to.
|
|
name: Name of the account.
|
|
street_address: Street address of the account.
|
|
city: City of the account.
|
|
state: State of the account.
|
|
zip_code: ZIP code of the account.
|
|
primary_contact_first_name: First name of the primary contact.
|
|
primary_contact_last_name: Last name of the primary contact.
|
|
primary_contact_phone: Phone number of the primary contact.
|
|
primary_contact_email: Email of the primary contact.
|
|
secondary_contact_first_name: First name of the secondary contact (optional).
|
|
secondary_contact_last_name: Last name of the secondary contact (optional).
|
|
secondary_contact_phone: Phone number of the secondary contact (optional).
|
|
secondary_contact_email: Email of the secondary contact (optional).
|
|
start_date: Start date of the account (YYYY-MM-DD).
|
|
end_date: End date of the account (YYYY-MM-DD, optional).
|
|
"""
|
|
self.account_repo = account_repo
|
|
self.customer_repo = customer_repo
|
|
self.customer_id = customer_id
|
|
self.name = name
|
|
self.street_address = street_address
|
|
self.city = city
|
|
self.state = state
|
|
self.zip_code = zip_code
|
|
self.primary_contact_first_name = primary_contact_first_name
|
|
self.primary_contact_last_name = primary_contact_last_name
|
|
self.primary_contact_phone = primary_contact_phone
|
|
self.primary_contact_email = primary_contact_email
|
|
self.secondary_contact_first_name = secondary_contact_first_name
|
|
self.secondary_contact_last_name = secondary_contact_last_name
|
|
self.secondary_contact_phone = secondary_contact_phone
|
|
self.secondary_contact_email = secondary_contact_email
|
|
self.start_date = start_date
|
|
self.end_date = end_date
|
|
|
|
def validate(self) -> Dict[str, Any]:
|
|
"""
|
|
Validate the account creation data.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Validation result with 'is_valid' and optional 'errors'.
|
|
"""
|
|
errors = []
|
|
|
|
# Check required fields
|
|
required_fields = [
|
|
'customer_id', 'name', 'street_address', 'city', 'state', 'zip_code',
|
|
'primary_contact_first_name', 'primary_contact_last_name',
|
|
'primary_contact_phone', 'primary_contact_email', 'start_date'
|
|
]
|
|
|
|
field_values = {
|
|
'customer_id': self.customer_id,
|
|
'name': self.name,
|
|
'street_address': self.street_address,
|
|
'city': self.city,
|
|
'state': self.state,
|
|
'zip_code': self.zip_code,
|
|
'primary_contact_first_name': self.primary_contact_first_name,
|
|
'primary_contact_last_name': self.primary_contact_last_name,
|
|
'primary_contact_phone': self.primary_contact_phone,
|
|
'primary_contact_email': self.primary_contact_email,
|
|
'start_date': self.start_date
|
|
}
|
|
|
|
missing_fields = validate_required_fields(field_values, required_fields)
|
|
|
|
if missing_fields:
|
|
errors.append(f"Required fields missing: {', '.join(missing_fields)}")
|
|
|
|
# Validate customer exists
|
|
if not errors and self.customer_id:
|
|
customer_validation = validate_model_exists(
|
|
self.customer_id, 'customer', self.customer_repo.get_by_id
|
|
)
|
|
if not customer_validation['valid']:
|
|
errors.append(customer_validation['error'])
|
|
|
|
if not errors and self.primary_contact_email and not is_valid_email(self.primary_contact_email):
|
|
errors.append("Invalid primary contact email format.")
|
|
|
|
if not errors and self.primary_contact_phone and not is_valid_phone(self.primary_contact_phone):
|
|
errors.append("Invalid primary contact phone format.")
|
|
|
|
if not errors and self.secondary_contact_email and not is_valid_email(self.secondary_contact_email):
|
|
errors.append("Invalid secondary contact email format.")
|
|
|
|
if not errors and self.secondary_contact_phone and not is_valid_phone(self.secondary_contact_phone):
|
|
errors.append("Invalid secondary contact phone format.")
|
|
|
|
# Validate date formats
|
|
if not errors and self.start_date and not is_valid_date(self.start_date):
|
|
errors.append("Invalid start date format. Use YYYY-MM-DD.")
|
|
|
|
if not errors and self.end_date and not is_valid_date(self.end_date):
|
|
errors.append("Invalid end date format. Use YYYY-MM-DD.")
|
|
|
|
# Validate start date is before end date if both provided
|
|
if not errors and self.start_date and self.end_date:
|
|
start = parse_date(self.start_date)
|
|
end = parse_date(self.end_date)
|
|
if start and end and start > end:
|
|
errors.append("Start date must be before end date.")
|
|
|
|
# Check if customer is active
|
|
if not errors:
|
|
customer = self.customer_repo.get_by_id(self.customer_id)
|
|
if customer and customer.end_date:
|
|
customer_end_date = parse_date(customer.end_date)
|
|
today = datetime.now().date()
|
|
if customer_end_date and customer_end_date < today:
|
|
errors.append(f"Cannot create account for inactive customer")
|
|
|
|
return {
|
|
'is_valid': len(errors) == 0,
|
|
'errors': errors
|
|
}
|
|
|
|
def execute(self) -> CommandResult[Account]:
|
|
"""
|
|
Execute the account creation command.
|
|
|
|
Returns:
|
|
CommandResult[Account]: Result of the command execution.
|
|
"""
|
|
# Validate command data
|
|
validation = self.validate()
|
|
if not validation['is_valid']:
|
|
return CommandResult.failure_result(validation['errors'])
|
|
|
|
try:
|
|
# Create account data
|
|
account_id = generate_uuid()
|
|
|
|
# Create account data dictionary
|
|
account_data = {
|
|
'id': account_id,
|
|
'customer_id': self.customer_id,
|
|
'name': self.name,
|
|
'street_address': self.street_address,
|
|
'city': self.city,
|
|
'state': self.state,
|
|
'zip_code': self.zip_code,
|
|
'primary_contact_first_name': self.primary_contact_first_name,
|
|
'primary_contact_last_name': self.primary_contact_last_name,
|
|
'primary_contact_phone': self.primary_contact_phone,
|
|
'primary_contact_email': self.primary_contact_email,
|
|
'secondary_contact_first_name': self.secondary_contact_first_name,
|
|
'secondary_contact_last_name': self.secondary_contact_last_name,
|
|
'secondary_contact_phone': self.secondary_contact_phone,
|
|
'secondary_contact_email': self.secondary_contact_email,
|
|
'start_date': self.start_date,
|
|
'end_date': self.end_date
|
|
}
|
|
|
|
# Save to repository
|
|
created_account = self.account_repo.create(account_data)
|
|
|
|
return CommandResult.success_result(
|
|
created_account,
|
|
f"Account {self.name} created successfully for customer {self.customer_id}"
|
|
)
|
|
|
|
except Exception as e:
|
|
return CommandResult.failure_result(
|
|
str(e),
|
|
"Failed to create account"
|
|
)
|
|
|
|
|
|
class UpdateAccountCommand(Command):
|
|
"""
|
|
Command to update an existing account.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
account_repo: AccountRepository,
|
|
account_id: str,
|
|
name: Optional[str] = None,
|
|
street_address: Optional[str] = None,
|
|
city: Optional[str] = None,
|
|
state: Optional[str] = None,
|
|
zip_code: Optional[str] = None,
|
|
primary_contact_first_name: Optional[str] = None,
|
|
primary_contact_last_name: Optional[str] = None,
|
|
primary_contact_phone: Optional[str] = None,
|
|
primary_contact_email: Optional[str] = None,
|
|
secondary_contact_first_name: Optional[str] = None,
|
|
secondary_contact_last_name: Optional[str] = None,
|
|
secondary_contact_phone: Optional[str] = None,
|
|
secondary_contact_email: Optional[str] = None,
|
|
start_date: Optional[str] = None,
|
|
end_date: Optional[str] = None
|
|
):
|
|
"""
|
|
Initialize the update account command.
|
|
|
|
Args:
|
|
account_repo: Repository for account operations.
|
|
account_id: ID of the account to update.
|
|
name: New name for the account.
|
|
street_address: New street address for the account.
|
|
city: New city for the account.
|
|
state: New state for the account.
|
|
zip_code: New ZIP code for the account.
|
|
primary_contact_first_name: New first name for the primary contact.
|
|
primary_contact_last_name: New last name for the primary contact.
|
|
primary_contact_phone: New phone number for the primary contact.
|
|
primary_contact_email: New email for the primary contact.
|
|
secondary_contact_first_name: New first name for the secondary contact.
|
|
secondary_contact_last_name: New last name for the secondary contact.
|
|
secondary_contact_phone: New phone number for the secondary contact.
|
|
secondary_contact_email: New email for the secondary contact.
|
|
start_date: New start date for the account.
|
|
end_date: New end date for the account.
|
|
"""
|
|
self.account_repo = account_repo
|
|
self.account_id = account_id
|
|
self.name = name
|
|
self.street_address = street_address
|
|
self.city = city
|
|
self.state = state
|
|
self.zip_code = zip_code
|
|
self.primary_contact_first_name = primary_contact_first_name
|
|
self.primary_contact_last_name = primary_contact_last_name
|
|
self.primary_contact_phone = primary_contact_phone
|
|
self.primary_contact_email = primary_contact_email
|
|
self.secondary_contact_first_name = secondary_contact_first_name
|
|
self.secondary_contact_last_name = secondary_contact_last_name
|
|
self.secondary_contact_phone = secondary_contact_phone
|
|
self.secondary_contact_email = secondary_contact_email
|
|
self.start_date = start_date
|
|
self.end_date = end_date
|
|
|
|
def validate(self) -> Dict[str, Any]:
|
|
"""
|
|
Validate the account update data.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Validation result with 'is_valid' and optional 'errors'.
|
|
"""
|
|
errors = []
|
|
|
|
# Validate account exists
|
|
if not is_valid_uuid(self.account_id):
|
|
errors.append("Invalid account ID format")
|
|
else:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if not account:
|
|
errors.append(f"Account with ID {self.account_id} not found")
|
|
|
|
if not errors and self.primary_contact_email is not None and not is_valid_email(self.primary_contact_email):
|
|
errors.append("Invalid primary contact email format.")
|
|
|
|
if not errors and self.primary_contact_phone is not None and not is_valid_phone(self.primary_contact_phone):
|
|
errors.append("Invalid primary contact phone format.")
|
|
|
|
if not errors and self.secondary_contact_email is not None and not is_valid_email(self.secondary_contact_email):
|
|
errors.append("Invalid secondary contact email format.")
|
|
|
|
if not errors and self.secondary_contact_phone is not None and not is_valid_phone(self.secondary_contact_phone):
|
|
errors.append("Invalid secondary contact phone format.")
|
|
|
|
# Validate date formats if provided
|
|
if not errors and self.start_date is not None and not is_valid_date(self.start_date):
|
|
errors.append("Invalid start date format. Use YYYY-MM-DD.")
|
|
|
|
if not errors and self.end_date is not None and not is_valid_date(self.end_date):
|
|
errors.append("Invalid end date format. Use YYYY-MM-DD.")
|
|
|
|
# Validate start date is before end date if both provided
|
|
if not errors and self.start_date and self.end_date:
|
|
start = parse_date(self.start_date)
|
|
end = parse_date(self.end_date)
|
|
if start and end and start > end:
|
|
errors.append("Start date must be before end date.")
|
|
|
|
# If only updating end_date, validate it's after the existing start_date
|
|
if not errors and self.end_date and not self.start_date:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if account:
|
|
end = parse_date(self.end_date)
|
|
start = parse_date(account.start_date)
|
|
if end and start and start > end:
|
|
errors.append("End date must be after the existing start date.")
|
|
|
|
return {
|
|
'is_valid': len(errors) == 0,
|
|
'errors': errors
|
|
}
|
|
|
|
def execute(self) -> CommandResult[Account]:
|
|
"""
|
|
Execute the account update command.
|
|
|
|
Returns:
|
|
CommandResult[Account]: Result of the command execution.
|
|
"""
|
|
# Validate command data
|
|
validation = self.validate()
|
|
if not validation['is_valid']:
|
|
return CommandResult.failure_result(validation['errors'])
|
|
|
|
try:
|
|
# Create a dictionary of fields to update
|
|
update_data = {}
|
|
|
|
# Add fields to update_data if they were provided
|
|
if self.name is not None:
|
|
update_data['name'] = self.name
|
|
|
|
if self.street_address is not None:
|
|
update_data['street_address'] = self.street_address
|
|
|
|
if self.city is not None:
|
|
update_data['city'] = self.city
|
|
|
|
if self.state is not None:
|
|
update_data['state'] = self.state
|
|
|
|
if self.zip_code is not None:
|
|
update_data['zip_code'] = self.zip_code
|
|
|
|
if self.primary_contact_first_name is not None:
|
|
update_data['primary_contact_first_name'] = self.primary_contact_first_name
|
|
|
|
if self.primary_contact_last_name is not None:
|
|
update_data['primary_contact_last_name'] = self.primary_contact_last_name
|
|
|
|
if self.primary_contact_phone is not None:
|
|
update_data['primary_contact_phone'] = self.primary_contact_phone
|
|
|
|
if self.primary_contact_email is not None:
|
|
update_data['primary_contact_email'] = self.primary_contact_email
|
|
|
|
if self.secondary_contact_first_name is not None:
|
|
update_data['secondary_contact_first_name'] = self.secondary_contact_first_name
|
|
|
|
if self.secondary_contact_last_name is not None:
|
|
update_data['secondary_contact_last_name'] = self.secondary_contact_last_name
|
|
|
|
if self.secondary_contact_phone is not None:
|
|
update_data['secondary_contact_phone'] = self.secondary_contact_phone
|
|
|
|
if self.secondary_contact_email is not None:
|
|
update_data['secondary_contact_email'] = self.secondary_contact_email
|
|
|
|
if self.start_date is not None:
|
|
update_data['start_date'] = self.start_date
|
|
|
|
if self.end_date is not None:
|
|
update_data['end_date'] = self.end_date
|
|
|
|
# Update the account with the data dictionary
|
|
updated_account = self.account_repo.update(self.account_id, update_data)
|
|
|
|
return CommandResult.success_result(
|
|
updated_account,
|
|
f"Account {self.account_id} updated successfully"
|
|
)
|
|
|
|
except Exception as e:
|
|
return CommandResult.failure_result(
|
|
str(e),
|
|
"Failed to update account"
|
|
)
|
|
|
|
|
|
class DeleteAccountCommand(Command):
|
|
"""
|
|
Command to delete an account.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
account_repo: AccountRepository,
|
|
account_id: str
|
|
):
|
|
"""
|
|
Initialize the delete account command.
|
|
|
|
Args:
|
|
account_repo: Repository for account operations.
|
|
account_id: ID of the account to delete.
|
|
"""
|
|
self.account_repo = account_repo
|
|
self.account_id = account_id
|
|
|
|
def validate(self) -> Dict[str, Any]:
|
|
"""
|
|
Validate the account deletion request.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Validation result with 'is_valid' and optional 'errors'.
|
|
"""
|
|
errors = []
|
|
|
|
# Validate account exists
|
|
if not is_valid_uuid(self.account_id):
|
|
errors.append("Invalid account ID format")
|
|
else:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if not account:
|
|
errors.append(f"Account with ID {self.account_id} not found")
|
|
|
|
# Check if account has associated services or projects
|
|
if not errors:
|
|
account_with_relations = self.account_repo.get_with_all_related(self.account_id)
|
|
if account_with_relations:
|
|
if hasattr(account_with_relations, 'services') and account_with_relations.services.exists():
|
|
errors.append(f"Cannot delete account with associated services")
|
|
if hasattr(account_with_relations, 'projects') and account_with_relations.projects.exists():
|
|
errors.append(f"Cannot delete account with associated projects")
|
|
|
|
return {
|
|
'is_valid': len(errors) == 0,
|
|
'errors': errors
|
|
}
|
|
|
|
def execute(self) -> CommandResult[bool]:
|
|
"""
|
|
Execute the account deletion command.
|
|
|
|
Returns:
|
|
CommandResult[bool]: Result of the command execution.
|
|
"""
|
|
# Validate command data
|
|
validation = self.validate()
|
|
if not validation['is_valid']:
|
|
return CommandResult.failure_result(validation['errors'])
|
|
|
|
try:
|
|
# Delete the account
|
|
success = self.account_repo.delete(self.account_id)
|
|
|
|
if success:
|
|
return CommandResult.success_result(
|
|
True,
|
|
f"Account {self.account_id} deleted successfully"
|
|
)
|
|
else:
|
|
return CommandResult.failure_result(
|
|
"Failed to delete account",
|
|
f"Account {self.account_id} could not be deleted"
|
|
)
|
|
|
|
except Exception as e:
|
|
return CommandResult.failure_result(
|
|
str(e),
|
|
"Failed to delete account"
|
|
)
|
|
|
|
|
|
class MarkAccountInactiveCommand(Command):
|
|
"""
|
|
Command to mark an account as inactive.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
account_repo: AccountRepository,
|
|
account_id: str,
|
|
end_date: Optional[str] = None
|
|
):
|
|
"""
|
|
Initialize the mark account inactive command.
|
|
|
|
Args:
|
|
account_repo: Repository for account operations.
|
|
account_id: ID of the account to mark as inactive.
|
|
end_date: End date for the account (defaults to today if not provided).
|
|
"""
|
|
self.account_repo = account_repo
|
|
self.account_id = account_id
|
|
self.end_date = end_date
|
|
|
|
def validate(self) -> Dict[str, Any]:
|
|
"""
|
|
Validate the mark account inactive request.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Validation result with 'is_valid' and optional 'errors'.
|
|
"""
|
|
errors = []
|
|
|
|
# Validate account exists
|
|
if not is_valid_uuid(self.account_id):
|
|
errors.append("Invalid account ID format")
|
|
else:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if not account:
|
|
errors.append(f"Account with ID {self.account_id} not found")
|
|
elif account.end_date is not None:
|
|
errors.append(f"Account is already marked as inactive")
|
|
|
|
# Validate end date format if provided
|
|
if not errors and self.end_date and not is_valid_date(self.end_date):
|
|
errors.append("Invalid end date format. Use YYYY-MM-DD.")
|
|
|
|
# Validate end date is after start date if provided
|
|
if not errors and self.end_date:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if account:
|
|
end = parse_date(self.end_date)
|
|
start = parse_date(account.start_date)
|
|
if end and start and start > end:
|
|
errors.append("End date must be after the start date.")
|
|
|
|
return {
|
|
'is_valid': len(errors) == 0,
|
|
'errors': errors
|
|
}
|
|
|
|
def execute(self) -> CommandResult[Account]:
|
|
"""
|
|
Execute the mark account inactive command.
|
|
|
|
Returns:
|
|
CommandResult[Account]: Result of the command execution.
|
|
"""
|
|
# Validate command data
|
|
validation = self.validate()
|
|
if not validation['is_valid']:
|
|
return CommandResult.failure_result(validation['errors'])
|
|
|
|
try:
|
|
# Mark the account as inactive
|
|
end_date = self.end_date or datetime.now().strftime('%Y-%m-%d')
|
|
updated_account = self.account_repo.update(
|
|
self.account_id,
|
|
{'end_date': end_date}
|
|
)
|
|
|
|
if updated_account:
|
|
return CommandResult.success_result(
|
|
updated_account,
|
|
f"Account {self.account_id} marked as inactive successfully"
|
|
)
|
|
else:
|
|
return CommandResult.failure_result(
|
|
"Failed to mark account as inactive",
|
|
f"Account {self.account_id} could not be marked as inactive"
|
|
)
|
|
|
|
except Exception as e:
|
|
return CommandResult.failure_result(
|
|
str(e),
|
|
"Failed to mark account as inactive"
|
|
)
|
|
|
|
|
|
class GetAccountRevenueCommand(Command):
|
|
"""
|
|
Command to get the revenue information for an account.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
account_repo: AccountRepository,
|
|
account_id: str
|
|
):
|
|
"""
|
|
Initialize the get account revenue command.
|
|
|
|
Args:
|
|
account_repo: Repository for account operations.
|
|
account_id: ID of the account to get revenue for.
|
|
"""
|
|
self.account_repo = account_repo
|
|
self.account_id = account_id
|
|
|
|
def validate(self) -> Dict[str, Any]:
|
|
"""
|
|
Validate the get account revenue request.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Validation result with 'is_valid' and optional 'errors'.
|
|
"""
|
|
errors = []
|
|
|
|
# Validate account exists
|
|
if not is_valid_uuid(self.account_id):
|
|
errors.append("Invalid account ID format")
|
|
else:
|
|
account = self.account_repo.get_by_id(self.account_id)
|
|
if not account:
|
|
errors.append(f"Account with ID {self.account_id} not found")
|
|
|
|
return {
|
|
'is_valid': len(errors) == 0,
|
|
'errors': errors
|
|
}
|
|
|
|
def execute(self) -> CommandResult[List[Any]]:
|
|
"""
|
|
Execute the get account revenue command.
|
|
|
|
Returns:
|
|
CommandResult[List[Any]]: Result of the command execution with revenue data.
|
|
"""
|
|
# Validate command data
|
|
validation = self.validate()
|
|
if not validation['is_valid']:
|
|
return CommandResult.failure_result(validation['errors'])
|
|
|
|
try:
|
|
# Retrieve the account's revenue information
|
|
account_with_revenues = self.account_repo.get_with_revenues(self.account_id)
|
|
|
|
if account_with_revenues and hasattr(account_with_revenues, 'revenues'):
|
|
revenues = list(account_with_revenues.revenues.all())
|
|
return CommandResult.success_result(
|
|
revenues,
|
|
f"Retrieved revenue data for account {self.account_id}"
|
|
)
|
|
else:
|
|
return CommandResult.failure_result(
|
|
"No revenue data found",
|
|
f"No revenue data found for account {self.account_id}"
|
|
)
|
|
|
|
except Exception as e:
|
|
return CommandResult.failure_result(
|
|
str(e),
|
|
"Failed to retrieve account revenue data"
|
|
)
|