def feedback(request): ''' Captures the server-to-server feedback and update the order accordingly. ''' # Build a dictionary with the URL parameters params = get_params(request) try: order = Order.objects.get(variables__key='ORDER_ID', variables__value=params['ORDERID']) # TODO: handle KeyError if no ORDERID is given except Order.DoesNotExist: # TODO: Log Feedback for non-existing order (email notification?) return bad_or_missing(request, _('Your order has already been processed.')) log.info('Params for order %s', order) for key, val in params.items(): log.info('%s: %s', key, val) error = _verify_feedback(request, order, params) if error: return bad_or_missing(request, error) return HttpResponse('OK')
def success(request): """ The order has been succesfully processed. We clear out the cart but let the payment processing get called by IPN """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # Build a dictionary with the URL parameters params = get_params(request) log.info('Params for order %s', order) for key, val in params.items(): log.info('%s: %s', key, val) # Verify the feedback unless the order has already been paid, # e.g in the case of free orders if not order.paid_in_full: error = _verify_feedback(request, order, params) if error: return bad_or_missing(request, error) del request.session['orderID'] return render(request, 'shop/checkout/success.html', {'order': order})
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None cartplaces = config_value('SHOP', 'CART_PRECISION') roundfactor = config_value('SHOP', 'CART_ROUNDING') if formdata.has_key('productname'): productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing(request, _("That product is not available at the moment.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _('The product you have requested does not exist.')) # First we validate that the number isn't too big. if decimal_too_big(formdata['quantity']): return _product_error(request, product, _("Please enter a smaller number.")) # Then we validate that we can round it appropriately. try: quantity = round_decimal(formdata['quantity'], places=cartplaces, roundfactor=roundfactor) except RoundedDecimalError, P: return _product_error(request, product, _("Invalid quantity."))
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None cartplaces = config_value('SHOP', 'CART_PRECISION') roundfactor = config_value('SHOP', 'CART_ROUNDING') if formdata.has_key('productname'): productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing( request, _("That product is not available at the moment.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing( request, _('The product you have requested does not exist.')) # First we validate that the number isn't too big. if decimal_too_big(formdata['quantity']): return _product_error(request, product, _("Please enter a smaller number.")) # Then we validate that we can round it appropriately. try: quantity = round_decimal(formdata['quantity'], places=cartplaces, roundfactor=roundfactor) except RoundedDecimalError: return _product_error(request, product, _("Invalid quantity.")) if quantity <= Decimal('0'): return _product_error(request, product, _("Please enter a positive number.")) cart = Cart.objects.from_request(request, create=True) # send a signal so that listeners can update product details before we add it to the cart. satchmo_cart_details_query.send(cart, product=product, quantity=quantity, details=details, request=request, form=formdata) try: added_item = cart.add_item(product, number_added=quantity, details=details) except CartAddProhibited, cap: return _product_error(request, product, cap.message)
def category_view_kamel(request, slug, parent_slugs='', template='product/category.html'): """Display the category, its child categories, and its products. Parameters: - slug: slug of category - parent_slugs: ignored """ if request.method == "GET": currpage = request.GET.get('page', 1) town = request.GET.get('town') else: currpage = 1 town = 'Gdansk' is_paged = False page = None try: category = Category.objects.get_by_site(slug=slug) products = list(category.active_products()) sale = find_best_auto_discount(products) count = config_value('PRODUCT', 'NUM_PAGINATED') paginator = Paginator(products, count) try: paginator.validate_number(currpage) except EmptyPage: return bad_or_missing(request, _("Invalid page number")) is_paged = paginator.num_pages > 1 page = paginator.page(currpage) except Category.DoesNotExist: return bad_or_missing( request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() ctx = { 'category': category, 'child_categories': child_categories, 'sale': sale, 'town': town, 'products': page.object_list, 'is_paginated': is_paged, 'page_obj': page, 'paginator': paginator } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, context_instance=RequestContext(request, ctx))
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None cartplaces = config_value('SHOP', 'CART_PRECISION') roundfactor = config_value('SHOP', 'CART_ROUNDING') if formdata.has_key('productname'): productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing(request, _("That product is not available at the moment.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _('The product you have requested does not exist.')) # First we validate that the number isn't too big. if decimal_too_big(formdata['quantity']): return _product_error(request, product, _("Please enter a smaller number.")) # Then we validate that we can round it appropriately. try: quantity = round_decimal(formdata['quantity'], places=cartplaces, roundfactor=roundfactor) except RoundedDecimalError: return _product_error(request, product, _("Invalid quantity.")) if quantity <= Decimal('0'): return _product_error(request, product, _("Please enter a positive number.")) cart = Cart.objects.from_request(request, create=True) # send a signal so that listeners can update product details before we add it to the cart. satchmo_cart_details_query.send( cart, product=product, quantity=quantity, details=details, request=request, form=formdata ) try: added_item = cart.add_item(product, number_added=quantity, details=details) except CartAddProhibited, cap: return _product_error(request, product, cap.message)
def category_view(request, slug, parent_slugs='', template='product/category.html'): """Display the category, its child categories, and its products. Parameters: - slug: slug of category - parent_slugs: ignored """ if request.method == "GET": currpage = request.GET.get('page', 1) else: currpage = 1 try: category = Category.objects.get_by_site(slug=slug) products = list(category.active_products()) sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing(request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() count = config_value('PRODUCT','NUM_PAGINATED') paginator = Paginator(products, count) try: paginator.validate_number(currpage) except InvalidPage: return bad_or_missing(request, _("Invalid page number")) page = paginator.page(currpage) min_in_page = (count * (page.number - 1) + 1) max_in_page = min_in_page + (len(page.object_list) - 1) ctx = { 'category': category, 'child_categories': child_categories, 'sale': sale, 'products': page.object_list, 'page_obj': page, 'paginator': paginator, 'min_in_page': min_in_page, 'max_in_page': max_in_page } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, context_instance=RequestContext(request, ctx))
def variation_manager(request, product_id=""): try: product = Product.objects.get(id=product_id) subtypes = product.get_subtypes() if 'ProductVariation' in subtypes: # got a variation, we want to work with its parent product = product.productvariation.parent.product if 'ConfigurableProduct' in product.get_subtypes(): url = urlresolvers.reverse("satchmo_admin_variation_manager", kwargs={'product_id': product.id}) return HttpResponseRedirect(url) if 'ConfigurableProduct' not in subtypes: return bad_or_missing( request, _('The product you have requested is not a Configurable Product.' )) except Product.DoesNotExist: return bad_or_missing( request, _('The product you have requested does not exist.')) if request.method == 'POST': new_data = request.POST.copy() form = VariationManagerForm(new_data, product=product) if form.is_valid(): log.debug("Saving form") try: form.save(request) except IntegrityError: messages.error( request, _('The product you are attempting to remove is linked to an order and can not be removed.' )) # rebuild the form form = VariationManagerForm(product=product) else: log.debug('errors on form') else: form = VariationManagerForm(product=product) ctx = RequestContext(request, { 'product': product, 'form': form, }) return render_to_response('product/admin/variation_manager.html', context_instance=ctx)
def charge_remaining_post(request): if not request.method == 'POST': return bad_or_missing(request, _("No form found in request.")) data = request.POST.copy() form = CustomChargeForm(data) if form.is_valid(): data = form.cleaned_data try: orderitem = OrderItem.objects.get(pk=data['orderitem']) except OrderItem.DoesNotExist: return bad_or_missing( request, _("The orderitem you have requested doesn't exist, or you don't have access to it." )) price = data['amount'] line_price = price * orderitem.quantity orderitem.unit_price = price orderitem.line_item_price = line_price orderitem.save() #print("Orderitem price now: %s" % orderitem.line_item_price) order = orderitem.order if not order.shipping_cost: order.shipping_cost = Decimal("0.00") if data['shipping']: order.shipping_cost += data['shipping'] order.recalculate_total() messages.add_message( request, messages.INFO, 'Charged for custom product and recalculated totals.') notes = data['notes'] if not notes: notes = 'Updated total price' order.add_status(notes=notes) return HttpResponseRedirect('/admin/shop/order/%i' % order.id) else: return render(request, 'admin/charge_remaining_confirm.html', {'form': form})
def home(request, template="shop/index.html"): # Display the category, its child categories, and its products. if request.method == "GET": currpage = request.GET.get('page', 1) else: currpage = 1 featured = display_featured() count = config_value('PRODUCT','NUM_PAGINATED') paginator = Paginator(featured, count) is_paged = False page = None try: paginator.validate_number(currpage) except EmptyPage: return bad_or_missing(request, _("Invalid page number")) is_paged = paginator.num_pages > 1 page = paginator.page(currpage) ctx = RequestContext(request, { 'all_products_list' : page.object_list, 'is_paginated' : is_paged, 'page_obj' : page, 'paginator' : paginator }) return render_to_response(template, context_instance=ctx)
def success(request): """ The order has been succesfully processed. """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # register the transaction order.add_status(status='New', notes=_("Order placed on ")+STORE_NAME) #processor = get_processor_by_key('PAYMENT_PAYMENTSPRO') #payment = processor.record_payment(order=order, amount=gross, transaction_id=txn_id) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity product.items_in_stock -= item.quantity product.save() # Clean up cart now, (TODO:the rest of the order will be cleaned on paypal IPN) #for cart in Cart.objects.filter(customer=order.contact): # cart.empty() cart = Cart.objects.from_request(request) cart.empty() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context)
def success(request): """ The order has been succesfully processed. We clear out the cart but let the payment processing get called by IPN """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _("Your order has already been processed.")) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity product.items_in_stock -= item.quantity product.save() log.warning(_("The contact is %s") % order.contact) # Clean up cart now, the rest of the order will be cleaned on paypal IPN for cart in Cart.objects.filter(customer=order.contact): log.warning(_("Processing cart item %s") % cart.pk) cart.empty() del request.session["orderID"] log.warning(request.session) context = RequestContext(request, {"order": order}) return render_to_response("shop/checkout/success.html", context)
def success(request): """ The order has been succesfully processed. We clear out the cart but let the payment processing get called by IPN """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity product.items_in_stock -= item.quantity product.save() # Clean up cart now, the rest of the order will be cleaned on paypal IPN for cart in Cart.objects.filter(customer=order.contact): cart.empty() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context)
def order_tracking(request, order_id): order = None try: contact = Contact.objects.from_request(request, create=False) try: order = Order.objects.get(id__exact=order_id, contact=contact) except Order.DoesNotExist: pass except Contact.DoesNotExist: contact = None if order is None: return bad_or_missing( request, _("The order you have requested doesn't exist, or you don't have access to it." )) ctx = RequestContext( request, { 'default_view_tax': config_value('TAX', 'DEFAULT_VIEW_TAX'), 'contact': contact, 'order': order }) return render_to_response('shop/order_tracking.html', context_instance=ctx)
def category_view(request, slug, parent_slugs='', template='product/category.html'): """Display the category, its child categories, and its products. Parameters: - slug: slug of category - parent_slugs: ignored """ try: category = Category.objects.get_by_site(slug=slug) products = list(category.active_products()) sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing( request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() ctx = { 'category': category, 'child_categories': child_categories, 'sale': sale, 'products': products, } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render(request, template, ctx)
def home(request, template="shop/index.html"): # Display the category, its child categories, and its products. if request.method == "GET": currpage = request.GET.get('page', 1) else: currpage = 1 featured = display_featured() count = config_value('PRODUCT', 'NUM_PAGINATED') paginator = Paginator(featured, count) is_paged = False page = None try: paginator.validate_number(currpage) except EmptyPage: return bad_or_missing(request, _("Invalid page number")) is_paged = paginator.num_pages > 1 page = paginator.page(currpage) ctx = RequestContext( request, { 'all_products_list': page.object_list, 'is_paginated': is_paged, 'page_obj': page, 'paginator': paginator }) return render_to_response(template, context_instance=ctx)
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # empty user cart for cart in Cart.objects.filter(customer=order.contact): cart.empty() cart.delete() cart = Cart.objects.from_request(request, create=False) if isinstance(cart, NullCart): pass else: cart.empty() cart.delete() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context_instance=context)
def success(request): """ The order has been succesfully processed. We clear out the cart but let the payment processing get called by IPN """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity if config_value('PRODUCT','TRACK_INVENTORY'): product.items_in_stock -= item.quantity product.save() # Clean up cart now, the rest of the order will be cleaned on paypal IPN for cart in Cart.objects.filter(customer=order.contact): cart.empty() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context)
def remove(request): """Remove an item from the cart.""" if not request.POST: # Should be a POST request return bad_or_missing(request, "Please use a POST request") success, cart, cartitem, errors = _set_quantity(request, force_delete=True) if request.is_ajax(): if errors: return _json_response({ 'errors': errors, 'results': _("Error") }, True) else: return _json_response({ 'cart_total': str(cart.total), 'cart_count': str(cart.numItems), 'item_id': cartitem.id, 'results': success, # Legacy }) else: if errors: return display(request, cart=cart, error_message=errors) else: url = urlresolvers.reverse('satchmo_cart') return HttpResponseRedirect(url)
def category_view(request, slug, parent_slugs='', template='product/category.html'): """Display the category, its child categories, and its products. Parameters: - slug: slug of category - parent_slugs: ignored """ try: category = Category.objects.get(slug=slug) products = list(category.active_products()) sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing(request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() ctx = { 'category': category, 'child_categories': child_categories, 'sale' : sale, 'products' : products, } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, RequestContext(request, ctx))
def multisuccess_view(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ target_view = None try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] payments_completed = order.payments_completed() if payments_completed: payment_completed = payments_completed[0].payment else: payment_completed = '' shop = Config.objects.get_current() postal_code = shop.postal_code city = shop.city phone = shop.phone fax = "" store_email = shop.store_email store_name = shop.store_name street1 = shop.street1 state = shop.state p_iva = config_value('SHOP_CONFIG','VAT') iban = config_value('SHOP_CONFIG','IBAN') # Cablare il campo per il rilevamento della tipologia # di pagamento target_view = [] if payment_completed: target_view.append( "shop/checkout/success_%s.html" % payment_completed.lower() ) target_view.append("shop/checkout/success_generic.html") return render_to_response( target_view, { 'order': order, 'payment': payment_completed, 'p_iva' : p_iva, 'iban' : iban, 'store_postal_code' : postal_code, 'store_phone' : phone, 'store_fax' : fax, 'store_email' : store_email, 'store_name' : store_name, 'store_street1' : street1, 'store_state' : state, 'store_city' : city, }, context_instance=RequestContext(request) )
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # empty user cart for cart in Cart.objects.filter(customer=order.contact): cart.empty() cart.delete() cart = Cart.objects.from_request(request, create=False) if isinstance(cart, NullCart): pass else: cart.empty() cart.delete() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context_instance=context)
def get_product(request, product_slug=None, selected_options=(), default_view_tax=None): """Basic product view""" errors = [m for m in get_messages(request) if m.level == constants.ERROR] try: product = Product.objects.get_by_site(active=True, slug=product_slug) except Product.DoesNotExist: return bad_or_missing( request, _('The product you have requested does not exist.')) if default_view_tax is None: default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX') subtype_names = product.get_subtypes() # Save product id for xheaders, in case we display a ConfigurableProduct product_id = product.id # Clone product object in order to have current product variations in context (extra_context) current_product = product if 'ProductVariation' in subtype_names: selected_options = product.productvariation.unique_option_ids #Display the ConfigurableProduct that this ProductVariation belongs to. product = product.productvariation.parent.product subtype_names = product.get_subtypes() best_discount = find_best_auto_discount(product) if errors: error_message = errors[0] else: error_message = None extra_context = { 'product': product, 'current_product': current_product, 'default_view_tax': default_view_tax, 'sale': best_discount, 'error_message': error_message, } # Get the template context from the Product. extra_context = product.add_template_context( context=extra_context, request=request, selected_options=selected_options, default_view_tax=default_view_tax) template = find_product_template(product, producttypes=subtype_names) context = RequestContext(request, extra_context) response = http.HttpResponse(template.render(context)) populate_xheaders(request, response, Product, product_id) return response
def get_product(request, product_slug=None, selected_options=(), default_view_tax=None): """Basic product view""" errors = [m for m in get_messages(request) if m.level == constants.ERROR] try: product = Product.objects.get_by_site(active=True, slug=product_slug) except Product.DoesNotExist: return bad_or_missing(request, _('The product you have requested does not exist.')) if default_view_tax is None: default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX') subtype_names = product.get_subtypes() # Save product id for xheaders, in case we display a ConfigurableProduct product_id = product.id # Clone product object in order to have current product variations in context (extra_context) current_product = product if 'ProductVariation' in subtype_names: selected_options = product.productvariation.unique_option_ids #Display the ConfigurableProduct that this ProductVariation belongs to. product = product.productvariation.parent.product subtype_names = product.get_subtypes() best_discount = find_best_auto_discount(product) if errors: error_message = errors[0] else: error_message = None extra_context = { 'product': product, 'current_product' : current_product, 'default_view_tax': default_view_tax, 'sale': best_discount, 'error_message' : error_message, } # Get the template context from the Product. extra_context = product.add_template_context(context=extra_context, request=request, selected_options=selected_options, default_view_tax=default_view_tax) template = find_product_template(product, producttypes=subtype_names) context = RequestContext(request, extra_context) response = http.HttpResponse(template.render(context)) try: from django.core.xheaders import populate_xheaders populate_xheaders(request, response, Product, product_id) except ImportError: pass return response
def charge_remaining_post(request): if not request.method == 'POST': return bad_or_missing(request, _("No form found in request.")) data = request.POST.copy() form = CustomChargeForm(data) if form.is_valid(): data = form.cleaned_data try: orderitem = OrderItem.objects.get(pk = data['orderitem']) except OrderItem.DoesNotExist: return bad_or_missing(request, _("The orderitem you have requested doesn't exist, or you don't have access to it.")) price = data['amount'] line_price = price*orderitem.quantity orderitem.unit_price = price orderitem.line_item_price = line_price orderitem.save() #print "Orderitem price now: %s" % orderitem.line_item_price order = orderitem.order if not order.shipping_cost: order.shipping_cost = Decimal("0.00") if data['shipping']: order.shipping_cost += data['shipping'] order.recalculate_total() messages.add_message(request, messages.INFO, 'Charged for custom product and recalculated totals.') notes = data['notes'] if not notes: notes = 'Updated total price' order.add_status(notes=notes) return HttpResponseRedirect('/admin/shop/order/%i' % order.id) else: ctx = RequestContext(request, {'form': form}) return render_to_response('admin/charge_remaining_confirm.html', context_instance=ctx)
def multisuccess_view(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ target_view = None try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] payments_completed = order.payments_completed() if payments_completed: payment_completed = payments_completed[0].payment else: payment_completed = '' shop = Config.objects.get_current() postal_code = shop.postal_code city = shop.city phone = shop.phone fax = "" store_email = shop.store_email store_name = shop.store_name street1 = shop.street1 state = shop.state p_iva = config_value('SHOP_CONFIG', 'VAT') iban = config_value('SHOP_CONFIG', 'IBAN') # Cablare il campo per il rilevamento della tipologia # di pagamento target_view = [] if payment_completed: target_view.append("shop/checkout/success_%s.html" % payment_completed.lower()) target_view.append("shop/checkout/success_generic.html") return render_to_response(target_view, { 'order': order, 'payment': payment_completed, 'p_iva': p_iva, 'iban': iban, 'store_postal_code': postal_code, 'store_phone': phone, 'store_fax': fax, 'store_email': store_email, 'store_name': store_name, 'store_street1': street1, 'store_state': state, 'store_city': city, }, context_instance=RequestContext(request))
def success(request): try: order = Order.objects.get(id=request.session['orderID']) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] return render_to_response('shop/checkout/bank_transfer/success.html', {'order': order}, context_instance=RequestContext(request))
def variation_manager(self, request, product_id = ""): # Slightly more complicated here, but again, only filter for the # current user's site if he's not a superuser. Redirect the actual # work to satchmo's original method. In essence this method here is # merely an authorization wrapper for #adminviews.variation_manager. try: if not request.user.is_superuser: Product.objects.get(id=product_id, site__exact=request.user.get_profile().site) return self.satchmo_variation_manager(request, product_id) except Product.DoesNotExist: return bad_or_missing(request, _('The product you have requested does not exist.'))
def variation_manager(request, product_id = ""): try: product = Product.objects.get(id=product_id) subtypes = product.get_subtypes() if 'ProductVariation' in subtypes: # got a variation, we want to work with its parent product = product.productvariation.parent.product if 'ConfigurableProduct' in product.get_subtypes(): url = urlresolvers.reverse("satchmo_admin_variation_manager", kwargs = {'product_id' : product.id}) return HttpResponseRedirect(url) if 'ConfigurableProduct' not in subtypes: return bad_or_missing(request, _('The product you have requested is not a Configurable Product.')) except Product.DoesNotExist: return bad_or_missing(request, _('The product you have requested does not exist.')) if request.method == 'POST': new_data = request.POST.copy() form = VariationManagerForm(new_data, product=product) if form.is_valid(): log.debug("Saving form") try: form.save(request) except IntegrityError: messages.error(request, _('The product you are attempting to remove is linked to an order and can not be removed.')) # rebuild the form form = VariationManagerForm(product=product) else: log.debug('errors on form') else: form = VariationManagerForm(product=product) ctx = RequestContext(request, { 'product' : product, 'form' : form, }) return render_to_response('product/admin/variation_manager.html', context_instance=ctx)
def failure(request): try: order = Order.objects.from_request(request) account = Account.objects.get(user=order.contact.user) except Order.DoesNotExist: return bad_or_missing(request, _("Your order has already been processed.")) return render_to_response( "shop/checkout/reward_points/failure.html", {"order": order, "account": account}, context_instance=RequestContext(request), )
def error(request): """ The order has been succesfully with errors. """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) return render_to_response('shop/checkout/creditcard/error.html', {'order': order,}, context_instance=RequestContext(request))
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] return render_to_response('shop/checkout/success.html', {'order': order}, context_instance=RequestContext(request))
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context_instance=context)
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None productslug = formdata['productname'] durationSLUG =formdata['durationSLUG'] product = Product.objects.get_by_site(slug=productslug) DK= PricingDate.objects.get(durationSLUG=durationSLUG) durationkey= DK.pk try: if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing(request, _("Computer says no.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _('A tiny (huge) mistake has been made and this product can\'t be found.')) cart = Cart.objects.from_request(request, create=True) # send a signal so that listeners can update product details before we add it to the cart. satchmo_cart_details_query.send( cart, product=product, duration=DK, request=request, form=formdata ) try: duration= PricingDate.objects.get(pk=durationkey) added_item = cart.add_item(product, duration) except CartAddProhibited, cap: return _product_error(request, product, cap.message)
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None cartplaces = config_value('SHOP', 'CART_PRECISION') roundfactor = config_value('SHOP', 'CART_ROUNDING') if formdata.has_key('productname'): productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing( request, _("That product is not available at the moment.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing( request, _('The product you have requested does not exist.')) # First we validate that the number isn't too big. if decimal_too_big(formdata['quantity']): return _product_error(request, product, _("Please enter a smaller number.")) # Then we validate that we can round it appropriately. try: quantity = round_decimal(formdata['quantity'], places=cartplaces, roundfactor=roundfactor) except RoundedDecimalError, P: return _product_error(request, product, _("Invalid quantity."))
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: bad_or_missing_message = 'Your order has already been processed.' return bad_or_missing(request, _(bad_or_missing_message)) amount = order.balance payment_module = config_get_group('PAYMENT_CREDITCARD') processor = get_processor_by_key('PAYMENT_CREDITCARD') account = request.GET.get('a', '') ecripted_string = request.GET.get('b', '') gpc = GestPayCrypt() gpc.SetShopLogin(account) gpc.SetShopTransactionID(str(order.id)) gpc.SetAmount("%.2f" % order.total) gpc.SetEncryptedString(str(ecripted_string)) # if gpc.Decrypt() == 1 --> Transaction is OK if gpc.Decrypt() == 1: processor.record_payment( order = order, amount = amount, transaction_id = gpc.GetBankTransactionID(), reason_code = gpc.GetAuthorizationCode() ) if order.notes is None: order.notes = "" else: order.notes += "\n\n" order.save() order.add_status( status = 'New', notes = "Pagato mediante BANCASELLA" ) # Make cart empty cart = Cart.objects.from_request(request) if cart: cart.empty() return render_to_response('shop/checkout/success_creditcard.html', {'order': order,}, context_instance=RequestContext(request))
def remove_ticket(request): if not request.POST: return bad_or_missing(request, "Please use a POST request") success, cart, cartitem, errors = _set_quantity(request, force_delete=True) if request.is_ajax(): if errors: return _json_response({'errors': errors, 'results': _("Error")}, True) else: return _json_response({ 'cart_total': str(cart.total), 'cart_count': str(cart.numItems), 'item_id': cartitem.id, 'results': success, # Legacy })
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) account = Account.objects.get(user=order.contact.user) except Order.DoesNotExist: return bad_or_missing(request, _("Your order has already been processed.")) del request.session["orderID"] return render_to_response( "shop/checkout/reward_points/success.html", {"order": order, "account": account}, context_instance=RequestContext(request), )
def charge_remaining(request, orderitem_id): """Given an orderitem_id, this returns a confirmation form.""" try: orderitem = OrderItem.objects.get(pk = orderitem_id) except OrderItem.DoesNotExist: return bad_or_missing(request, _("The orderitem you have requested doesn't exist, or you don't have access to it.")) amount = orderitem.product.customproduct.full_price data = { 'orderitem' : orderitem_id, 'amount' : amount, } form = CustomChargeForm(data) ctx = RequestContext(request, {'form' : form}) return render_to_response('payment/admin/charge_remaining_confirm.html', ctx)
def charge_remaining(request, orderitem_id): """Given an orderitem_id, this returns a confirmation form.""" try: orderitem = OrderItem.objects.get(pk = orderitem_id) except OrderItem.DoesNotExist: return bad_or_missing(request, _("The orderitem you have requested doesn't exist, or you don't have access to it.")) amount = orderitem.product.customproduct.full_price data = { 'orderitem' : orderitem_id, 'amount' : amount, } form = CustomChargeForm(data) ctx = RequestContext(request, {'form' : form}) return render_to_response('payment/admin/charge_remaining_confirm.html', context_instance=ctx)
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity product.items_in_stock -= item.quantity product.save() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context)
def dispatch(self, request, *args, **kwargs): self.object = self.get_object() self.product = self.object subtypes = self.object.get_subtypes() if 'ProductVariation' in subtypes: self.product = self.product.productvariation.parent.product if 'ConfigurableProduct' in self.product.get_subtypes(): url = reverse("satchmo_admin_variation_manager", kwargs={'product_id': self.product.id}) return HttpResponseRedirect(url) if 'ConfigurableProduct' not in subtypes: return bad_or_missing( self.request, _('The product you have requested is not a Configurable Product.' )) return super(VariationManagerView, self).dispatch(request, *args, **kwargs)
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] # We check to see if there are any gift certificates in the order gc_email_sent = False gc_in_orderitems = len(filter(lambda x: 'GiftCertificateProduct' in x.product.get_subtypes(), order.orderitem_set.all())) if gc_in_orderitems: gc_email_sent = gift_certificate_processor(order) return render_to_response('shop/checkout/success.html', {'order': order, 'gc_email_sent': gc_email_sent}, context_instance=RequestContext(request))
def success(request): """ The order has been succesfully processed. This can be used to generate a receipt or some other confirmation """ try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) del request.session['orderID'] # We check to see if there are any gift certificates in the order gc_email_sent = False gc_in_orderitems = len(filter(lambda x: 'GiftCertificateProduct' in x.product.get_subtypes(), order.orderitem_set.all())) if gc_in_orderitems: gc_email_sent = gift_certificate_processor(order) return render(request, 'shop/checkout/success.html', {'order': order, 'gc_email_sent': gc_email_sent}, )
def order_tracking(request, order_id): order = None try: contact = Contact.objects.from_request(request, create=False) try: order = Order.objects.get(id__exact=order_id, contact=contact) except Order.DoesNotExist: pass except Contact.DoesNotExist: contact = None if order is None: return bad_or_missing(request, _("The order you have requested doesn't exist, or you don't have access to it.")) ctx = RequestContext(request, { 'default_view_tax': config_value('TAX', 'DEFAULT_VIEW_TAX'), 'contact' : contact, 'order' : order}) return render_to_response('shop/order_tracking.html', context_instance=ctx)
def get_product(request, product_slug=None, selected_options=(), default_view_tax=NOTSET): """Basic product view""" errors = request.session.get('ERRORS', None) try: product = Product.objects.get_by_site(active=True, slug=product_slug) except Product.DoesNotExist: return bad_or_missing(request, _('The product you have requested does not exist.')) if default_view_tax == NOTSET: default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX') subtype_names = product.get_subtypes() if 'ProductVariation' in subtype_names: selected_options = product.productvariation.unique_option_ids #Display the ConfigurableProduct that this ProductVariation belongs to. product = product.productvariation.parent.product subtype_names = product.get_subtypes() best_discount = find_best_auto_discount(product) extra_context = { 'product': product, 'default_view_tax': default_view_tax, 'sale': best_discount, 'error_message' : errors, } # Get the template context from the Product. extra_context = product.add_template_context(context=extra_context, request=request, selected_options=selected_options, default_view_tax=default_view_tax) template = find_product_template(product, producttypes=subtype_names) context = RequestContext(request, extra_context) return http.HttpResponse(template.render(context))
def wishlist_add(request): """Add an item to the wishlist.""" try: contact = Contact.objects.from_request(request) except Contact.DoesNotExist: return _wishlist_requires_login(request) log.debug("FORM: %s", request.POST) formdata = request.POST.copy() productslug = None if formdata.has_key("productname"): productslug = formdata["productname"] try: product, details = product_from_post(productslug, formdata) template = find_product_template(product) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _("The product you have requested does not exist.")) wish = ProductWish.objects.create_if_new(product, contact, details) url = urlresolvers.reverse("satchmo_wishlist_view") return HttpResponseRedirect(url)
def wishlist_add(request): """Add an item to the wishlist.""" try: contact = Contact.objects.from_request(request) except Contact.DoesNotExist: return _wishlist_requires_login(request) log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None if formdata.has_key('productname'): productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) template = find_product_template(product) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _('The product you have requested does not exist.')) wish = ProductWish.objects.create_if_new(product, contact, details) url = urlresolvers.reverse('satchmo_wishlist_view') return HttpResponseRedirect(url)
def remove(request): """Remove an item from the cart.""" if not request.POST: # Should be a POST request return bad_or_missing(request, "Please use a POST request") success, cart, cartitem, errors = _set_quantity(request, force_delete=True) if request.is_ajax(): if errors: return _json_response({'errors': errors, 'results': _("Error")}, True) else: return _json_response({ 'cart_total': unicode(moneyfmt(cart.total)), 'cart_count': str(cart.numItems), 'item_id': cartitem.id, 'results': success, # Legacy }) else: if errors: return display(request, cart=cart, error_message=errors) else: url = urlresolvers.reverse('satchmo_cart') return HttpResponseRedirect(url)
def add(request, id=0, redirect_to='satchmo_cart'): """Add an item to the cart.""" log.debug('FORM: %s', request.POST) formdata = request.POST.copy() productslug = None cartplaces = config_value('SHOP', 'CART_PRECISION') roundfactor = config_value('SHOP', 'CART_ROUNDING') if 'productname' in formdata: productslug = formdata['productname'] try: product, details = product_from_post(productslug, formdata) if not (product and product.active): log.debug("product %s is not active" % productslug) return bad_or_missing(request, _("That product is not available at the moment.")) else: log.debug("product %s is active" % productslug) except (Product.DoesNotExist, MultiValueDictKeyError): log.debug("Could not find product: %s", productslug) return bad_or_missing(request, _('The product you have requested does not exist.')) # First we validate that the number isn't too big. if decimal_too_big(formdata['quantity']): return _product_error(request, product, _("Please enter a smaller number.")) # Then we validate that we can round it appropriately. try: quantity = round_decimal(formdata['quantity'], places=cartplaces, roundfactor=roundfactor) except RoundedDecimalError: return _product_error(request, product, _("Invalid quantity.")) if quantity <= Decimal('0'): return _product_error(request, product, _("Please enter a positive number.")) cart = Cart.objects.from_request(request, create=True) # send a signal so that listeners can update product details before we add it to the cart. satchmo_cart_details_query.send( cart, product=product, quantity=quantity, details=details, request=request, form=formdata ) try: added_item = cart.add_item(product, number_added=quantity, details=details) except CartAddProhibited as cap: return _product_error(request, product, cap.message) # got to here with no error, now send a signal so that listeners can also operate on this form. satchmo_cart_add_complete.send(cart, cart=cart, cartitem=added_item, product=product, request=request, form=formdata) satchmo_cart_changed.send(cart, cart=cart, request=request) if request.is_ajax(): data = { 'id': product.id, 'name': product.translated_name(), 'item_id': added_item.id, 'item_qty': str(round_decimal(quantity, 2)), 'item_price': six.text_type(moneyfmt(added_item.line_total)) or "0.00", 'cart_count': str(round_decimal(cart.numItems, 2)), 'cart_total': six.text_type(moneyfmt(cart.total)), # Legacy result, for now 'results': _("Success"), } log.debug('CART AJAX: %s', data) return _json_response(data) else: url = reverse(redirect_to) return HttpResponseRedirect(url)
def success(request): """ The order has been succesfully processed. We clear out the cart but let the payment processing get called by psb_back_resp """ try: # If we get a response from Paysbuy: front_resp_dict = psb_front_resp(request) test_or_live = front_resp_dict['test_or_live'] psb_front_data = front_resp_dict['psb_front_data'] invoice = psb_front_data['result'][2:] txn_num = psb_front_data['apCode'] cost = psb_front_data['amt'] if (psb_front_data['method'] == '06' and psb_front_data['result'][:2] == '02'): pay_result_message = 'Your order will be shipped upon receipt of funds.' elif psb_front_data['result'][:2] == '00': pay_result_message = 'Your order has been successfuly processed.' else: pay_result_message = 'Your order has failed. Please contact Paysbuy.' order = Order.objects.get(id__iexact=invoice) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity if config_value('PRODUCT', 'TRACK_INVENTORY'): product.items_in_stock -= item.quantity product.save() # Clean up cart now, the rest of the order will be cleaned on psb_back_resp for cart in Cart.objects.filter(customer=order.contact): cart.empty() del request.session['orderID'] context = RequestContext( request, { 'order': order, 'test_or_live': test_or_live, 'invoice': invoice, 'txn_num': txn_num, 'cost': cost, 'pay_result_message': pay_result_message, }) return render_to_response('shop/checkout/paysbuy/success.html', context) except: # If there is no response from Paysbuy we treat it as an internal request. try: order = Order.objects.from_request(request) except Order.DoesNotExist: return bad_or_missing(request, _('Your order has already been processed.')) # Added to track total sold for each product for item in order.orderitem_set.all(): product = item.product product.total_sold += item.quantity if config_value('PRODUCT', 'TRACK_INVENTORY'): product.items_in_stock -= item.quantity product.save() # Clean up cart now, the rest of the order will be cleaned on psb_back_resp for cart in Cart.objects.filter(customer=order.contact): cart.empty() del request.session['orderID'] context = RequestContext(request, {'order': order}) return render_to_response('shop/checkout/success.html', context)
def cron_rebill(request=None): """Rebill customers with expiring recurring subscription products This can either be run via a url with GET key authentication or directly from a shell script. """ #TODO: support re-try billing for failed transactions if request is not None: if not config_value('PAYMENT', 'ALLOW_URL_REBILL'): return bad_or_missing(request, _("Feature is not enabled.")) if 'key' not in request.GET or request.GET['key'] != config_value( 'PAYMENT', 'CRON_KEY'): return HttpResponse("Authentication Key Required") expiring_subscriptions = OrderItem.objects.filter( expire_date__gte=timezone.now()).order_by('order', 'id', 'expire_date') for item in expiring_subscriptions: if item.product.is_subscription: #TODO - need to add support for products with trial but non-recurring if item.product.subscriptionproduct.recurring_times and item.product.subscriptionproduct.recurring_times + item.product.subscriptionproduct.get_trial_terms( ).count() == OrderItem.objects.filter( order=item.order, product=item.product).count(): continue if item.expire_date == datetime.date( timezone.now()) and item.completed: if item.id == OrderItem.objects.filter( product=item.product, order=item.order).order_by('-id')[0].id: #bill => add orderitem, recalculate total, porocess card new_order_item = OrderItem( order=item.order, product=item.product, quantity=item.quantity, unit_price=item.unit_price, line_item_price=item.line_item_price) #if product is recurring, set subscription end if item.product.subscriptionproduct.recurring: new_order_item.expire_date = item.product.subscriptionproduct.calc_expire_date( ) #check if product has 2 or more trial periods and if the last one paid was a trial or a regular payment. ordercount = item.order.orderitem_set.all().count() if item.product.subscriptionproduct.get_trial_terms( ).count( ) > 1 and item.unit_price == item.product.subscriptionproduct.get_trial_terms( ordercount - 1).price: new_order_item.unit_price = item.product.subscriptionproduct.get_trial.terms( ordercount).price new_order_item.line_item_price = new_order_item.quantity * new_order_item.unit_price new_order_item.expire_date = item.product.subscriptionproduct.get_trial_terms( ordercount).calc_expire_date() new_order_item.save() item.order.recalculate_total() # if new_order_item.product.subscriptionproduct.is_shippable == 3: # item.order.total = item.order.total - item.order.shipping_cost # item.order.save() payments = item.order.payments.all()[0] #list of ipn based payment modules. Include processors that use 3rd party recurring billing. ipn_based = ['PAYPAL'] if not payments.payment in ipn_based and item.order.balance > 0: #run card #Do the credit card processing here & if successful, execute the success_handler payment_module = config_get_group('PAYMENT_%s' % payments.payment) credit_processor = payment_module.MODULE.load_module( 'processor') processor = credit_processor.PaymentProcessor( payment_module) processor.prepare_data(item.order) result = processor.process() if result.payment: reason_code = result.payment.reason_code else: reason_code = "unknown" log.info( """Processing %s recurring transaction with %s Order #%i Results=%s Response=%s Reason=%s""", payment_module.LABEL.value, payment_module.KEY.value, item.order.id, result.success, reason_code, result.message) if result.success: #success handler item.order.add_status( status='New', notes=ugettext( "Subscription Renewal Order successfully submitted" )) new_order_item.completed = True new_order_item.save() orderpayment = OrderPayment( order=item.order, amount=item.order.balance, payment=six.text_type( payment_module.KEY.value)) orderpayment.save() return HttpResponse()
def category_view(request, slug, parent_slugs='', template='product/category.html'): """Display the category, its child categories, and its products. Parameters: - slug: slug of category - parent_slugs: ignored """ if request.GET.has_key('order_by') and request.GET['order_by']: orderBy= request.GET['order_by'] if orderBy == 'price_inc': try: category = Category.objects.get_by_site(slug=slug) #products = list(category.active_products()) products = list(category.active_products()) if len(products): productsAndPrice = [] for p in products: price = p.unit_price productsAndPrice.append([price,p]) productsAndPrice.sort() sortedProducts = [] for pp in productsAndPrice: sortedProducts.append(pp[1]) products = sortedProducts # sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing(request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() cart = Cart.objects.from_request(request) if cart.numItems > 0: productsInCart = [item.product for item in cart.cartitem_set.all()] sale = find_best_auto_discount(productsInCart) else: sale = None ctx = { 'category': category, 'child_categories': child_categories, 'sale' : sale, 'products' : products, 'order_by' : 'price_inc' } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, context_instance=RequestContext(request, ctx)) else: try: category = Category.objects.get_by_site(slug=slug) #products = list(category.active_products()) products = list(category.active_products()) if len(products): productsAndPrice = [] for p in products: price = -p.unit_price productsAndPrice.append([price,p]) productsAndPrice.sort() sortedProducts = [] for pp in productsAndPrice: sortedProducts.append(pp[1]) products = sortedProducts # sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing(request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() cart = Cart.objects.from_request(request) if cart.numItems > 0: productsInCart = [item.product for item in cart.cartitem_set.all()] sale = find_best_auto_discount(productsInCart) else: sale = None ctx = { 'category': category, 'child_categories': child_categories, 'sale' : sale, 'products' : products, 'order_by' : 'price_dec' } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, context_instance=RequestContext(request, ctx)) else: try: category = Category.objects.get_by_site(slug=slug) #products = list(category.active_products()) products = list(category.active_products()) # productsAndPrice = [] # for p in products: # price = p.unit_price # productsAndPrice.append([price,p]) # productsAndPrice.sort() # sortedProducts = [] # for pp in productsAndPrice: # sortedProducts.append(pp[1]) # products = sortedProducts # sale = find_best_auto_discount(products) except Category.DoesNotExist: return bad_or_missing(request, _('The category you have requested does not exist.')) child_categories = category.get_all_children() cart = Cart.objects.from_request(request) if cart.numItems > 0: productsInCart = [item.product for item in cart.cartitem_set.all()] sale = find_best_auto_discount(productsInCart) else: sale = None ctx = { 'category': category, 'child_categories': child_categories, 'sale' : sale, 'products' : products, } index_prerender.send(Product, request=request, context=ctx, category=category, object_list=products) return render_to_response(template, context_instance=RequestContext(request, ctx))