Example #1
0
    def test_get_price(self):
        """
        Get a price/productname for a ProductVariation
        """
        response = self.client.get(prefix + '/product/DJ-Rocks/')
        self.assertContains(response,
                            "Django Rocks shirt",
                            count=1,
                            status_code=200)

        # this tests the unmolested price from the ConfigurableProduct, and
        # makes sure we get a good productname back for the ProductVariation
        response = self.client.post(prefix + '/product/DJ-Rocks/prices/', {
            "1": "S",
            "2": "B",
            "quantity": 1
        })
        self.assertEquals(
            response.content,
            '["DJ-Rocks_S_B", "%s20.00"]' % config_value('SHOP', 'CURRENCY'))

        # This tests the option price_change feature, and again the productname
        response = self.client.post(prefix + '/product/DJ-Rocks/prices/', {
            "1": "L",
            "2": "BL",
            "quantity": 2
        })
        self.assertEquals(
            response.content,
            '["DJ-Rocks_L_BL", "%s23.00"]' % config_value('SHOP', 'CURRENCY'))
Example #2
0
def check_with_akismet(comment=None, request=None, **kwargs):
    if config_value("PRODUCT", "AKISMET_ENABLE"):
        key = config_value("PRODUCT", "AKISMET_KEY")
        if key:             
            site = Site.objects.get_current()
            shop = urlresolvers.reverse('satchmo_shop_home')
            from akismet import Akismet
            akismet = Akismet(
                key=settings.AKISMET_API_KEY,
                blog_url='http://%s' % url_join(site.domain, shop))
            if akismet.verify_key():
                akismet_data = { 'comment_type': 'comment',
                                 'referrer': request.META.get('HTTP_REFERER', ""),
                                 'user_ip': comment.ip_address,
                                 'user_agent': '' }
                if akismet_api.comment_check(smart_str(comment.comment), data=akismet_data, build_data=True):
                    comment.is_public=False
                    comment.save()
                    log.info("Akismet marked comment #%i as spam", comment.id)
                else:
                    log.debug("Akismet accepted comment #%i", comment.id)
            else:
                log.warn("Akismet key '%s' not accepted by akismet service.", key)
        else:
            log.info("Akismet enabled, but no key found.  Please put in your admin settings.")
Example #3
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
Example #4
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
Example #5
0
def order_payload(order):
    data = {}
    data["api_key"] = config_value("satchmo.fulfilment.modules.six", "API_KEY")
    data["test"] = config_value("satchmo.fulfilment.modules.six", "TEST_MODE")
    data["allow_preorder"] = config_value("satchmo.fulfilment.modules.six", "ALLOW_PREORDER")
    data["update_stock"] = config_value("satchmo.fulfilment.modules.six", "UPDATE_STOCK")
    data["order"] = {}

    despatch_url = external_url(reverse("six_despatch", kwargs={"order_id": order.id, "verification_hash": order.verification_hash}))

    data["order"]["client_ref"] = order.id
    data["order"]["po_number"] = order.id
    data["order"]["date_placed"] = unicode(order.time_stamp)
    data["order"]["callback_url"] = despatch_url
    data["order"]["postage_speed"] = order.shipping_postage_speed
    data["order"]["postage_cost"] = float_price(order.shipping_cost)
    data["order"]["total_amount"] = float_price(order.sub_total)
    data["order"]["signed_for"] = order.shipping_signed_for
    data["order"]["tracked"] = order.shipping_tracked
    data["order"]["ShippingContact"] = {
        "dear": order.contact.user.first_name,
        "name": order.ship_addressee,
        "email": order.contact.user.email,
        "phone": get_phone_number(order),
        "address": order.ship_street1,
        "address_contd": order.ship_street2,
        "city": order.ship_city,
        "county": order.ship_state,
        "country": unicode(order.ship_country),
        "postcode": order.ship_postal_code,
    }
    data["order"]["BillingContact"] = {
        "name": order.bill_addressee,
        "email": order.contact.user.email,
        "phone": get_phone_number(order),
        "address": order.bill_street1,
        "address_contd": order.bill_street2,
        "city": order.bill_city,
        "county": order.bill_state,
        "country": unicode(order.bill_country),
        "postcode": order.bill_postal_code,
    }
    data["order"]["items"] = [
        {
            # Six limits slugs to 40 characters.  Six stores
            # client_refs with a length of 40 characters (truncated
            # silently).  When passing a > 40 character slug, the
            # whole slug is checked against the 40 character
            # client_ref and doesn't match.  So, we just truncate
            # slugs to 40 characters.
            "client_ref": item.product.slug[:40],
            "quantity": item.quantity,
            "price": float_price(item.unit_price),

        }
        for item in order.orderitem_set.all()
    ]

    return json.dumps(data)
Example #6
0
def make_urlpatterns():
    patterns = []
    for key in config_value('PAYMENT', 'MODULES'):
        cfg = config_get(key, 'MODULE')
        modulename = cfg.editor_value
        urlmodule = "%s.urls" % modulename
        patterns.append(url(config_value(key, 'URL_BASE'), [urlmodule, modulename, '']))
    return tuple(patterns)
Example #7
0
def make_urlpatterns():
    patterns = []
    for key in config_value('PAYMENT', 'MODULES'):
        cfg = config_get(key, 'MODULE')
        modulename = cfg.editor_value
        urlmodule = "%s.urls" % modulename
        patterns.append(url(config_value(key, 'URL_BASE'), [urlmodule]))
    return tuple(patterns)
Example #8
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)
            taxed_shipping_price = money_format(total)

        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()

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

    return shipping_options, shipping_dict
Example #9
0
    def test_custom_product(self):
        """
        Verify that the custom product is working as expected.
        """
        pm = config_get("PRODUCT", "PRODUCT_TYPES")
        pm.update(
            [
                "product::ConfigurableProduct",
                "product::ProductVariation",
                "product::CustomProduct",
                "product::SubscriptionProduct",
            ]
        )

        response = self.client.get(prefix + "/")
        self.assertContains(response, "Computer", count=1)
        response = self.client.get(prefix + "/product/satchmo-computer/")
        self.assertContains(response, "Memory", count=1)
        self.assertContains(response, "Case", count=1)
        self.assertContains(response, "Monogram", count=1)
        response = self.client.post(
            prefix + "/cart/add/",
            {"productname": "satchmo-computer", "5": "1.5gb", "6": "mid", "custom_monogram": "CBM", "quantity": 1},
        )
        self.assertRedirects(response, prefix + "/cart/", status_code=302, target_status_code=200)
        response = self.client.get(prefix + "/cart/")
        self.assertContains(response, '/satchmo-computer/">satchmo computer', count=1, status_code=200)
        self.assertContains(response, smart_str("%s168.00" % config_value("SHOP", "CURRENCY")), count=3)
        self.assertContains(response, smart_str("Monogram: CBM  %s10.00" % config_value("SHOP", "CURRENCY")), count=1)
        self.assertContains(
            response, smart_str("Case - External Case: Mid  %s10.00" % config_value("SHOP", "CURRENCY")), count=1
        )
        self.assertContains(
            response, smart_str("Memory - Internal RAM: 1.5 GB  %s25.00" % config_value("SHOP", "CURRENCY")), count=1
        )
        response = self.client.post(url("satchmo_checkout-step1"), get_step1_post_data(self.US))
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-step2"), status_code=302, target_status_code=200)
        data = {
            "credit_type": "Visa",
            "credit_number": "4485079141095836",
            "month_expires": "1",
            "year_expires": "2012",
            "ccv": "552",
            "shipping": "FlatRate",
        }
        response = self.client.post(url("DUMMY_satchmo_checkout-step2"), data)
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-step3"), status_code=302, target_status_code=200)
        response = self.client.get(url("DUMMY_satchmo_checkout-step3"))
        self.assertContains(
            response,
            smart_str("satchmo computer - %s168.00" % config_value("SHOP", "CURRENCY")),
            count=1,
            status_code=200,
        )
        response = self.client.post(url("DUMMY_satchmo_checkout-step3"), {"process": "True"})
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-success"), status_code=302, target_status_code=200)
        self.assertEqual(len(mail.outbox), 1)
Example #10
0
    def process(self):
        """
        Calculate the tax and return it
        """
        subtotal = self.order.sub_total - self.order.discount

        if config_value('TAX', 'TAX_SHIPPING'):
            subtotal += self.order.shipping_cost

        percent = config_value('TAX', 'PERCENT')
        return subtotal * (percent / 100)
Example #11
0
 def process(self):
     """
     Calculate the tax and return it
     """
     subtotal = self.order.sub_total - self.order.discount
     
     if config_value('TAX','TAX_SHIPPING'):
         subtotal += self.order.shipping_cost
     
     percent = config_value('TAX','PERCENT')
     return subtotal * (percent/100)
Example #12
0
def display_featured():
    """
    Used by the index generic view to choose how the featured products are displayed.
    Items can be displayed randomly or all in order
    """
    random_display = config_value('SHOP','RANDOM_FEATURED')
    num_to_display = config_value('SHOP','NUM_DISPLAY')
    q = Product.objects.featured_by_site()
    if not random_display:
        return q[:num_to_display]
    else:
        return q.order_by('?')[:num_to_display]
Example #13
0
    def test_checkout(self):
        """
        Run through a full checkout process
        """
        cache_delete()
        tax = config_get("TAX", "MODULE")
        tax.update("satchmo.tax.modules.percent")
        pcnt = config_get("TAX", "PERCENT")
        pcnt.update("10")
        shp = config_get("TAX", "TAX_SHIPPING")
        shp.update(False)

        self.test_cart_adding()
        response = self.client.post(url("satchmo_checkout-step1"), get_step1_post_data(self.US))
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-step2"), status_code=302, target_status_code=200)
        data = {
            "credit_type": "Visa",
            "credit_number": "4485079141095836",
            "month_expires": "1",
            "year_expires": "2009",
            "ccv": "552",
            "shipping": "FlatRate",
        }
        response = self.client.post(url("DUMMY_satchmo_checkout-step2"), data)
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-step3"), status_code=302, target_status_code=200)
        response = self.client.get(url("DUMMY_satchmo_checkout-step3"))
        self.assertContains(
            response, smart_str("Shipping + %s4.00" % config_value("SHOP", "CURRENCY")), count=1, status_code=200
        )
        self.assertContains(
            response, smart_str("Tax + %s4.60" % config_value("SHOP", "CURRENCY")), count=1, status_code=200
        )
        self.assertContains(
            response, smart_str("Total = %s54.60" % config_value("SHOP", "CURRENCY")), count=1, status_code=200
        )
        response = self.client.post(url("DUMMY_satchmo_checkout-step3"), {"process": "True"})
        self.assertRedirects(response, url("DUMMY_satchmo_checkout-success"), status_code=302, target_status_code=200)
        self.assertEqual(len(mail.outbox), 1)

        # Log in as a superuser
        user = User.objects.create_user("fredsu", "*****@*****.**", "passwd")
        user.is_staff = True
        user.is_superuser = True
        user.save()
        self.client.login(username="******", password="******")

        # Test pdf generation
        response = self.client.get("/admin/print/invoice/1/")
        self.assertContains(response, "reportlab", status_code=200)
        response = self.client.get("/admin/print/packingslip/1/")
        self.assertContains(response, "reportlab", status_code=200)
        response = self.client.get("/admin/print/shippinglabel/1/")
        self.assertContains(response, "reportlab", status_code=200)
Example #14
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)
            taxed_shipping_price = money_format(total)

        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()

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

    return shipping_options, shipping_dict
Example #15
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
Example #16
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
Example #17
0
def _get_shipping_choices(paymentmodule, cart, contact):
    """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 = {}
    
    for module in config_value('SHIPPING','MODULES'):
        #Create the list of information the user will see
        shipping_module = load_module(module)
        shipping_instance = shipping_module.Calc(cart, contact)
        if shipping_instance.valid():
            template = lookup_template(paymentmodule, 'shipping_options.html')
            t = loader.get_template(template)
            shipcost = shipping_instance.cost()
            c = Context({
                'amount': shipcost,
                'description' : shipping_instance.description(),
                'method' : shipping_instance.method(),
                'expected_delivery' : shipping_instance.expectedDelivery() })
            shipping_options.append((shipping_instance.id, t.render(c)))
            shipping_dict[shipping_instance.id] = shipcost
    
    return shipping_options, shipping_dict
Example #18
0
def get_newsletter_module():
    try:
        modulename = config_value('NEWSLETTER', 'MODULE')
    except AttributeError:
        modulename = 'satchmo.newsletter.ignore'
        
    return load_module(modulename)
Example #19
0
def get_newsletter_module():
    try:
        modulename = config_value("NEWSLETTER", "MODULE")
    except AttributeError:
        modulename = "satchmo.newsletter.ignore"

    return load_module(modulename)
Example #20
0
def view_user_data_listener(contact=None, contact_dict=None, **kwargs):
    module = config_value("NEWSLETTER", "MODULE")
    if module not in ("", "satchmo.newsletter.ignore"):
        contact_dict["show_newsletter"] = True
        contact_dict["newsletter"] = is_subscribed(contact)
    else:
        contact_dict["show_newsletter"] = False
Example #21
0
    def _save_rename(self, instance, **kwargs):
        if hasattr(self, '_renaming') and self._renaming:
            return
        if self.auto_rename == NOTSET:
            try:
                self.auto_rename = config_value('THUMBNAIL', 'RENAME_IMAGES')
            except SettingNotSet:
                self.auto_rename = False

        image = getattr(instance, self.attname)
        if image and self.auto_rename:
            if self.name_field:
                field = getattr(instance, self.name_field)
                image = rename_by_field(image.path, '%s-%s-%s' \
                                        % (instance.__class__.__name__,
                                           self.name,
                                           field
                                           )
                                        )
            else:
                # XXX this needs testing, maybe it can generate too long image names (max is 100)
                image = rename_by_field(image.path, '%s-%s-%s' \
                                        % (instance.__class__.__name__,
                                           self.name,
                                           instance._get_pk_val()
                                           )
                                        )
            setattr(instance, self.attname, image)
            self._renaming = True
            instance.save()
            self._renaming = False
Example #22
0
    def testCronRebill(self):
        for order in OrderItem.objects.all():
            price, expire_length = self.getTerms(order.product)
            if price is None:
                continue
            self.assertEqual(
                order.expire_date,
                datetime.date.today() + datetime.timedelta(days=expire_length))
            #set expire date to today for upcoming cron test
            order.expire_date = datetime.date.today()
            order.save()

        order_count = OrderItem.objects.count()
        self.c = Client()
        self.response = self.c.get(prefix + '/checkout/cron/')
        self.assertEqual(self.response.status_code, 200)
        self.assertEqual(self.response.content, 'Authentication Key Required')
        from django.conf import settings
        self.response = self.c.get(
            prefix + '/checkout/cron/',
            data={'key': config_value('PAYMENT', 'CRON_KEY')})
        self.assertEqual(self.response.status_code, 200)
        self.assertEqual(self.response.content, '')
        self.assert_(order_count < OrderItem.objects.count())
        self.assertEqual(order_count, OrderItem.objects.count() / 2.0)
        for order in OrderItem.objects.filter(
                expire_date__gt=datetime.datetime.now()):
            price, expire_length = self.getTerms(order.product,
                                                 ignore_trial=True)
            if price is None:
                continue
            self.assertEqual(
                order.expire_date,
                datetime.date.today() + datetime.timedelta(days=expire_length))
            self.assertEqual(order.order.balance, Decimal('0.00'))
Example #23
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
Example #24
0
def activate(request, activation_key):
    """
    Activates a user's account, if their key is valid and hasn't
    expired.

    """

    from registration.models import RegistrationProfile

    activation_key = activation_key.lower()
    account = RegistrationProfile.objects.activate_user(activation_key)

    if account:
        # ** hack for logging in the user **
        # when the login form is posted, user = authenticate(username=data['username'], password=data['password'])
        # ...but we cannot authenticate without password... so we work-around authentication
        account.backend = settings.AUTHENTICATION_BACKENDS[0]
        login(request, account)
        contact = Contact.objects.get(user=account)
        request.session['custID'] = contact.id
        send_welcome_email(contact.email, contact.first_name,
                           contact.last_name)

    context = RequestContext(
        request, {
            'account': account,
            'expiration_days': config_value('SHOP', 'ACCOUNT_ACTIVATION_DAYS'),
        })
    return render_to_response('registration/activate.html', context)
Example #25
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 = RequestContext(
        request, {
            'default_view_tax': config_value('TAX', 'DEFAULT_VIEW_TAX'),
            'contact': contact,
            'order': order
        })

    return render_to_response('shop/order_tracking.html', ctx)
Example #26
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',
         }
Example #27
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
Example #28
0
def get_newsletter_module():
    try:
        modulename = config_value('NEWSLETTER', 'MODULE')
    except AttributeError:
        modulename = 'satchmo.newsletter.ignore'

    return load_module(modulename)
Example #29
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 = RequestContext(
        request, {
            'all_products_list': page.object_list,
            'is_paginated': is_paged,
            'page_obj': page,
            'paginator': paginator
        })

    return render_to_response(template, ctx)
Example #30
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 = RequestContext(request, {
        'all_products_list' : page.object_list,        
        'is_paginated' : is_paged,
        'page_obj' : page,
        'paginator' : paginator
    })
    
    return render_to_response(template, ctx)
Example #31
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)
Example #32
0
    def testCronRebill(self):
        for order in OrderItem.objects.all():
            price, expire_length = self.getTerms(order.product)
            if price is None:
                continue
            self.assertEqual(order.expire_date, datetime.date.today() + datetime.timedelta(days=expire_length))
            #set expire date to today for upcoming cron test
            order.expire_date = datetime.date.today()
            order.save()

        order_count = OrderItem.objects.count()
        self.c = Client()
        self.response = self.c.get(prefix+'/checkout/cron/')
        self.assertEqual(self.response.status_code, 200)
        self.assertEqual(self.response.content, 'Authentication Key Required')
        from django.conf import settings
        self.response = self.c.get(prefix+'/checkout/cron/', data={'key': config_value('PAYMENT','CRON_KEY')})
        self.assertEqual(self.response.status_code, 200)
        self.assertEqual(self.response.content, '')
        self.assert_(order_count < OrderItem.objects.count())
        self.assertEqual(order_count, OrderItem.objects.count()/2.0)
        for order in OrderItem.objects.filter(expire_date__gt=datetime.datetime.now()):
            price, expire_length = self.getTerms(order.product, ignore_trial=True)
            if price is None:
                continue
            self.assertEqual(order.expire_date, datetime.date.today() + datetime.timedelta(days=expire_length))
            self.assertEqual(order.order.balance, Decimal('0.00'))
Example #33
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)
Example #34
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)
Example #35
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:
        print >> sys.stderr, "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
    })
Example #36
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',
        }
Example #37
0
    def __init__(self, request, paymentmodule, *args, **kwargs):
        super(SimplePayShipForm, self).__init__(*args, **kwargs)

        self.order = None
        self.orderpayment = None

        try:
            self.tempCart = Cart.objects.from_request(request)
            if self.tempCart.numItems > 0:
                products = [item.product for item in self.tempCart.cartitem_set.all()]
                sale = find_best_auto_discount(products)
                if sale:
                    self.fields['discount'].initial = sale.code

        except Cart.DoesNotExist:
            self.tempCart = None

        try:
            self.tempContact = Contact.objects.from_request(request)
        except Contact.DoesNotExist:
            self.tempContact = None

        if 'default_view_tax' in kwargs:
            default_view_tax = kwargs['default_view_tax']
        else:
            default_view_tax = config_value('TAX', 'TAX_SHIPPING')

        shipping_choices, shipping_dict = _get_shipping_choices(request, paymentmodule, self.tempCart, self.tempContact, default_view_tax=default_view_tax)
        self.fields['shipping'].choices = shipping_choices
        self.shipping_dict = shipping_dict

        signals.payment_form_init.send(SimplePayShipForm, form=self)
Example #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('SHOP', 'CURRENCY')))
Example #39
0
    def testBalanceMethods(self):
        order = make_test_order(self.US, "", include_non_taxed=True)
        order.recalculate_total(save=False)
        price = order.total
        subtotal = order.sub_total

        self.assertEqual(subtotal, Decimal("105.00"))
        self.assertEqual(price, Decimal("115.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("110.00"))
        self.assertEqual(order.balance_paid, Decimal("5.00"))

        self.assert_(order.is_partially_paid)

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

        self.assertEqual(order.balance, Decimal("0.00"))
        self.assertEqual(order.is_partially_paid, False)
        self.assert_(order.paid_in_full)
Example #40
0
 def _save_rename(self, instance, **kwargs):
     if hasattr(self, '_renaming') and self._renaming:
         return
     if self.auto_rename == NOTSET:
         try:
             self.auto_rename = config_value('THUMBNAIL', 'RENAME_IMAGES')
         except SettingNotSet:
             self.auto_rename = False
     
     image = getattr(instance, self.attname)
     if image and self.auto_rename:
         if self.name_field:
             field = getattr(instance, self.name_field)
             image = rename_by_field(image.path, '%s-%s-%s' \
                                     % (instance.__class__.__name__,
                                        self.name,
                                        field
                                        )
                                     )
         else:
             # XXX this needs testing, maybe it can generate too long image names (max is 100)
             image = rename_by_field(image.path, '%s-%s-%s' \
                                     % (instance.__class__.__name__,
                                        self.name,
                                        instance._get_pk_val()
                                        )
                                     )
         setattr(instance, self.attname, image)
         self._renaming = True
         instance.save()
         self._renaming = False
Example #41
0
def activate(request, activation_key):
    """
    Activates a user's account, if their key is valid and hasn't
    expired.

    """

    from registration.models import RegistrationProfile

    activation_key = activation_key.lower()
    account = RegistrationProfile.objects.activate_user(activation_key)

    if account:
        # ** hack for logging in the user **
        # when the login form is posted, user = authenticate(username=data['username'], password=data['password'])
        # ...but we cannot authenticate without password... so we work-around authentication
        account.backend = settings.AUTHENTICATION_BACKENDS[0]
        login(request, account)
        contact = Contact.objects.get(user=account)
        request.session['custID'] = contact.id
        send_welcome_email(contact.email, contact.first_name, contact.last_name)

    context = RequestContext(request, {
        'account': account,
        'expiration_days': config_value('SHOP', 'ACCOUNT_ACTIVATION_DAYS'),
    })
    return render_to_response('registration/activate.html', context)
Example #42
0
def _get_shipping_choices(paymentmodule, cart, contact):
    """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 = {}

    for module in config_value('SHIPPING', 'MODULES'):
        #Create the list of information the user will see
        shipping_module = load_module(module)
        shipping_instance = shipping_module.Calc(cart, contact)
        if shipping_instance.valid():
            template = lookup_template(paymentmodule, 'shipping_options.html')
            t = loader.get_template(template)
            shipcost = shipping_instance.cost()
            c = Context({
                'amount':
                shipcost,
                'description':
                shipping_instance.description(),
                'method':
                shipping_instance.method(),
                'expected_delivery':
                shipping_instance.expectedDelivery()
            })
            shipping_options.append((shipping_instance.id, t.render(c)))
            shipping_dict[shipping_instance.id] = shipcost

    return shipping_options, shipping_dict
Example #43
0
def get_product(request, category_slug, brand_slug, product_slug, selected_options=(),
                include_tax=NOTSET, default_view_tax=NOTSET):
    """Basic product view"""
    try:
        product = Product.objects.get_by_site(active=True, slug=product_slug)
    except Product.DoesNotExist:
        return bad_or_missing(request, _('The product you have requested does not exist.'))

    try:
        category = Category.objects.get(slug=category_slug)
    except Category.DoesNotExist:
        category = None
    brand = Brand.objects.get(slug=brand_slug)

    if default_view_tax == NOTSET:
        default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX')

    if default_view_tax:
        include_tax = True

    elif include_tax == NOTSET:
        include_tax = default_view_tax

    if default_view_tax:
        include_tax = True

    subtype_names = product.get_subtypes()

    if 'ProductVariation' in subtype_names:
        selected_options = product.productvariation.unique_option_ids
        # Display the ConfigurableProduct that this ProductVariation belongs to.
        product = product.productvariation.parent.product
        subtype_names = product.get_subtypes()

    best_discount = find_best_auto_discount(product)

    extra_context = {
        'product': product,
        'category': category,
        'brand': brand,
        'default_view_tax': default_view_tax,
        'sale': best_discount,
    }

    # Get the template context from the Product.
    extra_context = product.add_template_context(
        context=extra_context,
        request=request, selected_options=selected_options,
        include_tax=include_tax, default_view_tax=default_view_tax
    )

    if include_tax:
        tax_amt = get_tax(request.user, product, 1)
        extra_context['product_tax'] = tax_amt
        extra_context['price_with_tax'] = product.unit_price + tax_amt

    template = find_product_template(product, producttypes=subtype_names)
    context = RequestContext(request, extra_context)
    return http.HttpResponse(template.render(context))
Example #44
0
 def cost(self):
     """
     Complex calculations can be done here as long as the return value is a dollar figure
     """
     for cartitem in self.cart.cartitem_set.all():
         if cartitem.product.is_shippable:
             return config_value('SHIPPING', 'FLAT_RATE')
     return Decimal("0.00")
Example #45
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
Example #46
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
Example #47
0
def show_tracker(secure=False):
    """
    Output the google tracker code.
    """
    return ({
        "GOOGLE_CODE": config_value('GOOGLE', 'ANALYTICS_CODE'),
        "secure": secure
    })
Example #48
0
 def cost(self):
     """
     Complex calculations can be done here as long as the return value is a dollar figure
     """
     for cartitem in self.cart.cartitem_set.all():
         if cartitem.product.is_shippable:
             return config_value("SHIPPING", "FLAT_RATE")
     return Decimal("0.00")
Example #49
0
 def valid(self, order=None):
     """
     Exclude countries that we don't want to ship to, also exclude
     the United Kingdom as this shipping module doesn't support GB.
     """
     excluded_countries = config_value('satchmo.shipping.modules.royalmailcontract', 'EXCLUDE_COUNTRY')
     excluded_countries.append(u'GB')
     return self.contact.shipping_address.country.iso2_code not in excluded_countries
Example #50
0
def send_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 = Context({'order': new_order, 'shop_config': shop_config})
        subject = _("New order on %(shop_name)s") % {
            '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 not m 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), e:
            if settings.DEBUG:
                log.error('Error sending mail: %s' % e)
                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.'
                )
Example #51
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]
Example #52
0
def contact_info(request):
    """View which collects demographic information from customer."""

    #First verify that the cart exists and has items
    if request.session.get('cart'):
        tempCart = Cart.objects.get(id=request.session['cart'])
        if tempCart.numItems == 0:
            return render_to_response('checkout/empty_cart.html', RequestContext(request))
    else:
        return render_to_response('checkout/empty_cart.html', RequestContext(request))

    init_data = {}
    areas, countries, only_country = get_area_country_options(request)

    contact = Contact.from_request(request, create=False)

    if request.POST:
        new_data = request.POST.copy()
        if not tempCart.is_shippable:
            new_data['copy_address'] = True
        form = PaymentContactInfoForm(countries, areas, new_data,
            initial=init_data)

        if form.is_valid():
            if contact is None and request.user:
                contact = Contact(user=request.user)
            custID = form.save(contact=contact, update_newsletter=False)
            request.session['custID'] = custID
            #TODO - Create an order here and associate it with a session
            modulename = 'PAYMENT_' + new_data['paymentmethod']
            paymentmodule = config_get_group(modulename)
            url = lookup_url(paymentmodule, 'satchmo_checkout-step2')
            return http.HttpResponseRedirect(url)
    else:
        if contact:
            #If a person has their contact info, make sure we populate it in the form
            for item in contact.__dict__.keys():
                init_data[item] = getattr(contact,item)
            if contact.shipping_address:
                for item in contact.shipping_address.__dict__.keys():
                    init_data["ship_"+item] = getattr(contact.shipping_address,item)
            if contact.billing_address:
                for item in contact.billing_address.__dict__.keys():
                    init_data[item] = getattr(contact.billing_address,item)
            if contact.primary_phone:
                init_data['phone'] = contact.primary_phone.phone
        else:
            # Allow them to login from this page.
            request.session.set_test_cookie()
        form = PaymentContactInfoForm(countries, areas, initial=init_data)

    context = RequestContext(request, {
        'form': form,
        'country': only_country,
        'paymentmethod_ct': len(config_value('PAYMENT', 'MODULES'))
        })
    return render_to_response('checkout/form.html', context)
Example #53
0
def upload_dir(instance, filename):
    raw = "images/"

    try:
        raw = config_value('PRODUCT', 'IMAGE_DIR')
    except SettingNotSet:
        pass
    except ImportError, e:
        log.warn("Error getting upload_dir, OK if you are in SyncDB.")
Example #54
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 = RequestContext(request, {
        'products' : bestsellers(count),
    })
    return render_to_response(template, ctx)
Example #55
0
def display_bestratings(request, count=0, template='product/best_ratings.html'):
    """Display a list of the products with the best ratings in comments"""
    if count is None:
        count = config_value('SHOP', 'NUM_DISPLAY')
    
    ctx = RequestContext(request, {
        'products' : highest_rated(),
    })
    return render_to_response(template, ctx)
Example #56
0
 def valid(self, order=None):
     """
     Exclude countries that we don't want to ship to, also exclude
     the United Kingdom as this shipping module doesn't support GB.
     """
     excluded_countries = config_value(
         'satchmo.shipping.modules.royalmailcontract', 'EXCLUDE_COUNTRY')
     excluded_countries.append(u'GB')
     return self.contact.shipping_address.country.iso2_code not in excluded_countries
Example #57
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 = RequestContext(request, {
        'products' : bestsellers(count),
    })
    return render_to_response(template, ctx)
Example #58
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('SHOP', 'CURRENCY')))
Example #59
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
Example #60
0
 def get_subtypes(self):
     types = []
     for key in config_value('PRODUCT', 'PRODUCT_TYPES'):
         app, subtype = key.split("::")
         try:
             if getattr(self, subtype.lower()):
                 types += [subtype]
         except models.ObjectDoesNotExist:
             pass
     return tuple(types)