Example #1
0
from django.contrib import admin

from oscar.core.loading import import_module
product_models = import_module('product.models', [
    'Item', 'ItemClass', 'AttributeType', 'AttributeValueOption',
    'ItemAttributeValue', 'Option', 'ProductRecommendation', 'ProductImage',
    'Category', 'ItemCategory'
])


class AttributeInline(admin.TabularInline):
    model = product_models.ItemAttributeValue


class ProductRecommendationInline(admin.TabularInline):
    model = product_models.ProductRecommendation
    fk_name = 'primary'


class CategoryInline(admin.TabularInline):
    model = product_models.ItemCategory
    extra = 1


class ItemClassAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name", )}


class ItemAdmin(admin.ModelAdmin):
    list_display = ('get_title', 'upc', 'get_item_class', 'is_top_level',
                    'is_group', 'is_variant', 'attribute_summary',
Example #2
0
from django.core.urlresolvers import resolve

from oscar.core.loading import import_module

shipping_methods = import_module('shipping.repository', ['Repository'])


class ProgressChecker(object):
    u"""
    Class for testing whether the appropriate steps of the checkout
    have been completed.
    """
    
    # List of URL names that have to be completed (in this order)
    urls_for_steps = ['oscar-checkout-shipping-address',
                      'oscar-checkout-shipping-method',
                      'oscar-checkout-payment-method',
                      'oscar-checkout-preview',
                      'oscar-checkout-payment-details']
    
    def are_previous_steps_complete(self, request):
        u"""
        Checks whether the previous checkout steps have been completed.
        
        This uses the URL-name and the class-level list of required
        steps.
        """
        # Extract the URL name from the path
        complete_steps = self._get_completed_steps(request)
        try:
            url_name = self._get_url_name(request)
Example #3
0
from django.contrib.sites.models import Site

from oscar.core.loading import import_module
import_module('order.models', ['ShippingAddress', 'Order', 'Line', 
                               'LinePrice', 'LineAttribute', 'OrderDiscount'], locals())
import_module('order.signals', ['order_placed'], locals())


class OrderNumberGenerator(object):
    u"""
    Simple object for generating order numbers.

    We need this as the order number is often required for payment
    which takes place before the order model has been created.
    """

    def order_number(self, basket):
        u"""
        Return an order number for a given basket
        """
        return 100000 + basket.id


class OrderCreator(object):
    u"""
    Places the order by writing out the various models
    """
    
    def __init__(self, order_total_calculator):
        self.order_total_calculator = order_total_calculator
    
Example #4
0
import csv

from oscar.core.loading import import_module

import_module("reports.reports", ["ReportGenerator"], locals())
import_module("basket.models", ["Basket", "OPEN", "SUBMITTED"], locals())


class OpenBasketReportGenerator(ReportGenerator):

    filename_template = "open-baskets-%s-%s.csv"
    code = "open_baskets"
    description = "Open baskets"

    def generate(self, response):
        writer = csv.writer(response)
        header_row = [
            "User ID",
            "Username",
            "Name",
            "Email",
            "Basket status",
            "Num lines",
            "Num items",
            "Value",
            "Date of creation",
            "Time since creation",
        ]
        writer.writerow(header_row)

        baskets = Basket._default_manager.filter(status=basket_models.OPEN)
Example #5
0
from decimal import Decimal
from itertools import chain
import logging

from oscar.core.loading import import_module
import_module('offer.models', ['ConditionalOffer'], locals())

logger = logging.getLogger('oscar.offers')


class OfferApplicationError(Exception):
    pass

# This needs hooking into the offer application system.
class Discount(object):
    
    def __init__(self, offer):
        self.offer = offer
        self.discount = Decimal('0.00')
        self.frequency = 0
        
    def discount(self, discount):
        self.discount += discount
        self.frequency += 1
        
    def is_voucher_discount(self):
        return bool(self.offer.get_voucher())

    def get_voucher(self):
        return self.offer.get_voucher()
Example #6
0
 def test_a_specified_class_is_imported_correctly(self):
     module = import_module('product.models', ['Item'])
     self.assertEqual('oscar.apps.product.models', module.__name__)
from oscar.core.loading import import_module

search_forms = import_module('search.forms', ['MultiFacetedSearchForm'])


def search_form(request):
    """
    Ensures that the search form is available site wide
    """
    return {'search_form': search_forms.MultiFacetedSearchForm(request.GET)}
Example #8
0
from haystack.indexes import *

from oscar.core.loading import import_module
product_models = import_module('catalogue.models', ['Product'])


class AbstractProductIndex(SearchIndex):
    u"""
    Base class for products solr index definition.  Overide by creating your
    own copy of oscar.search_indexes.py
    """
    text = EdgeNgramField(document=True, use_template=True, template_name='search/indexes/product/item_text.txt')
    title = EdgeNgramField(model_attr='title', null=True)
    upc = CharField(model_attr="upc", null=True)
    product_score = FloatField(model_attr="score")
    date_created = DateTimeField(model_attr='date_created')
    date_updated = DateTimeField(model_attr='date_updated')

    def index_queryset(self):
        """
        Used when the entire index for model is updated.

        Orders by the most recently updated so that new objects are indexed first
        """
        return product_models.Product.objects.order_by('-date_updated')

    def get_updated_field(self):
        u"""
        Used to specify the field used to determine if an object has been updated

        Can be used to filter the query set when updating the index
Example #9
0
from datetime import date, datetime
from calendar import monthrange
import re

from django import forms

from oscar.core.loading import import_module

address_models = import_module('address.models', ['Country'])
order_models = import_module('order.models', ['BillingAddress'])
payment_models = import_module('payment.models', ['Bankcard'])
import_module('payment.utils', ['Bankcard'], locals())

VISA, MASTERCARD, AMEX, MAESTRO, DISCOVER = ('Visa', 'Mastercard',
                                             'American Express', 'Maestro',
                                             'Discover')


def bankcard_type(number):
    u"""
    Returns the type of a bankcard based on its number.
    """
    number = str(number)
    if len(number) == 13:
        if number[0] == "4":
            return VISA
    elif len(number) == 14:
        if number[:2] == "36":
            return MASTERCARD
    elif len(number) == 15:
        if number[:2] in ("34", "37"):
Example #10
0
import csv

from oscar.core.loading import import_module
import_module('reports.reports', ['ReportGenerator'], locals())
import_module('voucher.models', ['Voucher'], locals())


class VoucherReportGenerator(ReportGenerator):
    
    filename_template = 'voucher-performance.csv'
    code = 'vouchers'
    description = 'Voucher performance'
    
    def generate(self, response):
        writer = csv.writer(response)
        header_row = ['Voucher code',
                      'Added to a basket',
                      'Used in an order',
                      'Total discount',
                     ]
        writer.writerow(header_row)
        
        vouchers = Voucher._default_manager.all()
        for voucher in vouchers:
            row = [voucher.code, voucher.num_basket_additions, voucher.num_orders, voucher.total_discount]
            writer.writerow(row)

    def filename(self):
        return self.filename_template
Example #11
0
from django.contrib import admin

from oscar.core.loading import import_module
models = import_module('payment.models', ['Source', 'Transaction', 'SourceType'])

class SourceAdmin(admin.ModelAdmin):
    list_display = ('order', 'type', 'amount_allocated', 'amount_debited', 'balance', 'reference')

admin.site.register(models.Source, SourceAdmin)
admin.site.register(models.SourceType)
admin.site.register(models.Transaction)
Example #12
0
from django.conf.urls.defaults import *

from oscar.core.loading import import_module
import_module('basket.views', ['BasketView', 'LineView', 'SavedLineView'],
              locals())


def line_view(request, *args, **kwargs):
    return LineView()(request, *args, **kwargs)


def saved_line_view(request, *args, **kwargs):
    return SavedLineView()(request, *args, **kwargs)


def basket_view(request, *args, **kwargs):
    return BasketView()(request, *args, **kwargs)


urlpatterns = patterns(
    'oscar.basket.views',
    url(r'^line/(?P<line_reference>[\w-]+)/$',
        line_view,
        name='oscar-basket-line'),
    url(r'^saved-line/(?P<line_reference>[\w-]+)/$',
        saved_line_view,
        name='oscar-saved-basket-line'),
    url(r'^$', basket_view, name='oscar-basket'),
)
Example #13
0
from django.conf.urls.defaults import *

from oscar.core.decorators import class_based_view
from oscar.core.loading import import_module
import_module('product.views',
              ['ItemDetailView', 'ProductListView', 'ItemClassListView'],
              locals())

urlpatterns = patterns(
    'oscar.product.views',
    url(r'(?P<item_class_slug>[\w-]+)/(?P<item_slug>[\w-]*)-(?P<item_id>\d+)/$',
        ItemDetailView.as_view(),
        name='oscar-product-item'),
    url(r'(?P<item_class_slug>[\w-]+)/$',
        ItemClassListView.as_view(),
        name='oscar-product-item-class'),
    url(r'^$', ProductListView.as_view(), name='oscar-products'),
)
Example #14
0
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.views.generic import ListView, DetailView

from django.template.response import TemplateResponse
from django.contrib import messages
from django.db import transaction
from django.db.models import Q
from django.contrib.comments.views.moderation import delete

from oscar.core.loading import import_module
from oscar.views.generic import PostActionMixin

import_module('order.models', [
    'Order', 'Line', 'ShippingEvent', 'ShippingEventQuantity',
    'ShippingEventType', 'PaymentEvent', 'PaymentEventType', 'OrderNote'
], locals())
import_module('order_management.forms', ['SimpleSearch'], locals())


class OrderListView(ListView):
    u"""A list of orders"""
    context_object_name = "orders"
    template_name = 'order_management/browse.html'
    paginate_by = 20

    def get_queryset(self):
        if 'search_query' in self.request.GET and self.request.GET[
                'search_query'].strip():
            q = self.request.GET['search_query'].strip()
            q_list = [Q(number__icontains=q)]
Example #15
0
from django.dispatch import receiver
from django.db import IntegrityError
import logging

from oscar.core.loading import import_module
import_module('analytics.models', ['UserSearch', 'UserRecord', 'ProductRecord', 'UserProductView'], locals())
import_module('catalogue.signals', ['product_viewed', 'product_search'], locals())
import_module('basket.signals', ['basket_addition'], locals())
import_module('order.signals', ['order_placed'], locals())

# Helpers

logger = logging.getLogger('oscar.analytics')

def _record_product_view(product):
    try:
        record,_ = ProductRecord.objects.get_or_create(product=product)
        record.num_views += 1
        record.save()
    except IntegrityError:
        # get_or_create sometimes fails due to MySQL's weird transactions, fail silently
        logger.error("IntegrityError on ProductRecord.objects.get_or_create(product=product)")
    
def _record_user_product_view(user, product):
    if user.is_authenticated():
        # Update user record
        try:
            record,_ = UserRecord.objects.get_or_create(user=user)
            record.num_product_views += 1
            record.save()
        except IntegrityError:
Example #16
0
from django.contrib.sites.models import Site

from oscar.core.loading import import_module
import_module('order.models', [
    'ShippingAddress', 'Order', 'Line', 'LinePrice', 'LineAttribute',
    'OrderDiscount'
], locals())
import_module('order.signals', ['order_placed'], locals())


class OrderNumberGenerator(object):
    u"""
    Simple object for generating order numbers.

    We need this as the order number is often required for payment
    which takes place before the order model has been created.
    """
    def order_number(self, basket):
        u"""
        Return an order number for a given basket
        """
        return 100000 + basket.id


class OrderCreator(object):
    u"""
    Places the order by writing out the various models
    """
    def __init__(self, order_total_calculator):
        self.order_total_calculator = order_total_calculator
Example #17
0
import logging
import sys
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError

from oscar.core.loading import import_module

import_module("order.models", ["Order"], locals())
import_module("customer.models", ["CommunicationEventType"], locals())
import_module("customer.utils", ["Dispatcher"], locals())


class Command(BaseCommand):

    args = "<communication_event_type> <order number>"
    help = "For testing the content of order emails"

    def handle(self, *args, **options):
        logger = self._get_logger()
        if len(args) != 2:
            raise CommandError("Please select a event type and order number")

        try:
            order = Order.objects.get(number=args[1])
        except Order.DoesNotExist:
            raise CommandError("No order found with number %s" % args[1])

        try:
            event_type = CommunicationEventType.objects.get(code=args[0])
        except CommunicationEventType.DoesNotExist:
Example #18
0
from django.core.urlresolvers import resolve

from oscar.core.loading import import_module

shipping_methods = import_module('shipping.repository', ['Repository'])


class ProgressChecker(object):
    u"""
    Class for testing whether the appropriate steps of the checkout
    have been completed.
    """

    # List of URL names that have to be completed (in this order)
    urls_for_steps = [
        'oscar-checkout-shipping-address', 'oscar-checkout-shipping-method',
        'oscar-checkout-payment-method', 'oscar-checkout-preview',
        'oscar-checkout-payment-details'
    ]

    def are_previous_steps_complete(self, request):
        u"""
        Checks whether the previous checkout steps have been completed.
        
        This uses the URL-name and the class-level list of required
        steps.
        """
        # Extract the URL name from the path
        complete_steps = self._get_completed_steps(request)
        try:
            url_name = self._get_url_name(request)
Example #19
0
from django.core.urlresolvers import resolve

from oscar.core.loading import import_module
import_module('shipping.repository', ['Repository'], locals())


class CheckoutSessionData(object):
    u"""Class responsible for marshalling all the checkout session data."""
    SESSION_KEY = 'checkout_data'
    
    def __init__(self, request):
        self.request = request
        if self.SESSION_KEY not in self.request.session:
            self.request.session[self.SESSION_KEY] = {}
    
    def _check_namespace(self, namespace):
        if namespace not in self.request.session[self.SESSION_KEY]:
            self.request.session[self.SESSION_KEY][namespace] = {}
          
    def _get(self, namespace, key, default=None):
        u"""Return session value or None"""
        self._check_namespace(namespace)
        if key in self.request.session[self.SESSION_KEY][namespace]:
            return self.request.session[self.SESSION_KEY][namespace][key]
        return default
            
    def _set(self, namespace, key, value):
        u"""Set session value"""
        self._check_namespace(namespace)
        self.request.session[self.SESSION_KEY][namespace][key] = value
        self.request.session.modified = True
Example #20
0
import os
import zlib
import tarfile
import zipfile
import tempfile
import shutil
from PIL import Image as PImage

from django.core.files import File
from django.core.exceptions import FieldError
from django.db.models import get_model

from oscar.core.loading import import_module

import_module(
    'product.exceptions',
    ['ImageImportError', 'IdenticalImageError', 'InvalidImageArchive'],
    locals())

Category = get_model('product', 'category')
Item = get_model('product', 'item')
ProductImage = get_model('product', 'productimage')


def create_categories(bits):
    if len(bits) == 1:
        # Get or create root node
        try:
            root = Category.objects.get(depth=1, name=bits[0])
        except Category.DoesNotExist:
            root = Category.add_root(name=bits[0])
        return [root]
Example #21
0
from django import template

from oscar.core.loading import import_module
product_models = import_module('product.models', ['Item', 'ItemClass'])
history_helpers = import_module('customer.history_helpers', ['get_recently_viewed_product_ids'])

register = template.Library()

@register.inclusion_tag('customer/history/recently-viewed-products.html', takes_context=True)
def recently_viewed_products(context):
    u"""
    Inclusion tag listing the most recently viewed products
    """
    request = context['request']
    product_ids = history_helpers.get_recently_viewed_product_ids(request)
    product_dict = product_models.Item.browsable.in_bulk(product_ids)
    
    # Reordering as the id order gets messed up in the query
    product_ids.reverse()
    products = [product_dict[id] for id in product_ids if id in product_dict]
    return {'products': products}
Example #22
0
import csv
from oscar.apps.reports.reports import ReportGenerator

from oscar.core.loading import import_module
import_module('reports.reports', ['ReportGenerator'], locals())
import_module('basket.models', ['Basket', 'OPEN', 'SUBMITTED'], locals())


class OpenBasketReportGenerator(ReportGenerator):

    filename_template = 'open-baskets-%s-%s.csv'
    code = 'open_baskets'
    description = 'Open baskets'

    def generate(self, response):
        writer = csv.writer(response)
        header_row = [
            'User ID',
            'Username',
            'Name',
            'Email',
            'Basket status',
            'Num lines',
            'Num items',
            'Value',
            'Date of creation',
            'Time since creation',
        ]
        writer.writerow(header_row)

        baskets = Basket._default_manager.filter(status=Basket.OPEN)
Example #23
0
from django.shortcuts import get_object_or_404
from django.views.generic import TemplateView, ListView, DetailView, CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, Http404
from django.contrib import messages
from django.utils.translation import ugettext as _
from django.contrib.auth import authenticate, login as auth_login
from django.contrib.sites.models import get_current_site
from django.conf import settings
from django.db.models import get_model

from oscar.apps.address.forms import UserAddressForm
from oscar.views.generic import PostActionMixin
from oscar.apps.customer.forms import EmailAuthenticationForm, EmailUserCreationForm, SearchByDateRangeForm
from oscar.core.loading import import_module
import_module('customer.utils', ['Dispatcher'], locals())

order_model = get_model('order', 'Order')
order_line_model = get_model('order', 'Line')
basket_model = get_model('basket', 'Basket')
user_address_model = get_model('address', 'UserAddress')
email_model = get_model('customer', 'email')
communicationtype_model = get_model('customer', 'communicationeventtype')


class AccountSummaryView(ListView):
    """Customer order history"""
    context_object_name = "orders"
    template_name = 'customer/profile.html'
    paginate_by = 20
    model = order_model
Example #24
0
 def test_a_specified_class_is_imported_correctly(self):
     module = import_module('catalogue.models', ['Product'])
     self.assertEqual('oscar.apps.catalogue.models', module.__name__)
Example #25
0
from django.contrib import admin

from oscar.core.loading import import_module
import_module('offer.models', ['ConditionalOffer', 'Condition', 'Benefit', 'Range',
                                        'Voucher', 'VoucherApplication'], locals())

class ConditionAdmin(admin.ModelAdmin):
    list_display = ('type', 'value', 'range')

class BenefitAdmin(admin.ModelAdmin):
    list_display = ('__unicode__', 'type', 'value', 'range')
    
class VoucherAdmin(admin.ModelAdmin):
    list_display = ('name', 'code', 'usage', 'num_basket_additions', 'num_orders', 'total_discount')    
    readonly_fields = ('num_basket_additions', 'num_orders', 'total_discount')
    fieldsets = (
        (None, {
            'fields': ('name', 'code', 'usage', 'start_date', 'end_date')
        }),
        ('Benefit', {
            'fields': ('offers',)
        }),
        ('Usage', {
            'fields': ('num_basket_additions', 'num_orders', 'total_discount')
        }),
        
    )
    
class VoucherApplicationAdmin(admin.ModelAdmin):
    list_display = ('voucher', 'user', 'order', 'date_created')
    readonly_fields = ('voucher', 'user', 'order')        
Example #26
0
from django.contrib import admin

from oscar.core.loading import import_module
import_module('order.models', ['Order', 'OrderNote', 'CommunicationEvent', 'CommunicationEventType',
                                        'BillingAddress', 'ShippingAddress', 'Line',
                                        'LinePrice', 'ShippingEvent', 'ShippingEventType', 
                                        'PaymentEvent', 'PaymentEventType', 'LineAttribute', 'OrderDiscount'], locals())

class OrderAdmin(admin.ModelAdmin):
    list_display = ('number', 'total_incl_tax', 'site', 'user', 'billing_address', 'date_placed')
    readonly_fields = ('number', 'total_incl_tax', 'total_excl_tax', 'shipping_incl_tax', 'shipping_excl_tax')

class LineAdmin(admin.ModelAdmin):
    list_display = ('order', 'product', 'quantity')

class LinePriceAdmin(admin.ModelAdmin):
    list_display = ('order', 'line', 'price_incl_tax', 'quantity')

class CommunicationEventTypeAdmin(admin.ModelAdmin):
    exclude = ('code',)

class ShippingEventTypeAdmin(admin.ModelAdmin):
    list_display = ('name', 'is_required', 'sequence_number')
    exclude = ('code',)
    
class PaymentEventTypeAdmin(admin.ModelAdmin):
    exclude = ('code',)
    
class OrderNoteAdmin(admin.ModelAdmin):
    exclude = ('user',)
    
Example #27
0
from django.dispatch import receiver
from django.db.models.signals import m2m_changed, post_save

from oscar.core.loading import import_module
import_module('offer.models', ['Voucher'], locals())
import_module('order.models', ['OrderDiscount'], locals())

@receiver(m2m_changed)
def receive_basket_voucher_change(sender, **kwargs):
    if kwargs['model'] == Voucher and kwargs['action'] == 'post_add':
        voucher_id = list(kwargs['pk_set'])[0]
        voucher = Voucher._default_manager.get(pk=voucher_id)
        voucher.num_basket_additions += 1
        voucher.save()

@receiver(post_save, sender=OrderDiscount)        
def receive_order_discount_save(sender, instance, **kwargs):
    # Record the amount of discount against the appropriate offers
    # and vouchers
    discount = instance
    if discount.voucher:
        discount.voucher.total_discount += discount.amount
        discount.voucher.save()
    discount.offer.total_discount += discount.amount
    discount.offer.save()
    
    
        
    
Example #28
0
from django.core.urlresolvers import resolve

from oscar.core.loading import import_module
import_module('shipping.repository', ['Repository'], locals())


class CheckoutSessionData(object):
    u"""Class responsible for marshalling all the checkout session data."""
    SESSION_KEY = 'checkout_data'

    def __init__(self, request):
        self.request = request
        if self.SESSION_KEY not in self.request.session:
            self.request.session[self.SESSION_KEY] = {}

    def _check_namespace(self, namespace):
        if namespace not in self.request.session[self.SESSION_KEY]:
            self.request.session[self.SESSION_KEY][namespace] = {}

    def _get(self, namespace, key, default=None):
        u"""Return session value or None"""
        self._check_namespace(namespace)
        if key in self.request.session[self.SESSION_KEY][namespace]:
            return self.request.session[self.SESSION_KEY][namespace][key]
        return default

    def _set(self, namespace, key, value):
        u"""Set session value"""
        self._check_namespace(namespace)
        self.request.session[self.SESSION_KEY][namespace][key] = value
        self.request.session.modified = True
Example #29
0
from django.template import Context, loader, RequestContext
from django.template.response import TemplateResponse
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.views.generic import ListView, DetailView

from django.template.response import TemplateResponse
from django.contrib import messages
from django.db import transaction
from django.db.models import Q
from django.contrib.comments.views.moderation import delete

from oscar.core.loading import import_module
from oscar.views.generic import PostActionMixin
import_module('order.models', ['Order', 'Line', 'ShippingEvent', 'ShippingEventQuantity', 
                               'ShippingEventType', 'PaymentEvent', 'PaymentEventType', 'OrderNote'], locals())
import_module('order_management.forms', ['SimpleSearch'], locals())


class OrderListView(ListView):
    u"""A list of orders"""
    context_object_name = "orders"
    template_name = 'order_management/browse.html'
    paginate_by = 20

    def get_queryset(self):
        if 'search_query' in self.request.GET and self.request.GET['search_query'].strip():
            q = self.request.GET['search_query'].strip()
            q_list = [Q(number__icontains=q)]
            search_by = self.request.GET.getlist('search_by')
            if search_by:
import json

from django.dispatch import receiver
from django.conf import settings

from oscar.core.loading import import_module
import_module('product.signals', ['product_viewed'], locals())

MAX_PRODUCTS = settings.OSCAR_RECENTLY_VIEWED_PRODUCTS

# Helpers

def get_recently_viewed_product_ids(request):
    u"""
    Returns the list of ids of the last products browsed by the user
    
    Limited to the max number defined in settings.py
    under OSCAR_RECENTLY_VIEWED_PRODUCTS.
    """
    product_ids = [];
    if (request.COOKIES.has_key('oscar_recently_viewed_products')):
        try:
            product_ids = _get_list_from_json_string(request.COOKIES['oscar_recently_viewed_products'])
        except ValueError:
            # This can occur if something messes up the cookie
            pass
    return product_ids

def _update_recently_viewed_products(product, request, response):
    u"""
    Updates the cookies that store the recently viewed products
Example #31
0
from django.template import RequestContext
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
from django.forms import ModelForm
from django.contrib import messages
from django.core.urlresolvers import resolve
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _
from django.template.response import TemplateResponse
from django.core.mail import EmailMessage
from django.views.generic import DetailView, TemplateView, FormView, DeleteView, UpdateView, CreateView

from oscar.apps.shipping.methods import FreeShipping
from oscar.core.loading import import_module

import_module("checkout.forms", ["ShippingAddressForm"], locals())
import_module("checkout.calculators", ["OrderTotalCalculator"], locals())
import_module("checkout.utils", ["CheckoutSessionData"], locals())
import_module("checkout.signals", ["pre_payment", "post_payment"], locals())
import_module("order.models", ["Order", "ShippingAddress", "CommunicationEvent"], locals())
import_module("order.utils", ["OrderNumberGenerator", "OrderCreator"], locals())
import_module("address.models", ["UserAddress"], locals())
import_module("address.forms", ["UserAddressForm"], locals())
import_module("shipping.repository", ["Repository"], locals())
import_module("customer.models", ["Email", "CommunicationEventType"], locals())
import_module("customer.views", ["AccountAuthView"], locals())
import_module("customer.utils", ["Dispatcher"], locals())
import_module("payment.exceptions", ["RedirectRequired", "UnableToTakePayment", "PaymentError"], locals())
import_module("basket.models", ["Basket"], locals())

# Standard logger for checkout events
Example #32
0
import csv

from oscar.core.loading import import_module
import_module('reports.reports', ['ReportGenerator'], locals())
import_module('offer.models', ['ConditionalOffer'], locals())


class OfferReportGenerator(ReportGenerator):

    filename_template = 'conditional-offer-performance.csv'
    code = 'conditional-offers'
    description = 'Offer performance'

    def generate(self, response):
        writer = csv.writer(response)
        header_row = [
            'Offer',
            'Total discount',
        ]
        writer.writerow(header_row)

        for offer in ConditionalOffer._default_manager.all():
            row = [offer, offer.total_discount]
            writer.writerow(row)

    def filename(self):
        return self.filename_template
Example #33
0
import csv

from oscar.core.loading import import_module
report_classes = import_module('dashboard.reports.reports', ['ReportGenerator'])
analytics_models = import_module('analytics.models', ['ProductRecord', 'UserRecord'])


class ProductReportGenerator(report_classes.ReportGenerator):
    
    filename_template = 'product-analytics.csv'
    code = 'product_analytics'
    description = 'Product analytics'
    
    def generate(self, response):
        writer = csv.writer(response)
        header_row = ['Product',
                      'Views',
                      'Basket additions',
                      'Purchases',]
        writer.writerow(header_row)
        
        records = analytics_models.ProductRecord._default_manager.all()
        for record in records:
            row = [record.product, record.num_views, record.num_basket_additions, record.num_purchases]
            writer.writerow(row)
            
    def is_available_to(self, user):
        return user.is_staff
    
    def filename(self):
        return self.filename_template
Example #34
0
from oscar.apps.shipping.methods import FreeShipping
from oscar.core.loading import import_module
shipping_models = import_module('shipping.models', ['OrderAndItemLevelChargeMethod'])


class Repository(object):
    u"""
    Repository class responsible for returning ShippingMethod
    objects
    """
    
    def get_shipping_methods(self, user, basket, shipping_addr):
        u"""
        Returns all applicable shipping method objects
        for a given basket.
        
        We default to returning the Method models that have been defined but
        this behaviour can easily be overridden by subclassing this class
        and overriding this method.
        """ 
        methods = shipping_models.OrderAndItemLevelChargeMethod._default_manager.all()
        if not methods.count():
            return [FreeShipping()]
        
        for method in methods:
            method.set_basket(basket)
        return methods

    def find_by_code(self, code):
        u"""
        Returns the appropriate Method object for the given code
Example #35
0
from decimal import Decimal as D

from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.importlib import import_module as django_import_module

from oscar.core.loading import import_module
import_module('partner.wrappers', ['DefaultWrapper'], locals())


# Cache the partners for quicklookups
default_wrapper = DefaultWrapper()
partner_wrappers = {}
for partner, class_str in settings.OSCAR_PARTNER_WRAPPERS.items():
    bits = class_str.split('.')
    class_name = bits.pop()
    module_str = '.'.join(bits)
    module = django_import_module(module_str)
    partner_wrappers[partner] = getattr(module, class_name)()

def get_partner_wrapper(partner_name):
    """
    Returns the appropriate partner wrapper given the partner name
    """
    return partner_wrappers.get(partner_name, default_wrapper)


class AbstractPartner(models.Model):
    """
    Fulfillment partner
Example #36
0
from django.contrib import admin

from oscar.core.loading import import_module
import_module('voucher.models', ['Voucher', 'VoucherApplication'], locals())


class VoucherAdmin(admin.ModelAdmin):
    list_display = ('name', 'code', 'usage', 'num_basket_additions',
                    'num_orders', 'total_discount')
    readonly_fields = ('num_basket_additions', 'num_orders', 'total_discount')
    fieldsets = (
        (None, {
            'fields': ('name', 'code', 'usage', 'start_date', 'end_date')
        }),
        ('Benefit', {
            'fields': ('offers', )
        }),
        ('Usage', {
            'fields': ('num_basket_additions', 'num_orders', 'total_discount')
        }),
    )


class VoucherApplicationAdmin(admin.ModelAdmin):
    list_display = ('voucher', 'user', 'order', 'date_created')
    readonly_fields = ('voucher', 'user', 'order')


admin.site.register(Voucher, VoucherAdmin)
admin.site.register(VoucherApplication, VoucherApplicationAdmin)
Example #37
0
from django.template.response import TemplateResponse

from oscar.apps.checkout.views import (
    PaymentMethodView as CorePaymentMethodView,
    PaymentDetailsView as CorePaymentDetailsView,
    OrderPreviewView as CoreOrderPreviewView,
)
from oscar.apps.payment.forms import BankcardForm, BillingAddressForm
from oscar.apps.shipping.methods import ShippingMethod
from oscar.core.loading import import_module

import_module("payment.models", ["Source", "SourceType"], locals())
import_module("payment.exceptions", ["TransactionDeclinedException"], locals())
import_module("payment.utils", ["Bankcard"], locals())
import_module("payment.datacash.utils", ["Gateway", "Facade"], locals())
import_module("order.models", ["PaymentEvent", "PaymentEventType", "PaymentEventQuantity"], locals())


class PaymentMethodView(CorePaymentMethodView):
    template_file = "checkout/payment_method.html"

    def handle_GET(self):
        return TemplateResponse(self.request, self.template_file, self.context)

    def handle_POST(self):
        method = self.request.POST["method_code"]
        self.co_data.pay_by(method)
        return self.get_success_response()


class OrderPreviewView(CoreOrderPreviewView):
Example #38
0
from decimal import Decimal
from itertools import chain

from oscar.core.loading import import_module
import_module('offer.models', ['ConditionalOffer'], locals())


# This needs hooking into the offer application system.
class Discount(object):
    def __init__(self, offer):
        self.offer = offer
        self.discount = Decimal('0.00')
        self.frequency = 0

    def discount(self, discount):
        self.discount += discount
        self.frequency += 1

    def is_voucher_discount(self):
        return bool(self.offer.get_voucher())

    def get_voucher(self):
        return self.offer.get_voucher()


class Applicator(object):
    """
    For applying offers to a basket.
    """
    def apply(self, request, basket):
        """
Example #39
0
 def test_imports_a_class_correctly(self):
     module = import_module('analytics.models', ['ProductRecord'])
     self.assertEqual('oscar.apps.analytics.models', module.__name__)
Example #40
0
from haystack.indexes import *

from oscar.core.loading import import_module
product_models = import_module('product.models', ['Item', 'ItemClass'])


class AbstractProductIndex(SearchIndex):
    u"""
    Base class for products solr index definition.  Overide by creating your
    own copy of oscar.search_indexes.py
    """
    text = EdgeNgramField(
        document=True,
        use_template=True,
        template_name='oscar/search/indexes/product/item_text.txt')
    title = EdgeNgramField(model_attr='title')
    upc = CharField(model_attr="upc")
    item_class = CharField(model_attr="item_class", faceted=True)
    price_range = CharField(model_attr="price_range", faceted=True)
    score = FloatField(model_attr="score")
    date_created = DateTimeField(model_attr='date_created')
    date_updated = DateTimeField(model_attr='date_updated')

    def get_queryset(self):
        """
        Used when the entire index for model is updated.

        Orders by the most recently updated so that new objects are indexed first
        """
        return product_models.Item.objects.order_by('-date_updated')
Example #41
0
from django.contrib import admin

from oscar.core.loading import import_module
import_module('customer.models', ['Email', 'CommunicationEventType'], locals())

admin.site.register(Email)
admin.site.register(CommunicationEventType)


Example #42
0
from django.contrib import admin

from oscar.core.loading import import_module
models = import_module('partner.models', ['Partner', 'StockRecord'])

class StockRecordAdmin(admin.ModelAdmin):
    list_display = ('product', 'partner', 'partner_sku', 'price_excl_tax', 'cost_price', 'num_in_stock')
    list_filter = ('partner',)
    
admin.site.register(models.Partner)
admin.site.register(models.StockRecord, StockRecordAdmin)
Example #43
0
from haystack import site

from oscar.apps.search.abstract_indexes import AbstractProductIndex
from oscar.core.loading import import_module
product_models = import_module('product.models', ['Item'])


class ProductIndex(AbstractProductIndex):
    pass


site.register(product_models.Item, ProductIndex)

Example #44
0
import logging
import sys
import os
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError

from oscar.core.loading import import_module
import_module('catalogue.utils', ['Importer'], locals())


class Command(BaseCommand):
    
    args = '/path/to/folder'
    help = 'For importing product images from a folder'
    
    option_list = BaseCommand.option_list + (
        make_option('--filename',
            dest='filename',
            default='upc',
            help='Product field to lookup from image filename'),
        )

    def handle(self, *args, **options):
        if len(args) != 1:
            raise CommandError('Command requires a path to a single folder') 
        
        logger = self._get_logger()
        logger.info("Starting image import...")       
        
        dirname = args[0]
Example #45
0
from datetime import date, datetime

from django import forms

from oscar.core.loading import import_module
report_utils = import_module('reports.utils', ['GeneratorRepository'])

class ReportForm(forms.Form):
    
    generators = report_utils.GeneratorRepository().get_report_generators()
    
    type_choices = []
    for generator in generators:
        type_choices.append((generator.code, generator.description))
    report_type = forms.ChoiceField(widget=forms.Select(), choices=type_choices)
    start_date = forms.DateField(widget=forms.widgets.DateInput(format="%d/%m/%Y"), 
                                 help_text='Format dd/mm/YYYY',
                                 input_formats=['%d/%m/%y', '%d/%m/%Y'])
    end_date = forms.DateField(widget=forms.widgets.DateInput(format="%d/%m/%Y"), 
                               help_text='Format dd/mm/YYYY',
                               input_formats=['%d/%m/%y', '%d/%m/%Y'])
    
    def clean(self):
        if 'start_date' in self.cleaned_data and 'end_date' in self.cleaned_data and self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
            raise forms.ValidationError("Your start date must be before your end date")
        return self.cleaned_data
   
Example #46
0
from django.db import connection, transaction

from oscar.core.loading import import_module
import_module('analytics.models', ['ProductRecord'], locals())
import_module('catalogue.models', ['Product'], locals())


class ScoreCalculator(object):

    # Map of field name to weight
    weights = {'num_views': 1, 'num_basket_additions': 3, 'num_purchases': 5}

    def __init__(self, logger):
        self.logger = logger
        self.cursor = connection.cursor()

    def run(self):
        self.calculate_scores()
        self.update_product_models()

    def calculate_scores(self):
        self.logger.info("Calculating product scores")

        # Build the "SET ..." part of the SQL statement
        weighted_sum = " + ".join([
            "%s*`%s`" % (weight, field)
            for field, weight in self.weights.items()
        ])

        ctx = {
            'table': ProductRecord._meta.db_table,
import logging
import sys
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User

from oscar.core.loading import import_module
import_module('order.models', ['Order'], locals())
import_module('customer.models', ['CommunicationEventType'], locals())
import_module('customer.utils', ['Dispatcher'], locals())


class Command(BaseCommand):
    
    args = '<communication_event_type> <order number>'
    help = 'For testing the content of order emails'
    
    def handle(self, *args, **options):
        logger = self._get_logger()
        if len(args) != 2:
            raise CommandError("Please select a event type and order number")
        
        try:
            order = Order.objects.get(number=args[1])
        except Order.DoesNotExist:
            raise CommandError("No order found with number %s" % args[1])
        
        try:
            event_type = CommunicationEventType.objects.get(code=args[0])
        except CommunicationEventType.DoesNotExist:
from decimal import Decimal as D

from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.importlib import import_module as django_import_module

from oscar.core.loading import import_module

import_module('partner.wrappers', ['DefaultWrapper'], locals())

# Cache the partners for quicklookups
default_wrapper = DefaultWrapper()
partner_wrappers = {}
for partner, class_str in settings.OSCAR_PARTNER_WRAPPERS.items():
    bits = class_str.split('.')
    class_name = bits.pop()
    module_str = '.'.join(bits)
    module = django_import_module(module_str)
    partner_wrappers[partner] = getattr(module, class_name)()


def get_partner_wrapper(partner_name):
    """
    Returns the appropriate partner wrapper given the partner name
    """
    return partner_wrappers.get(partner_name, default_wrapper)


class AbstractPartner(models.Model):
    u"""Fulfillment partner"""
Example #49
0
import zlib

from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.db.models import get_model

from oscar.core.loading import import_module
import_module('offer.utils', ['Applicator'], locals())
basket_model = get_model('basket', 'basket')


class BasketMiddleware(object):
    
    def process_request(self, request):
        self.cookies_to_delete = []
        basket = self.get_basket(request)
        self.apply_offers_to_basket(request, basket)   
        request.basket = basket
    
    def get_basket(self, request):  
        manager = basket_model.open
        cookie_basket = self.get_cookie_basket(settings.OSCAR_BASKET_COOKIE_OPEN, 
                                               request, manager)
        
        if request.user.is_authenticated():
            # Signed-in user: if they have a cookie basket too, it means
            # that they have just signed in and we need to merge their cookie
            # basket into their user basket, then delete the cookie
            try:
                basket, _ = manager.get_or_create(owner=request.user)
            except basket_model.MultipleObjectsReturned:
Example #50
0
from django.conf.urls import *
from haystack.query import SearchQuerySet

from oscar.core.loading import import_module
import_module('search.views', ['Suggestions', 'MultiFacetedSearchView'],
              locals())
import_module('search.forms', ['MultiFacetedSearchForm'], locals())
import_module('search.search_indexes', ['ProductIndex'], locals())

sqs = SearchQuerySet()
for field_name, field in ProductIndex.fields.items():
    if field.faceted is True:
        # Ensure we facet the results set by the defined facetable fields
        sqs.facet(field_name)

urlpatterns = patterns(
    'search.apps.views',
    url(r'^suggest/$', Suggestions.as_view(), name='oscar-search-suggest'),
    url(r'^$',
        MultiFacetedSearchView(form_class=MultiFacetedSearchForm,
                               searchqueryset=sqs),
        name='oscar-search'),
)
Example #51
0
from django.conf.urls.defaults import *
from django.contrib.admin.views.decorators import staff_member_required

from oscar.core.loading import import_module
import_module('order_management.views', ['OrderListView', 'OrderView'], locals())

urlpatterns = patterns('oscar.order_management.views',
    url(r'^$', staff_member_required(OrderListView.as_view()), name='oscar-order-management-list'),
    url(r'^order/(?P<order_number>[\w-]*)/$', staff_member_required(OrderView.as_view()), name='oscar-order-management-order'),
)

Example #52
0
from django.dispatch import receiver
from django.db.models.signals import m2m_changed, post_save

from oscar.core.loading import import_module
from oscar.apps.basket.abstract_models import AbstractBasket
import_module('voucher.models', ['Voucher'], locals())
import_module('order.models', ['OrderDiscount'], locals())


@receiver(m2m_changed)
def receive_basket_voucher_change(sender, **kwargs):
    if (kwargs['model'] == Voucher and kwargs['action'] == 'post_add'
            and isinstance(kwargs['instance'], AbstractBasket)
            and kwargs['pk_set']):
        voucher_id = list(kwargs['pk_set'])[0]
        voucher = Voucher._default_manager.get(pk=voucher_id)
        voucher.num_basket_additions += 1
        voucher.save()


@receiver(post_save, sender=OrderDiscount)
def receive_order_discount_save(sender, instance, **kwargs):
    # Record the amount of discount against the appropriate offers
    # and vouchers
    discount = instance
    if discount.voucher:
        discount.voucher.total_discount += discount.amount
        discount.voucher.save()
    discount.offer.total_discount += discount.amount
    discount.offer.save()
Example #53
0
from django.http import HttpResponseRedirect, Http404
from django.shortcuts import get_object_or_404, render

from oscar.core.loading import import_module

promotions_models = import_module('promotions.models', ['PagePromotion', 'KeywordPromotion'])


class HomeView(object):
    u"""
    View for the homepage.
    """

    template_file = 'oscar/home.html'

    def __call__(self, request, *args, **kwargs):
        return render(request, self.template_file)


def page_promotion_click(request, page_promotion_id):
    u"""Records a click-through on a promotion"""
    page_prom = get_object_or_404(promotions_models.PagePromotion, id=page_promotion_id)
    if page_prom.promotion.has_link:
        page_prom.record_click()
        return HttpResponseRedirect(page_prom.promotion.link_url)
    return Http404()
    
def keyword_promotion_click(request, keyword_promotion_id):
    u"""Records a click-through on a promotion"""
    keyword_prom = get_object_or_404(promotions_models.KeywordPromotion, id=keyword_promotion_id)
    if keyword_prom.promotion.has_link:
Example #54
0
 def test_imports_a_class_correctly(self):
     module = import_module('analytics.models', ['ProductRecord'])
     self.assertEqual('oscar.apps.analytics.models', module.__name__)
Example #55
0
from datetime import date
from calendar import monthrange
import re

from django import forms

from oscar.core.loading import import_module

address_models = import_module('address.models', ['Country'])
order_models = import_module('order.models', ['BillingAddress'])
payment_models = import_module('payment.models', ['Bankcard'])
import_module('payment.utils', ['Bankcard'], locals())

VISA, MASTERCARD, AMEX, MAESTRO, DISCOVER = ('Visa', 'Mastercard', 'American Express', 'Maestro', 'Discover')

def bankcard_type(number):
    u"""
    Returns the type of a bankcard based on its number.
    """
    number = str(number)
    if len(number) == 13:
        if number[0] == "4":
            return VISA
    elif len(number) == 14:
        if number[:2] == "36":
            return MASTERCARD
    elif len(number) == 15:
        if number[:2] in ("34", "37"):
            return AMEX
    elif len(number) == 16:
        if number[:4] == "6011":
Example #56
0
from oscar.core.loading import import_module
order_reports = import_module('order.reports', ['OrderReportGenerator'])
analytics_reports = import_module(
    'analytics.reports', ['ProductReportGenerator', 'UserReportGenerator'])
basket_reports = import_module(
    'basket.reports',
    ['OpenBasketReportGenerator', 'SubmittedBasketReportGenerator'])
offer_reports = import_module(
    'offer.reports', ['VoucherReportGenerator', 'OfferReportGenerator'])


class GeneratorRepository(object):

    generators = [
        order_reports.OrderReportGenerator,
        analytics_reports.ProductReportGenerator,
        analytics_reports.UserReportGenerator,
        basket_reports.OpenBasketReportGenerator,
        basket_reports.SubmittedBasketReportGenerator,
        offer_reports.VoucherReportGenerator,
        offer_reports.OfferReportGenerator
    ]

    def get_report_generators(self):
        return self.generators

    def get_generator(self, code):
        for generator in self.generators:
            if generator.code == code:
                return generator
        return None
Example #57
0
from django.template import RequestContext
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
from django.forms import ModelForm
from django.contrib import messages
from django.core.urlresolvers import resolve
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _
from django.template.response import TemplateResponse
from django.core.mail import EmailMessage
from django.views.generic import DetailView, TemplateView, FormView, \
                                 DeleteView, UpdateView, CreateView

from oscar.apps.shipping.methods import FreeShipping
from oscar.core.loading import import_module
import_module('checkout.forms', ['ShippingAddressForm'], locals())
import_module('checkout.calculators', ['OrderTotalCalculator'], locals())
import_module('checkout.utils', ['CheckoutSessionData'], locals())
import_module('checkout.signals', ['pre_payment', 'post_payment'], locals())
import_module('order.models', ['Order', 'ShippingAddress', 'CommunicationEventType', 
                               'CommunicationEvent'], locals())
import_module('order.utils', ['OrderNumberGenerator', 'OrderCreator'], locals())
import_module('address.models', ['UserAddress'], locals())
import_module('address.forms', ['UserAddressForm'], locals())
import_module('shipping.repository', ['Repository'], locals())
import_module('customer.models', ['Email'], locals())
import_module('customer.views', ['AccountAuthView'], locals())
import_module('payment.exceptions', ['RedirectRequired', 'UnableToTakePayment', 
                                     'PaymentError'], locals())
import_module('basket.models', ['Basket'], locals())
from itertools import chain

from django.core.exceptions import ObjectDoesNotExist

from oscar.apps.promotions.abstract_models import BANNER, LEFT_POD, RIGHT_POD
from oscar.core.loading import import_module
import_module('promotions.models', ['PagePromotion', 'KeywordPromotion', 
                                    'PageMerchandisingBlock', 'KeywordMerchandisingBlock'], locals())


def promotions(request):
    u"""
    For adding bindings for banners and pods to the template
    context.
    """
    bindings = {
        'url_path': request.path
    }
    promotions = PagePromotion._default_manager.select_related().filter(page_url=request.path)

    if 'q' in request.GET:
        keyword_promotions = KeywordPromotion._default_manager.select_related().filter(keyword=request.GET['q'])
        if keyword_promotions.count() > 0:
            promotions = list(chain(promotions, keyword_promotions))

    bindings['banners'], bindings['left_pods'], bindings['right_pods'] = _split_by_position(promotions)

    return bindings

def merchandising_blocks(request):
    bindings = {
Example #59
0
import os
import csv
import sys
from decimal import Decimal as D

from oscar.core.loading import import_module

import_module('catalogue_import.exceptions', ['CatalogueImportException'], locals())
import_module('product.models', ['ItemClass', 'Item'], locals())
import_module('partner.models', ['Partner', 'StockRecord'], locals())


class Importer(object):
    u"""A catalogue importer object"""
    
    _flush = False
    
    def __init__(self, logger, delimiter=",", flush=False):
        self.logger = logger
        self._delimiter = delimiter
        self._flush = flush
        if flush:
            self.logger.info(" - Flushing product data before import")
    
    def handle(self, file_path=None):
        u"""Handles the actual import process"""
        if not file_path:
            raise CatalogueImportException("No file path supplied")
        
        if self._flush is True:
            self._flush_product_data()
Example #60
0
import logging
import sys
import os
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError

from oscar.core.loading import import_module
import_module('product.utils', ['Importer'], locals())


class Command(BaseCommand):

    args = '/path/to/folder'
    help = 'For importing product images from a folder'

    option_list = BaseCommand.option_list + (make_option(
        '--filename',
        dest='filename',
        default='upc',
        help='Product field to lookup from image filename'), )

    def handle(self, *args, **options):
        if len(args) != 1:
            raise CommandError('Command requires a path to a single folder')

        logger = self._get_logger()
        logger.info("Starting image import...")

        dirname = args[0]
        importer = Importer(logger, field=options.get('filename'))