Phase 0: Foundation & Credit System - Initial implementation

- Updated CREDIT_COSTS constants to Phase 0 format with new operations
- Enhanced CreditService with get_credit_cost() method and operation_type support
- Created AccountModuleSettings model for module enable/disable functionality
- Added AccountModuleSettingsSerializer and ViewSet
- Registered module settings API endpoint: /api/v1/system/settings/account-modules/
- Maintained backward compatibility with existing credit system
This commit is contained in:
Desktop
2025-11-16 23:24:44 +05:00
parent f84be4194f
commit 72a31b2edb
7 changed files with 220 additions and 45 deletions

View File

@@ -6,7 +6,7 @@ from igny8_core.auth.models import AccountBaseModel
# Import settings models
from .settings_models import (
SystemSettings, AccountSettings, UserSettings, ModuleSettings, AISettings
SystemSettings, AccountSettings, UserSettings, ModuleSettings, AccountModuleSettings, AISettings
)

View File

@@ -92,6 +92,61 @@ class ModuleSettings(BaseSettings):
return f"ModuleSetting: {self.module_name} - {self.key}"
class AccountModuleSettings(AccountBaseModel):
"""
Account-level module enable/disable settings.
Phase 0: Credit System - Module Settings
"""
# Module enable/disable flags
planner_enabled = models.BooleanField(default=True, help_text="Enable Planner module")
writer_enabled = models.BooleanField(default=True, help_text="Enable Writer module")
thinker_enabled = models.BooleanField(default=True, help_text="Enable Thinker module")
automation_enabled = models.BooleanField(default=True, help_text="Enable Automation module")
site_builder_enabled = models.BooleanField(default=True, help_text="Enable Site Builder module")
linker_enabled = models.BooleanField(default=True, help_text="Enable Linker module")
optimizer_enabled = models.BooleanField(default=True, help_text="Enable Optimizer module")
publisher_enabled = models.BooleanField(default=True, help_text="Enable Publisher module")
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'igny8_account_module_settings'
verbose_name = 'Account Module Settings'
verbose_name_plural = 'Account Module Settings'
# One settings record per account
constraints = [
models.UniqueConstraint(fields=['account'], name='unique_account_module_settings')
]
indexes = [
models.Index(fields=['account']),
]
def __str__(self):
account = getattr(self, 'account', None)
return f"ModuleSettings: {account.name if account else 'No Account'}"
@classmethod
def get_or_create_for_account(cls, account):
"""Get or create module settings for an account"""
settings, created = cls.objects.get_or_create(account=account)
return settings
def is_module_enabled(self, module_name):
"""Check if a module is enabled"""
module_map = {
'planner': self.planner_enabled,
'writer': self.writer_enabled,
'thinker': self.thinker_enabled,
'automation': self.automation_enabled,
'site_builder': self.site_builder_enabled,
'linker': self.linker_enabled,
'optimizer': self.optimizer_enabled,
'publisher': self.publisher_enabled,
}
return module_map.get(module_name, True) # Default to enabled if module not found
# AISettings extends IntegrationSettings (which already exists)
# We'll create it as a separate model that can reference IntegrationSettings
class AISettings(AccountBaseModel):

View File

@@ -2,7 +2,7 @@
Serializers for Settings Models
"""
from rest_framework import serializers
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AISettings
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AccountModuleSettings, AISettings
from .validators import validate_settings_schema
@@ -58,6 +58,18 @@ class ModuleSettingsSerializer(serializers.ModelSerializer):
return value
class AccountModuleSettingsSerializer(serializers.ModelSerializer):
"""Serializer for Account Module Settings (Phase 0)"""
class Meta:
model = AccountModuleSettings
fields = [
'id', 'planner_enabled', 'writer_enabled', 'thinker_enabled',
'automation_enabled', 'site_builder_enabled', 'linker_enabled',
'optimizer_enabled', 'publisher_enabled', 'created_at', 'updated_at'
]
read_only_fields = ['created_at', 'updated_at', 'account']
class AISettingsSerializer(serializers.ModelSerializer):
class Meta:
model = AISettings

View File

@@ -13,10 +13,10 @@ from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAu
from igny8_core.api.pagination import CustomPageNumberPagination
from igny8_core.api.throttles import DebugScopedRateThrottle
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AISettings
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, AccountModuleSettings, AISettings
from .settings_serializers import (
SystemSettingsSerializer, AccountSettingsSerializer, UserSettingsSerializer,
ModuleSettingsSerializer, AISettingsSerializer
ModuleSettingsSerializer, AccountModuleSettingsSerializer, AISettingsSerializer
)
@@ -276,6 +276,75 @@ class ModuleSettingsViewSet(AccountModelViewSet):
serializer.save(account=account)
@extend_schema_view(
list=extend_schema(tags=['System']),
retrieve=extend_schema(tags=['System']),
update=extend_schema(tags=['System']),
partial_update=extend_schema(tags=['System']),
)
class AccountModuleSettingsViewSet(AccountModelViewSet):
"""
ViewSet for managing account module enable/disable settings.
Phase 0: Credit System - Module Settings
One settings record per account (get_or_create pattern)
"""
queryset = AccountModuleSettings.objects.all()
serializer_class = AccountModuleSettingsSerializer
permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
pagination_class = CustomPageNumberPagination
throttle_scope = 'system'
throttle_classes = [DebugScopedRateThrottle]
def get_queryset(self):
"""Get module settings for current account"""
queryset = super().get_queryset()
return queryset.filter(account=self.request.account)
def list(self, request, *args, **kwargs):
"""Get or create module settings for account"""
account = request.account
settings = AccountModuleSettings.get_or_create_for_account(account)
serializer = self.get_serializer(settings)
return success_response(data=serializer.data, request=request)
def retrieve(self, request, pk=None):
"""Get module settings for account"""
account = request.account
try:
settings = AccountModuleSettings.objects.get(account=account, pk=pk)
except AccountModuleSettings.DoesNotExist:
# Create if doesn't exist
settings = AccountModuleSettings.get_or_create_for_account(account)
serializer = self.get_serializer(settings)
return success_response(data=serializer.data, request=request)
def perform_create(self, serializer):
"""Set account automatically"""
account = getattr(self.request, 'account', None)
if not account:
user = getattr(self.request, 'user', None)
if user:
account = getattr(user, 'account', None)
if not account:
from rest_framework.exceptions import ValidationError
raise ValidationError("Account is required")
serializer.save(account=account)
@action(detail=False, methods=['get'], url_path='check/(?P<module_name>[^/.]+)', url_name='check_module')
def check_module(self, request, module_name=None):
"""Check if a specific module is enabled"""
account = request.account
settings = AccountModuleSettings.get_or_create_for_account(account)
is_enabled = settings.is_module_enabled(module_name)
return success_response(
data={'module_name': module_name, 'enabled': is_enabled},
request=request
)
@extend_schema_view(
list=extend_schema(tags=['System']),
create=extend_schema(tags=['System']),

View File

@@ -7,7 +7,7 @@ from .views import AIPromptViewSet, AuthorProfileViewSet, StrategyViewSet, syste
from .integration_views import IntegrationSettingsViewSet
from .settings_views import (
SystemSettingsViewSet, AccountSettingsViewSet, UserSettingsViewSet,
ModuleSettingsViewSet, AISettingsViewSet
ModuleSettingsViewSet, AccountModuleSettingsViewSet, AISettingsViewSet
)
router = DefaultRouter()
router.register(r'prompts', AIPromptViewSet, basename='prompts')
@@ -17,6 +17,7 @@ router.register(r'settings/system', SystemSettingsViewSet, basename='system-sett
router.register(r'settings/account', AccountSettingsViewSet, basename='account-settings')
router.register(r'settings/user', UserSettingsViewSet, basename='user-settings')
router.register(r'settings/modules', ModuleSettingsViewSet, basename='module-settings')
router.register(r'settings/account-modules', AccountModuleSettingsViewSet, basename='account-module-settings')
router.register(r'settings/ai', AISettingsViewSet, basename='ai-settings')
# Custom URL patterns for integration settings - matching reference plugin structure