master plan implemenattion
This commit is contained in:
@@ -143,6 +143,83 @@ class UsageLimitsSerializer(serializers.Serializer):
|
||||
limits: LimitCardSerializer = LimitCardSerializer(many=True)
|
||||
|
||||
|
||||
class AccountPaymentMethodSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for Account Payment Methods
|
||||
Handles CRUD operations for account-specific payment methods
|
||||
"""
|
||||
id = serializers.IntegerField(read_only=True)
|
||||
type = serializers.ChoiceField(
|
||||
choices=[
|
||||
('stripe', 'Stripe (Credit/Debit Card)'),
|
||||
('paypal', 'PayPal'),
|
||||
('bank_transfer', 'Bank Transfer (Manual)'),
|
||||
('local_wallet', 'Local Wallet (Manual)'),
|
||||
('manual', 'Manual Payment'),
|
||||
]
|
||||
)
|
||||
display_name = serializers.CharField(max_length=100)
|
||||
is_default = serializers.BooleanField(default=False)
|
||||
is_enabled = serializers.BooleanField(default=True)
|
||||
is_verified = serializers.BooleanField(read_only=True, default=False)
|
||||
instructions = serializers.CharField(required=False, allow_blank=True, default='')
|
||||
metadata = serializers.JSONField(required=False, default=dict)
|
||||
created_at = serializers.DateTimeField(read_only=True)
|
||||
updated_at = serializers.DateTimeField(read_only=True)
|
||||
|
||||
def validate_display_name(self, value):
|
||||
"""Validate display_name uniqueness per account"""
|
||||
account = self.context.get('account')
|
||||
instance = getattr(self, 'instance', None)
|
||||
|
||||
if account:
|
||||
from igny8_core.business.billing.models import AccountPaymentMethod
|
||||
existing = AccountPaymentMethod.objects.filter(
|
||||
account=account,
|
||||
display_name=value
|
||||
)
|
||||
if instance:
|
||||
existing = existing.exclude(pk=instance.pk)
|
||||
if existing.exists():
|
||||
raise serializers.ValidationError(
|
||||
f"A payment method with name '{value}' already exists for this account."
|
||||
)
|
||||
return value
|
||||
|
||||
def create(self, validated_data):
|
||||
from igny8_core.business.billing.models import AccountPaymentMethod
|
||||
account = self.context.get('account')
|
||||
if not account:
|
||||
raise serializers.ValidationError("Account context is required")
|
||||
|
||||
# If this is marked as default, unset other defaults
|
||||
if validated_data.get('is_default', False):
|
||||
AccountPaymentMethod.objects.filter(
|
||||
account=account,
|
||||
is_default=True
|
||||
).update(is_default=False)
|
||||
|
||||
return AccountPaymentMethod.objects.create(
|
||||
account=account,
|
||||
**validated_data
|
||||
)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
from igny8_core.business.billing.models import AccountPaymentMethod
|
||||
|
||||
# If this is marked as default, unset other defaults
|
||||
if validated_data.get('is_default', False) and not instance.is_default:
|
||||
AccountPaymentMethod.objects.filter(
|
||||
account=instance.account,
|
||||
is_default=True
|
||||
).exclude(pk=instance.pk).update(is_default=False)
|
||||
|
||||
for attr, value in validated_data.items():
|
||||
setattr(instance, attr, value)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class AIModelConfigSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for AI Model Configuration (Read-Only API)
|
||||
|
||||
@@ -39,6 +39,7 @@ class ClustersResource(resources.ModelResource):
|
||||
class ClustersAdmin(ImportExportMixin, SiteSectorAdminMixin, Igny8ModelAdmin):
|
||||
resource_class = ClustersResource
|
||||
list_display = ['name', 'site', 'sector', 'keywords_count', 'volume', 'status', 'created_at']
|
||||
list_select_related = ['site', 'sector', 'account']
|
||||
list_filter = [
|
||||
('status', ChoicesDropdownFilter),
|
||||
('site', RelatedDropdownFilter),
|
||||
@@ -97,6 +98,7 @@ class KeywordsAdmin(ImportExportMixin, SiteSectorAdminMixin, Igny8ModelAdmin):
|
||||
resource_class = KeywordsResource
|
||||
list_display = ['keyword', 'seed_keyword', 'site', 'sector', 'cluster', 'volume', 'difficulty', 'country', 'status', 'created_at']
|
||||
list_editable = ['status'] # Enable inline editing for status
|
||||
list_select_related = ['site', 'sector', 'cluster', 'seed_keyword', 'seed_keyword__industry', 'seed_keyword__sector', 'account']
|
||||
list_filter = [
|
||||
('status', ChoicesDropdownFilter),
|
||||
('country', ChoicesDropdownFilter),
|
||||
@@ -107,7 +109,7 @@ class KeywordsAdmin(ImportExportMixin, SiteSectorAdminMixin, Igny8ModelAdmin):
|
||||
('difficulty', RangeNumericFilter),
|
||||
('created_at', RangeDateFilter),
|
||||
]
|
||||
search_fields = ['keyword', 'seed_keyword__keyword']
|
||||
search_fields = ['seed_keyword__keyword']
|
||||
ordering = ['-created_at']
|
||||
autocomplete_fields = ['cluster', 'site', 'sector', 'seed_keyword']
|
||||
actions = [
|
||||
@@ -218,6 +220,7 @@ class ContentIdeasResource(resources.ModelResource):
|
||||
class ContentIdeasAdmin(ImportExportMixin, SiteSectorAdminMixin, Igny8ModelAdmin):
|
||||
resource_class = ContentIdeasResource
|
||||
list_display = ['idea_title', 'site', 'sector', 'description_preview', 'content_type', 'content_structure', 'status', 'keyword_cluster', 'estimated_word_count', 'created_at']
|
||||
list_select_related = ['site', 'sector', 'keyword_cluster', 'account']
|
||||
list_filter = [
|
||||
('status', ChoicesDropdownFilter),
|
||||
('content_type', ChoicesDropdownFilter),
|
||||
|
||||
Reference in New Issue
Block a user