from ._base import * def store_novawow_cancel_view(request): return render(request, 'store/store_novawow_cancel.html') def store_novawow_view(request): username = request.session.get('username') if not username: return redirect('login') category_name = request.GET.get("category") # Obtener personajes del usuario desde la base de datos acore_characters with connections['acore_characters'].cursor() as cursor: cursor.execute(""" SELECT name FROM characters WHERE account = ( SELECT id FROM acore_auth.account WHERE username = %s ) """, [username]) characters = [row[0] for row in cursor.fetchall()] # Obtener categorías e ítems categories = Category.objects.prefetch_related("items").all() store_data = {category.name: list(category.items.values()) for category in categories} # Si se está solicitando una categoría específica, devolver solo los ítems de esa categoría if category_name: try: category = Category.objects.get(name=category_name) except Category.DoesNotExist: return JsonResponse({'success': False, 'message': 'Categoría no encontrada'}, status=404) return JsonResponse({'success': True, 'items': list(category.items.values())}) # Obtener carrito desde la sesión carrito = request.session.get('carrito', []) # Calcular el precio total con 2 decimales total_price = sum(Decimal(item['precio']) for item in carrito) total_price_with_iva = (total_price * Decimal('1.21')).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) if request.method == 'POST': # Obtener datos del body data = json.loads(request.body) character_name = data.get('character') carrito_cliente = data.get('carrito') or [] if not character_name: return JsonResponse({'success': False, 'message': 'Por favor, selecciona un personaje.'}) # Verificar si el personaje pertenece al usuario if character_name not in characters: return JsonResponse({'success': False, 'message': 'No tienes permiso para este personaje.'}) if not carrito_cliente: return JsonResponse({'success': False, 'message': 'El carrito está vacío.'}) # VALIDAR ÍTEMS Y PRECIOS CONTRA LA BASE DE DATOS (nunca confiar en el # precio ni en los ítems que manda el cliente). try: ids_solicitados = [int(item['id']) for item in carrito_cliente] except (KeyError, TypeError, ValueError): return JsonResponse({'success': False, 'message': 'Carrito no válido.'}) items_db = {i.item_id: i for i in Item.objects.filter(item_id__in=ids_solicitados)} carrito = [] # carrito saneado que se guardará en sesión total_price = Decimal('0.00') for item in carrito_cliente: item_id = int(item['id']) db_item = items_db.get(item_id) if not db_item: return JsonResponse({'success': False, 'message': f'Ítem no disponible en la tienda (ID {item_id}).'}) try: cantidad = max(1, int(item.get('cantidad', 1))) except (TypeError, ValueError): cantidad = 1 total_price += db_item.price * cantidad carrito.append({'id': item_id, 'nombre': db_item.name, 'cantidad': cantidad}) total_price_with_iva = (total_price * Decimal('1.21')).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) # Guardar en sesión el carrito YA VALIDADO (para la entrega tras el pago) request.session['carrito'] = carrito request.session.modified = True # Descripción del producto a partir de los datos validados product_description = ", ".join([f"{it['nombre']} x{it['cantidad']}" for it in carrito]) # Obtener detalles del usuario with connections['acore_auth'].cursor() as cursor: cursor.execute("SELECT id, email, last_ip FROM account WHERE username = %s", [username]) user_data = cursor.fetchone() if not user_data: return JsonResponse({'success': False, 'message': 'Cuenta no encontrada.'}) user_id, email, acore_ip = user_data # ID de la cuenta, email y la última IP # Crear sesión de pago con Stripe success_url = request.build_absolute_uri(reverse('store-novawow/success')) cancel_url = request.build_absolute_uri(reverse('store-novawow/cancel')) # Llamada corregida a create_checkout_session con todos los parámetros requeridos stripe_response = create_checkout_session( username=username, email=email, acore_ip=acore_ip, account_id=user_id, # Pasar el account_id amount=total_price_with_iva, # El precio con IVA character_name=character_name, success_url=success_url, cancel_url=cancel_url, product_name=f"Compra de ítems para el personaje: {character_name} : {product_description}" ) if stripe_response["success"]: request.session['store_novawow'] = character_name return JsonResponse({ 'success': True, 'session_id': stripe_response["session_id"], 'stripe_public_key': settings.STRIPE_PUBLIC_KEY }) else: return JsonResponse({'success': False, 'message': f'Error al iniciar el pago: {stripe_response["error"]}'}) return render(request, 'store/store_novawow.html', { 'characters': characters, 'store_data': store_data, 'categories': categories, 'total_price': total_price_with_iva }) @require_paid_stripe(redirect_to='store-novawow') def store_novawow_success_view(request): # Procesar el comando SOAP tras el pago exitoso character_name = request.session.get('store_novawow') carrito = request.session.get('carrito', []) if not character_name or not carrito: return redirect('store-novawow') # Contar correctamente los ítems por ID item_counts = Counter(item["id"] for item in carrito) # Generar la lista de ítems en formato "ID:Cantidad" items_str = " ".join(f"{item_id}:{count}" for item_id, count in item_counts.items()) # Construir el comando SOAP command = f".send items {character_name} 'Gracias por donar a Nova WoW' 'Aquí tienes tu donación' {items_str}" # Ejecutar el comando SOAP response = execute_soap_command(command) # Limpiar la sesión después del envío request.session.pop('store_novawow', None) request.session.pop('carrito', None) if response is None or response.strip() == "": message = f"Los ítems han sido añadidos al personaje {character_name} correctamente." return render(request, 'store/store_novawow_success.html', {'message': message}) else: return render(request, 'store/store_novawow_success.html', {'message': f"Error: {response}"}) def store_novawow_buscar_categoria_view(request, categoria): try: # Buscar la categoría desde el parámetro de la URL category = Category.objects.get(name=categoria) items = category.items.all().values("id", "name", "price", "image_url") return JsonResponse({"success": True, "items": list(items)}) except Category.DoesNotExist: return JsonResponse({"success": False, "message": "Categoría no encontrada"}, status=404)