def lookup_discount_code(request): amount = 0 order_obj = Order(request) total = order_obj.total order_obj.apply_discount(request.POST.get("discount_code")) new_total = order_obj.total amount = float(total) - float(new_total) ret = {"amount": str(amount), "total": str(new_total)} if order_obj.order.discount: ret.update({"description": order_obj.order.discount.description}) return HttpResponse(json.dumps(ret), mimetype="application/json")
class CheckoutView(FormView): """ Checkout for a single item (no cart) """ template_name = "checkout/form.html" template_name_ajax = "checkout/form.html" empty_redirect = "home" form_class = PaymentForm form_class_signup = SignupForm processor = payment_module.Processor() method = "direct" success_url = "checkout_confirm" messages = { "customer_info_error": { "level": messages.ERROR, "text": _("The payment information could not be validated") } } def get(self, *args, **kwargs): self.order_obj = Order(self.request) if not self.order_obj.order.items.count(): return redirect(self.empty_redirect) if (not self.request.user.is_authenticated() and not CHECKOUT["ANONYMOUS_CHECKOUT"]): self.form_class = self.form_class_signup return super(CheckoutView, self).get(*args, **kwargs) def post(self, *args, **kwargs): self.order_obj = Order(self.request) if (not self.request.user.is_authenticated() and not CHECKOUT["ANONYMOUS_CHECKOUT"]): self.form_class = self.form_class_signup incoming = self.retrieve_item() if self.request.POST.get("discount_code"): self.order_obj.apply_discount( self.request.POST.get("discount_code")) if self.order_obj.total == 0: self.order_obj.update_status(OrderModel.PENDING_PAYMENT) # goal: remove payment-related requirements if # no payment is necessary for field in self.form_class.base_fields.keys(): if field in PaymentForm.base_fields.keys(): self.form_class.base_fields[field].required = False return self.post_handler(incoming, *args, **kwargs) def post_handler(self, incoming, *args, **kwargs): if incoming: form = self.get_form_class()(initial=self.get_initial()) return self.render_to_response(self.get_context_data(form=form)) elif not self.order_obj.order.items.count(): return redirect(self.empty_redirect) return super(CheckoutView, self).post(*args, **kwargs) def retrieve_item(self): cf = CustomItemForm(self.request.POST) if cf.is_valid(): # clear any preexisting items self.order_obj.clear() # add item self.order_obj.add( cf.cleaned_data.get("item_amount"), description=cf.cleaned_data.get("item_description")) self.order_obj.update_totals() return True return False def get_initial(self): initial = super(CheckoutView, self).get_initial() if self.request.user.is_authenticated(): initial.update({ "billing_first_name": self.request.user.first_name, "billing_last_name": self.request.user.last_name }) initial["amount"] = self.order_obj.total if self.order_obj.get_transactions().count(): billing_data = self.order_obj.get_transactions().latest() for field_name in self.form_class().fields: if hasattr(billing_data, field_name): initial[field_name] = getattr(billing_data, field_name) return initial def get_context_data(self, **kwargs): ctx = kwargs if self.order_obj.order.discount: ctx["discount"] = self.order_obj.order.discount_amount ctx.update({ "checkout_method": self.method, "order": self.order_obj.order, }) return ctx def form_valid(self, form): if self.request.POST.get("referral_source"): referral = self.request.POST["referral_source"] if referral == "Other" and self.request.POST.get( "referral_source_other"): referral = self.request.POST["referral_source_other"] self.order_obj.add_referral(referral) self.order_obj.order.email = form.cleaned_data["email"] self.order_obj.order.save() if (not self.request.user.is_authenticated() and not CHECKOUT["ANONYMOUS_CHECKOUT"]): user = self.create_user(form) user = auth.authenticate(username=user.username, password=form.cleaned_data["password"]) auth.login(self.request, user) self.order_obj.order.user = user self.order_obj.order.save() self.after_signup(user, form) form_data = form.cleaned_data if self.request.user.is_authenticated(): form_data = self.update_from_user(form_data, self.request.user) # if payment is needed if self.order_obj.order.total > 0: success = self.save_customer_info(form_data) else: # no payment needed, e.g. full discount success = True if success: signals.form_complete.send(sender=None, order=self.order_obj.order, form=form) return redirect(self.get_success_url()) else: messages.add_message(self.request, self.messages["customer_info_error"]["level"], self.messages["customer_info_error"]["text"]) return self.form_invalid(form) def update_from_user(self, form_data, user): form_data.update({ "email": user.email, "first_name": user.first_name, "last_name": user.last_name, }) return form_data def form_invalid(self, form): signals.checkout_attempt.send(sender=self.form_class, order=self.order_obj.order, result=form.is_valid()) return super(CheckoutView, self).form_invalid(form) def create_user(self, form, commit=True, **kwargs): user = User(**kwargs) username = form.cleaned_data.get("username") if username is None: username = self.generate_username(form) user.username = username user.email = form.cleaned_data["email"].strip() password = form.cleaned_data.get("password") if password: user.set_password(password) else: user.set_unusable_password() if commit: user.save() return user def after_signup(self, user, form): signals.user_signed_up.send(sender=SignupForm, user=user, form=form) def save_customer_info(self, payment_data): if self.request.user.is_authenticated(): payment_data.update({ "email": self.request.user.email, "first_name": self.request.user.first_name, "last_name": self.request.user.last_name, }) success, reference_id, error, results = self.processor.create_customer( payment_data, customer_id=self.order_obj.order.customer_id) signals.post_create_customer.send(sender=None, user=self.request.user, success=success, reference_id=reference_id, error=error, results=results) if success: self.order_obj.order.customer_id = reference_id self.order_obj.order.save() card_details = self.processor.get_customer_card(reference_id) OrderTransaction.objects.get_or_create( order=self.order_obj.order, amount=self.order_obj.order.total, payment_method=OrderTransaction.CREDIT, last_four=self.processor.get_card_last4(card_details), reference_number=reference_id, billing_first_name=payment_data.get("billing_first_name") or\ payment_data.get("first_name") or\ self.request.user.first_name, billing_last_name=payment_data.get("billing_last_name") or\ payment_data.get("last_name") or \ self.request.user.last_name, billing_address1=payment_data.get("billing_address1", ""), billing_address2=payment_data.get("billing_address2", ""), billing_city=payment_data.get("billing_city", ""), billing_region=payment_data.get("billing_region", ""), billing_postal_code=payment_data.get("billing_postal_code", ""), billing_country=payment_data.get("billing_country", ""), ) self.order_obj.update_totals() self.order_obj.update_status(OrderModel.PENDING_PAYMENT) return True return False