def create(self, request): """ Add an item to the basket """ variant_id = request.data.get("variant_id", None) if variant_id is not None: variant = ProductVariant.objects.get(id=variant_id) quantity = int(request.data.get("quantity", 1)) items, bid = utils.get_basket_items(request) # Check if the variant is already in the basket in_basket = False for item in items: if item.variant.id == variant.id: item.increase_quantity(quantity) in_basket = True break if not in_basket: item = BasketItem(variant=variant, quantity=quantity, basket_id=bid) item.save() serializer = BasketItemSerializer(self.get_queryset(request), many=True) response = Response(data=serializer.data, status=status.HTTP_201_CREATED) else: response = Response({"message": "Missing 'variant_id'"}, status=status.HTTP_400_BAD_REQUEST) return response
def get_context_data(self, **kwargs): context = super(CheckoutView, self).get_context_data(**kwargs) items, _ = get_basket_items(self.request) total_price = sum(item.total() for item in items) site = getattr(self.request, 'site', None) context['checkout_form'] = self.checkout_form(self.request.POST or None) context['shipping_form'] = self.shipping_address_form( self.request.POST or None, prefix='shipping', site=site) context['basket'] = items context['total_price'] = total_price return context
def get_context_data(self, **kwargs): context = super(CheckoutView, self).get_context_data(**kwargs) items, _ = get_basket_items(self.request) total_price = sum(item.total() for item in items) discount = Discount.objects.filter(basket_id=basket_id(self.request), order=None).last() discount_total_price, discount_total_saved = discount_total( total_price, discount) site = getattr(self.request, 'site', None) context['checkout_form'] = self.checkout_form(self.request.POST or None) context['shipping_form'] = self.shipping_address_form( self.request.POST or None, prefix='shipping', site=site) context['billing_form'] = self.billing_address_form(self.request.POST or None, prefix='billing', site=site) context['basket'] = items default_shipping_rate = ShippingRate.objects.first().rate total_price = sum(item.total() for item in items) discount = Discount.objects.filter(basket_id=basket_id(self.request), order=None).last() discount_total_price, discount_total_saved = discount_total( total_price + default_shipping_rate, discount) context['total_price'] = total_price context['discount'] = discount context['discount_total_price'] = round(discount_total_price, 2) context['discount_total_saved'] = round(discount_total_saved, 2) context['default_shipping_rate'] = round(default_shipping_rate, 2) context['discount_plus_shipping'] = round( discount_total_price + default_shipping_rate, 2) context['total_plus_shipping'] = round( total_price + default_shipping_rate, 2) return context
def get_queryset(self, request=None): items, _ = utils.get_basket_items(request or self.request) return items
def verify_discount_code(request): # check that we got the 'code' from the request if code := request.POST.get('code'): # check if the discount code exists try: coupon = Coupon.objects.get(code=code) except Exception as e: return JsonResponse({ 'success': False, 'code': 'DOES_NOT_EXIST', 'reason': 'There is no existing match for the submitted code', }) else: # check if the coupon has expired if coupon.expiry_date < timezone.now( ) and not coupon.infinite_redemptions: return JsonResponse({ 'success': False, 'code': 'EXPIRED', 'reason': 'This discount code has past its expiry date', 'coupon': { 'type': coupon.discount_type, 'value': coupon.discount_value, 'description': coupon.description, 'expiry_date': coupon.expiry_date, } }) # check if the coupons amount of times the coupon has been redeemed exceeds # the max amount of times it can be redeemed if coupon.depleted: return JsonResponse({ 'success': False, 'code': 'DEPLETED', 'reason': 'This discount code has no more uses available', 'coupon': { 'type': coupon.discount_type, 'value': coupon.discount_value, 'description': coupon.description, 'max_redemptions': coupon.max_redemptions, 'redemptions': coupon.redemptions, 'expiry_date': coupon.expiry_date, } }) items, bid = get_basket_items(request) # check if the current basket id already has a discount associated with it # get (or create) the Discount object # is the object that tracks the transaction of actually using the code form the coupon # the order will be attached later when the order is completed try: discount = Discount.objects.get( basket_id=bid, # coupon=coupon, order=None, ) discount.coupon = coupon discount.save() except Discount.DoesNotExist: discount = Discount( basket_id=bid, coupon=coupon, order=None, ) discount.save() # get the total price from the items in the basket and run them through the discount total_price = sum(item.total() for item in items) if shipping_rate_id := request.POST.get('shipping'): try: shipping_rate = ShippingRate.objects.get( id=shipping_rate_id) except ShippingRate.DoesNotExist: # don't worry that it doesn't exist, just move along print('couldn\'t find a shipping rate') pass else: total_price += shipping_rate.rate discount_total_price, discount_total_saved = discount_total( total_price, discount) return JsonResponse({ 'success': True, 'code': 'VALID', 'reason': 'This discount code is valid', 'coupon': { 'type': coupon.discount_type, 'value': coupon.discount_value, 'description': coupon.description, 'max_redemptions': coupon.max_redemptions, 'redemptions': coupon.redemptions, 'expiry_date': coupon.expiry_date, 'discount_total_price': discount_total_price, 'discount_total_saved': discount_total_saved, } })
def basket(context): """ Return the BasketItems in the current basket """ items, _ = get_basket_items(context["request"]) return items
def basket_count(context): items, _ = get_basket_items(context["request"]) return len(list(items))
def create_order(email, request, addresses=None, shipping_address=None, billing_address=None, shipping_option=None, capture_payment=False): """ Create an order from a basket and customer infomation """ basket_items, _ = get_basket_items(request) if addresses: # Longclaw < 0.2 used 'shipping_name', longclaw > 0.2 uses a consistent # prefix (shipping_address_xxxx) try: shipping_name = addresses['shipping_name'] except KeyError: shipping_name = addresses['shipping_address_name'] shipping_country = addresses['shipping_address_country'] if not shipping_country: shipping_country = None shipping_address, _ = Address.objects.get_or_create( name=shipping_name, line_1=addresses['shipping_address_line1'], city=addresses['shipping_address_city'], postcode=addresses['shipping_address_zip'], country=shipping_country) shipping_address.save() try: billing_name = addresses['billing_name'] except KeyError: billing_name = addresses['billing_address_name'] billing_country = addresses['shipping_address_country'] if not billing_country: billing_country = None billing_address, _ = Address.objects.get_or_create( name=billing_name, line_1=addresses['billing_address_line1'], city=addresses['billing_address_city'], postcode=addresses['billing_address_zip'], country=billing_country) billing_address.save() else: shipping_country = shipping_address.country ip_address = get_real_ip(request) if shipping_country and shipping_option: site_settings = Configuration.for_site(request.site) shipping_rate = get_shipping_cost(site_settings, shipping_address.country.pk, shipping_option)['rate'] else: shipping_rate = Decimal(0) order = Order(email=email, ip_address=ip_address, shipping_address=shipping_address, billing_address=billing_address, shipping_rate=shipping_rate) order.save() # Create the order items & compute total total = 0 for item in basket_items: total += item.total() order_item = OrderItem(product=item.variant, quantity=item.quantity, order=order) order_item.save() if capture_payment: desc = 'Payment from {} for order id #{}'.format(email, order.id) try: transaction_id = GATEWAY.create_payment(request, total + shipping_rate, description=desc) order.payment_date = timezone.now() order.transaction_id = transaction_id # Once the order has been successfully taken, we can empty the basket destroy_basket(request) except PaymentError: order.status = order.FAILURE order.save() return order
def get_context_data(self, **kwargs): items, _ = utils.get_basket_items(self.request) total_price = sum(item.total() for item in items) return {"basket": items, "total_price": total_price}