django-cfg 1.2.25__py3-none-any.whl → 1.2.29__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 (37) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/config/providers.py +6 -16
  3. django_cfg/apps/payments/services/providers/cryptomus.py +2 -1
  4. django_cfg/apps/payments/static/payments/css/payments.css +340 -0
  5. django_cfg/apps/payments/static/payments/js/notifications.js +202 -0
  6. django_cfg/apps/payments/static/payments/js/payment-utils.js +318 -0
  7. django_cfg/apps/payments/static/payments/js/theme.js +86 -0
  8. django_cfg/apps/payments/templates/payments/base.html +182 -0
  9. django_cfg/apps/payments/templates/payments/components/payment_card.html +201 -0
  10. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +109 -0
  11. django_cfg/apps/payments/templates/payments/components/progress_bar.html +36 -0
  12. django_cfg/apps/payments/templates/payments/components/provider_stats.html +40 -0
  13. django_cfg/apps/payments/templates/payments/components/status_badge.html +27 -0
  14. django_cfg/apps/payments/templates/payments/components/status_overview.html +144 -0
  15. django_cfg/apps/payments/templates/payments/dashboard.html +346 -0
  16. django_cfg/apps/payments/templatetags/__init__.py +1 -0
  17. django_cfg/apps/payments/templatetags/payments_tags.py +315 -0
  18. django_cfg/apps/payments/urls_templates.py +52 -0
  19. django_cfg/apps/payments/views/templates/__init__.py +25 -0
  20. django_cfg/apps/payments/views/templates/ajax.py +312 -0
  21. django_cfg/apps/payments/views/templates/base.py +204 -0
  22. django_cfg/apps/payments/views/templates/dashboard.py +60 -0
  23. django_cfg/apps/payments/views/templates/payment_detail.py +102 -0
  24. django_cfg/apps/payments/views/templates/payment_management.py +164 -0
  25. django_cfg/apps/payments/views/templates/qr_code.py +174 -0
  26. django_cfg/apps/payments/views/templates/stats.py +240 -0
  27. django_cfg/apps/payments/views/templates/utils.py +181 -0
  28. django_cfg/apps/urls.py +3 -0
  29. django_cfg/models/payments.py +1 -0
  30. django_cfg/registry/core.py +1 -0
  31. django_cfg/template_archive/.gitignore +1 -0
  32. django_cfg/template_archive/django_sample.zip +0 -0
  33. {django_cfg-1.2.25.dist-info → django_cfg-1.2.29.dist-info}/METADATA +12 -15
  34. {django_cfg-1.2.25.dist-info → django_cfg-1.2.29.dist-info}/RECORD +37 -12
  35. {django_cfg-1.2.25.dist-info → django_cfg-1.2.29.dist-info}/WHEEL +0 -0
  36. {django_cfg-1.2.25.dist-info → django_cfg-1.2.29.dist-info}/entry_points.txt +0 -0
  37. {django_cfg-1.2.25.dist-info → django_cfg-1.2.29.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.2.25"
35
+ __version__ = "1.2.29"
36
36
  __license__ = "MIT"
37
37
 
38
38
  # Import registry for organized lazy loading
@@ -7,23 +7,13 @@ Defines configuration classes for different payment providers.
7
7
  from typing import Dict, Any, Optional
8
8
  from pydantic import BaseModel, Field, SecretStr
9
9
 
10
+ # Import the base PaymentProviderConfig from models.payments
11
+ from django_cfg.models.payments import PaymentProviderConfig as BasePaymentProviderConfig
10
12
 
11
- class PaymentProviderConfig(BaseModel):
12
- """Base configuration for payment providers."""
13
- enabled: bool = True
14
- sandbox: bool = Field(default=True, description="Use sandbox mode")
15
- api_key: SecretStr = Field(description="Provider API key")
16
- timeout: int = Field(default=30, description="Request timeout in seconds")
17
- max_retries: int = Field(default=3, description="Maximum retry attempts")
18
-
19
- def get_config_dict(self) -> Dict[str, Any]:
20
- """Get configuration as dictionary for provider initialization."""
21
- return {
22
- 'api_key': self.api_key.get_secret_value(),
23
- 'sandbox': self.sandbox,
24
- 'timeout': self.timeout,
25
- 'max_retries': self.max_retries
26
- }
13
+
14
+ class PaymentProviderConfig(BasePaymentProviderConfig):
15
+ """Extended base configuration for payment providers."""
16
+ pass
27
17
 
28
18
 
29
19
  class NowPaymentsConfig(PaymentProviderConfig):
@@ -13,7 +13,8 @@ from dataclasses import dataclass
13
13
  import requests
14
14
  from pydantic import BaseModel, Field, validator
15
15
 
16
- from .base import PaymentProvider, ProviderResponse, ProviderConfig
16
+ from .base import PaymentProvider, ProviderResponse
17
+ from ..internal_types import ProviderConfig
17
18
 
18
19
  logger = logging.getLogger(__name__)
19
20
 
@@ -0,0 +1,340 @@
1
+ /* Payment System Styles */
2
+
3
+ /* Payment Status Colors */
4
+ .payment-status-pending { @apply bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200; }
5
+ .payment-status-confirming { @apply bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200; }
6
+ .payment-status-confirmed { @apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200; }
7
+ .payment-status-completed { @apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200; }
8
+ .payment-status-failed { @apply bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200; }
9
+ .payment-status-expired { @apply bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200; }
10
+ .payment-status-cancelled { @apply bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200; }
11
+ .payment-status-refunded { @apply bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200; }
12
+
13
+ /* Payment Card Animations */
14
+ .payment-card {
15
+ @apply transition-all duration-200 hover:shadow-lg hover:-translate-y-1;
16
+ }
17
+
18
+ .payment-card:hover {
19
+ @apply ring-2 ring-blue-500 ring-opacity-50;
20
+ }
21
+
22
+ .payment-card.compact {
23
+ @apply p-4;
24
+ }
25
+
26
+ /* Progress Bar Styles */
27
+ .progress-bar {
28
+ @apply w-full bg-gray-200 rounded-full h-2 dark:bg-gray-700 overflow-hidden;
29
+ }
30
+
31
+ .progress-fill {
32
+ @apply bg-blue-600 h-2 rounded-full transition-all duration-500 ease-out;
33
+ }
34
+
35
+ .progress-fill.success {
36
+ @apply bg-green-600;
37
+ }
38
+
39
+ .progress-fill.warning {
40
+ @apply bg-yellow-600;
41
+ }
42
+
43
+ .progress-fill.danger {
44
+ @apply bg-red-600;
45
+ }
46
+
47
+ /* Progress Steps */
48
+ .progress-steps {
49
+ @apply flex justify-between items-center mb-4;
50
+ }
51
+
52
+ .progress-step {
53
+ @apply flex flex-col items-center text-center;
54
+ }
55
+
56
+ .progress-step.completed .step-icon {
57
+ @apply text-green-500;
58
+ }
59
+
60
+ .progress-step.active .step-icon {
61
+ @apply text-blue-500;
62
+ }
63
+
64
+ .step-label {
65
+ @apply text-xs text-gray-500 dark:text-gray-400 mt-1;
66
+ }
67
+
68
+ .step-icon {
69
+ @apply w-8 h-8 flex items-center justify-center rounded-full border-2 border-gray-300 dark:border-gray-600 mb-2;
70
+ }
71
+
72
+ .step-icon.completed {
73
+ @apply border-green-500 bg-green-500 text-white;
74
+ }
75
+
76
+ .step-icon.active {
77
+ @apply border-blue-500 bg-blue-500 text-white;
78
+ }
79
+
80
+ /* Real-time indicators */
81
+ .payment-live-indicator {
82
+ @apply inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800;
83
+ }
84
+
85
+ .payment-live-indicator::before {
86
+ content: '';
87
+ @apply w-2 h-2 bg-green-500 rounded-full mr-2 animate-pulse;
88
+ }
89
+
90
+ /* Status Overview Cards */
91
+ .status-overview {
92
+ @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8;
93
+ }
94
+
95
+ .status-card {
96
+ @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6 transition-all duration-200 hover:shadow-md;
97
+ }
98
+
99
+ .status-card:hover {
100
+ @apply transform scale-105;
101
+ }
102
+
103
+ /* Payment Table Styles */
104
+ .payments-table {
105
+ @apply min-w-full divide-y divide-gray-200 dark:divide-gray-700;
106
+ }
107
+
108
+ .payments-table th {
109
+ @apply px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider;
110
+ }
111
+
112
+ .payments-table td {
113
+ @apply px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white;
114
+ }
115
+
116
+ .payments-table tr:hover {
117
+ @apply bg-gray-50 dark:bg-gray-800;
118
+ }
119
+
120
+ /* Provider Icons */
121
+ .provider-icon {
122
+ @apply w-6 h-6 rounded;
123
+ }
124
+
125
+ .provider-icon.nowpayments {
126
+ @apply bg-orange-500;
127
+ }
128
+
129
+ .provider-icon.cryptapi {
130
+ @apply bg-blue-500;
131
+ }
132
+
133
+ .provider-icon.cryptomus {
134
+ @apply bg-purple-500;
135
+ }
136
+
137
+ .provider-icon.stripe {
138
+ @apply bg-indigo-500;
139
+ }
140
+
141
+ .provider-icon.internal {
142
+ @apply bg-gray-500;
143
+ }
144
+
145
+ /* QR Code Styles */
146
+ .qr-code-container {
147
+ @apply flex flex-col items-center space-y-2 p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700;
148
+ }
149
+
150
+ .qr-code {
151
+ @apply w-32 h-32 bg-gray-100 dark:bg-gray-700 rounded flex items-center justify-center;
152
+ }
153
+
154
+ /* Filter Styles */
155
+ .payment-filters {
156
+ @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6 mb-6;
157
+ }
158
+
159
+ .filter-group {
160
+ @apply flex flex-wrap gap-4 items-center;
161
+ }
162
+
163
+ .filter-input {
164
+ @apply min-w-0 flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-white;
165
+ }
166
+
167
+ .filter-select {
168
+ @apply px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-white;
169
+ }
170
+
171
+ /* Button Styles */
172
+ .btn {
173
+ @apply inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition-colors duration-200;
174
+ }
175
+
176
+ .btn-primary {
177
+ @apply bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2;
178
+ }
179
+
180
+ .btn-secondary {
181
+ @apply bg-gray-600 text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2;
182
+ }
183
+
184
+ .btn-success {
185
+ @apply bg-green-600 text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2;
186
+ }
187
+
188
+ .btn-danger {
189
+ @apply bg-red-600 text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2;
190
+ }
191
+
192
+ .btn-outline {
193
+ @apply border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
194
+ }
195
+
196
+ .btn-sm {
197
+ @apply px-3 py-1.5 text-xs;
198
+ }
199
+
200
+ .btn-lg {
201
+ @apply px-6 py-3 text-base;
202
+ }
203
+
204
+ /* Modal Styles */
205
+ .modal-overlay {
206
+ @apply fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50;
207
+ }
208
+
209
+ .modal-content {
210
+ @apply bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 max-h-screen overflow-y-auto;
211
+ }
212
+
213
+ .modal-header {
214
+ @apply px-6 py-4 border-b border-gray-200 dark:border-gray-700;
215
+ }
216
+
217
+ .modal-body {
218
+ @apply px-6 py-4;
219
+ }
220
+
221
+ .modal-footer {
222
+ @apply px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3;
223
+ }
224
+
225
+ /* Notification Styles */
226
+ .notification {
227
+ @apply max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden;
228
+ }
229
+
230
+ .notification.success {
231
+ @apply border-l-4 border-green-500;
232
+ }
233
+
234
+ .notification.error {
235
+ @apply border-l-4 border-red-500;
236
+ }
237
+
238
+ .notification.warning {
239
+ @apply border-l-4 border-yellow-500;
240
+ }
241
+
242
+ .notification.info {
243
+ @apply border-l-4 border-blue-500;
244
+ }
245
+
246
+ /* Responsive improvements */
247
+ @media (max-width: 768px) {
248
+ .payment-card {
249
+ @apply p-4;
250
+ }
251
+
252
+ .status-overview {
253
+ @apply grid-cols-2 gap-4;
254
+ }
255
+
256
+ .progress-steps {
257
+ @apply hidden;
258
+ }
259
+
260
+ .filter-group {
261
+ @apply flex-col items-stretch;
262
+ }
263
+
264
+ .payments-table {
265
+ @apply text-xs;
266
+ }
267
+
268
+ .payments-table th,
269
+ .payments-table td {
270
+ @apply px-3 py-2;
271
+ }
272
+ }
273
+
274
+ @media (max-width: 480px) {
275
+ .status-overview {
276
+ @apply grid-cols-1;
277
+ }
278
+ }
279
+
280
+ /* Loading animations */
281
+ .skeleton {
282
+ @apply animate-pulse bg-gray-200 dark:bg-gray-700 rounded;
283
+ }
284
+
285
+ .skeleton-text {
286
+ @apply h-4 bg-gray-200 dark:bg-gray-700 rounded;
287
+ }
288
+
289
+ .skeleton-text.w-1/4 {
290
+ @apply w-1/4;
291
+ }
292
+
293
+ .skeleton-text.w-1/2 {
294
+ @apply w-1/2;
295
+ }
296
+
297
+ .skeleton-text.w-3/4 {
298
+ @apply w-3/4;
299
+ }
300
+
301
+ /* Chart styles */
302
+ .chart-container {
303
+ @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6;
304
+ }
305
+
306
+ .chart-legend {
307
+ @apply flex justify-center space-x-6 mt-4;
308
+ }
309
+
310
+ .chart-legend-item {
311
+ @apply flex items-center space-x-2;
312
+ }
313
+
314
+ .chart-legend-color {
315
+ @apply w-3 h-3 rounded-full;
316
+ }
317
+
318
+ /* Dark mode adjustments */
319
+ @media (prefers-color-scheme: dark) {
320
+ .material-icons {
321
+ color: inherit;
322
+ }
323
+ }
324
+
325
+ /* Custom scrollbar */
326
+ .custom-scrollbar::-webkit-scrollbar {
327
+ width: 6px;
328
+ }
329
+
330
+ .custom-scrollbar::-webkit-scrollbar-track {
331
+ @apply bg-gray-100 dark:bg-gray-800;
332
+ }
333
+
334
+ .custom-scrollbar::-webkit-scrollbar-thumb {
335
+ @apply bg-gray-400 dark:bg-gray-600 rounded-full;
336
+ }
337
+
338
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
339
+ @apply bg-gray-500 dark:bg-gray-500;
340
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Notification System for Payment Dashboard
3
+ * Handles toast notifications with auto-dismiss and styling
4
+ */
5
+
6
+ class NotificationManager {
7
+ constructor() {
8
+ this.container = this.getOrCreateContainer();
9
+ this.notifications = new Map();
10
+ this.defaultDuration = 5000; // 5 seconds
11
+ }
12
+
13
+ getOrCreateContainer() {
14
+ let container = document.getElementById('notification-container');
15
+ if (!container) {
16
+ container = document.createElement('div');
17
+ container.id = 'notification-container';
18
+ container.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 z-50 space-y-2';
19
+ document.body.appendChild(container);
20
+ }
21
+ return container;
22
+ }
23
+
24
+ show(message, type = 'info', options = {}) {
25
+ const id = this.generateId();
26
+ const duration = options.duration || this.defaultDuration;
27
+ const persistent = options.persistent || false;
28
+
29
+ const notification = this.createNotificationElement(id, message, type, persistent);
30
+ this.container.appendChild(notification);
31
+ this.notifications.set(id, notification);
32
+
33
+ // Animate in
34
+ requestAnimationFrame(() => {
35
+ notification.classList.add('animate-in');
36
+ });
37
+
38
+ // Auto-dismiss if not persistent
39
+ if (!persistent) {
40
+ setTimeout(() => {
41
+ this.dismiss(id);
42
+ }, duration);
43
+ }
44
+
45
+ return id;
46
+ }
47
+
48
+ createNotificationElement(id, message, type, persistent) {
49
+ const notification = document.createElement('div');
50
+ notification.id = `notification-${id}`;
51
+ notification.className = `notification ${type} transform transition-all duration-300 translate-y-2 opacity-0`;
52
+
53
+ const typeIcons = {
54
+ success: 'check_circle',
55
+ error: 'error',
56
+ warning: 'warning',
57
+ info: 'info'
58
+ };
59
+
60
+ const typeColors = {
61
+ success: 'text-green-600',
62
+ error: 'text-red-600',
63
+ warning: 'text-yellow-600',
64
+ info: 'text-blue-600'
65
+ };
66
+
67
+ notification.innerHTML = `
68
+ <div class="p-4">
69
+ <div class="flex">
70
+ <div class="flex-shrink-0">
71
+ <span class="material-icons ${typeColors[type]}">${typeIcons[type]}</span>
72
+ </div>
73
+ <div class="ml-3 w-0 flex-1">
74
+ <p class="text-sm font-medium text-gray-900 dark:text-white">
75
+ ${this.escapeHtml(message)}
76
+ </p>
77
+ </div>
78
+ ${!persistent ? `
79
+ <div class="ml-4 flex-shrink-0 flex">
80
+ <button class="dismiss-btn bg-white dark:bg-gray-800 rounded-md inline-flex text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" onclick="window.notificationManager.dismiss('${id}')">
81
+ <span class="sr-only">Close</span>
82
+ <span class="material-icons text-sm">close</span>
83
+ </button>
84
+ </div>
85
+ ` : ''}
86
+ </div>
87
+ </div>
88
+ `;
89
+
90
+ // Add CSS class for animation
91
+ notification.style.setProperty('--tw-translate-y', '0.5rem');
92
+
93
+ return notification;
94
+ }
95
+
96
+ dismiss(id) {
97
+ const notification = this.notifications.get(id);
98
+ if (!notification) return;
99
+
100
+ // Animate out
101
+ notification.classList.add('animate-out');
102
+ notification.style.setProperty('--tw-translate-y', '-0.5rem');
103
+ notification.style.opacity = '0';
104
+
105
+ setTimeout(() => {
106
+ if (notification.parentNode) {
107
+ notification.parentNode.removeChild(notification);
108
+ }
109
+ this.notifications.delete(id);
110
+ }, 300);
111
+ }
112
+
113
+ dismissAll() {
114
+ this.notifications.forEach((notification, id) => {
115
+ this.dismiss(id);
116
+ });
117
+ }
118
+
119
+ // Convenience methods
120
+ success(message, options = {}) {
121
+ return this.show(message, 'success', options);
122
+ }
123
+
124
+ error(message, options = {}) {
125
+ return this.show(message, 'error', options);
126
+ }
127
+
128
+ warning(message, options = {}) {
129
+ return this.show(message, 'warning', options);
130
+ }
131
+
132
+ info(message, options = {}) {
133
+ return this.show(message, 'info', options);
134
+ }
135
+
136
+ // Payment-specific notifications
137
+ paymentCreated(paymentId) {
138
+ return this.success(`Payment #${paymentId} created successfully`);
139
+ }
140
+
141
+ paymentCompleted(paymentId) {
142
+ return this.success(`Payment #${paymentId} completed!`);
143
+ }
144
+
145
+ paymentFailed(paymentId, reason = '') {
146
+ const message = `Payment #${paymentId} failed${reason ? ': ' + reason : ''}`;
147
+ return this.error(message);
148
+ }
149
+
150
+ paymentCancelled(paymentId) {
151
+ return this.warning(`Payment #${paymentId} cancelled`);
152
+ }
153
+
154
+ connectionStatus(connected) {
155
+ if (connected) {
156
+ return this.success('Connected to payment system', { duration: 3000 });
157
+ } else {
158
+ return this.error('Connection lost', { persistent: true });
159
+ }
160
+ }
161
+
162
+ // Utility methods
163
+ generateId() {
164
+ return Math.random().toString(36).substr(2, 9);
165
+ }
166
+
167
+ escapeHtml(text) {
168
+ const map = {
169
+ '&': '&amp;',
170
+ '<': '&lt;',
171
+ '>': '&gt;',
172
+ '"': '&quot;',
173
+ "'": '&#039;'
174
+ };
175
+ return text.replace(/[&<>"']/g, (m) => map[m]);
176
+ }
177
+ }
178
+
179
+ // Add CSS animations dynamically
180
+ const style = document.createElement('style');
181
+ style.textContent = `
182
+ .notification.animate-in {
183
+ transform: translateY(0);
184
+ opacity: 1;
185
+ }
186
+
187
+ .notification.animate-out {
188
+ transform: translateY(-0.5rem);
189
+ opacity: 0;
190
+ }
191
+ `;
192
+ document.head.appendChild(style);
193
+
194
+ // Initialize notification manager when DOM is loaded
195
+ document.addEventListener('DOMContentLoaded', () => {
196
+ window.notificationManager = new NotificationManager();
197
+ });
198
+
199
+ // Export for use in other modules
200
+ if (typeof module !== 'undefined' && module.exports) {
201
+ module.exports = NotificationManager;
202
+ }