Добавлены операции с кошельком клиента: пополнение и возврат
- Добавлены view wallet_deposit и wallet_withdraw с защитой (login_required, is_staff, CSRF) - Новые маршруты: /customers/<pk>/wallet/deposit/ и /customers/<pk>/wallet/withdraw/ - UI на странице клиента: две симметричные формы для пополнения и списания баланса - Пополнение: произвольная сумма с обязательным описанием (подарки, компенсации) - Возврат/списание: с ограничением макс. суммы = текущий баланс, обязательное описание - Все операции логируются в WalletTransaction с типом 'adjustment' - Защита от операций с системным клиентом - Компактный симметричный дизайн форм с фиксированной высотой подсказок
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.contrib import messages
|
||||
from django.core.paginator import Paginator
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.exceptions import ValidationError, PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.contrib.auth.decorators import login_required
|
||||
import phonenumbers
|
||||
import json
|
||||
from decimal import Decimal
|
||||
from .models import Customer
|
||||
from .forms import CustomerForm
|
||||
|
||||
@@ -484,3 +485,72 @@ def api_create_customer(request):
|
||||
'success': False,
|
||||
'error': f'Ошибка сервера: {str(e)}'
|
||||
}, status=500)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["POST"])
|
||||
def wallet_deposit(request, pk):
|
||||
"""Пополнение кошелька клиента"""
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied("У вас нет прав для изменения баланса кошелька клиента.")
|
||||
|
||||
customer = get_object_or_404(Customer, pk=pk)
|
||||
|
||||
if customer.is_system_customer:
|
||||
messages.error(request, 'Операции с кошельком недоступны для системного клиента.')
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
amount_str = request.POST.get('amount') or ''
|
||||
description = (request.POST.get('description') or '').strip()
|
||||
|
||||
try:
|
||||
amount = Decimal(amount_str.replace(',', '.'))
|
||||
except Exception:
|
||||
messages.error(request, 'Некорректное значение суммы для пополнения.')
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
try:
|
||||
customer.adjust_wallet(amount, description, request.user)
|
||||
messages.success(request, f'Кошелёк клиента пополнен на {amount:.2f} руб.')
|
||||
except ValueError as e:
|
||||
messages.error(request, str(e))
|
||||
except ValidationError as e:
|
||||
messages.error(request, '; '.join(e.messages) if hasattr(e, 'messages') else str(e))
|
||||
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["POST"])
|
||||
def wallet_withdraw(request, pk):
|
||||
"""Возврат / списание с кошелька клиента"""
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied("У вас нет прав для изменения баланса кошелька клиента.")
|
||||
|
||||
customer = get_object_or_404(Customer, pk=pk)
|
||||
|
||||
if customer.is_system_customer:
|
||||
messages.error(request, 'Операции с кошельком недоступны для системного клиента.')
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
amount_str = request.POST.get('amount') or ''
|
||||
description = (request.POST.get('description') or '').strip()
|
||||
|
||||
try:
|
||||
amount = Decimal(amount_str.replace(',', '.'))
|
||||
except Exception:
|
||||
messages.error(request, 'Некорректное значение суммы для списания.')
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
# Для списания делаем сумму отрицательной
|
||||
withdraw_amount = -amount
|
||||
|
||||
try:
|
||||
customer.adjust_wallet(withdraw_amount, description, request.user)
|
||||
messages.success(request, f'С кошелька клиента списано {amount:.2f} руб.')
|
||||
except ValueError as e:
|
||||
messages.error(request, str(e))
|
||||
except ValidationError as e:
|
||||
messages.error(request, '; '.join(e.messages) if hasattr(e, 'messages') else str(e))
|
||||
|
||||
return redirect('customers:customer-detail', pk=pk)
|
||||
|
||||
Reference in New Issue
Block a user