from django.shortcuts import render from django.views.decorators.csrf import csrf_protect from .forms import SignupForm from django.contrib.auth.models import User from .models import Game from django.views.generic.edit import UpdateView from django.http import HttpResponseRedirect from django.urls import reverse_lazy from django.db.models import Sum, F, DecimalField from .models import ShoppingCart from .models import ShoppingCartItem from .forms import ShoppingCartFormSet from decimal import Decimal from django.shortcuts import get_object_or_404 from django.contrib import messages from django.contrib.auth.decorators import login_required import json import requests from django.core.serializers.json import DjangoJSONEncoder from gamestore import settings from http import HTTPStatus from .models import OrderItem def _prepare_order_data(cart): cart_items = ShoppingCartItem.objects.values_list( 'game__name', 'price_per_unit', 'game__id', 'quantity').filter(cart__id=cart.id) order = cart_items.aggregate( total_order=Sum(F('price_per_unit') * F('quantity'), output_field=DecimalField(decimal_places=2)) ) order_items = [OrderItem(*x)._asdict() for x in cart_items] order_customer = { 'customer_id': cart.user.id, 'email': cart.user.email, 'name': f'{cart.user.first_name} {cart.user.last_name}' } order_dict = { 'items': order_items, 'order_customer': order_customer, 'total': order['total_order'] } return json.dumps(order_dict, cls=DjangoJSONEncoder) @login_required def my_orders(request): headers = { 'Authorization': f'Token {settings.ORDER_SERVICE_AUTHTOKEN}', 'Content-type': 'application/json' } get_order_endpoint = f'/api/customer/{request.user.id}/orders/get/' service_url = f'{settings.ORDER_SERVICE_BASEURL}{get_order_endpoint}' response = requests.get( service_url, headers=headers ) if HTTPStatus(response.status_code) is HTTPStatus.OK: request_data = json.loads(response.text) context = {'orders': request_data} else: messages.add_message( request, messages.ERROR, ('Unfortunately, we could not retrieve your orders.' ' Try again later.')) context = {'orders': []} return render(request, 'main/my-orders.html', context) @login_required def send_cart(request): cart = ShoppingCart.objects.get(user_id=request.user.id) data = _prepare_order_data(cart) headers = { 'Authorization': f'Token {settings.ORDER_SERVICE_AUTHTOKEN}', 'Content-type': 'application/json' } service_url = f'{settings.ORDER_SERVICE_BASEURL}/api/order/add/' response = requests.post( service_url, headers=headers, data=data) if HTTPStatus(response.status_code) is HTTPStatus.CREATED: request_data = json.loads(response.text) ShoppingCart.objects.empty(cart) messages.add_message( request, messages.INFO, ('We received your order!' 'ORDER ID: {}').format(request_data['order_id'])) else: messages.add_message( request, messages.ERROR, ('Unfortunately, we could not receive your order.' ' Try again later.')) return HttpResponseRedirect(reverse_lazy('user-cart')) @login_required def add_to_cart(request, game_id): game = get_object_or_404(Game, pk=game_id) cart = ShoppingCart.objects.get_by_user(request.user) existing_item = ShoppingCartItem.objects.get_existing_item(cart, game) if existing_item is None: price = (Decimal(0) if not hasattr(game, 'pricelist') else game.pricelist.price_per_unit) new_item = ShoppingCartItem( game=game, quantity=1, price_per_unit=price, cart=cart ) new_item.save() else: existing_item.quantity = F('quantity') + 1 existing_item.save() messages.add_message( request, messages.INFO, f'The game {game.name} has been added to your cart.') return HttpResponseRedirect(reverse_lazy('user-cart')) class ShoppingCartEditView(UpdateView): model = ShoppingCart form_class = ShoppingCartFormSet template_name = 'main/cart.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) items = ShoppingCartItem.objects.get_items(self.object) context['is_cart_empty'] = (items.count() == 0) order = items.aggregate( total_order=Sum(F('price_per_unit') * F('quantity'), output_field=DecimalField()) ) context['total_order'] = order['total_order'] return context def get_object(self): try: return ShoppingCart.objects.get_by_user(self.request.user) except ShoppingCart.DoesNotExist: new_cart = ShoppingCart.objects.create_cart(self.request.user) new_cart.save() return new_cart def form_valid(self, form): form.save() return HttpResponseRedirect(reverse_lazy('user-cart')) def index(request): max_highlighted_games = 3 max_game_list = 9 highlighted_games_list = Game.objects.get_highlighted() games_list = Game.objects.get_not_highlighted() show_more_link_highlighted = highlighted_games_list.count() > max_highlighted_games show_more_link_games = games_list.count() > max_game_list context = { 'highlighted_games_list': highlighted_games_list[:max_highlighted_games], 'games_list': games_list[:max_game_list], 'show_more_link_games': show_more_link_games, 'show_more_link_highlighted': show_more_link_highlighted } return render(request, 'main/index.html', context) @csrf_protect def signup(request): if request.method == 'POST': form = SignupForm(request.POST) if form.is_valid(): user = User.objects.create_user( username=form.cleaned_data['username'], first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name'], email=form.cleaned_data['email'], password=form.cleaned_data['password'] ) user.save() return render(request, 'main/create_account_success.html', {}) else: form = SignupForm() return render(request, 'main/signup.html', {'form': form}) def show_all_games(request): games = Game.objects.all() context = {'games': games} return render(request, 'main/all_games.html', context) def show_highlighted_games(request): games = Game.objects.get_highlighted() context = {'games': games} return render(request, 'main/highlighted.html', context)