Beispiel #1
0
    def process(self, order=None):
        """
        Calculate the tax and return it
        """
        if order:
            self.order = order
        else:
            order = self.order

        percent = config_value("TAX", "PERCENT")

        sub_total = Decimal("0.00")
        for item in order.orderitem_set.filter(product__taxable=True):
            sub_total += item.sub_total

        itemtax = sub_total * (percent / 100)
        taxrates = {"%i%%" % percent: itemtax}

        if config_value("TAX", "TAX_SHIPPING"):
            shipping = order.shipping_sub_total
            sub_total += shipping
            ship_tax = shipping * (percent / 100)
            taxrates["Shipping"] = ship_tax

        tax = sub_total * (percent / 100)
        return tax, taxrates
Beispiel #2
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()

    valid_methods = []
    for method in methods:
        method.calculate(cart, contact)
        if method.valid():
            valid_methods.append((method, method.cost()))

    # sort methods by cost
    valid_methods.sort(key=lambda method_cost: int(method_cost[1]))

    for method, shipcost in valid_methods:
        template = lookup_template(paymentmodule, "shipping_options.html")
        t = loader.get_template(template)
        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)

            currency_code = currency_for_request(request)
            taxed_shipping_price = money_format(total, currency_code)

        data = {
            "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,
        }

        if hasattr(method, "shipping_discount"):
            data["discount"] = method.shipping_discount()

        shipping_options.append((method.id, t.render(data)))
        shipping_dict[method.id] = shipcost

    return shipping_options, shipping_dict
Beispiel #3
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()

    valid_methods = []
    for method in methods:
        method.calculate(cart, contact)
        if method.valid():
            valid_methods.append((method, method.cost()))

    # sort methods by cost
    valid_methods.sort(key=lambda method_cost: int(method_cost[1]))

    for method, shipcost in valid_methods:
        template = lookup_template(paymentmodule, "shipping_options.html")
        t = loader.get_template(template)
        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)

            currency_code = currency_for_request(request)
            taxed_shipping_price = money_format(total, currency_code)

        data = {
            "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,
        }

        if hasattr(method, "shipping_discount"):
            data["discount"] = method.shipping_discount()

        shipping_options.append((method.id, t.render(data)))
        shipping_dict[method.id] = shipcost

    return shipping_options, shipping_dict
Beispiel #4
0
    def shipping(self, subtotal=None):
        if subtotal is None and self.order:
            subtotal = self.order.shipping_sub_total

        if subtotal:
            subtotal = self.order.shipping_sub_total
            if config_value("TAX", "TAX_SHIPPING"):
                percent = config_value("TAX", "PERCENT")
                t = subtotal * (percent / 100)
            else:
                t = Decimal("0.00")
        else:
            t = Decimal("0.00")

        return t
Beispiel #5
0
def make_urlpatterns():
    patterns = []
    for key in config_value("PAYMENT", "MODULES"):
        try:
            cfg = config_get(key, "MODULE")
        except SettingNotSet:
            log.warning("Could not find module %s, skipping", key)
            continue
        module_name = cfg.editor_value
        url_module = "%s.urls" % module_name
        namespace = module_name.split(".")[-1]
        patterns.append(
            path(config_value(key, "URL_BASE"),
                 [url_module, module_name, namespace]))
    return patterns
Beispiel #6
0
def make_urlpatterns():
    patterns = []
    for key in config_value("PAYMENT", "MODULES"):
        try:
            cfg = config_get(key, "MODULE")
        except SettingNotSet:
            log.warning("Could not find module %s, skipping", key)
            continue
        module_name = cfg.editor_value
        url_module = "%s.urls" % module_name
        namespace = module_name.split(".")[-1]
        patterns.append(
            path(config_value(key, "URL_BASE"), [url_module, module_name, namespace])
        )
    return patterns
Beispiel #7
0
    def testBalanceMethods(self):
        order = TestOrderFactory()
        order.recalculate_total(save=False)
        price = order.total
        subtotal = order.sub_total

        self.assertEqual(subtotal, Decimal("25.00"))
        self.assertEqual(price, Decimal("35.00"))
        self.assertEqual(order.balance, price)

        paytype = config_value("PAYMENT", "MODULES")[0]
        pmt = OrderPayment(order=order, payment=paytype, amount=Decimal("5.00"))
        pmt.save()

        self.assertEqual(order.balance, Decimal("30.00"))
        self.assertEqual(order.balance_paid, Decimal("5.00"))

        self.assertTrue(order.is_partially_paid)

        pmt = OrderPayment(order=order, payment=paytype, amount=Decimal("30.00"))
        pmt.save()

        self.assertEqual(order.balance, Decimal("0.00"))
        self.assertFalse(order.is_partially_paid)
        self.assertTrue(order.paid_in_full)
Beispiel #8
0
def payment_live(settings):
    try:
        if config_value("PAYMENT", "LIVE"):
            return settings["LIVE"].value
    except SettingNotSet:
        pass
    return False
Beispiel #9
0
def google_adwords_signup(context):
    """
    Output signup info in the format that Google adwords needs.
    """
    request = context["request"]
    try:
        request = context["request"]
    except KeyError:
        logger.warning(
            "Template satchmo.show.templatetags.google.google_adwords_sale couldn't get the request from the context.  Are you missing the request context_processor?"
        )
        return ""

    secure = request.is_secure()
    try:
        language_code = request.LANGUAGE_CODE
    except AttributeError:
        language_code = settings.LANGUAGE_CODE

    return {
        "GOOGLE_ADWORDS_ID": config_value("GOOGLE", "ADWORDS_ID"),
        "Store": settings.SITE_NAME,
        "value": 1,
        "label": "signup",
        "secure": secure,
        "language_code": language_code,
    }
Beispiel #10
0
def google_adwords_sale(context):
    """
    Output our receipt in the format that Google Adwords needs.
    """
    order = context["order"]
    try:
        request = context["request"]
    except KeyError:
        logging.warning(
            "Template satchmo.show.templatetags.google.google_adwords_sale couldn't get the request from the context.  Are you missing the request context_processor?"
        )
        return ""

    secure = request.is_secure()
    try:
        language_code = request.LANGUAGE_CODE
    except KeyError:
        language_code = settings.LANGUAGE_CODE

    return {
        "GOOGLE_ADWORDS_ID": config_value("GOOGLE", "ADWORDS_ID"),
        "Store": settings.SITE_NAME,
        "value": order.total,
        "label": "purchase",
        "secure": secure,
        "language_code": language_code,
    }
Beispiel #11
0
def cartitem_total(parser, token):
    """Returns the line total for the cartitem, possibly with tax added.  If currency evaluates true,
    then return the total formatted through money_format.

    Example::

        {% cartitem_total cartitem [show_tax] [currency] %}
    """

    tokens = token.contents.split()
    if len(tokens) < 2:
        raise template.TemplateSyntaxError(
            "'%s' tag requires a cartitem argument" % tokens[0]
        )

    cartitem = tokens[1]

    if len(tokens) > 2:
        show_tax = tokens[2]
    else:
        show_tax = config_value("TAX", "DEFAULT_VIEW_TAX")

    if len(tokens) > 3:
        show_currency = tokens[3]
    else:
        show_currency = "True"

    return CartitemTotalNode(cartitem, show_currency, show_tax)
Beispiel #12
0
    def __init__(self, request, payment_module):
        self.request = request
        self.paymentModule = payment_module
        processor_module = payment_module.MODULE.load_module("processor")
        self.processor = processor_module.PaymentProcessor(self.paymentModule)
        self.viewTax = config_value("TAX", "DEFAULT_VIEW_TAX")
        self.order = None
        self.cart = None
        self.extra_context = {}

        # To override the form_handler, set this
        # otherwise it will use the built-in `_onForm`
        self.onForm = self._onForm

        # To override the success method, set this
        # othewise it will use the built-in `_onSuccess`
        self.onSuccess = self._onSuccess

        # False on any "can not continue" error
        self.valid = False

        # The value to be returned from the view
        # an HttpResponse or a HttpRedirect
        self.response = None

        self.processorMessage = ""
        self.processorReasonCode = ""
        self.processorResults = None

        self.templates = {
            "CONFIRM": "checkout/confirm.html",
            "EMPTY_CART": "checkout/empty_cart",
            "404": "shop_404.html",
        }
def edit_subtypes(product):
    output = "<ul>"
    subtypes = product.get_subtypes()
    for key in config_value("PRODUCT", "PRODUCT_TYPES"):
        app, subtype = key.split("::")
        is_config = "ConfigurableProduct" in subtypes
        if subtype in subtypes:
            output += (
                '<li><a href="/admin/%s/%s/%s/">' % (app, subtype.lower(), product.pk)
                + _("Edit %(subtype)s") % {"subtype": subtype}
                + "</a></li>"
            )
            if is_config or subtype == "ProductVariation":
                output += (
                    '<li><a href="/product/admin/%s/variations/">Variation Manager</a></li>'
                    % (product.slug)
                )
        else:
            if not (is_config and subtype == "ProductVariation"):
                output += (
                    ' <li><a href="/admin/%s/%s/add/?product=%s">'
                    % (app, subtype.lower(), product.pk)
                    + _("Add %(subtype)s") % {"subtype": subtype}
                    + "</a></li>"
                )

    output += "</ul>"
    return output
Beispiel #14
0
    def __init__(self, request, payment_module):
        self.request = request
        self.paymentModule = payment_module
        processor_module = payment_module.MODULE.load_module("processor")
        self.processor = processor_module.PaymentProcessor(self.paymentModule)
        self.viewTax = config_value("TAX", "DEFAULT_VIEW_TAX")
        self.order = None
        self.cart = None
        self.extra_context = {}

        # To override the form_handler, set this
        # otherwise it will use the built-in `_onForm`
        self.onForm = self._onForm

        # To override the success method, set this
        # othewise it will use the built-in `_onSuccess`
        self.onSuccess = self._onSuccess

        # False on any "can not continue" error
        self.valid = False

        # The value to be returned from the view
        # an HttpResponse or a HttpRedirect
        self.response = None

        self.processorMessage = ""
        self.processorReasonCode = ""
        self.processorResults = None

        self.templates = {
            "CONFIRM": "checkout/confirm.html",
            "EMPTY_CART": "checkout/empty_cart",
            "404": "shop_404.html",
        }
Beispiel #15
0
def cartitem_total(parser, token):
    """Returns the line total for the cartitem, possibly with tax added.  If currency evaluates true,
    then return the total formatted through money_format.

    Example::

        {% cartitem_total cartitem [show_tax] [currency] %}
    """

    tokens = token.contents.split()
    if len(tokens) < 2:
        raise template.TemplateSyntaxError(
            "'%s' tag requires a cartitem argument" % tokens[0])

    cartitem = tokens[1]

    if len(tokens) > 2:
        show_tax = tokens[2]
    else:
        show_tax = config_value("TAX", "DEFAULT_VIEW_TAX")

    if len(tokens) > 3:
        show_currency = tokens[3]
    else:
        show_currency = "True"

    return CartitemTotalNode(cartitem, show_currency, show_tax)
Beispiel #16
0
def google_adwords_sale(context):
    """
    Output our receipt in the format that Google Adwords needs.
    """
    order = context["order"]
    try:
        request = context["request"]
    except KeyError:
        logging.warning(
            "Template satchmo.show.templatetags.google.google_adwords_sale couldn't get the request from the context.  Are you missing the request context_processor?"
        )
        return ""

    secure = request.is_secure()
    try:
        language_code = request.LANGUAGE_CODE
    except KeyError:
        language_code = settings.LANGUAGE_CODE

    return {
        "GOOGLE_ADWORDS_ID": config_value("GOOGLE", "ADWORDS_ID"),
        "Store": settings.SITE_NAME,
        "value": order.total,
        "label": "purchase",
        "secure": secure,
        "language_code": language_code,
    }
Beispiel #17
0
def displayDoc(request, id, doc):
    # Create the HttpResponse object with the appropriate PDF headers for an invoice or a packing slip
    order = get_object_or_404(Order, pk=id)
    shopDetails = Config.objects.get_current()
    filename_prefix = shopDetails.site.domain
    if doc == "invoice":
        filename = "%s-invoice.pdf" % filename_prefix
        template = "invoice.rml"
    elif doc == "packingslip":
        filename = "%s-packingslip.pdf" % filename_prefix
        template = "packing-slip.rml"
    elif doc == "shippinglabel":
        filename = "%s-shippinglabel.pdf" % filename_prefix
        template = "shipping-label.rml"
    else:
        return HttpResponseRedirect("/admin")
    response = HttpResponse(mimetype="application/pdf")
    response["Content-Disposition"] = "attachment; filename=%s" % filename
    icon_uri = config_value("SHOP", "LOGO_URI")
    t = loader.get_template(os.path.join("pdf", template))
    c = Context(
        {
            "filename": filename,
            "iconURI": icon_uri,
            "shopDetails": shopDetails,
            "order": order,
        }
    )
    pdf = trml2pdf.parseString(smart_str(t.render(c)))
    response.write(pdf)
    return response
Beispiel #18
0
def displayDoc(request, id, doc):
    # Create the HttpResponse object with the appropriate PDF headers
    # for an invoice or a packing slip
    order = get_object_or_404(Order, pk=id)
    shopDetails = Config.objects.get_current()
    filename_prefix = Site.objects.get_current().domain
    if doc == "invoice":
        filename = "%s-invoice.pdf" % filename_prefix
        template = "invoice.rml"
    elif doc == "packingslip":
        filename = "%s-packingslip.pdf" % filename_prefix
        template = "packing-slip.rml"
    elif doc == "shippinglabel":
        filename = "%s-shippinglabel.pdf" % filename_prefix
        template = "shipping-label.rml"
    else:
        return HttpResponseRedirect("/admin")
    response = HttpResponse(mimetype="application/pdf")
    response["Content-Disposition"] = "attachment; filename=%s" % filename
    icon_uri = config_value("SHOP", "LOGO_URI")
    t = loader.get_template(os.path.join("pdf", template))
    c = Context(
        {
            "filename": filename,
            "iconURI": icon_uri,
            "shopDetails": shopDetails,
            "order": order,
        }
    )
    pdf = trml2pdf.parseString(smart_str(t.render(c)))
    response.write(pdf)
    return response
Beispiel #19
0
def display_bestsellers(request, count=0, template="product/best_sellers.html"):
    """Display a list of the products which have sold the most"""
    if count == 0:
        count = config_value("SHOP", "NUM_PAGINATED")

    ctx = {"products": bestsellers(count)}
    return render(request, template, ctx)
Beispiel #20
0
def edit_subtypes(product):
    output = "<ul>"
    subtypes = product.get_subtypes()
    for key in config_value("PRODUCT", "PRODUCT_TYPES"):
        app, subtype = key.split("::")
        is_config = "ConfigurableProduct" in subtypes
        if subtype in subtypes:
            output += ('<li><a href="/admin/%s/%s/%s/">' %
                       (app, subtype.lower(), product.pk) +
                       _("Edit %(subtype)s") % {
                           "subtype": subtype
                       } + "</a></li>")
            if is_config or subtype == "ProductVariation":
                output += (
                    '<li><a href="/product/admin/%s/variations/">Variation Manager</a></li>'
                    % (product.slug))
        else:
            if not (is_config and subtype == "ProductVariation"):
                output += (' <li><a href="/admin/%s/%s/add/?product=%s">' %
                           (app, subtype.lower(), product.pk) +
                           _("Add %(subtype)s") % {
                               "subtype": subtype
                           } + "</a></li>")

    output += "</ul>"
    return output
Beispiel #21
0
    def testBalanceMethods(self):
        order = TestOrderFactory()
        order.recalculate_total(save=False)
        price = order.total
        subtotal = order.sub_total

        self.assertEqual(subtotal, Decimal("25.00"))
        self.assertEqual(price, Decimal("35.00"))
        self.assertEqual(order.balance, price)

        paytype = config_value("PAYMENT", "MODULES")[0]
        pmt = OrderPayment(order=order,
                           payment=paytype,
                           amount=Decimal("5.00"))
        pmt.save()

        self.assertEqual(order.balance, Decimal("30.00"))
        self.assertEqual(order.balance_paid, Decimal("5.00"))

        self.assertTrue(order.is_partially_paid)

        pmt = OrderPayment(order=order,
                           payment=paytype,
                           amount=Decimal("30.00"))
        pmt.save()

        self.assertEqual(order.balance, Decimal("0.00"))
        self.assertFalse(order.is_partially_paid)
        self.assertTrue(order.paid_in_full)
Beispiel #22
0
def order_tracking(request, order_id):
    order = None
    try:
        contact = Contact.objects.from_request(request, create=False)
        try:
            order = Order.objects.get(id__exact=order_id, contact=contact)
        except Order.DoesNotExist:
            pass
    except Contact.DoesNotExist:
        contact = None

    if order is None:
        return bad_or_missing(
            request,
            _("The order you have requested doesn't exist, or you don't have access to it."
              ),
        )

    ctx = {
        "default_view_tax": config_value("TAX", "DEFAULT_VIEW_TAX"),
        "contact": contact,
        "order": order,
    }

    return render(request, "shop/order_tracking.html", ctx)
Beispiel #23
0
 def handle(self, *args, **options):
     for fulfilment_house in config_value("FULFILMENT", "MODULES"):
         if options["verbosity"] >= 2:
             self.stdout.write(
                 "Fulfilling with {house}".format(house=fulfilment_house)
             )
         logger.debug("Fulfilling with {house}".format(house=fulfilment_house))
         api_module = "{fulfilment_house}.api".format(
             fulfilment_house=fulfilment_house
         )
         module = importlib.import_module(api_module)
         for order in Order.objects.unfulfilled().order_by("time_stamp"):
             if module.send_order(order):
                 if options["verbosity"] >= 2:
                     self.stdout.write('Order fulfilment processed "%s"' % order)
                 logger.info('Order fulfilment processed "%s"' % order)
             else:
                 if options["verbosity"] >= 2:
                     self.stdout.write(
                         'Order fulfilment not processed,  Something went wrong. "%s"'
                         % order
                     )
                 logger.warning(
                     'Order fulfilment not processed,  Something went wrong. "%s"'
                     % order
                 )
Beispiel #24
0
def order_tracking(request, order_id):
    order = None
    try:
        contact = Contact.objects.from_request(request, create=False)
        try:
            order = Order.objects.get(id__exact=order_id, contact=contact)
        except Order.DoesNotExist:
            pass
    except Contact.DoesNotExist:
        contact = None

    if order is None:
        return bad_or_missing(
            request,
            _(
                "The order you have requested doesn't exist, or you don't have access to it."
            ),
        )

    ctx = {
        "default_view_tax": config_value("TAX", "DEFAULT_VIEW_TAX"),
        "contact": contact,
        "order": order,
    }

    return render(request, "shop/order_tracking.html", ctx)
Beispiel #25
0
def home(request, template="base_index.html"):
    # Display the category, its child categories, and its products.

    if request.method == "GET":
        currpage = request.GET.get("page", 1)
    else:
        currpage = 1

    featured = display_featured()

    count = config_value("SHOP", "NUM_PAGINATED")

    paginator = Paginator(featured, count)

    is_paged = False
    page = None

    try:
        paginator.validate_number(currpage)
    except EmptyPage:
        return bad_or_missing(request, _("Invalid page number"))

    is_paged = paginator.num_pages > 1
    page = paginator.page(currpage)

    ctx = {
        "all_products_list": page.object_list,
        "is_paginated": is_paged,
        "page_obj": page,
        "paginator": paginator,
    }

    return render(request, template, ctx)
Beispiel #26
0
def google_adwords_signup(context):
    """
    Output signup info in the format that Google adwords needs.
    """
    request = context["request"]
    try:
        request = context["request"]
    except KeyError:
        logger.warning(
            "Template satchmo.show.templatetags.google.google_adwords_sale couldn't get the request from the context.  Are you missing the request context_processor?"
        )
        return ""

    secure = request.is_secure()
    try:
        language_code = request.LANGUAGE_CODE
    except AttributeError:
        language_code = settings.LANGUAGE_CODE

    return {
        "GOOGLE_ADWORDS_ID": config_value("GOOGLE", "ADWORDS_ID"),
        "Store": settings.SITE_NAME,
        "value": 1,
        "label": "signup",
        "secure": secure,
        "language_code": language_code,
    }
Beispiel #27
0
def show_tracker(secure=False):
    """
    Output the google tracker code.
    """
    return {
        "GOOGLE_CODE": config_value("GOOGLE", "ANALYTICS_CODE"),
        "secure": secure
    }
Beispiel #28
0
def shipping_methods():
    methods = []
    modules = config_value("SHIPPING", "MODULES")
    logger.debug("Getting shipping methods: %s", modules)
    for m in modules:
        module = load_module(m)
        methods.extend(module.get_methods())
    return methods
Beispiel #29
0
def credit_choices(settings=None, include_module_if_no_choices=False):
    choices = []
    keys = []
    for module in config_value("PAYMENT", "MODULES"):
        vals = config_choice_values(module, "CREDITCHOICES")
        for val in vals:
            key, label = val
            if key not in keys:
                keys.append(key)
                pair = (key, ugettext(label))
                choices.append(pair)
        if include_module_if_no_choices and not vals:
            key = config_value(module, "KEY")
            label = config_value(module, "LABEL")
            pair = (key, ugettext(label))
            choices.append(pair)
    return choices
Beispiel #30
0
def send_owner_order_notice(new_order,
                            template="email/order/placed_notice.txt"):
    """Send an order confirmation mail to the owner.
    """
    from satchmo.shop.models import Config

    if config_value("PAYMENT", "ORDER_EMAIL_OWNER"):
        shop_config = Config.objects.get_current()
        shop_email = shop_config.store_email
        t = loader.get_template(template)
        c = {"order": new_order, "shop_config": shop_config}
        subject = _("New order on {shop_name}").format(
            shop_name=shop_config.store_name)

        eddresses = [shop_email]
        more = config_value("PAYMENT", "ORDER_EMAIL_EXTRA")
        if more:
            more = [m.strip() for m in more.split(",")]
            for m in more:
                if m not in eddresses:
                    eddresses.append(m)

        eddresses = [e for e in eddresses if e]
        if not eddresses:
            log.warn("No shop owner email specified, skipping owner_email")
            return

        try:
            body = t.render(c)
            message = EmailMessage(subject, body, shop_email, eddresses)
            message.send()

        except (SocketError, SMTPRecipientsRefused) as e:
            if settings.DEBUG:
                log.warn(
                    "Ignoring email error, since you are running in DEBUG mode.  Email was:\nTo:%s\nSubject: %s\n---\n%s",
                    ",".join(eddresses),
                    subject,
                    body,
                )
            else:
                log.fatal("Error sending mail: %s" % e)
                raise IOError(
                    "Could not send email, please check to make sure your email settings are correct, and that you are not being blocked by your ISP."
                )
Beispiel #31
0
def display_featured(limit=None, random=None):
    """
    Used by the index generic view to choose how the featured products are displayed.
    Items can be displayed randomly or all in order
    """
    if random:
        random_display = random
    else:
        random_display = config_value("SHOP", "RANDOM_FEATURED")
    if limit:
        num_to_display = limit
    else:
        num_to_display = config_value("SHOP", "NUM_DISPLAY")
    q = Product.objects.featured_by_site().filter(items_in_stock__gt=0)
    if not random_display:
        return q[:num_to_display]
    else:
        return q.order_by("?")[:num_to_display]
Beispiel #32
0
def display_bestsellers(request,
                        count=0,
                        template="product/best_sellers.html"):
    """Display a list of the products which have sold the most"""
    if count == 0:
        count = config_value("SHOP", "NUM_PAGINATED")

    ctx = {"products": bestsellers(count)}
    return render(request, template, ctx)
Beispiel #33
0
def display_featured(limit=None, random=None):
    """
    Used by the index generic view to choose how the featured products are displayed.
    Items can be displayed randomly or all in order
    """
    if random:
        random_display = random
    else:
        random_display = config_value("SHOP", "RANDOM_FEATURED")
    if limit:
        num_to_display = limit
    else:
        num_to_display = config_value("SHOP", "NUM_DISPLAY")
    q = Product.objects.featured().filter(items_in_stock__gt=0)
    if not random_display:
        return q[:num_to_display]
    else:
        return q.order_by("?")[:num_to_display]
Beispiel #34
0
    def testSmallPayment(self):
        order = TestOrderFactory()
        order.recalculate_total(save=False)

        paytype = config_value("PAYMENT", "MODULES")[0]
        pmt = OrderPayment(order=order, payment=paytype, amount=Decimal("0.000001"))
        pmt.save()

        self.assertTrue(order.is_partially_paid)
Beispiel #35
0
 def cost(self):
     """
     Complex calculations can be done here as long as the return value is a dollar figure
     """
     assert self._calculated
     for cartitem in self.cart.cartitem_set.all():
         if cartitem.product.is_shippable:
             return config_value("SHIPPING", "FLAT_RATE")
     return Decimal("0.00")
Beispiel #36
0
 def test_product(self):
     # Test for an easily missed reversion. When you lookup a productvariation product then
     # you should get the page of the parent configurableproduct, but with the options for
     # that variation already selected
     response = self.client.get(prefix + "/product/neat-book-soft/")
     self.assertContains(response, 'option value="soft" selected="selected"')
     self.assertContains(
         response, smart_str("%s5.00" % config_value("CURRENCY", "CURRENCY"))
     )
Beispiel #37
0
def send_owner_order_notice(new_order, template="email/order/placed_notice.txt"):
    """Send an order confirmation mail to the owner.
    """
    from satchmo.shop.models import Config

    if config_value("PAYMENT", "ORDER_EMAIL_OWNER"):
        shop_config = Config.objects.get_current()
        shop_email = shop_config.store_email
        t = loader.get_template(template)
        c = {"order": new_order, "shop_config": shop_config}
        subject = _("New order on {shop_name}").format(shop_name=shop_config.store_name)

        eddresses = [shop_email]
        more = config_value("PAYMENT", "ORDER_EMAIL_EXTRA")
        if more:
            more = [m.strip() for m in more.split(",")]
            for m in more:
                if m not in eddresses:
                    eddresses.append(m)

        eddresses = [e for e in eddresses if e]
        if not eddresses:
            log.warn("No shop owner email specified, skipping owner_email")
            return

        try:
            body = t.render(c)
            message = EmailMessage(subject, body, shop_email, eddresses)
            message.send()

        except (SocketError, SMTPRecipientsRefused) as e:
            if settings.DEBUG:
                log.warn(
                    "Ignoring email error, since you are running in DEBUG mode.  Email was:\nTo:%s\nSubject: %s\n---\n%s",
                    ",".join(eddresses),
                    subject,
                    body,
                )
            else:
                log.fatal("Error sending mail: %s" % e)
                raise IOError(
                    "Could not send email, please check to make sure your email settings are correct, and that you are not being blocked by your ISP."
                )
Beispiel #38
0
 def test_product(self):
     # Test for an easily missed reversion. When you lookup a productvariation product then
     # you should get the page of the parent configurableproduct, but with the options for
     # that variation already selected
     response = self.client.get(prefix + "/product/neat-book-soft/")
     self.assertContains(response,
                         'option value="soft" selected="selected"')
     self.assertContains(
         response,
         smart_str("%s5.00" % config_value("CURRENCY", "CURRENCY")))
Beispiel #39
0
 def cost(self):
     """
     Complex calculations can be done here as long as the return value is a dollar figure
     """
     fee = Decimal("0.00")
     rate = config_value("SHIPPING", "PER_RATE")
     for cartitem in self.cart.cartitem_set.all():
         if cartitem.product.is_shippable:
             fee += rate * cartitem.quantity
     return fee
Beispiel #40
0
def labelled_payment_choices():
    active_payment_modules = config_choice_values("PAYMENT", "MODULES", translate=True)

    choices = []
    for module, module_name in active_payment_modules:
        label = config_value(module, "LABEL", default=module_name)
        choices.append((module, label))

    signals.payment_choices.send(None, choices=choices)
    return choices
Beispiel #41
0
def confirm_info(request):
    "Create form to send to WorldPay"
    # Check that items are in stock
    cart = Cart.objects.from_request(request)
    if cart.not_enough_stock():
        return HttpResponseRedirect(reverse("satchmo_cart"))

    try:
        order = Order.objects.from_request(request)
    except Order.DoesNotExist:
        order = None

    if not (order and order.validate(request)):
        context = {"message": _("Your order is no longer valid.")}

        return render(request, "shop_404.html", context)

    template = lookup_template(payment_module,
                               "checkout/worldpay/confirm.html")

    live = payment_module.LIVE.value
    currency = order.currency.iso_4217_code
    inst_id = payment_module.INSTID.value
    default_view_tax = config_value("TAX", "DEFAULT_VIEW_TAX")

    if live:
        post_url = payment_module.CONNECTION.value
    else:
        post_url = payment_module.CONNECTION_TEST.value

    if payment_module.MD5.value > "":
        # Doing the MD5 Signature dance
        # Generating secret "secret;amount;currency;cartId"
        balance = trunc_decimal(order.balance, 2)
        signature = "%s:%s:%s:%s" % (
            payment_module.MD5.value,
            balance,
            currency,
            order.id,
        )
        MD5 = md5(signature).hexdigest()
    else:
        MD5 = False

    ctx = {
        "order": order,
        "inst_id": inst_id,
        "currency": currency,
        "post_url": post_url,
        "default_view_tax": default_view_tax,
        "PAYMENT_LIVE": live,
        "MD5": MD5,
        "session": request.session.session_key,
    }
    return render(request, template, ctx)
Beispiel #42
0
    def testSmallPayment(self):
        order = TestOrderFactory()
        order.recalculate_total(save=False)

        paytype = config_value("PAYMENT", "MODULES")[0]
        pmt = OrderPayment(order=order,
                           payment=paytype,
                           amount=Decimal("0.000001"))
        pmt.save()

        self.assertTrue(order.is_partially_paid)
Beispiel #43
0
    def testSimpleRequires(self):
        v = config_value("req1", "bool2")
        self.assertTrue(v)

        keys = [cfg.key for cfg in self.g1]
        self.assertEqual(keys, ["c2", "c3", "bool1", "bool2"])

        c = config_get("req1", "bool1")
        c.update(True)

        keys = [cfg.key for cfg in self.g1]
        self.assertEqual(keys, ["c1", "c2", "c3", "bool1", "bool2"])
Beispiel #44
0
    def testRequiresSingleValue(self):
        v = config_value("SHOP", "valchoices2")
        self.assertEqual(v, "a")

        keys = [cfg.key for cfg in self.g2]
        self.assertEqual(keys, ["c1"])

        c = config_get("SHOP", "valchoices2")
        c.update("b")

        keys = [cfg.key for cfg in self.g2]
        self.assertEqual(keys, ["c2"])
Beispiel #45
0
    def testRequiresSingleValue(self):
        v = config_value("SHOP", "valchoices2")
        self.assertEqual(v, "a")

        keys = [cfg.key for cfg in self.g2]
        self.assertEqual(keys, ["c1"])

        c = config_get("SHOP", "valchoices2")
        c.update("b")

        keys = [cfg.key for cfg in self.g2]
        self.assertEqual(keys, ["c2"])
Beispiel #46
0
    def testSimpleRequires(self):
        v = config_value("req1", "bool2")
        self.assertTrue(v)

        keys = [cfg.key for cfg in self.g1]
        self.assertEqual(keys, ["c2", "c3", "bool1", "bool2"])

        c = config_get("req1", "bool1")
        c.update(True)

        keys = [cfg.key for cfg in self.g1]
        self.assertEqual(keys, ["c1", "c2", "c3", "bool1", "bool2"])
Beispiel #47
0
def convert_to_currency(value, currency_code, ignore_buffer=False):
    """Convert a Decimal value using the current exchange rate for the supplied currency_code"""
    if value is None or value == Decimal("0.00"):
        return Decimal("0.00")

    currency = Currency.objects.get_primary()
    if currency_code is not None and currency_code != currency.iso_4217_code:
        try:
            currency = Currency.objects.accepted().get(iso_4217_code=currency_code)
        except Currency.DoesNotExist:
            pass

        try:
            exchange_rate = currency.exchange_rates.latest().rate
        except ExchangeRate.DoesNotExist:
            exchange_rate = Decimal("1.00")

        # Add a small buffer
        if value and ignore_buffer is False:
            buffer = config_value("CURRENCY", "BUFFER")
            value = value + buffer

        # Multiply by the exchange rate
        value = value * exchange_rate

        # Quantize value using bankers rounding
        value = value.quantize(Decimal(".01"), rounding=ROUND_HALF_EVEN)

        # Round up to the nearest half unit of currency
        if config_value("CURRENCY", "ROUND_UP"):
            if value % 1 > Decimal("0.5"):
                value = Decimal(math.ceil(value))
            else:
                value = Decimal(math.floor(value)) + Decimal("0.5")

    # Take away 1 minor unit of currency
    if config_value("CURRENCY", "PSYCHOLOGICAL_PRICING") and value == math.ceil(value):
        value = value - Decimal("0.01")

    return value
Beispiel #48
0
    def shipping(self, subtotal=None):
        if subtotal is None and self.order:
            subtotal = self.order.shipping_sub_total

        if subtotal:
            rate = None
            if config_value("TAX", "TAX_SHIPPING"):
                try:
                    tc = TaxClass.objects.get(title=config_value("TAX", "TAX_CLASS"))
                    rate = self.get_rate(taxclass=tc)
                except:
                    log.error("'Shipping' TaxClass doesn't exist.")

            if rate:
                t = rate * subtotal
            else:
                t = Decimal("0.00")

        else:
            t = Decimal("0.00")

        return t
Beispiel #49
0
    def test_downloadable_zero_shipping(self):
        subtypes = config_value("PRODUCT", "PRODUCT_TYPES")
        if "product::DownloadableProduct" in subtypes:
            subtype2 = DownloadableProduct.objects.create(product=self.product1)
            self.assertEqual(
                self.product1.get_subtypes(),
                ("ConfigurableProduct", "DownloadableProduct"),
            )

            self.assertFalse(subtype2.is_shippable)
            self.assertFalse(self.product1.is_shippable)
            self.assertFalse(self.cart1.is_shippable)
            self.assertEqual(flat(self.cart1, None).cost(), Decimal("0.00"))
            self.assertEqual(per(self.cart1, None).cost(), Decimal("0.00"))