def save(self, request): self.full_clean() for name, value in self.cleaned_data.items(): opt, key = name.split('__') prod = Product.objects.get(slug__exact=key) subtypes = prod.get_subtypes() if opt == 'qty': if value != prod.items_in_stock: messages.add_message( request, messages.INFO, 'Updated %s stock to %s' % (key, value)) log.debug('Saving new qty=%d for %s' % (value, key)) prod.items_in_stock = value prod.save() elif opt == 'price': if 'CustomProduct' in subtypes: full_price = prod.customproduct.full_price else: full_price = prod.unit_price if value != full_price: messages.add_message( request, messages.INFO, 'Updated %s unit price to %s' % (key, value)) log.debug('Saving new price %s for %s' % (value, key)) try: price = Price.objects.get(product=prod, quantity='1') except Price.DoesNotExist: price = Price(product=prod, quantity='1') price.price = value price.save() elif opt == "active": if value != prod.active: if value: note = "Activated %s" else: note = "Deactivated %s" messages.add_message(request, messages.INFO, note % (key)) prod.active = value prod.save() elif opt == "featured": if value != prod.featured: if value: note = "%s is now featured" else: note = "%s is no longer featured" messages.add_message(request, messages.INFO, note % (key)) prod.featured = value prod.save()
def save(self, request): self.full_clean() for name, value in self.cleaned_data.items(): opt, key = name.split('__') prod = Product.objects.get(slug__exact=key) subtypes = prod.get_subtypes() if opt=='qty': if value != prod.items_in_stock: messages.add_message(request, messages.INFO, 'Updated %s stock to %s' % (key, value)) log.debug('Saving new qty=%d for %s' % (value, key)) prod.items_in_stock = value prod.save() elif opt=='price': if 'CustomProduct' in subtypes: full_price = prod.customproduct.full_price else: full_price = prod.unit_price if value != full_price: messages.add_message(request, messages.INFO, 'Updated %s unit price to %s' % (key, value)) log.debug('Saving new price %s for %s' % (value, key)) try: price = Price.objects.get(product=prod, quantity='1') except Price.DoesNotExist: price = Price(product=prod, quantity='1') price.price = value price.save() elif opt=="active": if value != prod.active: if value: note = "Activated %s" else: note = "Deactivated %s" messages.add_message(request, messages.INFO, note % (key)) prod.active = value prod.save() elif opt=="featured": if value != prod.featured: if value: note = "%s is now featured" else: note = "%s is no longer featured" messages.add_message(request, messages.INFO, note % (key)) prod.featured = value prod.save()
def save(self, request): self.full_clean() for name, value in self.cleaned_data.items(): opt, key = name.split("__") prod = Product.objects.get(slug__exact=key) subtypes = prod.get_subtypes() if opt == "qty": if value != prod.items_in_stock: request.user.message_set.create(message="Updated %s stock to %s" % (key, value)) log.debug("Saving new qty=%d for %s" % (value, key)) prod.items_in_stock = value prod.save() elif opt == "price": if "CustomProduct" in subtypes: full_price = prod.customproduct.full_price else: full_price = prod.unit_price if value != full_price: request.user.message_set.create(message="Updated %s unit price to %s" % (key, value)) log.debug("Saving new price %s for %s" % (value, key)) try: price = Price.objects.get(product=prod, quantity="1") except Price.DoesNotExist: price = Price(product=prod, quantity="1") price.price = value price.save() elif opt == "active": if value != prod.active: if value: note = "Activated %s" else: note = "Deactivated %s" request.user.message_set.create(message=note % (key)) prod.active = value prod.save() elif opt == "featured": if value != prod.featured: if value: note = "%s is now featured" else: note = "%s is no longer featured" request.user.message_set.create(message=note % (key)) prod.featured = value prod.save()
def force_recalculate_total(self, save=True): """Calculates sub_total, taxes and total.""" zero = Decimal("0.0000000000") total_discount = Decimal("0.0000000000") discount = Discount.objects.by_code(self.discount_code) discount.calc(self) discounts = discount.item_discounts itemprices = [] fullprices = [] for lineitem in self.orderitem_set.all(): lid = lineitem.id if lid in discounts: lineitem.discount = discounts[lid] else: lineitem.discount = zero # now double check against other discounts, such as tiered discounts adjustment = get_product_quantity_adjustments(lineitem.product, qty=lineitem.quantity) if adjustment and adjustment.price: baseprice = adjustment.price.price finalprice = adjustment.final_price() #We need to add in any OrderItemDetail price adjustments before we do anything else baseprice += lineitem.get_detail_price() finalprice += lineitem.get_detail_price() if baseprice > finalprice or baseprice != lineitem.unit_price: unitdiscount = (lineitem.discount/lineitem.quantity) + baseprice-finalprice unitdiscount = trunc_decimal(unitdiscount, 2) linediscount = unitdiscount * lineitem.quantity total_discount += linediscount fullydiscounted = (baseprice - unitdiscount) * lineitem.quantity lineitem.unit_price = baseprice lineitem.discount = linediscount lineitem.line_item_price = baseprice * lineitem.quantity log.debug('Adjusting lineitem unit price for %s. Full price=%s, discount=%s. Final price for qty %d is %s', lineitem.product.slug, baseprice, unitdiscount, lineitem.quantity, fullydiscounted) if save: lineitem.save() itemprices.append(lineitem.sub_total) fullprices.append(lineitem.line_item_price) shipprice = Price() shipprice.price = self.shipping_cost shipadjust = PriceAdjustmentCalc(shipprice) if 'Shipping' in discounts: shipadjust += PriceAdjustment('discount', _('Discount'), discounts['Shipping']) signals.satchmo_shipping_price_query.send(self, adjustment=shipadjust) shipdiscount = shipadjust.total_adjustment() self.shipping_discount = shipdiscount total_discount += shipdiscount self.discount = total_discount if itemprices: item_sub_total = reduce(operator.add, itemprices) else: item_sub_total = zero if fullprices: full_sub_total = reduce(operator.add, fullprices) else: full_sub_total = zero self.sub_total = full_sub_total taxProcessor = get_tax_processor(self) totaltax, taxrates = taxProcessor.process() self.tax = totaltax # clear old taxes for taxdetl in self.taxes.all(): taxdetl.delete() for taxdesc, taxamt in taxrates.items(): taxdetl = OrderTaxDetail(order=self, tax=taxamt, description=taxdesc, method=taxProcessor.method) taxdetl.save() log.debug("Order #%i, recalc: sub_total=%s, shipping=%s, discount=%s, tax=%s", self.id, moneyfmt(item_sub_total), moneyfmt(self.shipping_sub_total), moneyfmt(self.discount), moneyfmt(self.tax)) self.total = Decimal(item_sub_total + self.shipping_sub_total + self.tax) if save: self.save()
def _get_shipping_choices(request, paymentmodule, cart, contact, default_view_tax=False, order=None): """Iterate through legal shipping modules, building the list for display to the user. Returns the shipping choices list, along with a dictionary of shipping choices, useful for building javascript that operates on shipping choices. """ shipping_options = [] shipping_dict = {} rendered = {} if not order: try: order = Order.objects.from_request(request) except Order.DoesNotExist: pass discount = None if order: try: discount = Discount.objects.by_code(order.discount_code) except Discount.DoesNotExist: pass if not cart.is_shippable: methods = [shipping_method_by_key('NoShipping'),] else: methods = shipping_methods() tax_shipping = config_value_safe('TAX','TAX_SHIPPING', False) shipping_tax = None if tax_shipping: taxer = _get_taxprocessor(request) shipping_tax = TaxClass.objects.get(title=config_value('TAX', 'TAX_CLASS')) for method in methods: method.calculate(cart, contact) if method.valid(): template = lookup_template(paymentmodule, 'shipping/options.html') t = loader.get_template(template) shipcost = finalcost = method.cost() if discount and order: order.shipping_cost = shipcost discount.calc(order) shipdiscount = discount.item_discounts.get('Shipping', 0) else: shipdiscount = 0 # set up query to determine shipping price to show shipprice = Price() shipprice.price = shipcost shipadjust = PriceAdjustmentCalc(shipprice) if shipdiscount: shipadjust += PriceAdjustment('discount', _('Discount'), shipdiscount) satchmo_shipping_price_query.send(cart, adjustment=shipadjust) shipdiscount = shipadjust.total_adjustment() if shipdiscount: finalcost -= shipdiscount shipping_dict[method.id] = {'cost' : shipcost, 'discount' : shipdiscount, 'final' : finalcost} taxed_shipping_price = None if tax_shipping: taxcost = taxer.by_price(shipping_tax, finalcost) total = finalcost + taxcost taxed_shipping_price = moneyfmt(total) shipping_dict[method.id]['taxedcost'] = total shipping_dict[method.id]['tax'] = taxcost c = RequestContext(request, { 'amount': finalcost, 'description' : method.description(), 'method' : method.method(), 'expected_delivery' : method.expectedDelivery(), 'default_view_tax' : default_view_tax, 'shipping_tax': shipping_tax, 'taxed_shipping_price': taxed_shipping_price}) rendered[method.id] = t.render(c) #now sort by price, low to high sortme = [(value['cost'], key) for key, value in shipping_dict.items()] sortme.sort() shipping_options = [(key, rendered[key]) for cost, key in sortme] shipping_choices_query.send(sender=cart, cart=cart, paymentmodule=paymentmodule, contact=contact, default_view_tax=default_view_tax, order=order, shipping_options = shipping_options, shipping_dict = shipping_dict) return shipping_options, shipping_dict
def _get_shipping_choices(request, paymentmodule, cart, contact, default_view_tax=False, order=None): """Iterate through legal shipping modules, building the list for display to the user. Returns the shipping choices list, along with a dictionary of shipping choices, useful for building javascript that operates on shipping choices. """ shipping_options = [] shipping_dict = {} rendered = {} if not order: try: order = Order.objects.from_request(request) except Order.DoesNotExist: pass discount = None if order: try: discount = Discount.objects.by_code(order.discount_code) except Discount.DoesNotExist: pass if not cart.is_shippable: methods = [ shipping_method_by_key('NoShipping'), ] else: methods = shipping_methods() tax_shipping = config_value_safe('TAX', 'TAX_SHIPPING', False) shipping_tax = None if tax_shipping: taxer = _get_taxprocessor(request) shipping_tax = TaxClass.objects.get( title=config_value('TAX', 'TAX_CLASS')) for method in methods: method.calculate(cart, contact) if method.valid(order=order): template = lookup_template(paymentmodule, 'shipping/options.html') t = loader.get_template(template) shipcost = finalcost = method.cost() if discount and order: order.shipping_cost = shipcost discount.calc(order) shipdiscount = discount.item_discounts.get('Shipping', 0) else: shipdiscount = 0 # set up query to determine shipping price to show shipprice = Price() shipprice.price = shipcost shipadjust = PriceAdjustmentCalc(shipprice) if shipdiscount: shipadjust += PriceAdjustment('discount', _('Discount'), shipdiscount) satchmo_shipping_price_query.send(cart, adjustment=shipadjust) shipdiscount = shipadjust.total_adjustment() if shipdiscount: finalcost -= shipdiscount shipping_dict[method.id] = { 'cost': shipcost, 'discount': shipdiscount, 'final': finalcost } taxed_shipping_price = None if tax_shipping: taxcost = taxer.by_price(shipping_tax, finalcost) total = finalcost + taxcost taxed_shipping_price = moneyfmt(total) shipping_dict[method.id]['taxedcost'] = total shipping_dict[method.id]['tax'] = taxcost c = RequestContext( request, { 'amount': finalcost, 'description': method.description(), 'method': method.method(), 'expected_delivery': method.expectedDelivery(), 'default_view_tax': default_view_tax, 'shipping_tax': shipping_tax, 'taxed_shipping_price': taxed_shipping_price }) rendered[method.id] = t.render(c) #now sort by price, low to high sortme = [(value['cost'], key) for key, value in shipping_dict.items()] sortme.sort() shipping_options = [(key, rendered[key]) for cost, key in sortme] shipping_choices_query.send(sender=cart, cart=cart, paymentmodule=paymentmodule, contact=contact, default_view_tax=default_view_tax, order=order, shipping_options=shipping_options, shipping_dict=shipping_dict) return shipping_options, shipping_dict
def force_recalculate_total(self, save=True): """Calculates sub_total, taxes and total.""" zero = Decimal("0.0000000000") discount = Discount.objects.by_code(self.discount_code) discount.calc(self) self.discount = discount.total discounts = discount.item_discounts itemprices = [] fullprices = [] for lineitem in self.orderitem_set.all(): lid = lineitem.id if lid in discounts: lineitem.discount = discounts[lid] else: lineitem.discount = zero if save: lineitem.save() itemprices.append(lineitem.sub_total) fullprices.append(lineitem.line_item_price) shipprice = Price() shipprice.price = self.shipping_cost shipadjust = PriceAdjustmentCalc(shipprice) if 'Shipping' in discounts: shipadjust += PriceAdjustment('discount', _('Discount'), discounts['Shipping']) signals.satchmo_shipping_price_query.send(self, adjustment=shipadjust) self.shipping_discount = shipadjust.total_adjustment() if itemprices: item_sub_total = reduce(operator.add, itemprices) else: item_sub_total = zero if fullprices: full_sub_total = reduce(operator.add, fullprices) else: full_sub_total = zero self.sub_total = full_sub_total taxProcessor = get_tax_processor(self) totaltax, taxrates = taxProcessor.process() self.tax = totaltax # clear old taxes for taxdetl in self.taxes.all(): taxdetl.delete() for taxdesc, taxamt in taxrates.items(): taxdetl = OrderTaxDetail(order=self, tax=taxamt, description=taxdesc, method=taxProcessor.method) taxdetl.save() log.debug("Order #%i, recalc: sub_total=%s, shipping=%s, discount=%s, tax=%s", self.id, moneyfmt(item_sub_total), moneyfmt(self.shipping_sub_total), moneyfmt(self.discount), moneyfmt(self.tax)) self.total = Decimal(item_sub_total + self.shipping_sub_total + self.tax) if save: self.save()
def get_product(self, day, schedule=None, tour_time=None, create=True): """ Get the TourProduct for the given day and time. If create is false and product does not exist, return None. """ if schedule and tour_time: assert False, 'Make up your mind, use a schedule or a tour_time, not both' if not schedule and not tour_time: assert False, 'Need a time buddy' try: if schedule: tour_product = TourProduct.objects.filter(tour_type=self, day=day).filter( Q(schedule=schedule) | Q(tour_time=schedule.tour_time))[0] else: tour_product = TourProduct.objects.get(tour_type=self, day=day, tour_time=tour_time) if tour_product.tour_type.has_price_raise(): p = tour_product.product.price_set.all()[0] p.price = self.get_raised_base_price(tour_product.day) p.save() return tour_product except (TourProduct.DoesNotExist, IndexError): if create: # print 'creating product... ', day product = Product() product.site = Site.objects.get_current() product.name = '%s on %s at ' % (self.name, day.strftime('%B %d, %Y')) if schedule: product.name += schedule.tour_time.strftime('%I:%M %p') else: product.name += tour_time.strftime('%I:%M %p') product.items_in_stock = self.get_capacity_for_day(day) product.shipclass = 'NO' # see product.models.SHIP_CLASS_CHOICES product.save() tour_product = TourProduct() tour_product.product = product tour_product.tour_type = self tour_product.day = day if schedule: tour_product.schedule = schedule tour_product.tour_time = schedule.tour_time else: tour_product.schedule = None tour_product.tour_time = tour_time tour_product.save() p = Price() p.product = product if tour_product.tour_type.has_price_raise(): p.price = self.get_raised_base_price(tour_product.day) else: p.price = self.base_price p.save() # Create Variations if self.option_group_id: configurable_product = ConfigurableProduct(product=product) configurable_product.save() configurable_product.option_group.add(self.option_group) configurable_product.create_subs = True configurable_product.save() return tour_product else: return None