from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import ListView, DetailView from django.contrib import messages from django.contrib.auth import login from django.contrib.auth.decorators import login_required from django.db.models import Q, Avg, Count from django.db import transaction # from rest_framework import viewsets # Temporär auskommentiert # from rest_framework.permissions import IsAuthenticatedOrReadOnly # Temporär auskommentiert from .models import Product, Cart, CartItem, Order, OrderItem, Review, UserProfile, Wishlist, FAQ, ContactMessage, CustomOrder, OrderProgress, GalleryImage, Category from .forms import OrderForm, CustomUserCreationForm, CustomAuthenticationForm, ReviewForm, UserProfileForm, ContactForm, CustomOrderForm, OrderProgressForm # from .serializers import ProductSerializer, ReviewSerializer # Temporär auskommentiert import stripe from django.conf import settings from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.utils import timezone from django.core.mail import send_mail from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage import json # import paypalrestsdk # Temporär auskommentiert # from payments import get_payment_model, RedirectNeeded # Temporär auskommentiert # from paypal.standard.ipn.models import PayPalIPN # Temporär auskommentiert from django.urls import reverse from django.http import HttpResponse # from paypal.standard.forms import PayPalPaymentsForm # Temporär auskommentiert import logging from django.core.exceptions import ValidationError from django.http import Http404 logger = logging.getLogger(__name__) # Create your views here. class ProductListView(ListView): model = Product template_name = 'products/product_list.html' context_object_name = 'products' paginate_by = 12 def get_queryset(self): try: queryset = Product.objects.all().annotate( average_rating=Avg('reviews__rating'), review_count=Count('reviews') ).select_related('category').prefetch_related( 'reviews__user', # Optimiert N+1 Queries für Reviews 'wishlist_users' # Optimiert Wishlist-Queries ) # Erweiterte Suchfilter search_query = self.request.GET.get('search') if search_query: # Verbesserte Suche mit Q-Objekten search_terms = search_query.split() q_objects = Q() for term in search_terms: q_objects |= ( Q(name__icontains=term) | Q(description__icontains=term) | Q(fursuit_type__icontains=term) | Q(style__icontains=term) | Q(category__name__icontains=term) ) queryset = queryset.filter(q_objects) # Preisbereich Filter mit Validierung min_price = self.request.GET.get('min_price') max_price = self.request.GET.get('max_price') if min_price and min_price.isdigit(): queryset = queryset.filter(price__gte=float(min_price)) if max_price and max_price.isdigit(): queryset = queryset.filter(price__lte=float(max_price)) # Fursuit-Typ Filter fursuit_type = self.request.GET.get('fursuit_type') if fursuit_type: queryset = queryset.filter(fursuit_type=fursuit_type) # Style Filter style = self.request.GET.get('style') if style: queryset = queryset.filter(style=style) # Kategorie Filter category = self.request.GET.get('category') if category: queryset = queryset.filter(category__slug=category) # Verfügbarkeit Filter availability = self.request.GET.get('availability') if availability == 'in_stock': queryset = queryset.filter(stock__gt=0) elif availability == 'low_stock': queryset = queryset.filter(stock__lte=5, stock__gt=0) elif availability == 'out_of_stock': queryset = queryset.filter(stock=0) # Sortierung mit verbesserter Performance sort = self.request.GET.get('sort', '-created') if sort == 'price': queryset = queryset.order_by('price') elif sort == '-price': queryset = queryset.order_by('-price') elif sort == 'name': queryset = queryset.order_by('name') elif sort == '-name': queryset = queryset.order_by('-name') elif sort == '-rating': queryset = queryset.order_by('-average_rating') elif sort == 'popularity': queryset = queryset.order_by('-review_count') else: # Default: Neueste zuerst queryset = queryset.order_by('-created') return queryset.distinct() except Exception as e: logger.error(f"Error in ProductListView.get_queryset: {e}") return Product.objects.none() def get_context_data(self, **kwargs): try: context = super().get_context_data(**kwargs) # Zusätzliche Context-Daten context['categories'] = Category.objects.all() context['fursuit_types'] = Product.FURSUIT_TYPE_CHOICES context['styles'] = Product.STYLE_CHOICES return context except Exception as e: logger.error(f"Error in ProductListView.get_context_data: {e}") return super().get_context_data(**kwargs) class ProductDetailView(DetailView): model = Product template_name = 'products/product_detail.html' context_object_name = 'product' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.request.user.is_authenticated: context['user_has_reviewed'] = Review.objects.filter( product=self.object, user=self.request.user ).exists() context['review_form'] = ReviewForm() return context def get_or_create_cart(request): if request.user.is_authenticated: cart, created = Cart.objects.get_or_create(user=request.user) else: session_key = request.session.session_key if not session_key: request.session.create() session_key = request.session.session_key cart, created = Cart.objects.get_or_create(session_id=session_key) return cart def add_to_cart(request, product_id): if request.method == 'POST': product = get_object_or_404(Product, id=product_id) quantity = int(request.POST.get('quantity', 1)) if quantity > product.stock: messages.error(request, 'Nicht genügend Artikel auf Lager!') return redirect('products:product_detail', pk=product_id) cart = get_or_create_cart(request) cart_item, created = CartItem.objects.get_or_create( cart=cart, product=product, defaults={'quantity': quantity} ) if not created: cart_item.quantity += quantity cart_item.save() messages.success(request, f'{quantity}x {product.name} wurde zum Warenkorb hinzugefügt.') return redirect('products:cart_detail') def cart_detail(request): cart = get_or_create_cart(request) return render(request, 'products/cart_detail.html', {'cart': cart}) def create_order(request): if request.method == 'POST': cart = get_or_create_cart(request) if not cart.items.exists(): messages.error(request, 'Ihr Warenkorb ist leer.') return redirect('products:cart_detail') # Erstelle eine neue Bestellung order = Order.objects.create( user=request.user if request.user.is_authenticated else None, full_name=f"{request.user.first_name} {request.user.last_name}" if request.user.is_authenticated else "", email=request.user.email if request.user.is_authenticated else "", total_amount=cart.get_total() ) # Füge die Artikel aus dem Warenkorb zur Bestellung hinzu for cart_item in cart.items.all(): OrderItem.objects.create( order=order, product=cart_item.product, product_name=cart_item.product.name, quantity=cart_item.quantity, price=cart_item.product.price ) # Leere den Warenkorb cart.items.all().delete() messages.success(request, 'Ihre Bestellung wurde erfolgreich erstellt.') return redirect('products:checkout', order_id=order.id) return redirect('products:cart_detail') @login_required def checkout(request, order_id): order = get_object_or_404(Order, id=order_id) if request.user.is_authenticated and order.user != request.user: messages.error(request, 'Sie haben keine Berechtigung, diese Bestellung einzusehen.') return redirect('products:product_list') # PayPal Zahlungsformular erstellen host = request.get_host() paypal_dict = { "business": settings.PAYPAL_RECEIVER_EMAIL, "amount": str(order.total_amount), "item_name": f"Bestellung #{order.id}", "invoice": str(order.id), "currency_code": "EUR", "notify_url": request.build_absolute_uri('/paypal/'), "return_url": request.build_absolute_uri(f'/products/payment/success/{order.id}/'), "cancel_return": request.build_absolute_uri(f'/products/payment/failed/{order.id}/'), } form = PayPalPaymentsForm(initial=paypal_dict) return render(request, 'products/checkout.html', { 'order': order, 'form': form }) @csrf_exempt @login_required def create_paypal_order(request): if request.method != 'POST': return JsonResponse({'error': 'Nur POST-Anfragen erlaubt'}, status=405) data = json.loads(request.body) order = get_object_or_404(Order, id=data['order_id'], user=request.user) payment = paypalrestsdk.Payment({ "intent": "sale", "payer": { "payment_method": "paypal" }, "transactions": [{ "amount": { "total": str(order.total_amount), "currency": "EUR" }, "description": f"Bestellung #{order.id}" }], "redirect_urls": { "return_url": f"{settings.SITE_URL}/products/order/confirmation/{order.id}/", "cancel_url": f"{settings.SITE_URL}/products/checkout/{order.id}/" } }) if payment.create(): return JsonResponse({'paypal_order_id': payment.id}) else: return JsonResponse({'error': payment.error}, status=400) @csrf_exempt @login_required def capture_paypal_order(request): if request.method != 'POST': return JsonResponse({'error': 'Nur POST-Anfragen erlaubt'}, status=405) data = json.loads(request.body) order = get_object_or_404(Order, id=data['order_id'], user=request.user) payment_id = data['paypal_order_id'] payment = paypalrestsdk.Payment.find(payment_id) if payment.execute({'payer_id': payment.payer.payer_info.payer_id}): order.status = 'paid' order.payment_id = payment_id order.save() # E-Mail-Bestätigung senden send_payment_confirmation_email(order) return JsonResponse({'success': True}) else: return JsonResponse({'error': payment.error}, status=400) def order_confirmation(request, order_id): order = get_object_or_404(Order, id=order_id) if request.user.is_authenticated and order.user != request.user: messages.error(request, 'Sie haben keine Berechtigung, diese Bestellung einzusehen.') return redirect('products:product_list') return render(request, 'products/order_confirmation.html', {'order': order}) def update_cart_item(request, item_id): if request.method == 'POST': cart_item = get_object_or_404(CartItem, id=item_id) quantity = int(request.POST.get('quantity', 1)) if quantity > cart_item.product.stock: messages.error(request, 'Nicht genügend Artikel auf Lager!') elif quantity > 0: cart_item.quantity = quantity cart_item.save() messages.success(request, 'Warenkorb wurde aktualisiert.') else: cart_item.delete() messages.success(request, 'Artikel wurde aus dem Warenkorb entfernt.') return redirect('products:cart_detail') def remove_from_cart(request, item_id): if request.method == 'POST': cart_item = get_object_or_404(CartItem, id=item_id) cart_item.delete() messages.success(request, 'Artikel wurde aus dem Warenkorb entfernt.') return redirect('products:cart_detail') def register(request): if request.method == 'POST': form = CustomUserCreationForm(request.POST) if form.is_valid(): user = form.save() login(request, user) messages.success(request, 'Registrierung erfolgreich!') return redirect('products:product_list') else: form = CustomUserCreationForm() return render(request, 'registration/register.html', {'form': form}) @login_required def add_review(request, product_id): product = get_object_or_404(Product, id=product_id) if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid(): review = form.save(commit=False) review.product = product review.user = request.user review.save() messages.success(request, 'Ihre Bewertung wurde erfolgreich hinzugefügt.') else: messages.error(request, 'Es gab einen Fehler beim Hinzufügen Ihrer Bewertung.') return redirect('product_detail', pk=product_id) @login_required def profile_view(request): if request.method == 'POST': form = UserProfileForm(request.POST, instance=request.user.userprofile) if form.is_valid(): form.save() messages.success(request, 'Profil wurde erfolgreich aktualisiert.') return redirect('products:profile') else: form = UserProfileForm(instance=request.user.userprofile) return render(request, 'products/profile.html', {'form': form}) @login_required def order_history(request): orders = Order.objects.filter(user=request.user).order_by('-created') return render(request, 'products/order_history.html', {'orders': orders}) @login_required def wishlist_view(request): wishlist, created = Wishlist.objects.get_or_create(user=request.user) return render(request, 'products/wishlist.html', {'wishlist': wishlist}) @login_required def add_to_wishlist(request, product_id): product = get_object_or_404(Product, id=product_id) wishlist, created = Wishlist.objects.get_or_create(user=request.user) wishlist.products.add(product) messages.success(request, f'{product.name} wurde zu Ihrer Wunschliste hinzugefügt.') return redirect('product_detail', product_id=product_id) @login_required def remove_from_wishlist(request, product_id): product = get_object_or_404(Product, id=product_id) wishlist = get_object_or_404(Wishlist, user=request.user) wishlist.products.remove(product) messages.success(request, f'{product.name} wurde von Ihrer Wunschliste entfernt.') return redirect('wishlist') def faq_list(request): faqs = FAQ.objects.all() categories = FAQ.objects.values_list('category', flat=True).distinct() return render(request, 'products/faq.html', { 'faqs': faqs, 'categories': categories }) def contact(request): if request.method == 'POST': form = ContactForm(request.POST, user=request.user) if form.is_valid(): contact_message = form.save(commit=False) if request.user.is_authenticated: contact_message.user = request.user contact_message.save() messages.success( request, 'Vielen Dank für Ihre Nachricht! Wir werden uns schnellstmöglich bei Ihnen melden.' ) return redirect('contact_success') else: form = ContactForm(user=request.user) return render(request, 'products/contact.html', {'form': form}) def contact_success(request): return render(request, 'products/contact_success.html') @login_required def custom_order(request): if request.method == 'POST': form = CustomOrderForm(request.POST, request.FILES) if form.is_valid(): custom_order = form.save(commit=False) custom_order.user = request.user custom_order.save() messages.success( request, 'Ihre Anfrage wurde erfolgreich übermittelt. Wir werden uns in Kürze mit einem Angebot bei Ihnen melden.' ) return redirect('custom_order_success', order_id=custom_order.id) else: form = CustomOrderForm() return render(request, 'products/custom_order.html', { 'form': form }) @login_required def custom_order_success(request, order_id): order = get_object_or_404(CustomOrder, id=order_id, user=request.user) return render(request, 'products/custom_order_success.html', { 'order': order }) @login_required def custom_order_detail(request, order_id): order = get_object_or_404(CustomOrder, id=order_id, user=request.user) progress_updates = order.progress_updates.all() return render(request, 'products/custom_order_detail.html', { 'order': order, 'progress_updates': progress_updates }) def gallery(request): # Hole alle Galeriebilder images = GalleryImage.objects.all().order_by('order', '-created') # Filter nach Typ fursuit_type = request.GET.get('fursuit_type') if fursuit_type: images = images.filter(fursuit_type=fursuit_type) # Filter nach Stil style = request.GET.get('style') if style: images = images.filter(style=style) # Sortierung sort = request.GET.get('sort', 'order') if sort == 'newest': images = images.order_by('-created') elif sort == 'oldest': images = images.order_by('created') context = { 'images': images, 'fursuit_types': GalleryImage.FURSUIT_TYPE_CHOICES, 'fursuit_styles': GalleryImage.STYLE_CHOICES, 'current_type': fursuit_type, 'current_style': style, 'current_sort': sort } print(f"Anzahl der geladenen Bilder: {images.count()}") # Debug-Ausgabe for img in images: print(f"Bild: {img.title}, URL: {img.image.url}") # Debug-Ausgabe return render(request, 'products/gallery.html', context) @login_required def add_progress_update(request, order_id): order = get_object_or_404(CustomOrder, id=order_id) if not request.user.is_staff: messages.error(request, 'Sie haben keine Berechtigung für diese Aktion.') return redirect('custom_order_detail', order_id=order_id) if request.method == 'POST': form = OrderProgressForm(request.POST, request.FILES) if form.is_valid(): progress = form.save(commit=False) progress.custom_order = order progress.save() messages.success(request, 'Fortschritts-Update wurde hinzugefügt.') # Wenn alle Schritte abgeschlossen sind, setze den Status auf "ready" if all(update.completed for update in order.progress_updates.all()): order.status = 'ready' order.save() return redirect('custom_order_detail', order_id=order_id) else: form = OrderProgressForm() return render(request, 'products/add_progress.html', { 'form': form, 'order': order }) @login_required def dashboard(request): # Basis-Informationen user_profile = request.user.userprofile wishlist = Wishlist.objects.get_or_create(user=request.user)[0] cart = get_or_create_cart(request) # Custom Orders mit Fortschritt custom_orders = CustomOrder.objects.filter(user=request.user).order_by('-created') for order in custom_orders: order.progress_percentage = calculate_order_progress(order) # Letzte Bestellungen mit Details recent_orders = Order.objects.filter(user=request.user).order_by('-created')[:5] for order in recent_orders: order.items_count = order.items.count() # Bewertungsübersicht reviews = Review.objects.filter(user=request.user).select_related('product').order_by('-created')[:5] # Statistiken stats = { 'total_orders': Order.objects.filter(user=request.user).count(), 'total_custom_orders': CustomOrder.objects.filter(user=request.user).count(), 'total_reviews': Review.objects.filter(user=request.user).count(), 'wishlist_count': wishlist.products.count(), } return render(request, 'products/dashboard.html', { 'user_profile': user_profile, 'custom_orders': custom_orders, 'recent_orders': recent_orders, 'reviews': reviews, 'stats': stats, 'wishlist': wishlist, 'cart': cart, }) def calculate_order_progress(order): """Berechne den Fortschritt einer Custom Order in Prozent.""" if order.status == 'cancelled': return 0 elif order.status == 'completed': return 100 # Status-Gewichtung status_weights = { 'pending': 10, 'quoted': 20, 'approved': 30, 'in_progress': 50, 'ready': 90, 'shipped': 95, } base_progress = status_weights.get(order.status, 0) # Zusätzlicher Fortschritt basierend auf OrderProgress if order.status == 'in_progress': completed_stages = order.progress_updates.filter(completed=True).count() total_stages = len(OrderProgress.PROGRESS_CHOICES) stage_progress = (completed_stages / total_stages) * 40 # 40% für Fortschrittsstufen return base_progress + stage_progress return base_progress # API ViewSets - Temporär auskommentiert # class ProductViewSet(viewsets.ModelViewSet): # queryset = Product.objects.all() # serializer_class = ProductSerializer # permission_classes = [IsAuthenticatedOrReadOnly] # class ReviewViewSet(viewsets.ModelViewSet): # queryset = Review.objects.all() # serializer_class = ReviewSerializer # permission_classes = [IsAuthenticatedOrReadOnly] # def perform_create(self, serializer): # serializer.save(user=self.request.user) # Stripe-Konfiguration stripe.api_key = settings.STRIPE_SECRET_KEY def create_payment_intent(request, order_id): """Erstellt einen Stripe Payment Intent für eine Bestellung.""" try: order = get_object_or_404(Order, id=order_id) # Stripe akzeptiert nur Cent-Beträge amount = int(order.total_amount * 100) # Payment Intent erstellen intent = stripe.PaymentIntent.create( amount=amount, currency='eur', metadata={ 'order_id': order.id, 'user_id': request.user.id if request.user.is_authenticated else None } ) # Order aktualisieren order.stripe_payment_intent_id = intent.id order.save() return JsonResponse({ 'clientSecret': intent.client_secret, 'amount': amount }) except Exception as e: return JsonResponse({'error': str(e)}, status=400) def payment_view(request, order_id): """Zeigt die Zahlungsseite an.""" order = get_object_or_404(Order, id=order_id) # Überprüfen, ob die Bestellung dem Benutzer gehört if request.user.is_authenticated and order.user != request.user: messages.error(request, 'Sie haben keine Berechtigung für diese Bestellung.') return redirect('dashboard') # Überprüfen, ob die Bestellung bereits bezahlt wurde if order.payment_status == 'paid': messages.info(request, 'Diese Bestellung wurde bereits bezahlt.') return redirect('order_detail', order_id=order.id) context = { 'order': order, 'stripe_publishable_key': settings.STRIPE_PUBLISHABLE_KEY } return render(request, 'products/payment.html', context) @csrf_exempt def stripe_webhook(request): """Webhook für Stripe-Events.""" payload = request.body sig_header = request.META.get('HTTP_STRIPE_SIGNATURE') try: event = stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_WEBHOOK_SECRET ) except ValueError as e: return JsonResponse({'error': 'Invalid payload'}, status=400) except stripe.error.SignatureVerificationError as e: return JsonResponse({'error': 'Invalid signature'}, status=400) if event.type == 'payment_intent.succeeded': payment_intent = event.data.object handle_successful_payment(payment_intent) elif event.type == 'payment_intent.payment_failed': payment_intent = event.data.object handle_failed_payment(payment_intent) return JsonResponse({'status': 'success'}) def handle_successful_payment(payment_intent): """Verarbeitet erfolgreiche Zahlungen.""" order_id = payment_intent.metadata.get('order_id') if order_id: try: order = Order.objects.get(id=order_id) order.payment_status = 'paid' order.payment_date = timezone.now() order.status = 'processing' order.stripe_payment_method_id = payment_intent.payment_method order.save() # E-Mail-Benachrichtigung senden send_payment_confirmation_email(order) except Order.DoesNotExist: print(f"Bestellung {order_id} nicht gefunden") def handle_failed_payment(payment_intent): """Verarbeitet fehlgeschlagene Zahlungen.""" order_id = payment_intent.metadata.get('order_id') if order_id: try: order = Order.objects.get(id=order_id) order.payment_status = 'failed' order.save() # E-Mail-Benachrichtigung senden send_payment_failed_email(order) except Order.DoesNotExist: print(f"Bestellung {order_id} nicht gefunden") @login_required def payment_success(request, order_id): """Zeigt die Erfolgsseite nach erfolgreicher Zahlung an.""" order = get_object_or_404(Order, id=order_id, user=request.user) messages.success(request, 'Ihre Zahlung wurde erfolgreich verarbeitet!') return render(request, 'products/payment_success.html', {'order': order}) @login_required def payment_failed(request, order_id): """Zeigt die Fehlerseite nach fehlgeschlagener Zahlung an.""" order = get_object_or_404(Order, id=order_id, user=request.user) messages.error(request, 'Die Zahlung konnte nicht verarbeitet werden. Bitte versuchen Sie es erneut.') return render(request, 'products/payment_failed.html', {'order': order}) # Hilfsfunktionen für E-Mail-Benachrichtigungen def send_payment_confirmation_email(order): """Sendet eine Bestätigungs-E-Mail nach erfolgreicher Zahlung.""" subject = f'Zahlungsbestätigung für Bestellung #{order.id}' message = f""" Sehr geehrte(r) {order.full_name}, vielen Dank für Ihre Zahlung. Ihre Bestellung #{order.id} wurde erfolgreich bezahlt. Bestelldetails: - Gesamtbetrag: {order.total_amount} € - Zahlungsmethode: {order.get_payment_method_display()} - Zahlungsdatum: {order.payment_date.strftime('%d.%m.%Y %H:%M')} Wir werden Ihre Bestellung schnellstmöglich bearbeiten. Mit freundlichen Grüßen Ihr Fursuit-Shop Team """ send_mail( subject, message, settings.DEFAULT_FROM_EMAIL, [order.email], fail_silently=False, ) def send_payment_failed_email(order): """Sendet eine Benachrichtigung nach fehlgeschlagener Zahlung.""" subject = f'Zahlungsproblem bei Bestellung #{order.id}' message = f""" Sehr geehrte(r) {order.full_name}, leider ist die Zahlung für Ihre Bestellung #{order.id} fehlgeschlagen. Sie können die Zahlung unter folgendem Link erneut versuchen: {settings.SITE_URL}/payment/{order.id}/ Falls Sie Fragen haben, kontaktieren Sie uns bitte. Mit freundlichen Grüßen Ihr Fursuit-Shop Team """ send_mail( subject, message, settings.DEFAULT_FROM_EMAIL, [order.email], fail_silently=False, ) @login_required def payment_process(request, order_id): order = get_object_or_404(Order, id=order_id, user=request.user) if request.method == 'POST': # Initiiere PayPal-Zahlung paypal_dict = { "business": settings.PAYPAL_RECEIVER_EMAIL, "amount": str(order.total_amount), "item_name": f"Bestellung #{order.id}", "invoice": str(order.id), "notify_url": request.build_absolute_uri(reverse('paypal-ipn')), "return_url": request.build_absolute_uri(reverse('payment_success', args=[order.id])), "cancel_return": request.build_absolute_uri(reverse('payment_failed', args=[order.id])), "custom": json.dumps({ "order_id": order.id, "user_id": request.user.id, }) } form = PayPalPaymentsForm(initial=paypal_dict) return render(request, 'products/payment_process.html', {'order': order, 'form': form}) return render(request, 'products/payment_process.html', {'order': order}) @csrf_exempt def paypal_ipn(request): """PayPal IPN (Instant Payment Notification) Handler""" if request.method == "POST": try: ipn_obj = PayPalIPN(request.POST) ipn_obj.verify() if ipn_obj.payment_status == "Completed": # Zahlung war erfolgreich try: order = Order.objects.get(id=ipn_obj.invoice) order.status = 'paid' order.payment_method = 'paypal' order.payment_id = ipn_obj.txn_id order.save() # Sende Bestätigungs-E-Mail send_payment_confirmation_email(order) except Order.DoesNotExist: pass return HttpResponse("OK") except Exception as e: return HttpResponse(str(e)) return HttpResponse("OK")