Beispiel #1
0
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")
Beispiel #2
0
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")
Beispiel #3
0
    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)
Beispiel #4
0
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))
Beispiel #5
0
 def balance_due(self):
     if self.balance:
         b = self.balance
     else:
         b = Decimal('0.00')
         
     return moneyfmt(b)
Beispiel #6
0
 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
Beispiel #7
0
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)
Beispiel #8
0
    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
Beispiel #9
0
    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
Beispiel #10
0
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
Beispiel #11
0
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))
Beispiel #12
0
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
Beispiel #13
0
    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)
Beispiel #14
0
 def _order_total(self):
     #Needed for the admin list display
     return moneyfmt(self.total)
Beispiel #15
0
    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()
Beispiel #16
0
 def balance_forward(self):
     return moneyfmt(self.balance)
Beispiel #17
0
 def _amount_total(self):
     return moneyfmt(self.amount)
Beispiel #18
0
 def __unicode__(self):
     sb = moneyfmt(self.start_balance)
     b = moneyfmt(self.balance)
     return u"Gift Cert: %s/%s" % (sb, b)
Beispiel #19
0
    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.'))
Beispiel #20
0
 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)))
Beispiel #21
0
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