Coverage for /home/chris/workspace/django-shop/shop/models/cartmodel: 97.62%

# Coverage for /home/chris/workspace/django-shop/shop/models/cartmodel : 97.62%

## 70 statements 69 run 1 missing 0 excluded 1 partial

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # -*- coding: utf-8 -*- from decimal import Decimal from django.contrib.auth.models import User from django.db import models from shop.cart.modifiers_pool import cart_modifiers_pool from shop.models.productmodel import Product class Cart(models.Model): """ This should be a rather simple list of items. Ideally it should be bound to a session and not to a User is we want to let people buy from our shop without having to register with us. """ # If the user is null, that means this is used for a session user = models.OneToOneField(User, null=True, blank=True) date_created = models.DateTimeField(auto_now_add=True) last_updated = models.DateTimeField(auto_now=True) class Meta: app_label = 'shop' def __init__(self, *args, **kwargs): super(Cart, self).__init__(*args,**kwargs) # That will hold things like tax totals or total discount self.subtotal_price = Decimal('0.0') self.total_price = Decimal('0.0') self.extra_price_fields = [] # List of tuples (label, value) def add_product(self,product, quantity=1): """ Adds a (new) product to the cart """ # Let's see if we already have an Item with the same product ID if CartItem.objects.filter(cart=self).filter(product=product).exists(): cart_item = CartItem.objects.filter(cart=self).filter(product=product)[0] cart_item.quantity = cart_item.quantity + int(quantity) cart_item.save() else: cart_item = CartItem.objects.create(cart=self,quantity=quantity,product=product) cart_item.save() self.save() # to get the last updated timestamp def update_quantity(self, cart_item_id, quantity): """ Updates the quantity for given cart item or deletes it if its quantity reaches `0` """ cart_item = self.items.get(pk=cart_item_id) 52 if quantity == 0: cart_item.delete() else: cart_item.quantity = quantity cart_item.save() self.save() def delete_item(self, cart_item_id): """ A simple convenience method to delete one of the cart's items. This allows to implicitely check for "access rights" since we insure the cartitem is actually in the user's cart """ cart_item = self.items.get(pk=cart_item_id) cart_item.delete() self.save() def update(self): """ This should be called whenever anything is changed in the cart (added or removed) It will loop on all line items in the cart, and call all the price modifiers on each row. After doing this, it will compute and update the order's total and subtotal fields, along with any payment field added along the way by modifiers. Note that theses added fields are not stored - we actually want to reflect rebate and tax changes on the *cart* items, but we don't want that for the order items (since they are legally binding after the "purchase" button was pressed) """ items = CartItem.objects.filter(cart=self) self.subtotal_price = Decimal('0.0') # Reset the subtotal for item in items: # For each OrderItem (order line)... self.subtotal_price = self.subtotal_price + item.update() item.save() # Now we have to iterate over the registered modifiers again (unfortunately) # to pass them the whole Order this time for modifier in cart_modifiers_pool.get_modifiers_list(): modifier.process_cart(self) self.total_price = self.subtotal_price # Like for line items, most of the modifiers will simply add a field # to extra_price_fields, let's update the total with them for label, value in self.extra_price_fields: self.total_price = self.total_price + value def empty(self): """ Remove all cart items """ self.items.all().delete() self.delete() @property def total_quantity(self): """ Returns the total quantity of all items in the cart """ return sum([ci.quantity for ci in self.items.all()]) class CartItem(models.Model): """ This is a holder for the quantity of items in the cart and, obviously, a pointer to the actual Product being purchased :) """ cart = models.ForeignKey(Cart, related_name="items") quantity = models.IntegerField() product = models.ForeignKey(Product) class Meta: app_label = 'shop' def __init__(self, *args, **kwargs): # That will hold extra fields to display to the user # (ex. taxes, discount) super(CartItem, self).__init__(*args,**kwargs) self.extra_price_fields = [] # list of tuples (label, value) # These must not be stored, since their components can be changed between # sessions / logins etc... self.line_subtotal = Decimal('0.0') self.line_total = Decimal('0.0') def update(self): self.line_subtotal = self.product.get_price() * self.quantity self.line_total = self.line_subtotal for modifier in cart_modifiers_pool.get_modifiers_list(): # We now loop over every registered price modifier, # most of them will simply add a field to extra_payment_fields modifier.process_cart_item(self) for label, value in self.extra_price_fields: self.line_total = self.line_total + value return self.line_total