django-cfg 1.3.7__py3-none-any.whl → 1.3.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +258 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +171 -461
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
  48. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  49. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
  50. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  51. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  52. django_cfg/apps/payments/middleware/api_access.py +32 -6
  53. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
  54. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
  55. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
  56. django_cfg/apps/payments/models/balance.py +12 -0
  57. django_cfg/apps/payments/models/currencies.py +106 -32
  58. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  59. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  60. django_cfg/apps/payments/services/core/payment_service.py +1 -1
  61. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  62. django_cfg/apps/payments/services/providers/base.py +95 -39
  63. django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
  64. django_cfg/apps/payments/services/providers/models/base.py +122 -0
  65. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  66. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  67. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  68. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  69. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  70. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  71. django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
  72. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  73. django_cfg/apps/payments/services/providers/registry.py +4 -32
  74. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  75. django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
  76. django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
  77. django_cfg/apps/payments/tasks/__init__.py +39 -0
  78. django_cfg/apps/payments/tasks/types.py +73 -0
  79. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  80. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  81. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  82. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  83. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  84. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  85. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  86. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  87. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  88. django_cfg/apps/payments/urls_admin.py +1 -1
  89. django_cfg/apps/payments/views/api/currencies.py +5 -5
  90. django_cfg/apps/payments/views/overview/services.py +2 -2
  91. django_cfg/apps/payments/views/serializers/currencies.py +4 -3
  92. django_cfg/apps/support/admin/__init__.py +10 -1
  93. django_cfg/apps/support/admin/support_admin.py +338 -141
  94. django_cfg/apps/tasks/admin/__init__.py +11 -0
  95. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  96. django_cfg/config.py +1 -1
  97. django_cfg/core/config.py +10 -5
  98. django_cfg/core/generation.py +1 -1
  99. django_cfg/management/commands/__init__.py +13 -1
  100. django_cfg/management/commands/app_agent_diagnose.py +470 -0
  101. django_cfg/management/commands/app_agent_generate.py +342 -0
  102. django_cfg/management/commands/app_agent_info.py +308 -0
  103. django_cfg/management/commands/migrate_all.py +9 -3
  104. django_cfg/management/commands/migrator.py +11 -6
  105. django_cfg/management/commands/rundramatiq.py +3 -2
  106. django_cfg/middleware/__init__.py +0 -2
  107. django_cfg/models/api_keys.py +115 -0
  108. django_cfg/modules/django_admin/__init__.py +64 -0
  109. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  110. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  111. django_cfg/modules/django_admin/decorators/display.py +106 -0
  112. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  113. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  114. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  115. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  116. django_cfg/modules/django_admin/models/__init__.py +20 -0
  117. django_cfg/modules/django_admin/models/action_models.py +33 -0
  118. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  119. django_cfg/modules/django_admin/models/base.py +26 -0
  120. django_cfg/modules/django_admin/models/display_models.py +31 -0
  121. django_cfg/modules/django_admin/utils/badges.py +159 -0
  122. django_cfg/modules/django_admin/utils/displays.py +247 -0
  123. django_cfg/modules/django_app_agent/__init__.py +87 -0
  124. django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
  125. django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
  126. django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
  127. django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
  128. django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
  129. django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
  130. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
  131. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
  132. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
  133. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
  134. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
  135. django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
  136. django_cfg/modules/django_app_agent/core/__init__.py +33 -0
  137. django_cfg/modules/django_app_agent/core/config.py +300 -0
  138. django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
  139. django_cfg/modules/django_app_agent/models/__init__.py +71 -0
  140. django_cfg/modules/django_app_agent/models/base.py +283 -0
  141. django_cfg/modules/django_app_agent/models/context.py +496 -0
  142. django_cfg/modules/django_app_agent/models/enums.py +481 -0
  143. django_cfg/modules/django_app_agent/models/requests.py +500 -0
  144. django_cfg/modules/django_app_agent/models/responses.py +585 -0
  145. django_cfg/modules/django_app_agent/pytest.ini +6 -0
  146. django_cfg/modules/django_app_agent/services/__init__.py +42 -0
  147. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
  148. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
  149. django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
  150. django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
  151. django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
  152. django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
  153. django_cfg/modules/django_app_agent/services/base.py +437 -0
  154. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
  155. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
  156. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
  157. django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
  158. django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
  159. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
  160. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
  161. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
  162. django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
  163. django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
  164. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
  165. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
  166. django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
  167. django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
  168. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
  169. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
  170. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
  171. django_cfg/modules/django_app_agent/services/report_service.py +332 -0
  172. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
  173. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
  174. django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
  175. django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
  176. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
  177. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
  178. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
  179. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
  180. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
  181. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
  182. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
  183. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
  184. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
  185. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
  186. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
  187. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
  188. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
  189. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
  190. django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
  191. django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
  192. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
  193. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
  194. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
  195. django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
  196. django_cfg/modules/django_app_agent/ui/cli.py +419 -0
  197. django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
  198. django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
  199. django_cfg/modules/django_app_agent/utils/logging.py +360 -0
  200. django_cfg/modules/django_app_agent/utils/validation.py +417 -0
  201. django_cfg/modules/django_currency/__init__.py +2 -2
  202. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  203. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  204. django_cfg/modules/django_currency/core/converter.py +12 -12
  205. django_cfg/modules/django_currency/database/__init__.py +2 -2
  206. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  207. django_cfg/modules/django_llm/llm/client.py +10 -2
  208. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  209. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  210. django_cfg/modules/django_unfold/dashboard.py +14 -13
  211. django_cfg/modules/django_unfold/models/config.py +1 -1
  212. django_cfg/registry/core.py +3 -0
  213. django_cfg/registry/third_party.py +2 -2
  214. django_cfg/template_archive/django_sample.zip +0 -0
  215. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
  216. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/RECORD +223 -117
  217. django_cfg/apps/accounts/admin/activity.py +0 -96
  218. django_cfg/apps/accounts/admin/group.py +0 -17
  219. django_cfg/apps/accounts/admin/otp.py +0 -59
  220. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  221. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  222. django_cfg/apps/accounts/admin/user.py +0 -300
  223. django_cfg/apps/agents/core/agent.py +0 -281
  224. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  225. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  226. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  227. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  228. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  229. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  230. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  231. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  232. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  233. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  234. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  235. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  236. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  237. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  238. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  239. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  240. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  241. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  242. django_cfg/apps/tasks/admin.py +0 -320
  243. django_cfg/middleware/static_nocache.py +0 -55
  244. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  245. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  246. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  247. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  248. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  249. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
  250. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
  251. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
django_cfg/__init__.py CHANGED
@@ -32,7 +32,7 @@ Example:
32
32
  default_app_config = "django_cfg.apps.DjangoCfgConfig"
33
33
 
34
34
  # Version information
35
- __version__ = "1.3.7"
35
+ __version__ = "1.3.9"
36
36
  __license__ = "MIT"
37
37
 
38
38
  # Import registry for organized lazy loading
@@ -1,18 +1,34 @@
1
1
  """
2
- Admin configuration for Accounts app.
2
+ Accounts admin interfaces using Django Admin Utilities.
3
+
4
+ Modern, clean admin interfaces with Material Icons and consistent styling.
3
5
  """
4
6
 
5
- from .user import CustomUserAdmin
6
- from .otp import OTPSecretAdmin
7
- from .registration_source import RegistrationSourceAdmin, UserRegistrationSourceAdmin
8
- from .activity import UserActivityAdmin
9
- from .group import GroupAdmin
7
+ from django.contrib import admin
8
+
9
+ # Import all admin classes
10
+ from .user_admin import CustomUserAdmin
11
+ from .activity_admin import UserActivityAdmin
12
+ from .otp_admin import OTPSecretAdmin
13
+ from .registration_admin import RegistrationSourceAdmin, UserRegistrationSourceAdmin
14
+ from .group_admin import GroupAdmin
15
+ from .twilio_admin import TwilioResponseAdmin, TwilioResponseInline
16
+
17
+ # All models are registered in their respective admin files using @admin.register
18
+ # This provides:
19
+ # - Clean separation of concerns
20
+ # - Material Icons integration
21
+ # - Type-safe configurations
22
+ # - Performance optimizations
23
+ # - Consistent styling with django_admin module
10
24
 
11
25
  __all__ = [
12
26
  'CustomUserAdmin',
13
- 'OTPSecretAdmin',
27
+ 'UserActivityAdmin',
28
+ 'OTPSecretAdmin',
14
29
  'RegistrationSourceAdmin',
15
30
  'UserRegistrationSourceAdmin',
16
- 'UserActivityAdmin',
17
31
  'GroupAdmin',
32
+ 'TwilioResponseAdmin',
33
+ 'TwilioResponseInline',
18
34
  ]
@@ -0,0 +1,146 @@
1
+ """
2
+ User Activity admin interface using Django Admin Utilities.
3
+
4
+ Enhanced activity tracking with Material Icons and optimized queries.
5
+ """
6
+
7
+ from django.contrib import admin
8
+ from unfold.admin import ModelAdmin
9
+
10
+ from django_cfg.modules.django_admin import (
11
+ OptimizedModelAdmin,
12
+ DisplayMixin,
13
+ UserDisplayConfig,
14
+ DateTimeDisplayConfig,
15
+ StatusBadgeConfig,
16
+ Icons,
17
+ display
18
+ )
19
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
20
+
21
+ from ..models import UserActivity
22
+ from .filters import ActivityTypeFilter
23
+
24
+
25
+ @admin.register(UserActivity)
26
+ class UserActivityAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
27
+ """Enhanced admin for UserActivity model using Django Admin Utilities."""
28
+
29
+ # Performance optimization
30
+ select_related_fields = ['user']
31
+
32
+ list_display = [
33
+ 'user_display',
34
+ 'activity_type_display',
35
+ 'description_display',
36
+ 'ip_address_display',
37
+ 'created_at_display'
38
+ ]
39
+ list_display_links = ['user_display', 'activity_type_display']
40
+ list_filter = [ActivityTypeFilter, 'activity_type', 'created_at']
41
+ search_fields = ['user__username', 'user__email', 'description', 'ip_address']
42
+ readonly_fields = ['created_at']
43
+ date_hierarchy = 'created_at'
44
+ ordering = ['-created_at']
45
+
46
+ fieldsets = (
47
+ ('Activity', {
48
+ 'fields': ('user', 'activity_type', 'description')
49
+ }),
50
+ ('Related Object', {
51
+ 'fields': ('object_id', 'object_type'),
52
+ 'classes': ('collapse',),
53
+ 'description': 'Optional reference to related model instance'
54
+ }),
55
+ ('Request Info', {
56
+ 'fields': ('ip_address', 'user_agent'),
57
+ 'classes': ('collapse',)
58
+ }),
59
+ ('Timestamp', {
60
+ 'fields': ('created_at',)
61
+ }),
62
+ )
63
+
64
+ @display(description="User")
65
+ def user_display(self, obj):
66
+ """Enhanced user display with avatar."""
67
+ config = UserDisplayConfig(
68
+ show_avatar=True,
69
+ avatar_size=20,
70
+ show_email=False
71
+ )
72
+ return self.display_user_simple(obj.user, config)
73
+
74
+ @display(description="Activity")
75
+ def activity_type_display(self, obj):
76
+ """Activity type with appropriate icons."""
77
+ activity_icons = {
78
+ 'login': Icons.LOGIN,
79
+ 'logout': Icons.LOGOUT,
80
+ 'otp_requested': Icons.EMAIL,
81
+ 'otp_verified': Icons.VERIFIED,
82
+ 'profile_updated': Icons.EDIT,
83
+ 'registration': Icons.PERSON_ADD,
84
+ }
85
+
86
+ activity_variants = {
87
+ 'login': 'success',
88
+ 'logout': 'info',
89
+ 'otp_requested': 'warning',
90
+ 'otp_verified': 'success',
91
+ 'profile_updated': 'info',
92
+ 'registration': 'primary',
93
+ }
94
+
95
+ icon = activity_icons.get(obj.activity_type, Icons.DESCRIPTION)
96
+ variant = activity_variants.get(obj.activity_type, 'info')
97
+
98
+ config = StatusBadgeConfig(
99
+ show_icons=True,
100
+ icon=icon,
101
+ custom_mappings={obj.get_activity_type_display(): variant}
102
+ )
103
+
104
+ return StatusBadge.create(
105
+ text=obj.get_activity_type_display(),
106
+ variant=variant,
107
+ config=config
108
+ )
109
+
110
+ @display(description="Description")
111
+ def description_display(self, obj):
112
+ """Truncated description with full text in tooltip."""
113
+ if len(obj.description) > 50:
114
+ truncated = f"{obj.description[:47]}..."
115
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.DESCRIPTION)
116
+ return StatusBadge.create(
117
+ text=truncated,
118
+ variant="secondary",
119
+ config=config
120
+ )
121
+
122
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.DESCRIPTION)
123
+ return StatusBadge.create(
124
+ text=obj.description,
125
+ variant="info",
126
+ config=config
127
+ )
128
+
129
+ @display(description="IP Address")
130
+ def ip_address_display(self, obj):
131
+ """IP address with network icon."""
132
+ if not obj.ip_address:
133
+ return "—"
134
+
135
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.PUBLIC)
136
+ return StatusBadge.create(
137
+ text=obj.ip_address,
138
+ variant="secondary",
139
+ config=config
140
+ )
141
+
142
+ @display(description="When")
143
+ def created_at_display(self, obj):
144
+ """Created time with relative display."""
145
+ config = DateTimeDisplayConfig(show_relative=True)
146
+ return self.display_datetime_relative(obj, 'created_at', config)
@@ -1,51 +1,63 @@
1
1
  """
2
2
  Custom admin filters for Accounts app.
3
+
4
+ Enhanced filters with better organization and performance.
3
5
  """
4
6
 
5
7
  from django.contrib import admin
6
8
  from django.utils import timezone
7
9
  from datetime import timedelta
10
+ from django.db import models
11
+ from django.db.models import Count
8
12
 
9
13
 
10
14
  class UserStatusFilter(admin.SimpleListFilter):
15
+ """Enhanced user status filter with clear categories."""
11
16
  title = "User Status"
12
17
  parameter_name = "user_status"
13
18
 
14
19
  def lookups(self, request, model_admin):
15
20
  return (
16
- ("active", "Active"),
17
- ("inactive", "Inactive"),
18
- ("staff", "Staff"),
19
- ("superuser", "Superuser"),
21
+ ("active", "Active Users"),
22
+ ("inactive", "Inactive Users"),
23
+ ("staff", "⚙️ Staff Members"),
24
+ ("superuser", "👑 Superusers"),
25
+ ("regular", "👤 Regular Users"),
20
26
  )
21
27
 
22
28
  def queryset(self, request, queryset):
23
29
  if self.value() == "active":
24
- return queryset.filter(is_active=True, is_staff=False)
30
+ return queryset.filter(is_active=True, is_staff=False, is_superuser=False)
25
31
  elif self.value() == "inactive":
26
32
  return queryset.filter(is_active=False)
27
33
  elif self.value() == "staff":
28
- return queryset.filter(is_staff=True)
34
+ return queryset.filter(is_staff=True, is_superuser=False)
29
35
  elif self.value() == "superuser":
30
36
  return queryset.filter(is_superuser=True)
37
+ elif self.value() == "regular":
38
+ return queryset.filter(is_active=True, is_staff=False, is_superuser=False)
31
39
  return queryset
32
40
 
33
41
 
34
42
  class OTPStatusFilter(admin.SimpleListFilter):
43
+ """Enhanced OTP status filter with time-based categories."""
35
44
  title = "OTP Status"
36
45
  parameter_name = "otp_status"
37
46
 
38
47
  def lookups(self, request, model_admin):
39
48
  return (
40
- ("active", "Active"),
41
- ("used", "Used"),
42
- ("expired", "Expired"),
43
- ("recent", "Recent (24h)"),
49
+ ("valid", "✅ Valid & Active"),
50
+ ("used", "🔒 Used"),
51
+ ("expired", "Expired"),
52
+ ("recent", "🕐 Recent (24h)"),
53
+ ("today", "📅 Today"),
44
54
  )
45
55
 
46
56
  def queryset(self, request, queryset):
47
57
  now = timezone.now()
48
- if self.value() == "active":
58
+ today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
59
+
60
+ if self.value() == "valid":
49
61
  return queryset.filter(is_used=False, expires_at__gt=now)
50
62
  elif self.value() == "used":
51
63
  return queryset.filter(is_used=True)
@@ -53,17 +65,21 @@ class OTPStatusFilter(admin.SimpleListFilter):
53
65
  return queryset.filter(is_used=False, expires_at__lte=now)
54
66
  elif self.value() == "recent":
55
67
  return queryset.filter(created_at__gte=now - timedelta(hours=24))
68
+ elif self.value() == "today":
69
+ return queryset.filter(created_at__gte=today_start)
56
70
  return queryset
57
71
 
58
72
 
59
73
  class RegistrationSourceStatusFilter(admin.SimpleListFilter):
60
- title = "Registration Source Status"
61
- parameter_name = "registration_source_status"
74
+ """Registration source status filter."""
75
+ title = "Source Status"
76
+ parameter_name = "source_status"
62
77
 
63
78
  def lookups(self, request, model_admin):
64
79
  return (
65
- ("active", "Active"),
66
- ("inactive", "Inactive"),
80
+ ("active", "Active Sources"),
81
+ ("inactive", "Inactive Sources"),
82
+ ("popular", "🔥 Popular (10+ users)"),
67
83
  )
68
84
 
69
85
  def queryset(self, request, queryset):
@@ -71,28 +87,88 @@ class RegistrationSourceStatusFilter(admin.SimpleListFilter):
71
87
  return queryset.filter(is_active=True)
72
88
  elif self.value() == "inactive":
73
89
  return queryset.filter(is_active=False)
90
+ elif self.value() == "popular":
91
+ # Sources with 10 or more users
92
+ return queryset.annotate(
93
+ user_count=Count('user_registration_sources')
94
+ ).filter(user_count__gte=10)
74
95
  return queryset
75
96
 
76
97
 
77
98
  class ActivityTypeFilter(admin.SimpleListFilter):
99
+ """Enhanced activity type filter with time-based options."""
78
100
  title = "Activity Type"
79
101
  parameter_name = "activity_type"
80
102
 
81
103
  def lookups(self, request, model_admin):
82
104
  return (
83
- ("login", "Login"),
84
- ("logout", "Logout"),
85
- ("otp_requested", "OTP Requested"),
86
- ("otp_verified", "OTP Verified"),
87
- ("profile_updated", "Profile Updated"),
88
- ("registration", "Registration"),
89
- ("recent", "Recent (24h)"),
105
+ ("login", "🔐 Login"),
106
+ ("logout", "🚪 Logout"),
107
+ ("otp_requested", "📧 OTP Requested"),
108
+ ("otp_verified", "OTP Verified"),
109
+ ("profile_updated", "✏️ Profile Updated"),
110
+ ("registration", "👤 Registration"),
111
+ ("recent", "🕐 Recent (24h)"),
112
+ ("today", "📅 Today"),
90
113
  )
91
114
 
92
115
  def queryset(self, request, queryset):
93
116
  now = timezone.now()
117
+ today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
118
+
94
119
  if self.value() == "recent":
95
120
  return queryset.filter(created_at__gte=now - timedelta(hours=24))
121
+ elif self.value() == "today":
122
+ return queryset.filter(created_at__gte=today_start)
96
123
  elif self.value():
97
124
  return queryset.filter(activity_type=self.value())
98
125
  return queryset
126
+
127
+
128
+ class TwilioResponseStatusFilter(admin.SimpleListFilter):
129
+ """Twilio response status filter."""
130
+ title = "Response Status"
131
+ parameter_name = "twilio_status"
132
+
133
+ def lookups(self, request, model_admin):
134
+ return (
135
+ ("success", "✅ Successful"),
136
+ ("error", "❌ With Errors"),
137
+ ("pending", "⏳ Pending"),
138
+ ("recent", "🕐 Recent (24h)"),
139
+ )
140
+
141
+ def queryset(self, request, queryset):
142
+ now = timezone.now()
143
+
144
+ if self.value() == "success":
145
+ return queryset.filter(error_code__isnull=True, error_message__isnull=True)
146
+ elif self.value() == "error":
147
+ return queryset.filter(
148
+ models.Q(error_code__isnull=False) |
149
+ models.Q(error_message__isnull=False)
150
+ )
151
+ elif self.value() == "pending":
152
+ return queryset.filter(status__in=['queued', 'sending', 'sent'])
153
+ elif self.value() == "recent":
154
+ return queryset.filter(created_at__gte=now - timedelta(hours=24))
155
+ return queryset
156
+
157
+
158
+ class TwilioResponseTypeFilter(admin.SimpleListFilter):
159
+ """Twilio response type filter."""
160
+ title = "Service Type"
161
+ parameter_name = "twilio_service"
162
+
163
+ def lookups(self, request, model_admin):
164
+ return (
165
+ ("sms", "📱 SMS"),
166
+ ("voice", "📞 Voice"),
167
+ ("verify", "🔐 Verify"),
168
+ ("email", "📧 Email"),
169
+ )
170
+
171
+ def queryset(self, request, queryset):
172
+ if self.value():
173
+ return queryset.filter(service_type=self.value())
174
+ return queryset
@@ -0,0 +1,86 @@
1
+ """
2
+ Group admin interface using Django Admin Utilities.
3
+
4
+ Enhanced group management with Material Icons and user counts.
5
+ """
6
+
7
+ from django.contrib import admin
8
+ from django.contrib.auth.models import Group
9
+ from unfold.admin import ModelAdmin
10
+
11
+ from django_cfg.modules.django_admin import (
12
+ OptimizedModelAdmin,
13
+ DisplayMixin,
14
+ StatusBadgeConfig,
15
+ Icons,
16
+ display
17
+ )
18
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
19
+
20
+
21
+ # Unregister the default Group admin
22
+ admin.site.unregister(Group)
23
+
24
+
25
+ @admin.register(Group)
26
+ class GroupAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
27
+ """Enhanced admin for Group model using Django Admin Utilities."""
28
+
29
+ list_display = [
30
+ 'name_display',
31
+ 'users_count_display',
32
+ 'permissions_count_display'
33
+ ]
34
+ list_display_links = ['name_display']
35
+ search_fields = ['name']
36
+ filter_horizontal = ['permissions']
37
+ ordering = ['name']
38
+
39
+ fieldsets = (
40
+ ('Group Details', {
41
+ 'fields': ('name',)
42
+ }),
43
+ ('Permissions', {
44
+ 'fields': ('permissions',),
45
+ 'classes': ('collapse',)
46
+ }),
47
+ )
48
+
49
+ @display(description="Group Name")
50
+ def name_display(self, obj):
51
+ """Group name display with group icon."""
52
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.GROUP)
53
+ return StatusBadge.create(
54
+ text=obj.name,
55
+ variant="primary",
56
+ config=config
57
+ )
58
+
59
+ @display(description="Users")
60
+ def users_count_display(self, obj):
61
+ """Count of users in this group."""
62
+ count = obj.user_set.count()
63
+ if count == 0:
64
+ return "—"
65
+
66
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.PEOPLE)
67
+ return StatusBadge.create(
68
+ text=f"{count} user{'s' if count != 1 else ''}",
69
+ variant="info",
70
+ config=config
71
+ )
72
+
73
+ @display(description="Permissions")
74
+ def permissions_count_display(self, obj):
75
+ """Count of permissions in this group."""
76
+ count = obj.permissions.count()
77
+ if count == 0:
78
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.SECURITY)
79
+ return StatusBadge.create(text="No permissions", variant="secondary", config=config)
80
+
81
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.SECURITY)
82
+ return StatusBadge.create(
83
+ text=f"{count} permission{'s' if count != 1 else ''}",
84
+ variant="warning",
85
+ config=config
86
+ )
@@ -1,16 +1,24 @@
1
1
  """
2
- Inline admin classes for Accounts app.
2
+ Inline admin classes for Accounts app using Django Admin Utilities.
3
+
4
+ Enhanced inline classes with better organization and conditional loading.
3
5
  """
4
6
 
5
7
  from unfold.admin import TabularInline
6
- from ..models import UserRegistrationSource, UserActivity
7
8
 
9
+ from django_cfg.modules.base import BaseCfgModule
10
+ from django_cfg.apps.support.models import Ticket
11
+ from ..models import UserRegistrationSource, UserActivity
8
12
 
9
13
  class UserRegistrationSourceInline(TabularInline):
14
+ """Enhanced inline for user registration sources."""
10
15
  model = UserRegistrationSource
11
16
  extra = 0
12
17
  readonly_fields = ["registration_date"]
13
18
  fields = ["source", "first_registration", "registration_date"]
19
+ ordering = ["-registration_date"]
20
+ verbose_name = "Registration Source"
21
+ verbose_name_plural = "Registration Sources"
14
22
 
15
23
  def has_add_permission(self, request, obj=None):
16
24
  return True
@@ -20,10 +28,14 @@ class UserRegistrationSourceInline(TabularInline):
20
28
 
21
29
 
22
30
  class RegistrationSourceInline(TabularInline):
31
+ """Enhanced inline for registration source users."""
23
32
  model = UserRegistrationSource
24
33
  extra = 0
25
34
  readonly_fields = ["registration_date"]
26
35
  fields = ["user", "first_registration", "registration_date"]
36
+ ordering = ["-registration_date"]
37
+ verbose_name = "User Registration"
38
+ verbose_name_plural = "User Registrations"
27
39
 
28
40
  def has_add_permission(self, request, obj=None):
29
41
  return True
@@ -33,11 +45,19 @@ class RegistrationSourceInline(TabularInline):
33
45
 
34
46
 
35
47
  class UserActivityInline(TabularInline):
48
+ """Enhanced inline for user activities."""
36
49
  model = UserActivity
37
50
  extra = 0
38
- readonly_fields = ["created_at"]
51
+ readonly_fields = ["created_at", "activity_type", "description"]
39
52
  fields = ["activity_type", "description", "ip_address", "created_at"]
40
53
  ordering = ["-created_at"]
54
+ verbose_name = "Activity"
55
+ verbose_name_plural = "Recent Activities"
56
+
57
+ # Show only recent activities to avoid performance issues
58
+ def get_queryset(self, request):
59
+ qs = super().get_queryset(request)
60
+ return qs[:10] # Limit to 10 most recent activities
41
61
 
42
62
  def has_add_permission(self, request, obj=None):
43
63
  return False
@@ -47,13 +67,12 @@ class UserActivityInline(TabularInline):
47
67
 
48
68
 
49
69
  class UserEmailLogInline(TabularInline):
50
- """Inline for viewing user's email logs."""
70
+ """Enhanced inline for viewing user's email logs."""
51
71
 
52
72
  def __init__(self, *args, **kwargs):
53
73
  # Check if newsletter app is available and enabled
54
74
  self.model = None
55
75
  try:
56
- from django_cfg.modules.base import BaseCfgModule
57
76
  base_module = BaseCfgModule()
58
77
 
59
78
  # Only import if newsletter is enabled
@@ -73,7 +92,14 @@ class UserEmailLogInline(TabularInline):
73
92
  fields = ["newsletter", "campaign", "subject", "status", "created_at", "sent_at"]
74
93
  ordering = ["-created_at"]
75
94
  verbose_name = "Email Log"
76
- verbose_name_plural = "Email Logs"
95
+ verbose_name_plural = "Email History"
96
+
97
+ # Show only recent emails to avoid performance issues
98
+ def get_queryset(self, request):
99
+ if not self.model:
100
+ return self.model.objects.none()
101
+ qs = super().get_queryset(request)
102
+ return qs[:15] # Limit to 15 most recent emails
77
103
 
78
104
  def has_add_permission(self, request, obj=None):
79
105
  return False
@@ -86,7 +112,6 @@ class UserEmailLogInline(TabularInline):
86
112
  if not self.model:
87
113
  return False
88
114
  try:
89
- from django_cfg.modules.base import BaseCfgModule
90
115
  base_module = BaseCfgModule()
91
116
  return base_module.is_newsletter_enabled()
92
117
  except Exception:
@@ -94,18 +119,16 @@ class UserEmailLogInline(TabularInline):
94
119
 
95
120
 
96
121
  class UserSupportTicketsInline(TabularInline):
97
- """Inline for viewing user's support tickets."""
122
+ """Enhanced inline for viewing user's support tickets."""
98
123
 
99
124
  def __init__(self, *args, **kwargs):
100
125
  # Check if support app is available and enabled
101
126
  self.model = None
102
127
  try:
103
- from django_cfg.modules.base import BaseCfgModule
104
128
  base_module = BaseCfgModule()
105
129
 
106
130
  # Only import if support is enabled
107
131
  if base_module.is_support_enabled():
108
- from django_cfg.apps.support.models import Ticket
109
132
  self.model = Ticket
110
133
  except (ImportError, Exception):
111
134
  # Support app not available or not enabled
@@ -116,12 +139,19 @@ class UserSupportTicketsInline(TabularInline):
116
139
  super().__init__(*args, **kwargs)
117
140
 
118
141
  extra = 0
119
- readonly_fields = ["uuid", "subject", "status", "created_at"]
120
- fields = ["uuid", "subject", "status", "created_at"]
142
+ readonly_fields = ["uuid", "subject", "status", "priority", "created_at"]
143
+ fields = ["uuid", "subject", "status", "priority", "created_at"]
121
144
  ordering = ["-created_at"]
122
145
  verbose_name = "Support Ticket"
123
146
  verbose_name_plural = "Support Tickets"
124
147
 
148
+ # Show only recent tickets to avoid performance issues
149
+ def get_queryset(self, request):
150
+ if not self.model:
151
+ return self.model.objects.none()
152
+ qs = super().get_queryset(request)
153
+ return qs[:10] # Limit to 10 most recent tickets
154
+
125
155
  def has_add_permission(self, request, obj=None):
126
156
  return False
127
157
 
@@ -133,7 +163,6 @@ class UserSupportTicketsInline(TabularInline):
133
163
  if not self.model:
134
164
  return False
135
165
  try:
136
- from django_cfg.modules.base import BaseCfgModule
137
166
  base_module = BaseCfgModule()
138
167
  return base_module.is_support_enabled()
139
168
  except Exception: