test: add service tests and fix architecture violations
- Add comprehensive unit tests for FeatureService (24 tests) - Add comprehensive unit tests for UsageService (11 tests) - Fix API-002/API-003 architecture violations in feature/usage APIs - Move database queries from API layer to service layer - Create UsageService for usage and limits management - Create custom exceptions (FeatureNotFoundError, TierNotFoundError) - Fix ValidationException usage in content_pages.py - Refactor vendor features API to use proper response models - All 35 new tests passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -263,6 +263,13 @@ from .onboarding import (
|
||||
OnboardingSyncNotCompleteException,
|
||||
)
|
||||
|
||||
# Feature management exceptions
|
||||
from .feature import (
|
||||
FeatureNotFoundError,
|
||||
InvalidFeatureCodesError,
|
||||
TierNotFoundError,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Base exceptions
|
||||
"WizamartException",
|
||||
@@ -456,4 +463,8 @@ __all__ = [
|
||||
"OnboardingCsvUrlRequiredException",
|
||||
"OnboardingSyncJobNotFoundException",
|
||||
"OnboardingSyncNotCompleteException",
|
||||
# Feature exceptions
|
||||
"FeatureNotFoundError",
|
||||
"TierNotFoundError",
|
||||
"InvalidFeatureCodesError",
|
||||
]
|
||||
|
||||
42
app/exceptions/feature.py
Normal file
42
app/exceptions/feature.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# app/exceptions/feature.py
|
||||
"""
|
||||
Feature management exceptions.
|
||||
"""
|
||||
|
||||
from app.exceptions.base import ResourceNotFoundException, ValidationException
|
||||
|
||||
|
||||
class FeatureNotFoundError(ResourceNotFoundException):
|
||||
"""Feature not found."""
|
||||
|
||||
def __init__(self, feature_code: str):
|
||||
super().__init__(
|
||||
resource_type="Feature",
|
||||
identifier=feature_code,
|
||||
message=f"Feature '{feature_code}' not found",
|
||||
)
|
||||
self.feature_code = feature_code
|
||||
|
||||
|
||||
class TierNotFoundError(ResourceNotFoundException):
|
||||
"""Subscription tier not found."""
|
||||
|
||||
def __init__(self, tier_code: str):
|
||||
super().__init__(
|
||||
resource_type="SubscriptionTier",
|
||||
identifier=tier_code,
|
||||
message=f"Tier '{tier_code}' not found",
|
||||
)
|
||||
self.tier_code = tier_code
|
||||
|
||||
|
||||
class InvalidFeatureCodesError(ValidationException):
|
||||
"""Invalid feature codes provided."""
|
||||
|
||||
def __init__(self, invalid_codes: set[str]):
|
||||
codes_str = ", ".join(sorted(invalid_codes))
|
||||
super().__init__(
|
||||
message=f"Invalid feature codes: {codes_str}",
|
||||
details={"invalid_codes": list(invalid_codes)},
|
||||
)
|
||||
self.invalid_codes = invalid_codes
|
||||
Reference in New Issue
Block a user