def get_price(request, product_slug): """Get base price for a product, returning the answer encoded as JSON.""" quantity = 1 try: product = Product.objects.get_by_site(active=True, slug=product_slug) except Product.DoesNotExist: return http.HttpResponseNotFound(json_encode(('', _("not available"))), mimetype="text/javascript") prod_slug = product.slug if request.method == "POST" and request.POST.has_key('quantity'): quantity = int(request.POST['quantity']) if 'ConfigurableProduct' in product.get_subtypes(): cp = product.configurableproduct chosen_options = optionids_from_post(cp, request.POST) pvp = cp.get_product_from_options(chosen_options) if not pvp: return http.HttpResponse(json_encode(('', _("not available"))), mimetype="text/javascript") prod_slug = pvp.slug price = moneyfmt(pvp.get_qty_price(quantity)) else: price = moneyfmt(product.get_qty_price(quantity)) if not price: return http.HttpResponse(json_encode(('', _("not available"))), mimetype="text/javascript") return http.HttpResponse(json_encode((prod_slug, price)), mimetype="text/javascript")
def get_price_detail(request, product_slug): """Get all price details for a product, returning the response encoded as JSON.""" results = { "success" : False, "message" : _("not available") } price = None if request.method=="POST": reqdata = request.POST else: reqdata = request.GET try: product = Product.objects.get_by_site(active=True, slug=product_slug) found = True prod_slug = product.slug if reqdata.has_key('quantity'): quantity = int(reqdata['quantity']) else: quantity = 1 if 'ConfigurableProduct' in product.get_subtypes(): cp = product.configurableproduct chosen_options = optionids_from_post(cp, reqdata) product = cp.get_product_from_options(chosen_options) if product: price = product.get_qty_price(quantity) base_tax = get_tax(request.user, product, quantity) price_with_tax = price+base_tax results['slug'] = product.slug results['currency_price'] = moneyfmt(price) results['price'] = float(price) results['tax'] = float(base_tax) results['currency_tax'] = moneyfmt(base_tax) results['currency_price_with_tax'] = moneyfmt(price_with_tax) results['price_with_tax'] = float(price_with_tax) results['success'] = True results['message'] = "" except Product.DoesNotExist: found = False data = json_encode(results) if found: return http.HttpResponse(data, mimetype="text/javascript") else: return http.HttpResponseNotFound(data, mimetype="text/javascript")
def apply_to_order(self, order): """Apply up to the full amount of the balance of this cert to the order. Returns new balance. """ amount = min(order.balance, self.balance) log.info('applying %s from giftcert #%i [%s] to order #%i [%s]', moneyfmt(amount), self.id, moneyfmt(self.balance), order.id, moneyfmt(order.balance)) config = config_get_group('PAYMENT_GIFTCERTIFICATE') orderpayment = record_payment(order, config, amount) return self.use(amount, orderpayment=orderpayment)
def currency(value, args=""): """Convert a value to a money formatted string. places: required number of places after the decimal point curr: optional currency symbol before the sign (may be blank) wrapcents:tag to wrap the part after the decimal point Usage: val|currency val|currency:'places=2' val|currency:'places=2:wrapcents=sup' """ if value == '' or value is None: return value args, kwargs = get_filter_args(args, keywords=('places','curr', 'wrapcents'), intargs=('places',), stripquotes=True) try: value = Decimal(str(value)) except InvalidOperation: log.error("Could not convert value '%s' to decimal", value) raise if not 'places' in kwargs: kwargs['places'] = 2 return mark_safe(moneyfmt(value, **kwargs))
def balance_due(self): if self.balance: b = self.balance else: b = Decimal('0.00') return moneyfmt(b)
def render(self, context): try: show_tax = self.show_tax.resolve(context) except template.VariableDoesNotExist: show_tax = self.raw_tax if show_tax: tag = CartitemLineTaxedTotalNode(self.raw_cartitem, self.raw_currency) return tag.render(context) try: cartitem = self.cartitem.resolve(context) except template.VariableDoesNotExist: log.warn('Could not resolve template variable: %s', self.cartitem) return '' try: show_currency = self.show_currency.resolve(context) except template.VariableDoesNotExist: show_currency = self.raw_currency if show_currency: return moneyfmt(cartitem.line_total) else: return cartitem.line_total
def option_total_price(product, option_item): """ Returns the price as (+$1.00) or (-$1.00) depending on the sign of the price change The currency symbol is set in the settings.py file """ if option_item.price_change: val = product.unit_price + option_item.price_change else: val = product.unit_price return moneyfmt(val)
def render(self, context): taxer = _get_taxprocessor(context["request"]) try: item = template.resolve_variable(self.cartitem, context) except template.VariableDoesNotExist: raise template.TemplateSyntaxError("No such variable: %s", self.cartitem) total = item.line_total + taxer.by_price(item.product.taxClass, item.line_total) if self.currency: return moneyfmt(total) return total
def render(self, context): taxer = _get_taxprocessor(context["request"]) try: price = template.resolve_variable(self.price, context) except template.VariableDoesNotExist: raise template.TemplateSyntaxError("No such variable: %s", self.price) total = price + taxer.by_price(self.taxclass, price) if self.currency: return moneyfmt(total) return total
def option_price(option_item): """ Returns the price as (+$1.00) or (-$1.00) depending on the sign of the price change The currency symbol is set in the settings.py file """ output = "" if option_item.price_change != 0: amount = moneyfmt(abs(option_item.price_change)) if option_item.price_change < 0: output = "(- %s)" % amount if option_item.price_change > 0: output = "(+ %s)" % amount return output
def tiered_shipping(price, args=""): if not args: raise template.TemplateSyntaxError( 'tiered_shipping needs the name of the carrier, as value|tiered_shipping:"carrier"' ) try: c = Carrier.objects.get(key=args) except Carrier.DoesNotExist: raise template.TemplateSyntaxError( 'tiered_shipping needs the name of a valid carrier, could not find carrier "%s"' % args ) shipping = c.price(Decimal(price)) return mark_safe(moneyfmt(shipping))
def _get_shipping_choices(request, paymentmodule, cart, contact, default_view_tax=False): """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 = {} if not cart.is_shippable: methods = [shipping_method_by_key('NoShipping'),] else: methods = shipping_methods() for method in methods: method.calculate(cart, contact) if method.valid(): template = lookup_template(paymentmodule, 'shipping_options.html') t = loader.get_template(template) shipcost = method.cost() shipping_tax = None taxed_shipping_price = None if config_value('TAX','TAX_SHIPPING'): shipping_tax = config_value('TAX', 'TAX_CLASS') taxer = _get_taxprocessor(request) total = shipcost + taxer.by_price(shipping_tax, shipcost) taxed_shipping_price = moneyfmt(total) c = RequestContext(request, { 'amount': shipcost, '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}) shipping_options.append((method.id, t.render(c))) shipping_dict[method.id] = shipcost return shipping_options, shipping_dict
def process(self): """ Process the transaction and return a tuple: (success/failure, reason code, response text) """ if self.order.paid_in_full: success = True reason_code = "0" response_text = _("No balance to pay") else: try: gc = GiftCertificate.objects.from_order(self.order) except GiftCertificate.DoesNotExist: success = False reason_code="1" response_text = _("No such Gift Certificate") if not gc.valid: success = False reason_code="2" response_text = _("Bad Gift Certificate") else: gc.apply_to_order(self.order) reason_code = "0" response_text = _("Success") success = True if not self.order.paid_in_full: response_text = _("%s balance remains after gift certificate was applied") % moneyfmt(self.order.balance) return (success, reason_code, response_text)
def _order_total(self): #Needed for the admin list display return moneyfmt(self.total)
def force_recalculate_total(self, save=True): """Calculates sub_total, taxes and total.""" from satchmo.discount.utils import find_discount_for_code zero = Decimal("0.0000000000") discount = find_discount_for_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) if 'Shipping' in discounts: self.shipping_discount = discounts['Shipping'] else: self.shipping_discount = zero 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 balance_forward(self): return moneyfmt(self.balance)
def _amount_total(self): return moneyfmt(self.amount)
def __unicode__(self): sb = moneyfmt(self.start_balance) b = moneyfmt(self.balance) return u"Gift Cert: %s/%s" % (sb, b)
def isValid(self, cart=None): """ Make sure this discount still has available uses and is in the current date range. If a cart has been populated, validate that it does apply to the products we have selected. """ if not self.active: return (False, ugettext('This coupon is disabled.')) if self.startDate > datetime.date.today(): return (False, ugettext('This coupon is not active yet.')) if self.endDate < datetime.date.today(): return (False, ugettext('This coupon has expired.')) if self.numUses > self.allowedUses: return (False, ugettext('This discount has exceeded the number of allowed uses.')) if not cart: return (True, ugettext('Valid.')) minOrder = self.minOrder or 0 if cart.total < minOrder: return (False, ugettext('This discount only applies to orders of at least %s.' % moneyfmt(minOrder))) validItems = False if self.validProducts.count() == 0: validItems = True else: validItems = len(self._valid_products(cart.cartitem_set)) if validItems: return (True, ugettext('Valid.')) else: return (False, ugettext('This discount cannot be applied to the products in your cart.'))
def order_link(self): return mark_safe(u'<a href="/admin/shop/order/%i/">%s #%i (%s)</a>' % ( self.order.id, ugettext('Order'), self.order.id, moneyfmt(self.order.total)))
def productvariation_details(product, include_tax, user, create=False): """Build the product variation details, for conversion to javascript. Returns variation detail dictionary built like so: details = { "OPTION_KEY" : { "SLUG": "Variation Slug", "PRICE" : {"qty" : "$price", [...]}, "SALE" : {"qty" : "$price", [...]}, "TAXED" : "$taxed price", # omitted if no taxed price requested "QTY" : 1 }, [...] } """ config = Config.objects.get_current() ignore_stock = config.no_stock_checkout discount = find_best_auto_discount(product) use_discount = discount and discount.percentage > 0 if include_tax: taxer = get_taxprocessor(user) tax_class = product.taxClass details = {'SALE' : use_discount} curr = config_value('SHOP', 'CURRENCY') curr = curr.replace("_", " ") variations = ProductPriceLookup.objects.filter(parentid=product.id) if variations.count() == 0: if create: log.debug('Creating price lookup for %s', product) ProductPriceLookup.objects.smart_create_for_product(product) variations = ProductPriceLookup.objects.filter(parentid=product.id) else: log.warning('You must run satchmo_rebuild_pricing and add it to a cron-job to run every day, or else the product details will not work for product detail pages.') for detl in variations: key = detl.key if details.has_key(key): detail = details[key] else: detail = {} detail['SLUG'] = detl.productslug if not detl.active: qty = -1 elif ignore_stock: qty = 10000 else: qty = detl.items_in_stock detail['QTY'] = qty detail['PRICE'] = {} if use_discount: detail['SALE'] = {} if include_tax: detail['TAXED'] = {} if use_discount: detail['TAXED_SALE'] = {} details[key] = detail price = detl.dynamic_price detail['PRICE'][detl.quantity] = moneyfmt(price, curr=curr) if use_discount: detail['SALE'][detl.quantity] = moneyfmt(calc_by_percentage(price, discount.percentage), curr=curr) if include_tax: tax_price = taxer.by_price(tax_class, price) + price detail['TAXED'][detl.quantity] = moneyfmt(tax_price, curr=curr) detail['TAXED_SALE'][detl.quantity] = moneyfmt(calc_by_percentage(tax_price, discount.percentage), curr=curr) return details