def _handle_voucher(request, prefix): ''' Handles a voucher form in the given request. Returns the voucher form instance, and whether the voucher code was handled. ''' voucher_form = forms.VoucherForm(request.POST or None, prefix=prefix) current_cart = CartController.for_user(request.user) if (voucher_form.is_valid() and voucher_form.cleaned_data["voucher"].strip()): voucher = voucher_form.cleaned_data["voucher"] voucher = inventory.Voucher.normalise_code(voucher) if len(current_cart.cart.vouchers.filter(code=voucher)) > 0: # This voucher has already been applied to this cart. # Do not apply code handled = False else: try: current_cart.apply_voucher(voucher) except Exception as e: voucher_form.add_error("voucher", e) handled = True else: handled = False return (voucher_form, handled)
def handle_voucher(request, prefix): ''' Handles a voucher form in the given request. Returns the voucher form instance, and whether the voucher code was handled. ''' voucher_form = forms.VoucherForm(request.POST or None, prefix=prefix) current_cart = CartController.for_user(request.user) if (voucher_form.is_valid() and voucher_form.cleaned_data["voucher"].strip()): voucher = voucher_form.cleaned_data["voucher"] voucher = inventory.Voucher.normalise_code(voucher) if len(current_cart.cart.vouchers.filter(code=voucher)) > 0: # This voucher has already been applied to this cart. # Do not apply code handled = False else: try: current_cart.apply_voucher(voucher) except Exception as e: voucher_form.add_error("voucher", e) handled = True else: handled = False return (voucher_form, handled)
def checkout(request): ''' Runs the checkout process for the current cart. If the query string contains ``fix_errors=true``, Registrasion will attempt to fix errors preventing the system from checking out, including by cancelling expired discounts and vouchers, and removing any unavailable products. Returns: render or redirect: If the invoice is generated successfully, or there's already a valid invoice for the current cart, redirect to ``invoice``. If there are errors when generating the invoice, render ``registrasion/checkout_errors.html`` with the following data:: { "error_list", [str, ...] # The errors to display. } ''' current_cart = CartController.for_user(request.user) if "fix_errors" in request.GET and request.GET["fix_errors"] == "true": current_cart.fix_simple_errors() try: current_invoice = InvoiceController.for_cart(current_cart.cart) except ValidationError as ve: return _checkout_errors(request, ve) return redirect("invoice", current_invoice.invoice.id)
def extend_reservation(request, user_id, days=7): ''' Allows staff to extend the reservation on a given user's cart. ''' user = User.objects.get(id=int(user_id)) cart = CartController.for_user(user) cart.extend_reservation(datetime.timedelta(days=days)) return redirect(request.META["HTTP_REFERER"])
def handle_products(request, category, products, prefix): ''' Handles a products list form in the given request. Returns the form instance, the discounts applicable to this form, and whether the contents were handled. ''' current_cart = CartController.for_user(request.user) ProductsForm = forms.ProductsForm(category, products) # Create initial data for each of products in category items = commerce.ProductItem.objects.filter( product__in=products, cart=current_cart.cart, ).select_related("product") quantities = [] seen = set() for item in items: quantities.append((item.product, item.quantity)) seen.add(item.product) zeros = set(products) - seen for product in zeros: quantities.append((product, 0)) products_form = ProductsForm( request.POST or None, product_quantities=quantities, prefix=prefix, ) if request.method == "POST" and products_form.is_valid(): if products_form.has_changed(): set_quantities_from_products_form(products_form, current_cart) # If category is required, the user must have at least one # in an active+valid cart if category.required: carts = commerce.Cart.objects.filter(user=request.user) items = commerce.ProductItem.objects.filter( product__category=category, cart=carts, ) if len(items) == 0: products_form.add_error( None, "You must have at least one item from this category", ) handled = False if products_form.errors else True discounts = discount.available_discounts(request.user, [], products) return products_form, discounts, handled
def checkout(request): ''' Runs checkout for the current cart of items, ideally generating an invoice. ''' current_cart = CartController.for_user(request.user) if "fix_errors" in request.GET and request.GET["fix_errors"] == "true": current_cart.fix_simple_errors() try: current_invoice = InvoiceController.for_cart(current_cart.cart) except ValidationError as ve: return checkout_errors(request, ve) return redirect("invoice", current_invoice.invoice.id)
def checkout(request, user_id=None): ''' Runs the checkout process for the current cart. If the query string contains ``fix_errors=true``, Registrasion will attempt to fix errors preventing the system from checking out, including by cancelling expired discounts and vouchers, and removing any unavailable products. Arguments: user_id (castable to int): If the requesting user is staff, then the user ID can be used to run checkout for another user. Returns: render or redirect: If the invoice is generated successfully, or there's already a valid invoice for the current cart, redirect to ``invoice``. If there are errors when generating the invoice, render ``registrasion/checkout_errors.html`` with the following data:: { "error_list", [str, ...] # The errors to display. } ''' if user_id is not None: if request.user.is_staff: user = User.objects.get(id=int(user_id)) else: raise Http404() else: user = request.user current_cart = CartController.for_user(user) if "fix_errors" in request.GET and request.GET["fix_errors"] == "true": current_cart.fix_simple_errors() try: current_invoice = InvoiceController.for_cart(current_cart.cart) except ValidationError as ve: return _checkout_errors(request, ve) return redirect("invoice", current_invoice.invoice.id)
def amend_registration(request, user_id): ''' Allows staff to amend a user's current registration cart, and etc etc. ''' user = User.objects.get(id=int(user_id)) current_cart = CartController.for_user(user) items = commerce.ProductItem.objects.filter( cart=current_cart.cart, ).select_related("product") initial = [{"product": i.product, "quantity": i.quantity} for i in items] StaffProductsFormSet = forms.staff_products_formset_factory(user) formset = StaffProductsFormSet( request.POST or None, initial=initial, prefix="products", ) for item, form in zip(items, formset): queryset = inventory.Product.objects.filter(id=item.product.id) form.fields["product"].queryset = queryset voucher_form = forms.VoucherForm( request.POST or None, prefix="voucher", ) if request.POST and formset.is_valid(): pq = [ (f.cleaned_data["product"], f.cleaned_data["quantity"]) for f in formset if "product" in f.cleaned_data and f.cleaned_data["product"] is not None ] try: current_cart.set_quantities(pq) return redirect(amend_registration, user_id) except ValidationError as ve: for ve_field in ve.error_list: product, message = ve_field.message for form in formset: if "product" not in form.cleaned_data: # This is the empty form. continue if form.cleaned_data["product"] == product: form.add_error("quantity", message) if request.POST and voucher_form.has_changed() and voucher_form.is_valid(): try: current_cart.apply_voucher(voucher_form.cleaned_data["voucher"]) return redirect(amend_registration, user_id) except ValidationError as ve: voucher_form.add_error(None, ve) ic = ItemController(user) data = { "user": user, "paid": ic.items_purchased(), "cancelled": ic.items_released(), "form": formset, "voucher_form": voucher_form, } return render(request, "registrasion/amend_registration.html", data)
def attendee(request, form, user_id=None): ''' Returns a list of all manifested attendees if no attendee is specified, else displays the attendee manifest. ''' if user_id is None and form.cleaned_data["user"] is not None: user_id = form.cleaned_data["user"] if user_id is None: return attendee_list(request) attendee = people.Attendee.objects.get(user__id=user_id) name = attendee.attendeeprofilebase.attendee_name() reports = [] profile_data = [] try: profile = people.AttendeeProfileBase.objects.get_subclass( attendee=attendee) fields = profile._meta.get_fields() except people.AttendeeProfileBase.DoesNotExist: fields = [] exclude = set(["attendeeprofilebase_ptr", "id"]) for field in fields: if field.name in exclude: # Not actually important continue if not hasattr(field, "verbose_name"): continue # Not a publicly visible field value = getattr(profile, field.name) if isinstance(field, models.ManyToManyField): value = ", ".join(str(i) for i in value.all()) profile_data.append((field.verbose_name, value)) cart = CartController.for_user(attendee.user) reservation = cart.cart.reservation_duration + cart.cart.time_last_updated profile_data.append(("Current cart reserved until", reservation)) reports.append(ListReport("Profile", ["", ""], profile_data)) links = [] links.append(( reverse(views.badge, args=[user_id]), "View badge", )) links.append(( reverse(views.amend_registration, args=[user_id]), "Amend current cart", )) links.append(( reverse(views.extend_reservation, args=[user_id]), "Extend reservation", )) reports.append(Links("Actions for " + name, links)) # Paid and pending products ic = ItemController(attendee.user) reports.append( ListReport( "Paid Products", ["Product", "Quantity"], [(pq.product, pq.quantity) for pq in ic.items_purchased()], )) reports.append( ListReport( "Unpaid Products", ["Product", "Quantity"], [(pq.product, pq.quantity) for pq in ic.items_pending()], )) # Invoices invoices = commerce.Invoice.objects.filter(user=attendee.user, ) reports.append( QuerysetReport( "Invoices", ["id", "get_status_display", "value"], invoices, headings=["Invoice ID", "Status", "Value"], link_view=views.invoice, )) # Credit Notes credit_notes = commerce.CreditNote.objects.filter( invoice__user=attendee.user, ).select_related("invoice", "creditnoteapplication", "creditnoterefund") reports.append( QuerysetReport( "Credit Notes", ["id", "status", "value"], credit_notes, link_view=views.credit_note, )) # All payments payments = commerce.PaymentBase.objects.filter( invoice__user=attendee.user, ).select_related("invoice") reports.append( QuerysetReport( "Payments", ["invoice__id", "id", "reference", "amount"], payments, link_view=views.invoice, )) return reports