123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #!/usr/bin/env python
- """ Django models for cart """
- # -*- coding: utf-8 -*-
- from decimal import Decimal
- from django.db import models
- from django.utils.translation import ugettext_lazy as _
- from django.contrib.contenttypes.models import ContentType
- from django.contrib.auth.models import User
- from .managers import CartManager, CartItemManager
- from pbp_core.utils import temp_code, pbp_converter
- class Cart(models.Model):
- """ Shopping cart """
- # basically session_key
- cart_id = models.CharField(max_length=50, db_index=True)
- owner = models.ForeignKey(User, related_name="cart", null=True, blank=True)
- creation_date = models.DateTimeField(auto_now_add=True)
- last_update = models.DateTimeField(auto_now_add=True, auto_now=True)
- checked_out = models.BooleanField(default=False)
- objects = CartManager()
- class Meta:
- """ Django model meta class """
- verbose_name = _("Cart")
- verbose_name_plural = _("Carts")
- ordering = ("-creation_date",)
- def __unicode__(self):
- """ unicode name of model """
- return u"Cart: {0}".format(unicode(self.cart_id))
- @property
- def has_items(self):
- """ is the cart empty?"""
- return self.item_count > 0
- @property
- def cart_items(self):
- """ return all cart items"""
- return self.items.all()
- @property
- def item_count(self):
- """ number of items """
- return self.items.count()
- @property
- def cart_shipping_total(self):
- """ Total shipping cost"""
- price = Decimal(0.0)
- for item in self.cart_items:
- price = price + item.total_shipping_cost
- return price
- @property
- def cart_subtotal(self):
- """ cart subtotal"""
- price = Decimal(0.0)
- for item in self.cart_items:
- price = price + item.total_price
- return price
- @property
- def cart_total(self):
- """ total cart cost"""
- return self.cart_subtotal + self.cart_shipping_total
- @property
- def purchase_description(self):
- """ the purchase description for carts """
- description = ""
- for item in self.cart_items:
- description = description + "<br>" + item.by_line
- return description
- @property
- def buyer_id(self):
- """ the buyer for the person who created the cart"""
- if self.owner:
- return self.owner.pk
- return None
- class CartItemGiftDetail(models.Model):
- """ Cart Item gift detail """
- first_name = models.CharField(max_length=30)
- last_name = models.CharField(max_length=30)
- company = models.CharField(max_length=30, blank=True, null=True)
- address1 = models.CharField(max_length=30)
- address2 = models.CharField(max_length=30, blank=True, null=True)
- city = models.CharField(max_length=30)
- region = models.CharField(max_length=30)
- phone = models.CharField(max_length=30)
- country = models.CharField(max_length=30)
- country_other = models.CharField(max_length=30)
- postal_code = models.CharField(max_length=30)
- plus_four = models.CharField(max_length=4)
- email = models.CharField(max_length=30)
- bill_on_renewal = models.CharField(max_length=10)
- gift_card_delivery = models.CharField(max_length=10)
- message = models.CharField(max_length=72, null=True, blank=True)
- class CartItem(models.Model):
- """ Cart items """
- cart = models.ForeignKey(Cart, verbose_name=_("cart"), related_name="items")
- quantity = models.PositiveIntegerField(verbose_name=_("quantity"))
- # need a unique value we can reference when editing
- # that won't be easy to spoof
- cart_token = models.CharField(_("Cart Token"), max_length=255, db_index=True)
- # product as generic relation
- content_type = models.ForeignKey(ContentType)
- object_id = models.PositiveIntegerField()
- gift_detail = models.OneToOneField(CartItemGiftDetail, null=True, blank=True)
- account_number = models.CharField(max_length=7, null=True, blank=True)
- class Meta:
- """ Model meta class"""
- verbose_name = _("item")
- verbose_name_plural = _("items")
- ordering = ("cart",)
- objects = CartItemManager()
- def __unicode__(self):
- """ unicode repr of class """
- return "Item in cart: " + unicode(self.product)
- def save(self, *args, **kwargs):
- """ We need to set the cart_token to make sure it is unique """
- # This check should be skipped since cart_token is required.
- # keeping it in for now to clean up stale data
- if not self.cart_token:
- if not self.pk:
- self.cart_token = temp_code()
- super(CartItem, self).save(*args, **kwargs)
- # saving with force_insert twice leads to sad
- kwargs.pop("force_insert", None)
- encode_value = pbp_converter.encode(str(self.pk))
- self.cart_token = "P%s" % encode_value
- super(CartItem, self).save(*args, **kwargs)
- @property
- def is_gift(self):
- """ is this a gift? """
- if self.gift_detail:
- return True
- return False
- @property
- def image(self):
- """ get the image """
- return self.product.image
- @property
- def unit_price(self):
- """ unit price """
- return self.product.price
- @property
- def name(self):
- """ name """
- return self.product.title
- @property
- def description(self):
- """ description """
- return self.product.description
- @property
- def by_line(self):
- """ get the byline"""
- return "{0} {1}".format(self.name, self.description)
- @property
- def sku(self):
- """ get the sku """
- return self.product.sku
- @property
- def total_shipping_cost(self):
- """ Shipping costs. If there is just one item take the shipping_cost
- from the product, if there is more then one, for each item after the
- first one, the shipping cost is shipping_cost_multiple for each item
- total them together to get the total shipping cost
- """
- initial_cost = self.product.shipping_cost
- extra_item_costs = self.product.shipping_cost_multiple
- if self.quantity == 0:
- return 0.0
- if self.quantity == 1:
- return initial_cost
- elif self.quantity > 1:
- return initial_cost + ((self.quantity - 1) * extra_item_costs)
- @property
- def total_price(self):
- """ total price """
- return self.quantity * self.unit_price
- @property
- def sub_total(self):
- """ price including shipping """
- return self.total_price + self.total_shipping_cost
- def get_product(self):
- """ get the product """
- return self.content_type.get_object_for_this_type(id=self.object_id)
- def set_product(self, product):
- """ set the product """
- self.content_type = ContentType.objects.get_for_model(type(product))
- self.object_id = product.pk
- product = property(get_product, set_product)
|