many fixes of backeend and fronteend

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-06 16:41:35 +00:00
parent a0eee0df42
commit bfb07947ea
19 changed files with 638 additions and 19 deletions

View File

@@ -2,7 +2,9 @@
Billing Module Admin
"""
from django.contrib import admin
from django.utils.html import format_html
from igny8_core.admin.base import AccountAdminMixin
from igny8_core.business.billing.models import CreditCostConfig
from .models import CreditTransaction, CreditUsageLog, AccountPaymentMethod
@@ -70,3 +72,78 @@ class AccountPaymentMethodAdmin(AccountAdminMixin, admin.ModelAdmin):
}),
)
@admin.register(CreditCostConfig)
class CreditCostConfigAdmin(admin.ModelAdmin):
list_display = [
'operation_type',
'display_name',
'credits_cost_display',
'unit',
'is_active',
'cost_change_indicator',
'updated_at',
'updated_by'
]
list_filter = ['is_active', 'unit', 'updated_at']
search_fields = ['operation_type', 'display_name', 'description']
fieldsets = (
('Operation', {
'fields': ('operation_type', 'display_name', 'description')
}),
('Cost Configuration', {
'fields': ('credits_cost', 'unit', 'is_active')
}),
('Audit Trail', {
'fields': ('previous_cost', 'updated_by', 'created_at', 'updated_at'),
'classes': ('collapse',)
}),
)
readonly_fields = ['created_at', 'updated_at', 'previous_cost']
def credits_cost_display(self, obj):
"""Show cost with color coding"""
if obj.credits_cost >= 20:
color = 'red'
elif obj.credits_cost >= 10:
color = 'orange'
else:
color = 'green'
return format_html(
'<span style="color: {}; font-weight: bold;">{} credits</span>',
color,
obj.credits_cost
)
credits_cost_display.short_description = 'Cost'
def cost_change_indicator(self, obj):
"""Show if cost changed recently"""
if obj.previous_cost is not None:
if obj.credits_cost > obj.previous_cost:
icon = '📈' # Increased
color = 'red'
elif obj.credits_cost < obj.previous_cost:
icon = '📉' # Decreased
color = 'green'
else:
icon = '➡️' # Same
color = 'gray'
return format_html(
'{} <span style="color: {};">({}{})</span>',
icon,
color,
obj.previous_cost,
obj.credits_cost
)
return ''
cost_change_indicator.short_description = 'Recent Change'
def save_model(self, request, obj, form, change):
"""Track who made the change"""
obj.updated_by = request.user
super().save_model(request, obj, form, change)

View File

@@ -4,6 +4,6 @@ from django.apps import AppConfig
class BillingConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'igny8_core.modules.billing'
verbose_name = 'Billing'
verbose_name = 'Billing & Tenancy'

View File

@@ -0,0 +1,88 @@
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('planner', '0007_fix_cluster_unique_constraint'),
('igny8_core_auth', '0006_soft_delete_and_retention'),
]
operations = [
migrations.AddField(
model_name='clusters',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='clusters',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='clusters',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='clusters',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='clusters',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='contentideas',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='contentideas',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='contentideas',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='contentideas',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='contentideas',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='keywords',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='keywords',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='keywords',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='keywords',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='keywords',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
]

View File

@@ -0,0 +1,88 @@
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('writer', '0011_content_external_metadata_content_external_type_and_more'),
('igny8_core_auth', '0006_soft_delete_and_retention'),
]
operations = [
migrations.AddField(
model_name='content',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='content',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='content',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='content',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='content',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='images',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='images',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='images',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='images',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='images',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='tasks',
name='delete_reason',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='tasks',
name='deleted_at',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
migrations.AddField(
model_name='tasks',
name='deleted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='igny8_core_auth.user'),
),
migrations.AddField(
model_name='tasks',
name='is_deleted',
field=models.BooleanField(db_index=True, default=False),
),
migrations.AddField(
model_name='tasks',
name='restore_until',
field=models.DateTimeField(blank=True, db_index=True, null=True),
),
]