I have two models orders/carts. I got braintreee implemented and working fine with sandbox. Now need to get cashondelivery model implemented with minimum iteration. So I did created a form out of field "payment_options" from Order models. I need help to generalize the process to implement COD. I know its a lengthy code set but I would appreciate if someone can take couple minutes to look at it. Secondly its not letting me call two different forms in my carts CheckoutView so some help would be great. For the sake of process I had to provide complete set of code so please don't mind if question is over populated. Following is my code:
Orders/models.py: from decimal import Decimal from django.conf import settings from django.core.urlresolvers import reverse from django.db import models from django.db.models.signals import pre_save, post_save from carts.models import Cart import braintree if settings.DEBUG: braintree.Configuration.configure(braintree.Environment.Sandbox, merchant_id=settings.BRAINTREE_MERCHANT_ID, public_key=settings.BRAINTREE_PUBLIC, private_key=settings.BRAINTREE_PRIVATE) class UserCheckout(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True) #not required email = models.EmailField(unique=True) #--> required braintree_id = models.CharField(max_length=120, null=True, blank=True) def __unicode__(self): #def __str__(self): return self.email @property def get_braintree_id(self,): instance = self if not instance.braintree_id: result = braintree.Customer.create({ "email": instance.email, }) if result.is_success: instance.braintree_id = *result.customer.id* <http://result.customer.id/> instance.save() return instance.braintree_id def get_client_token(self): customer_id = self.get_braintree_id if customer_id: client_token = braintree.ClientToken.generate({ "customer_id": customer_id }) return client_token return None def update_braintree_id(sender, instance, *args, **kwargs): if not instance.braintree_id: instance.get_braintree_id post_save.connect(update_braintree_id, sender=UserCheckout) ADDRESS_TYPE = ( ('billing', 'Billing'), ('shipping', 'Shipping'), ) class UserAddress(models.Model): user = models.ForeignKey(UserCheckout) type = models.CharField(max_length=120, choices=ADDRESS_TYPE) street = models.CharField(max_length=120) city = models.CharField(max_length=120) state = models.CharField(max_length=120) zipcode = models.CharField(max_length=120) def __unicode__(self): return self.street def get_address(self): return "%s, %s, %s %s" %(self.street, self.city, self.state, self.zipcode) ORDER_STATUS_CHOICES = ( ('created', 'Created'), ('paid', 'Paid'), ('shipped', 'Shipped'), ('refunded', 'Refunded'), ) PAYMENT_BY =( ('paypal', 'Paypal'), ('creditcard', 'Credit Card'), ('cash on delivery', 'Cash On Delivery'), ) class Order(models.Model): status = models.CharField(max_length=120, choices=ORDER_STATUS_CHOICES, default='created') cart = models.ForeignKey(Cart) user = models.ForeignKey(UserCheckout, null=True) billing_address = models.ForeignKey(UserAddress, related_name='billing_address', null=True) shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address', null=True) shipping_total_price = models.DecimalField(max_digits=50, decimal_places=2, default=5.99) order_total = models.DecimalField(max_digits=50, decimal_places=2, ) order_id = models.CharField(max_length=20, null=True, blank=True) payment_options = models.CharField(max_length=20, choices=PAYMENT_BY) def __unicode__(self): return str(*self.cart.id* <http://self.cart.id/>) class Meta: ordering = ['-id'] def get_absolute_url(self): return reverse("order_detail", kwargs={"pk": *self.pk* <http://self.pk/>}) def mark_completed(self, order_id=None): self.status = "paid" if order_id and not self.order_id: self.order_id = order_id self.save() def order_pre_save(sender, instance, *args, **kwargs): shipping_total_price = instance.shipping_total_price cart_total = instance.cart.total order_total = Decimal(shipping_total_price) + Decimal(cart_total) instance.order_total = order_total Orders/forms.py: from django import forms from django.contrib.auth import get_user_model from .models import Order from .models import UserAddress User = get_user_model() class GuestCheckoutForm(forms.Form): email = forms.EmailField() email2 = forms.EmailField(label='Verify Email') def clean_email2(self): email = self.cleaned_data.get("email") email2 = self.cleaned_data.get("email2") if email == email2: user_exists = User.objects.filter(email=email).count() if user_exists != 0: raise forms.ValidationError("This User already exists. Please login instead.") return email2 else: raise forms.ValidationError("Please confirm emails are the same") class AddressForm(forms.Form): billing_address = forms.ModelChoiceField( queryset=UserAddress.objects.filter(type="billing"), widget = forms.RadioSelect, empty_label = None ) shipping_address = forms.ModelChoiceField( queryset=UserAddress.objects.filter(type="shipping"), widget = forms.RadioSelect, empty_label = None, ) class UserAddressForm(forms.ModelForm): class Meta: model = UserAddress fields = [ 'street', 'city', 'state', 'zipcode', 'type' ] class OrderForm(forms.ModelForm): class Meta: model = Order fields = [ 'payment_options' ] Orders/views.py: from django.contrib import messages from django.http import Http404 from django.shortcuts import redirect from django.views.generic.edit import CreateView, FormView from django.views.generic.detail import DetailView from django.views.generic.list import ListView from .forms import AddressForm, UserAddressForm from .mixins import CartOrderMixin, LoginRequiredMixin from .models import UserAddress, UserCheckout, Order class OrderDetail(DetailView): model = Order def dispatch(self, request, *args, **kwargs): try: user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) except UserCheckout.DoesNotExist: user_checkout = UserCheckout.objects.get(user=request.user) except: user_checkout = None obj = self.get_object() if obj.user == user_checkout and user_checkout is not None: return super(OrderDetail, self).dispatch(request, *args, **kwargs) else: raise Http404 class OrderList(ListView): queryset = Order.objects.all() def get_queryset(self): user_check_id = *self.request.user.id* <http://self.request.user.id/> user_checkout = UserCheckout.objects.get(id=user_check_id) return super(OrderList, self).get_queryset().filter(user=user_checkout) class UserAddressCreateView(CreateView): form_class = UserAddressForm template_name = "forms.html" success_url = "/checkout/address/" def get_checkout_user(self): user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) return user_checkout def form_valid(self, form, *args, **kwargs): form.instance.user = self.get_checkout_user() return super(UserAddressCreateView, self).form_valid(form, *args, **kwargs) class AddressSelectFormView(CartOrderMixin, FormView): form_class = AddressForm template_name = "orders/address_select.html" def dispatch(self, *args, **kwargs): b_address, s_address = self.get_addresses() if b_address.count() == 0: messages.success(self.request, "Please add a billing address before continuing") return redirect("user_address_create") elif s_address.count() == 0: messages.success(self.request, "Please add a shipping address before continuing") return redirect("user_address_create") else: return super(AddressSelectFormView, self).dispatch(*args, **kwargs) def get_addresses(self, *args, **kwargs): user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) b_address = UserAddress.objects.filter( user=user_checkout, type='billing', ) s_address = UserAddress.objects.filter( user=user_checkout, type='shipping', ) return b_address, s_address def get_form(self, *args, **kwargs): form = super(AddressSelectFormView, self).get_form(*args, **kwargs) b_address, s_address = self.get_addresses() form.fields["billing_address"].queryset = b_address form.fields["shipping_address"].queryset = s_address return form def form_valid(self, form, *args, **kwargs): billing_address = form.cleaned_data["billing_address"] shipping_address = form.cleaned_data["shipping_address"] order = self.get_order() order.billing_address = billing_address order.shipping_address = shipping_address order.save() return super(AddressSelectFormView, self).form_valid(form, *args, **kwargs) def get_success_url(self, *args, **kwargs): return "/checkout/" Carts/models.py: from decimal import Decimal from django.conf import settings from django.core.urlresolvers import reverse from django.db import models from django.db.models.signals import pre_save, post_save, post_delete from products.models import Variation class CartItem(models.Model): cart = models.ForeignKey("Cart") item = models.ForeignKey(Variation) quantity = models.PositiveIntegerField(default=1) line_item_total = models.DecimalField(max_digits=10, decimal_places=2) def __unicode__(self): return self.item.title def remove(self): return self.item.remove_from_cart() def cart_item_pre_save_receiver(sender, instance, *args, **kwargs): qty = instance.quantity if qty >= 1: price = instance.item.get_price() line_item_total = Decimal(qty) * Decimal(price) instance.line_item_total = line_item_total pre_save.connect(cart_item_pre_save_receiver, sender=CartItem) def cart_item_post_save_receiver(sender, instance, *args, **kwargs): instance.cart.update_subtotal() post_save.connect(cart_item_post_save_receiver, sender=CartItem) post_delete.connect(cart_item_post_save_receiver, sender=CartItem) class Cart(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True) items = models.ManyToManyField(Variation, through=CartItem) timestamp = models.DateTimeField(auto_now_add=True, auto_now=False) updated = models.DateTimeField(auto_now_add=False, auto_now=True) subtotal = models.DecimalField(max_digits=50, decimal_places=2, default=25.00) tax_percentage = models.DecimalField(max_digits=10, decimal_places=5, default=0.085) tax_total = models.DecimalField(max_digits=50, decimal_places=2, default=25.00) total = models.DecimalField(max_digits=50, decimal_places=2, default=25.00) # discounts # shipping def __unicode__(self): return str(*self.id* <http://self.id/>) def update_subtotal(self): print "updating..." subtotal = 0 items = self.cartitem_set.all() for item in items: subtotal += item.line_item_total self.subtotal = "%.2f" %(subtotal) self.save() def do_tax_and_total_receiver(sender, instance, *args, **kwargs): subtotal = Decimal(instance.subtotal) tax_total = round(subtotal * Decimal(instance.tax_percentage), 2) #8.5% print instance.tax_percentage total = round(subtotal + Decimal(tax_total), 2) instance.tax_total = "%.2f" %(tax_total) instance.total = "%.2f" %(total) #instance.save() pre_save.connect(do_tax_and_total_receiver, sender=Cart) *Carts/views.py:* import braintree from django.conf import settings from django.contrib import messages from django.contrib.auth.forms import AuthenticationForm from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect, Http404, JsonResponse from django.shortcuts import render, get_object_or_404, redirect from django.views.generic.base import View from django.views.generic.detail import SingleObjectMixin, DetailView from django.views.generic.edit import FormMixin from orders.forms import GuestCheckoutForm, OrderForm from orders.mixins import CartOrderMixin from orders.models import UserCheckout, Order, UserAddress from products.models import Variation from .models import Cart, CartItem if settings.DEBUG: braintree.Configuration.configure(braintree.Environment.Sandbox, merchant_id=settings.BRAINTREE_MERCHANT_ID, public_key=settings.BRAINTREE_PUBLIC, private_key=settings.BRAINTREE_PRIVATE) class ItemCountView(View): def get(self, request, *args, **kwargs): if request.is_ajax(): cart_id = self.request.session.get("cart_id") if cart_id == None: count = 0 else: cart = Cart.objects.get(id=cart_id) count = cart.items.count() request.session["cart_item_count"] = count return JsonResponse({"count": count}) else: raise Http404 class CartView(SingleObjectMixin, View): model = Cart template_name = "carts/view.html" def get_object(self, *args, **kwargs): self.request.session.set_expiry(0) #5 minutes cart_id = self.request.session.get("cart_id") if cart_id == None: cart = Cart() cart.tax_percentage = 0.075 cart.save() cart_id = *cart.id* <http://cart.id/> self.request.session["cart_id"] = cart_id cart = Cart.objects.get(id=cart_id) if self.request.user.is_authenticated(): cart.user = self.request.user cart.save() return cart def get(self, request, *args, **kwargs): cart = self.get_object() item_id = request.GET.get("item") delete_item = request.GET.get("delete", False) flash_message = "" item_added = False if item_id: item_instance = get_object_or_404(Variation, id=item_id) qty = request.GET.get("qty", 1) try: if int(qty) < 1: delete_item = True except: raise Http404 cart_item, created = CartItem.objects.get_or_create(cart=cart, item=item_instance) if created: flash_message = "Successfully added to the cart" item_added = True if delete_item: flash_message = "Item removed successfully." cart_item.delete() else: if not created: flash_message = "Quantity has been updated successfully." cart_item.quantity = qty cart_item.save() if not request.is_ajax(): return HttpResponseRedirect(reverse("cart")) #return cart_item.cart.get_absolute_url() if request.is_ajax(): try: total = cart_item.line_item_total except: total = None try: subtotal = cart_item.cart.subtotal except: subtotal = None try: cart_total = cart_item.cart.total except: cart_total = None try: tax_total = cart_item.cart.tax_total except: tax_total = None try: total_items = cart_item.cart.items.count() except: total_items = 0 data = { "deleted": delete_item, "item_added": item_added, "line_total": total, "subtotal": subtotal, "cart_total": cart_total, "tax_total": tax_total, "flash_message": flash_message, "total_items": total_items } return JsonResponse(data) context = { "object": self.get_object() } template = self.template_name return render(request, template, context) class CheckoutView(CartOrderMixin, FormMixin, DetailView): model = Cart template_name = "carts/checkout_view.html" form_class = GuestCheckoutForm def get_object(self, *args, **kwargs): cart = self.get_cart() if cart == None: return None return cart def get_context_data(self, *args, **kwargs): context = super(CheckoutView, self).get_context_data(*args, **kwargs) user_can_continue = False user_check_id = self.request.session.get("user_checkout_id") if self.request.user.is_authenticated(): user_can_continue = True user_checkout, created = UserCheckout.objects.get_or_create(email=self.request.user.email) user_checkout.user = self.request.user user_checkout.save() context["client_token"] = user_checkout.get_client_token() self.request.session["user_checkout_id"] = *user_checkout.id* <http://user_checkout.id/> elif not self.request.user.is_authenticated() and user_check_id == None: context["login_form"] = AuthenticationForm() context["next_url"] = self.request.build_absolute_uri() else: pass if user_check_id != None: user_can_continue = True if not self.request.user.is_authenticated(): #GUEST USER user_checkout_2 = UserCheckout.objects.get(id=user_check_id) context["client_token"] = user_checkout_2.get_client_token() #if self.get_cart() is not None: context["order"] = self.get_order() context["user_can_continue"] = user_can_continue context["form"] = self.get_form() return context def post(self, request, *args, **kwargs): self.object = self.get_object() form = self.get_form() if form.is_valid(): email = form.cleaned_data.get("email") user_checkout, created = UserCheckout.objects.get_or_create(email=email) request.session["user_checkout_id"] = *user_checkout.id* <http://user_checkout.id/> return self.form_valid(form) else: return self.form_invalid(form) def get_success_url(self): return reverse("checkout") def get(self, request, *args, **kwargs): get_data = super(CheckoutView, self).get(request, *args, **kwargs) cart = self.get_object() if cart == None: return redirect("cart") new_order = self.get_order() user_checkout_id = request.session.get("user_checkout_id") if user_checkout_id != None: user_checkout = UserCheckout.objects.get(id=user_checkout_id) if new_order.billing_address == None or new_order.shipping_address == None: return redirect("order_address") new_order.user = user_checkout new_order.save() return get_data class CheckoutFinalView(CartOrderMixin, View): def post(self, request, *args, **kwargs): order = self.get_order() order_total = order.order_total nonce = request.POST.get("payment_method_nonce") payment_options = order.payment_options if nonce: result = braintree.Transaction.sale({ "amount": order_total, "payment_method_nonce": nonce, "billing": { "postal_code": "%s" %(order.billing_address.zipcode), }, "options": { "submit_for_settlement": True } }) if result.is_success: #*result.transaction.id* <http://result.transaction.id/> to order order.mark_completed(order_id=result.transaction.id) messages.success(request, "Thank you for your order.") del request.session["cart_id"] del request.session["order_id"] else: #messages.success(request, "There was a problem with your order.") messages.success(request, "%s" %(result.message)) return redirect("checkout") else: if payment_options == 'Cash On Delivery': order.mark_completed() messages.success(request, "Thank you for your order.") del request.session['cart_id'] del request.session['order_id'] return redirect("checkout") return redirect("order_detail", pk=*order.pk* <http://order.pk/>) def get(self, request, *args, **kwargs): return redirect("checkout") Please advise how to create a cash on delivery process based on above code -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ff14511d-7bb3-4d5e-b041-7b012f2cc1f3%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.