def ready(self): self.order_list_view = get_class('dashboard.orders.views', 'OrderListView') self.order_detail_view = get_class('dashboard.orders.views', 'OrderDetailView') self.shipping_address_view = get_class('dashboard.orders.views', 'ShippingAddressUpdateView') self.line_detail_view = get_class('dashboard.orders.views', 'LineDetailView') self.order_stats_view = get_class('dashboard.orders.views', 'OrderStatsView')
def proxy_map(self): return { self.COUNT: get_class( 'offer.conditions', 'CountCondition'), self.VALUE: get_class( 'offer.conditions', 'ValueCondition'), self.COVERAGE: get_class( 'offer.conditions', 'CoverageCondition'), }
def test_raise_importerror_if_app_raises_importerror(self): """ This tests that Oscar doesn't fall back to using the Oscar catalogue app if the overriding app throws an ImportError. """ apps = list(settings.INSTALLED_APPS) apps[apps.index('oscar.apps.catalogue')] = 'tests._site.import_error_app.catalogue' with override_settings(INSTALLED_APPS=apps): with self.assertRaises(ImportError): get_class('catalogue.app', 'CatalogueApplication')
def get_product_search_handler_class(): """ Determine the search handler to use. Currently only Solr is supported as a search backend, so it falls back to rudimentary category browsing if that isn't enabled. """ # Use get_class to ensure overridability if is_solr_supported(): return get_class("catalogue.search_handlers", "ProductSearchHandler") else: return get_class("catalogue.search_handlers", "SimpleProductSearchHandler")
def prepare_basket(request, product, voucher=None): """ Create or get the basket, add the product, apply a voucher, and record referral data. Existing baskets are merged. The specified product will be added to the remaining open basket. If voucher is passed, all existing vouchers added to the basket are removed because we allow only one voucher per basket. Vouchers are not applied if an enrollment code product is in the basket. Arguments: request (Request): The request object made to the view. product (Product): Product to be added to the basket. voucher (Voucher): Voucher to apply to the basket. Returns: basket (Basket): Contains the product to be redeemed and the Voucher applied. """ basket = Basket.get_basket(request.user, request.site) basket.flush() basket.add_product(product, 1) if product.get_product_class().name == ENROLLMENT_CODE_PRODUCT_CLASS_NAME: basket.clear_vouchers() elif voucher: basket.clear_vouchers() basket.vouchers.add(voucher) Applicator().apply(basket, request.user, request) logger.info('Applied Voucher [%s] to basket [%s].', voucher.code, basket.id) attribute_cookie_data(basket, request) # Call signal handler to notify listeners that something has been added to the basket basket_addition = get_class('basket.signals', 'basket_addition') basket_addition.send(sender=basket_addition, product=product, user=request.user, request=request, basket=basket) return basket
def test_raise_importerror_if_app_raises_importerror(self): """ This tests that Oscar doesn't fall back to using the Oscar core app class if the overriding app class throws an ImportError. "get_class()" returns None in this case, since there is no such named class in the core app. We use this fictitious class because classes in the "models" and "views" modules (along with modules they are related to) are imported as part of the Django app-loading process, which is triggered when we override the INSTALLED_APPS setting. """ apps = list(settings.INSTALLED_APPS) apps[apps.index('tests._site.apps.catalogue')] = 'tests._site.import_error_app.catalogue' with override_settings(INSTALLED_APPS=apps): with self.assertRaises(ImportError): get_class('catalogue.import_error_module', 'ImportErrorClass')
def create_menu(menu_items, parent=None): """ Create the navigation nodes based on a passed list of dicts """ nodes = [] access_fn_str = settings.OSCAR_DASHBOARD_DEFAULT_ACCESS_FUNCTION default_fn = get_class(*access_fn_str.rsplit('.', 1)) for menu_dict in menu_items: try: label = menu_dict['label'] except KeyError: raise ImproperlyConfigured( "No label specified for menu item in dashboard") children = menu_dict.get('children', []) if children: node = Node(label=label, icon=menu_dict.get('icon', None), access_fn=menu_dict.get('access_fn', default_fn)) create_menu(children, parent=node) else: node = Node(label=label, icon=menu_dict.get('icon', None), url_name=menu_dict.get('url_name', None), url_kwargs=menu_dict.get('url_kwargs', None), url_args=menu_dict.get('url_args', None), access_fn=menu_dict.get('access_fn', default_fn)) if parent is None: nodes.append(node) else: parent.add_child(node) return nodes
def get_session(self): if hasattr(self, 'user_session'): return self.user_session else: try: return get_class('user.session', 'UserSessionData')(self.request) except (ImportError, AppNotFoundError, ClassNotFoundError, ModuleNotFoundError): return FictaSessionData(self.request)
def test_override_class_loader(self): # Clear lru cache for the class loader get_class_loader.cache_clear() View = get_class('catalogue.views', 'ProductDetailView') self.assertEqual(View, DummyClass) # Clear lru cache for the class loader again get_class_loader.cache_clear()
def ready(self): self.index_view = get_class('checkout.views', 'IndexView') self.shipping_address_view = get_class('checkout.views', 'ShippingAddressView') self.user_address_update_view = get_class('checkout.views', 'UserAddressUpdateView') self.user_address_delete_view = get_class('checkout.views', 'UserAddressDeleteView') self.shipping_method_view = get_class('checkout.views', 'ShippingMethodView') self.payment_method_view = get_class('checkout.views', 'PaymentMethodView') self.payment_details_view = get_class('checkout.views', 'PaymentDetailsView') self.thankyou_view = get_class('checkout.views', 'ThankYouView')
def get_product_search_handler_class(): """ Determine the search handler to use. Currently only Solr is supported as a search backend, so it falls back to rudimentary category browsing if that isn't enabled. """ # Use get_class to ensure overridability if settings.OSCAR_PRODUCT_SEARCH_HANDLER is not None: return import_string(settings.OSCAR_PRODUCT_SEARCH_HANDLER) if is_solr_supported(): return get_class('catalogue.search_handlers', 'SolrProductSearchHandler') elif is_elasticsearch_supported(): return get_class( 'catalogue.search_handlers', 'ESProductSearchHandler', ) else: return get_class( 'catalogue.search_handlers', 'SimpleProductSearchHandler')
def ready(self): self.list_view = get_class('dashboard.partners.views', 'PartnerListView') self.create_view = get_class('dashboard.partners.views', 'PartnerCreateView') self.manage_view = get_class('dashboard.partners.views', 'PartnerManageView') self.delete_view = get_class('dashboard.partners.views', 'PartnerDeleteView') self.user_link_view = get_class('dashboard.partners.views', 'PartnerUserLinkView') self.user_unlink_view = get_class('dashboard.partners.views', 'PartnerUserUnlinkView') self.user_create_view = get_class('dashboard.partners.views', 'PartnerUserCreateView') self.user_select_view = get_class('dashboard.partners.views', 'PartnerUserSelectView') self.user_update_view = get_class('dashboard.partners.views', 'PartnerUserUpdateView')
def ready(self): self.list_view = get_class('dashboard.offers.views', 'OfferListView') self.metadata_view = get_class('dashboard.offers.views', 'OfferMetaDataView') self.condition_view = get_class('dashboard.offers.views', 'OfferConditionView') self.benefit_view = get_class('dashboard.offers.views', 'OfferBenefitView') self.restrictions_view = get_class('dashboard.offers.views', 'OfferRestrictionsView') self.delete_view = get_class('dashboard.offers.views', 'OfferDeleteView') self.detail_view = get_class('dashboard.offers.views', 'OfferDetailView')
def default_access_fn(user, url_name, url_args=None, url_kwargs=None): """ Given a url_name and a user, this function tries to assess whether the user has the right to access the URL. The application instance of the view is fetched via dynamic imports, and those assumptions will only hold true if the standard Oscar layout is followed. Once the permissions for the view are known, the access logic used by the dashboard decorator is evaluated This function might seem costly, but a simple comparison with DTT did not show any change in response time """ exception = ImproperlyConfigured( "Please follow Oscar's default dashboard app layout or set a " "custom access_fn") if url_name is None: # it's a heading return True # get view module string. try: url = reverse(url_name, args=url_args, kwargs=url_kwargs) except NoReverseMatch: # In Oscar 1.5 this exception was silently ignored which made debugging # very difficult. Now it is being logged and in future the exception will # be propagated. logger.exception('Invalid URL name {}'.format(url_name)) return False view_module = resolve(url).func.__module__ # We can't assume that the view has the same parent module as the app, # as either the app or view can be customised. So we turn the module # string (e.g. 'oscar.apps.dashboard.catalogue.views') into an app # label that can be loaded by get_class (e.g. # 'dashboard.catalogue.app), which then essentially checks # INSTALLED_APPS for the right module to load match = re.search('(dashboard[\w\.]*)\.views$', view_module) if not match: raise exception app_label_str = match.groups()[0] + '.app' try: app_instance = get_class(app_label_str, 'application') except AppNotFoundError: raise exception # handle name-spaced view names if ':' in url_name: view_name = url_name.split(':')[1] else: view_name = url_name permissions = app_instance.get_permissions(view_name) return check_permissions(user, permissions)
def ready(self): self.list_view = get_class('dashboard.ranges.views', 'RangeListView') self.create_view = get_class('dashboard.ranges.views', 'RangeCreateView') self.update_view = get_class('dashboard.ranges.views', 'RangeUpdateView') self.delete_view = get_class('dashboard.ranges.views', 'RangeDeleteView') self.products_view = get_class('dashboard.ranges.views', 'RangeProductListView') self.reorder_view = get_class('dashboard.ranges.views', 'RangeReorderView')
def ready(self): from oscar.apps.promotions.conf import PROMOTION_CLASSES self.list_view = get_class('dashboard.promotions.views', 'ListView') self.page_list = get_class('dashboard.promotions.views', 'PageListView') self.page_detail = get_class('dashboard.promotions.views', 'PageDetailView') self.create_redirect_view = get_class('dashboard.promotions.views', 'CreateRedirectView') self.delete_page_promotion_view = get_class('dashboard.promotions.views', 'DeletePagePromotionView') # Dynamically set the CRUD views for all promotion classes view_names = ( ('create_%s_view', 'Create%sView'), ('update_%s_view', 'Update%sView'), ('delete_%s_view', 'Delete%sView'), ) for klass in PROMOTION_CLASSES: for attr_name, view_name in view_names: full_attr_name = attr_name % klass.classname() full_view_name = view_name % klass.__name__ view = get_class('dashboard.promotions.views', full_view_name) vars(self)[full_attr_name] = view
def render_content(self, options): request = options['request'] Partner = get_class('partner.models', 'Partner') manufacturer_list = Partner.objects.all() context = RequestContext(options['request'], { 'widget': self, 'request': request, 'manufacturer_list': manufacturer_list, }) return render_to_string(self.get_template, context)
def ready(self): from django.contrib.auth.forms import SetPasswordForm self.catalogue_app = apps.get_app_config('catalogue') self.customer_app = apps.get_app_config('customer') self.basket_app = apps.get_app_config('basket') self.checkout_app = apps.get_app_config('checkout') self.search_app = apps.get_app_config('search') self.dashboard_app = apps.get_app_config('dashboard') self.offer_app = apps.get_app_config('offer') self.password_reset_form = get_class('customer.forms', 'PasswordResetForm') self.set_password_form = SetPasswordForm
def _default_access_fn(self, user): """ Given a url_name and a user, this function tries to assess whether the user has the right to access the URL. The application instance of the view is fetched via dynamic imports, and those assumptions will only hold true if the standard Oscar layout is followed. Once the permissions for the view are known, the access logic used by the dashboard decorator is evaluated This function might seem costly, but a simple comparison with DTT did not show any change in response time """ exception = ImproperlyConfigured( "Please follow Oscar's default dashboard app layout or set a " "custom access_fn") if self.is_heading: return True # get view module string try: url = reverse(self.url_name, args=self.url_args, kwargs=self.url_kwargs) view_module = resolve(url).func.__module__ except (NoReverseMatch, Http404): # if there's no match, no need to display it return False # We can't assume that the view has the same parent module as the app, # as either the app or view can be customised. So we turn the module # string (e.g. 'oscar.apps.dashboard.catalogue.views') into an app # label that can be loaded by get_class (e.g. # 'dashboard.catalogue.app), which then essentially checks # INSTALLED_APPS for the right module to load match = re.search('(dashboard[\w\.]*)\.views$', view_module) if not match: raise exception app_label_str = match.groups()[0] + '.app' try: app_instance = get_class(app_label_str, 'application') except AppNotFoundError: raise exception # handle name-spaced view names if ':' in self.url_name: view_name = self.url_name.split(':')[1] else: view_name = self.url_name permissions = app_instance.get_permissions(view_name) return check_permissions(user, permissions)
def ready(self): self.index_view = get_class('dashboard.views', 'IndexView') self.catalogue_app = apps.get_app_config('catalogue_dashboard') self.reports_app = apps.get_app_config('reports_dashboard') self.orders_app = apps.get_app_config('orders_dashboard') self.users_app = apps.get_app_config('users_dashboard') self.pages_app = apps.get_app_config('pages_dashboard') self.partners_app = apps.get_app_config('partners_dashboard') self.offers_app = apps.get_app_config('offers_dashboard') self.ranges_app = apps.get_app_config('ranges_dashboard') self.reviews_app = apps.get_app_config('reviews_dashboard') self.vouchers_app = apps.get_app_config('vouchers_dashboard') self.comms_app = apps.get_app_config('communications_dashboard') self.shipping_app = apps.get_app_config('shipping_dashboard')
def update(self, request, *args, **kwargs): order = self.get_object() if not order.is_fulfillable: return Response(status=status.HTTP_406_NOT_ACCEPTABLE) logger.info('Attempting fulfillment of order [%s]...', order.number) post_checkout = get_class('checkout.signals', 'post_checkout') post_checkout.send(sender=post_checkout, order=order) if order.is_fulfillable: logger.warning('Fulfillment of order [%s] failed!', order.number) return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) serializer = self.get_serializer(order) return Response(serializer.data)
def ready(self): self.index_view = get_class('dashboard.users.views', 'IndexView') self.user_detail_view = get_class('dashboard.users.views', 'UserDetailView') self.password_reset_view = get_class('dashboard.users.views', 'PasswordResetView') self.alert_list_view = get_class('dashboard.users.views', 'ProductAlertListView') self.alert_update_view = get_class('dashboard.users.views', 'ProductAlertUpdateView') self.alert_delete_view = get_class('dashboard.users.views', 'ProductAlertDeleteView')
def test_load_formset_new_destination(self): BaseBasketLineFormSet = get_class('basket.formsets', 'BaseBasketLineFormSet') self.assertEqual('oscar.apps.basket.formsets', BaseBasketLineFormSet.__module__) StockRecordFormSet = get_class('dashboard.catalogue.formsets', 'StockRecordFormSet') self.assertEqual('oscar.apps.dashboard.catalogue.formsets', StockRecordFormSet.__module__) OrderedProductFormSet = get_class('dashboard.promotions.formsets', 'OrderedProductFormSet') OrderedProductForm = get_class('dashboard.promotions.forms', 'OrderedProductForm') self.assertTrue(isinstance(OrderedProductFormSet().forms[0], OrderedProductForm)) LineFormset = get_class('wishlists.formsets', 'LineFormset') WishListLineForm = get_class('wishlists.forms', 'WishListLineForm') self.assertTrue(isinstance(LineFormset(instance=self.wishlist).forms[0], WishListLineForm))
def assign_basket_strategy(basket, request): # fixes too early import of Selector # TODO: check if this is still true, now the basket models nolonger # require this module to be loaded. global Selector if hasattr(request, 'strategy'): basket.strategy = request.strategy else: # in management commands, the request might not be available. if Selector is None: Selector = get_class('partner.strategy', 'Selector') basket.strategy = Selector().strategy( request=request, user=request.user) apply_offers(request, basket) return basket
def fulfill(self, request, number=None): # pylint: disable=unused-argument """ Fulfill order """ order = self.get_object() if not order.is_fulfillable: return Response(status=status.HTTP_406_NOT_ACCEPTABLE) logger.info('Attempting fulfillment of order [%s]...', order.number) post_checkout = get_class('checkout.signals', 'post_checkout') post_checkout.send(sender=post_checkout, order=order, request=request) if order.is_fulfillable: logger.warning('Fulfillment of order [%s] failed!', order.number) return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) serializer = self.get_serializer(order) return Response(serializer.data)
def proxy_map(self): return { self.PERCENTAGE: get_class( 'offer.benefits', 'PercentageDiscountBenefit'), self.FIXED: get_class( 'offer.benefits', 'AbsoluteDiscountBenefit'), self.MULTIBUY: get_class( 'offer.benefits', 'MultibuyDiscountBenefit'), self.FIXED_PRICE: get_class( 'offer.benefits', 'FixedPriceBenefit'), self.SHIPPING_ABSOLUTE: get_class( 'offer.benefits', 'ShippingAbsoluteDiscountBenefit'), self.SHIPPING_FIXED_PRICE: get_class( 'offer.benefits', 'ShippingFixedPriceBenefit'), self.SHIPPING_PERCENTAGE: get_class( 'offer.benefits', 'ShippingPercentageDiscountBenefit') }
def children(self, page, **kwargs): from oscar.core.loading import get_class Store = get_class('stores.models', 'Store') stores = Store.objects.all() for store in stores: yield PagePretender( title=store.name, url=store.get_absolute_url(), tree_id=page.tree_id, level=page.level + 1, language=getattr(page, 'language', settings.LANGUAGE_CODE), slug=store.slug, parent=page, parent_id=page.id, lft=page.lft, rght=page.rght, _mptt_meta=getattr(page, '_mptt_meta', None), )
def children(self, page, **kwargs): from oscar.core.loading import get_class Category = get_class('catalogue.categories', 'Category') categories = Category.objects.all() for category in categories: yield PagePretender( title=category.name, url=category.get_absolute_url(), tree_id=page.tree_id, level=page.level + 1, language=getattr(page, 'language', settings.LANGUAGE_CODE), slug=category.slug, parent=page, parent_id=page.id, lft=page.lft, rght=page.rght, _mptt_meta=getattr(page, '_mptt_meta', None), )
def test_load_formset_old_destination(self): BaseBasketLineFormSet = get_class('basket.forms', 'BaseBasketLineFormSet') self.assertEqual('oscar.apps.basket.formsets', BaseBasketLineFormSet.__module__) StockRecordFormSet = get_class('dashboard.catalogue.forms', 'StockRecordFormSet') self.assertEqual('oscar.apps.dashboard.catalogue.formsets', StockRecordFormSet.__module__) OrderedProductFormSet = get_class('dashboard.promotions.forms', 'OrderedProductFormSet') OrderedProductForm = get_class('dashboard.promotions.forms', 'OrderedProductForm') # Since OrderedProductFormSet created with metaclass, it has __module__ # attribute pointing to the Django module. Thus, we test if formset was # loaded correctly by initiating class instance and checking its forms. self.assertTrue(isinstance(OrderedProductFormSet().forms[0], OrderedProductForm)) LineFormset = get_class('wishlists.forms', 'LineFormset') WishListLineForm = get_class('wishlists.forms', 'WishListLineForm') self.assertTrue(isinstance(LineFormset(instance=self.wishlist).forms[0], WishListLineForm))
import json from django.conf import settings from oscar.core.loading import get_class, get_model product_viewed = get_class('catalogue.signals', 'product_viewed') Product = get_model('catalogue', 'Product') def get(request): """ Return a list of recently viewed products """ ids = extract(request) # Reordering as the ID order gets messed up in the query product_dict = Product.browsable.in_bulk(ids) ids.reverse() return [product_dict[id] for id in ids if id in product_dict] def extract(request, response=None): """ Extract the IDs of products in the history cookie """ ids = [] cookie_name = settings.OSCAR_RECENTLY_VIEWED_COOKIE_NAME if cookie_name in request.COOKIES: try: ids = json.loads(request.COOKIES[cookie_name])
from django import forms from django.contrib.auth.models import Permission from django.contrib.auth.password_validation import validate_password from django.utils.translation import ugettext_lazy as _ from django.utils.translation import pgettext_lazy from oscar.core.compat import existing_user_fields, get_user_model from oscar.core.loading import get_class, get_model User = get_user_model() Partner = get_model('partner', 'Partner') PartnerAddress = get_model('partner', 'PartnerAddress') EmailUserCreationForm = get_class('customer.forms', 'EmailUserCreationForm') class PartnerSearchForm(forms.Form): name = forms.CharField(required=False, label=pgettext_lazy(u"Partner's name", u"Name")) class PartnerCreateForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(PartnerCreateForm, self).__init__(*args, **kwargs) # Partner.name is optional and that is okay. But if creating through # the dashboard, it seems sensible to enforce as it's the only field # in the form. self.fields['name'].required = True class Meta: model = Partner fields = ('name', )
"""Functions used for data retrieval and manipulation by the API.""" import logging from oscar.core.loading import get_model, get_class from ecommerce.extensions.api import exceptions NoShippingRequired = get_class('shipping.methods', 'NoShippingRequired') OrderTotalCalculator = get_class('checkout.calculators', 'OrderTotalCalculator') Product = get_model('catalogue', 'Product') logger = logging.getLogger(__name__) def get_product(sku): """Retrieve the product corresponding to the provided SKU.""" try: return Product.objects.get(stockrecords__partner_sku=sku) except Product.DoesNotExist: raise exceptions.ProductNotFoundError( exceptions.PRODUCT_NOT_FOUND_DEVELOPER_MESSAGE.format(sku=sku)) def get_order_metadata(basket): """Retrieve information required to place an order. Arguments: basket (Basket): The basket whose contents are to be ordered. Returns:
def prepare_basket(request, products, voucher=None): """ Create or get the basket, add products, apply a voucher, and record referral data. Existing baskets are merged. Specified products will be added to the remaining open basket. If voucher is passed, all existing vouchers added to the basket are removed because we allow only one voucher per basket. Vouchers are not applied if an enrollment code product is in the basket. Arguments: request (Request): The request object made to the view. products (List): List of products to be added to the basket. voucher (Voucher): Voucher to apply to the basket. Returns: basket (Basket): Contains the product to be redeemed and the Voucher applied. """ basket = Basket.get_basket(request.user, request.site) basket.flush() basket.save() basket_addition = get_class('basket.signals', 'basket_addition') already_purchased_products = [] bundle = request.GET.get('bundle') _set_basket_bundle_status(bundle, basket) if request.site.siteconfiguration.enable_embargo_check: if not embargo_check(request.user, request.site, products): messages.error( request, _('Due to export controls, we cannot allow you to access this course at this time.' )) logger.warning( 'User [%s] blocked by embargo check, not adding products to basket', request.user.username) return basket is_multi_product_basket = True if len(products) > 1 else False for product in products: if product.is_enrollment_code_product or \ not UserAlreadyPlacedOrder.user_already_placed_order(user=request.user, product=product, site=request.site): basket.add_product(product, 1) # Call signal handler to notify listeners that something has been added to the basket basket_addition.send( sender=basket_addition, product=product, user=request.user, request=request, basket=basket, is_multi_product_basket=is_multi_product_basket) else: already_purchased_products.append(product) logger.warning( 'User [%s] attempted to repurchase the [%s] seat of course [%s]', request.user.username, mode_for_product(product), product.course_id) if already_purchased_products and basket.is_empty: raise AlreadyPlacedOrderException if len(products) == 1 and products[0].is_enrollment_code_product: basket.clear_vouchers() elif voucher: basket.clear_vouchers() basket.vouchers.add(voucher) Applicator().apply(basket, request.user, request) logger.info('Applied Voucher [%s] to basket [%s].', voucher.code, basket.id) attribute_cookie_data(basket, request) return basket
import datetime import logging import pytz from django.core.management.base import BaseCommand, CommandError from django.db.models import Sum from oscar.core.loading import get_class, get_model from ecommerce.core.constants import COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME, SEAT_PRODUCT_CLASS_NAME from ecommerce.core.utils import use_read_replica_if_available logger = logging.getLogger(__name__) Order = get_model('order', 'Order') PaymentEvent = get_model('order', 'PaymentEvent') PaymentEventType = get_model('order', 'PaymentEventType') PaymentEventTypeName = get_class('order.constants', 'PaymentEventTypeName') DEFAULT_START_DELTA_TIME = 240 DEFAULT_END_DELTA_TIME = 60 VALID_PRODUCT_CLASS_NAMES = [ SEAT_PRODUCT_CLASS_NAME, COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME ] class Command(BaseCommand): ORDERS_WITHOUT_PAYMENTS = None MULTI_PAYMENT_ON_ORDER = None ORDER_PAYMENT_TOTALS_MISMATCH = None REFUND_AMOUNT_EXCEEDED = None PAID_EVENT_TYPE = None REFUNDED_EVENT_TYPE = None
def proxy_map(self): return { self.COUNT: get_class('offer.conditions', 'CountCondition'), self.VALUE: get_class('offer.conditions', 'ValueCondition'), self.COVERAGE: get_class('offer.conditions', 'CoverageCondition'), }
from django_tables2 import A, Column, LinkColumn, TemplateColumn from oscar.core.loading import get_class DashboardTable = get_class('dashboard.tables', 'DashboardTable') class UserTable(DashboardTable): check = TemplateColumn( template_name='dashboard/users/user_row_checkbox.html', verbose_name=' ', orderable=False) email = LinkColumn('dashboard:user-detail', args=[A('id')], accessor='email') name = Column(accessor='get_full_name', order_by=('last_name', 'first_name')) active = Column(accessor='is_active') staff = Column(accessor='is_staff') date_registered = Column(accessor='date_joined') num_orders = Column(accessor='orders.count', orderable=False) actions = TemplateColumn( template_name='dashboard/users/user_row_actions.html', verbose_name=' ') icon = "group" class Meta(DashboardTable.Meta): template = 'dashboard/users/table.html'
from django.test import override_settings from oscar.core.loading import get_class, get_model from oscar.test.factories import ProductFactory, RangeFactory, create_order from ecommerce.extensions.basket.utils import prepare_basket from ecommerce.extensions.fulfillment.status import ORDER from ecommerce.extensions.order.constants import PaymentEventTypeName from ecommerce.extensions.payment.constants import CARD_TYPES from ecommerce.extensions.payment.models import PaymentProcessorResponse from ecommerce.extensions.payment.processors.cybersource import Cybersource from ecommerce.extensions.payment.processors.paypal import Paypal from ecommerce.extensions.test.factories import UserFactory, create_basket, prepare_voucher from ecommerce.management.utils import FulfillFrozenBaskets, refund_basket_transactions from ecommerce.tests.testcases import TestCase Free = get_class('shipping.methods', 'Free') OrderTotalCalculator = get_class('checkout.calculators', 'OrderTotalCalculator') OrderNumberGenerator = get_class('order.utils', 'OrderNumberGenerator') OrderCreator = get_class('order.utils', 'OrderCreator') Order = get_model('order', 'Order') PaymentEvent = get_model('order', 'PaymentEvent') Source = get_model('payment', 'Source') class RefundBasketTransactionsTests(TestCase): def test_no_basket_ids(self): assert refund_basket_transactions(self.site, []) == ( 0, 0,
def create(self, request, *args, **kwargs): """Add products to the authenticated user's basket. Expects an array of product objects, 'products', each containing a SKU, in the request body. The SKUs are used to populate the user's basket with the corresponding products. The caller indicates whether checkout should occur by providing a Boolean value in the request body, 'checkout'. If checkout operations are requested and the contents of the user's basket are free, an order is placed immediately. If checkout operations are requested but the contents of the user's basket are not free, pre-payment operations are performed instead of placing an order. The caller indicates which payment processor to use by providing a string in the request body, 'payment_processor_name'. Protected by JWT authentication. Consuming services (e.g., the LMS) must authenticate themselves by passing a JWT in the Authorization HTTP header, prepended with the string 'JWT '. The JWT payload should contain user details. At a minimum, these details must include a username; providing an email is recommended. Arguments: request (HttpRequest): With parameters 'products', 'checkout', and 'payment_processor_name' in the body. Returns: 200 if a basket was created successfully; the basket ID is included in the response body along with either an order number corresponding to the placed order (None if one wasn't placed) or payment information (None if payment isn't required). 400 if the client provided invalid data or attempted to add an unavailable product to their basket, with reason for the failure in JSON format. 401 if an unauthenticated request is denied permission to access the endpoint. 429 if the client has made requests at a rate exceeding that allowed by the configured rate limit. 500 if an error occurs when attempting to initiate checkout. Examples: Create a basket for the user with username 'Saul' as follows. Successful fulfillment requires that a user with username 'Saul' exists on the LMS, and that EDX_API_KEY be configured within both the LMS and the ecommerce service. >>> url = 'http://*****:*****@bettercallsaul.com'}, 'insecure-secret-key') >>> headers = { 'content-type': 'application/json', 'Authorization': 'JWT ' + token } If checkout is not desired: >>> data = {'products': [{'sku': 'SOME-SEAT'}, {'sku': 'SOME-OTHER-SEAT'}], 'checkout': False} >>> response = requests.post(url, data=json.dumps(data), headers=headers) >>> response.json() { 'id': 7, 'order': None, 'payment_data': None } If the product with SKU 'FREE-SEAT' is free and checkout is desired: >>> data = {'products': [{'sku': 'FREE-SEAT'}], 'checkout': True, 'payment_processor_name': 'paypal'} >>> response = requests.post(url, data=json.dumps(data), headers=headers) >>> response.json() { 'id': 7, 'order': {'number': 'OSCR-100007'}, 'payment_data': None } If the product with SKU 'PAID-SEAT' is not free and checkout is desired: >>> data = {'products': [{'sku': 'PAID-SEAT'}], 'checkout': True, 'payment_processor_name': 'paypal'} >>> response = requests.post(url, data=json.dumps(data), headers=headers) >>> response.json() { 'id': 7, 'order': None, 'payment_data': { 'payment_processor_name': 'paypal', 'payment_form_data': {...}, 'payment_page_url': 'https://www.someexternallyhostedpaymentpage.com' } } """ # Explicitly delimit operations which will be rolled back if an exception occurs. # atomic() context managers restore atomicity at points where we are modifying data # (baskets, then orders) to ensure that we don't leave the system in a dirty state # in the event of an error. with transaction.atomic(): basket = Basket.create_basket(request.site, request.user) basket_id = basket.id attribute_cookie_data(basket, request) requested_products = request.data.get('products') if requested_products: is_multi_product_basket = True if len( requested_products) > 1 else False for requested_product in requested_products: # Ensure the requested products exist sku = requested_product.get('sku') if sku: try: product = data_api.get_product(sku) except api_exceptions.ProductNotFoundError as error: return self._report_bad_request( error.message, api_exceptions.PRODUCT_NOT_FOUND_USER_MESSAGE) else: return self._report_bad_request( api_exceptions.SKU_NOT_FOUND_DEVELOPER_MESSAGE, api_exceptions.SKU_NOT_FOUND_USER_MESSAGE) # Ensure the requested products are available for purchase before adding them to the basket availability = basket.strategy.fetch_for_product( product).availability if not availability.is_available_to_buy: return self._report_bad_request( api_exceptions. PRODUCT_UNAVAILABLE_DEVELOPER_MESSAGE.format( sku=sku, availability=availability.message), api_exceptions.PRODUCT_UNAVAILABLE_USER_MESSAGE) basket.add_product(product) logger.info('Added product with SKU [%s] to basket [%d]', sku, basket_id) # Call signal handler to notify listeners that something has been added to the basket basket_addition = get_class('basket.signals', 'basket_addition') basket_addition.send( sender=basket_addition, product=product, user=request.user, request=request, basket=basket, is_multi_product_basket=is_multi_product_basket) else: # If no products were included in the request, we cannot checkout. return self._report_bad_request( api_exceptions.PRODUCT_OBJECTS_MISSING_DEVELOPER_MESSAGE, api_exceptions.PRODUCT_OBJECTS_MISSING_USER_MESSAGE) if request.data.get('checkout') is True: # Begin the checkout process, if requested, with the requested payment processor. payment_processor_name = request.data.get('payment_processor_name') if payment_processor_name: try: payment_processor = get_processor_class_by_name( payment_processor_name) except payment_exceptions.ProcessorNotFoundError as error: return self._report_bad_request( error.message, payment_exceptions.PROCESSOR_NOT_FOUND_USER_MESSAGE) else: payment_processor = get_default_processor_class() try: response_data = self._checkout(basket, payment_processor(request.site), request) except Exception as ex: # pylint: disable=broad-except basket.delete() logger.exception( 'Failed to initiate checkout for Basket [%d]. The basket has been deleted.', basket_id) return Response({'developer_message': ex.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) else: # Return a serialized basket, if checkout was not requested. response_data = self._generate_basic_response(basket) return Response(response_data, status=status.HTTP_200_OK)
from ecommerce.core.utils import get_cache_key from ecommerce.enterprise.entitlements import get_entitlement_voucher from ecommerce.extensions.analytics.utils import audit_log from ecommerce.extensions.api import data as data_api from ecommerce.extensions.api import exceptions as api_exceptions from ecommerce.extensions.api.permissions import IsStaffOrOwner from ecommerce.extensions.api.serializers import BasketSerializer, OrderSerializer from ecommerce.extensions.api.throttles import ServiceUserThrottle from ecommerce.extensions.basket.constants import TEMPORARY_BASKET_CACHE_KEY from ecommerce.extensions.basket.utils import attribute_cookie_data from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin from ecommerce.extensions.partner.shortcuts import get_partner_for_site from ecommerce.extensions.payment import exceptions as payment_exceptions from ecommerce.extensions.payment.helpers import get_default_processor_class, get_processor_class_by_name Applicator = get_class('offer.applicator', 'Applicator') Basket = get_model('basket', 'Basket') logger = logging.getLogger(__name__) Order = get_model('order', 'Order') OrderNumberGenerator = get_class('order.utils', 'OrderNumberGenerator') Product = get_model('catalogue', 'Product') Selector = get_class('partner.strategy', 'Selector') User = get_user_model() Voucher = get_model('voucher', 'Voucher') class BasketCreateView(EdxOrderPlacementMixin, generics.CreateAPIView): """Endpoint for creating baskets. If requested, performs checkout operations on baskets, placing an order if the contents of the basket are free, and generating payment parameters otherwise.
import waffle from django.conf import settings from django.contrib import messages from django.db import transaction from django.utils.translation import ugettext_lazy as _ from oscar.apps.basket.signals import voucher_addition from oscar.core.loading import get_class, get_model from ecommerce.courses.utils import mode_for_product from ecommerce.extensions.offer.constants import CUSTOM_APPLICATOR_USE_FLAG from ecommerce.extensions.order.exceptions import AlreadyPlacedOrderException from ecommerce.extensions.order.utils import UserAlreadyPlacedOrder from ecommerce.extensions.payment.utils import embargo_check from ecommerce.referrals.models import Referral Applicator = get_class('offer.applicator', 'Applicator') CustomApplicator = get_class('offer.applicator', 'CustomApplicator') Basket = get_model('basket', 'Basket') BasketAttribute = get_model('basket', 'BasketAttribute') BasketAttributeType = get_model('basket', 'BasketAttributeType') BUNDLE = 'bundle_identifier' ORGANIZATION_ATTRIBUTE_TYPE = 'organization' ENTERPRISE_CATALOG_ATTRIBUTE_TYPE = 'enterprise_catalog_uuid' StockRecord = get_model('partner', 'StockRecord') OrderLine = get_model('order', 'Line') Refund = get_model('refund', 'Refund') Voucher = get_model('voucher', 'Voucher') logger = logging.getLogger(__name__)
from decimal import Decimal as D from django.conf import settings from django.utils.translation import gettext_lazy as _ from oscar.core.loading import get_class, get_classes, get_model from oscar.templatetags.currency_filters import currency Benefit = get_model('offer', 'Benefit') BasketDiscount, SHIPPING_DISCOUNT, ZERO_DISCOUNT = get_classes( 'offer.results', ['BasketDiscount', 'SHIPPING_DISCOUNT', 'ZERO_DISCOUNT']) CoverageCondition, ValueCondition = get_classes( 'offer.conditions', ['CoverageCondition', 'ValueCondition']) range_anchor = get_class('offer.utils', 'range_anchor') __all__ = [ 'PercentageDiscountBenefit', 'AbsoluteDiscountBenefit', 'FixedPriceBenefit', 'ShippingBenefit', 'MultibuyDiscountBenefit', 'ShippingAbsoluteDiscountBenefit', 'ShippingFixedPriceBenefit', 'ShippingPercentageDiscountBenefit', ] def apply_discount(line, discount, quantity, offer=None, incl_tax=None): """ Apply a given discount to the passed basket """
logger = logging.getLogger(__name__) Basket = get_model('basket', 'Basket') Benefit = get_model('offer', 'Benefit') BillingAddress = get_model('order', 'BillingAddress') Catalog = get_model('catalogue', 'Catalog') Category = get_model('catalogue', 'Category') Line = get_model('order', 'Line') Order = get_model('order', 'Order') Partner = get_model('partner', 'Partner') Product = get_model('catalogue', 'Product') ProductAttributeValue = get_model('catalogue', 'ProductAttributeValue') ProductCategory = get_model('catalogue', 'ProductCategory') Refund = get_model('refund', 'Refund') Selector = get_class('partner.strategy', 'Selector') StockRecord = get_model('partner', 'StockRecord') Voucher = get_model('voucher', 'Voucher') User = get_user_model() COURSE_DETAIL_VIEW = 'api:v2:course-detail' PRODUCT_DETAIL_VIEW = 'api:v2:product-detail' def is_custom_code(obj): """Helper method to check if the voucher contains custom code. """ return not is_enrollment_code(obj) and retrieve_quantity(obj) == 1 def is_enrollment_code(obj): benefit = retrieve_voucher(obj).benefit
from django.views.decorators.csrf import csrf_exempt from django.views.generic import FormView, View from oscar.apps.partner import strategy from oscar.apps.payment.exceptions import PaymentError, TransactionDeclined, UserCancelled from oscar.core.loading import get_class, get_model from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin from ecommerce.extensions.checkout.utils import get_receipt_page_url from ecommerce.extensions.payment.exceptions import InvalidBasketError, InvalidSignatureError from ecommerce.extensions.payment.forms import PaymentForm from ecommerce.extensions.payment.processors.cybersource import Cybersource from ecommerce.extensions.payment.utils import clean_field_value logger = logging.getLogger(__name__) Applicator = get_class('offer.utils', 'Applicator') Basket = get_model('basket', 'Basket') BillingAddress = get_model('order', 'BillingAddress') Country = get_model('address', 'Country') NoShippingRequired = get_class('shipping.methods', 'NoShippingRequired') Order = get_model('order', 'Order') OrderNumberGenerator = get_class('order.utils', 'OrderNumberGenerator') OrderTotalCalculator = get_class('checkout.calculators', 'OrderTotalCalculator') class CybersourceSubmitView(FormView): """ Starts CyberSource payment process. This view is intended to be called asynchronously by the payment form. The view expects POST data containing a `Basket` ID. The specified basket is frozen, and CyberSource parameters are returned as a JSON object.
import logging from decimal import Decimal from django.contrib.sites.models import Site from django.conf import settings from django.http import Http404 from django.urls import reverse from mollie.api.client import Client from oscar.apps.payment.exceptions import UnableToTakePayment from oscar.core.loading import get_class, get_model from . import signals logger = logging.getLogger('oscar.checkout') EventHandler = get_class('order.processing', 'EventHandler') Order = None SourceType = None def _lazy_get_payment_event_models(): global PaymentEvent global PaymentEventType global PaymentEventQuantity PaymentEvent = get_model('order', 'PaymentEvent') PaymentEventType = get_model('order', 'PaymentEventType') PaymentEventQuantity = get_model('order', 'PaymentEventQuantity') def _lazy_get_models():
from ecommerce.extensions.payment.processors.paypal import Paypal from ecommerce.extensions.payment.tests.mixins import PaymentEventsMixin, PaypalMixin from ecommerce.extensions.payment.views.paypal import PaypalPaymentExecutionView from ecommerce.extensions.test.factories import create_basket from ecommerce.invoice.models import Invoice from ecommerce.tests.testcases import TestCase JSON = 'application/json' Basket = get_model('basket', 'Basket') Order = get_model('order', 'Order') PaymentEvent = get_model('order', 'PaymentEvent') PaymentEventType = get_model('order', 'PaymentEventType') PaymentProcessorResponse = get_model('payment', 'PaymentProcessorResponse') Product = get_model('catalogue', 'Product') Selector = get_class('partner.strategy', 'Selector') SourceType = get_model('payment', 'SourceType') Voucher = get_model('voucher', 'Voucher') post_checkout = get_class('checkout.signals', 'post_checkout') @ddt.ddt class PaypalPaymentExecutionViewTests(PaypalMixin, PaymentEventsMixin, TestCase): """Test handling of users redirected by PayPal after approving payment.""" def setUp(self): super(PaypalPaymentExecutionViewTests, self).setUp() self.basket = create_basket(owner=factories.UserFactory(), site=self.site)
from django import forms from django.conf import settings from django.utils.translation import ugettext_lazy as _ from oscar.apps.promotions.conf import PROMOTION_CLASSES from oscar.core.loading import get_class, get_classes from oscar.forms.fields import ExtendedURLField HandPickedProductList, RawHTML, SingleProduct, PagePromotion, OrderedProduct \ = get_classes('promotions.models', ['HandPickedProductList', 'RawHTML', 'SingleProduct', 'PagePromotion', 'OrderedProduct']) ProductSelect = get_class('dashboard.catalogue.widgets', 'ProductSelect') class PromotionTypeSelectForm(forms.Form): choices = [] for klass in PROMOTION_CLASSES: choices.append((klass.classname(), klass._meta.verbose_name)) promotion_type = forms.ChoiceField(choices=tuple(choices), label=_("Promotion type")) class RawHTMLForm(forms.ModelForm): class Meta: model = RawHTML fields = ['name', 'body'] def __init__(self, *args, **kwargs): super(RawHTMLForm, self).__init__(*args, **kwargs) self.fields['body'].widget.attrs['class'] = "no-widget-init"
from decimal import Decimal as D from django.db import models from django.conf import settings from django.db.models import get_model from django.utils.translation import ugettext_lazy as _ from django.utils.importlib import import_module as django_import_module from oscar.core.utils import slugify from oscar.core.loading import get_class from oscar.apps.partner.exceptions import InvalidStockAdjustment DefaultWrapper = get_class('partner.wrappers', 'DefaultWrapper') # Cache dict of partner_id => availability wrapper instance partner_wrappers = None default_wrapper = DefaultWrapper() def get_partner_wrapper(partner_id): """ Returns the appropriate partner wrapper given the partner's PK """ if partner_wrappers is None: _load_partner_wrappers() return partner_wrappers.get(partner_id, default_wrapper) def _load_partner_wrappers(): # Prime cache of partner wrapper dict global partner_wrappers
import datetime from oscar.core.loading import get_model, get_class from django.views import generic from django.core.exceptions import ObjectDoesNotExist Post = get_model('appblog', 'Post') Category = get_model('appblog', 'Category') CategoryGroup = get_model('appblog', 'CategoryGroup') SearchPostForm = get_class('appblog.forms', 'SearchPostForm') class BlogPostView(generic.ListView): template_name = 'appblog/blog-post-list.html' model = Post paginate_by = 2 context_object_name = 'posts' form_class = SearchPostForm def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['categories'] = self.get_categories() context['form'] = self.form_class() return context def get_posts_published(self, queryset): return queryset.filter(post_date__lte=datetime.date.today())
class InvestorsDashboardApplication(DashboardApplication): name = None default_permissions = [ 'is_staff', ] permissions_map = { 'investor-list': (['is_staff'], ['investor.dashboard_access']), 'investor-manage': (['is_staff'], ['investor.dashboard_access']), 'investment-create': (['is_staff'], ['investor.dashboard_access']), 'investmentcomments-create': (['is_staff'], ['investor.dashboard_access'], ['company.dashboard_access']), 'investor-member': (['is_staff'], ['investor.dashboard_access']), 'investor-order': (['is_staff'], ['investor.dashboard_access']), 'project-announcement-list': (['is_staff'], ['investor.dashboard_access']), 'project-announcement-create': (['is_staff'], ['investor.dashboard_access']), 'project-announcement-detail': (['is_staff'], ['investor.dashboard_access']), #'create_investment_comments_view': (['is_staff'], ['investor.dashboard_access']), #'money-list': (['is_staff'], ['investor.dashboard_access']), } list_view = get_class('dashboard.investors.views', 'InvestorListView') create_view = get_class('dashboard.investors.views', 'InvestorCreateView') manage_view = get_class('dashboard.investors.views', 'InvestorManageView') delete_view = get_class('dashboard.investors.views', 'InvestorDeleteView') create_investment_view = get_class('dashboard.investors.views', 'InvestmentCreateView') create_investment_comments_view = get_class( 'dashboard.investors.views', 'InvestmentCommentsCreateView') user_link_view = get_class('dashboard.investors.views', 'InvestorUserLinkView') user_unlink_view = get_class('dashboard.investors.views', 'InvestorUserUnlinkView') user_create_view = get_class('dashboard.investors.views', 'InvestorUserCreateView') user_select_view = get_class('dashboard.investors.views', 'InvestorUserSelectView') user_update_view = get_class('dashboard.investors.views', 'InvestorUserUpdateView') investor_member_view = get_class('dashboard.investors.views', 'InvestorMembersView') investor_order_view = get_class('dashboard.investors.views', 'InvestorOrderView') project_announcement_create_view = get_class( 'dashboard.investors.views', 'ProjectAnnouncementCreateView') project_announcement_list_view = get_class('dashboard.investors.views', 'ProjectAnnouncementListView') project_announcement_detail_view = get_class( 'dashboard.investors.views', 'ProjectAnnouncementDetailView') def get_urls(self): urls = [ url(r'^$', self.list_view.as_view(), name='investor-list'), url(r'^create/$', self.create_view.as_view(), name='investor-create'), url(r'^(?P<pk>\d+)/$', self.manage_view.as_view(), name='investor-manage'), url(r'^(?P<pk>\d+)/delete/$', self.delete_view.as_view(), name='investor-delete'), url(r'^(?P<investor_pk>\d+)/users/add/$', self.user_create_view.as_view(), name='investor-user-create'), url(r'^(?P<investor_pk>\d+)/users/select/$', self.user_select_view.as_view(), name='investor-user-select'), url(r'^(?P<investor_pk>\d+)/users/(?P<user_pk>\d+)/link/$', self.user_link_view.as_view(), name='investor-user-link'), url(r'^(?P<investor_pk>\d+)/users/(?P<user_pk>\d+)/unlink/$', self.user_unlink_view.as_view(), name='investor-user-unlink'), url(r'^(?P<investor_pk>\d+)/users/(?P<user_pk>\d+)/update/$', self.user_update_view.as_view(), name='investor-user-update'), url(r'^createinvestment/(?P<company_pk>\d+)/(?P<pk>\d+)/$', self.create_investment_view.as_view(), name='investment-create'), url(r'^createinvestmentcomments/(?P<company_pk>\d+)/(?P<prospectus_pk>\d+)/(?P<pk>\d+)/$', self.create_investment_comments_view.as_view(), name='investmentcomments-create'), url(r'^investor/members/$', self.investor_member_view.as_view(), name='investor-member'), url(r'^investor/orders/$', self.investor_order_view.as_view(), name='investor-order'), url(r'^projectannouncementlist/$', self.project_announcement_list_view.as_view(), name='project-announcement-list'), url(r'^createprojectannouncement/(?P<investor_pk>\d+)/$', self.project_announcement_create_view.as_view(), name='project-announcement-create'), url(r'^detailprojectannouncement/(?P<investor_pk>\d+)/(?P<pk>\d+)/$', self.project_announcement_detail_view.as_view(), name='project-announcement-detail'), ] return self.post_process_urls(urls)
from django.db.models.query import Q from django.template.defaultfilters import date as date_filter from django.urls import reverse from django.utils.functional import cached_property from django.utils.timezone import get_current_timezone, now from django.utils.translation import gettext_lazy as _ from oscar.core.compat import AUTH_USER_MODEL from oscar.core.loading import (cached_import_string, get_class, get_classes, get_model) from oscar.models import fields from oscar.templatetags.currency_filters import currency ActiveOfferManager, RangeManager, BrowsableRangeManager \ = get_classes('offer.managers', ['ActiveOfferManager', 'RangeManager', 'BrowsableRangeManager']) ZERO_DISCOUNT = get_class('offer.results', 'ZERO_DISCOUNT') load_proxy, unit_price = get_classes('offer.utils', ['load_proxy', 'unit_price']) class BaseOfferMixin(models.Model): class Meta: abstract = True def proxy(self): """ Return the proxy model """ klassmap = self.proxy_map # Short-circuit logic if current class is already a proxy class. if self.__class__ in klassmap.values():
from django import forms from django.utils.translation import gettext_lazy as _ from oscar.core.loading import get_class from oscar.forms.widgets import DatePickerInput GeneratorRepository = get_class('dashboard.reports.utils', 'GeneratorRepository') class ReportForm(forms.Form): generators = GeneratorRepository().get_report_generators() type_choices = [] count =1 for generator in generators: if(count<=5): type_choices.append((generator.code, generator.description)) print(generator.description) count +=1 report_type = forms.ChoiceField(widget=forms.Select(), choices=type_choices, label=_("Report Type"), help_text=_("Only the offer and order" " reports use the selected" " date range")) date_from = forms.DateField(label=_("Date from"), required=False, widget=DatePickerInput) date_to = forms.DateField(label=_("Date to"), help_text=_("The report is inclusive of this"
from ecommerce.core.url_utils import get_lms_url from ecommerce.extensions.api.serializers import OrderSerializer from ecommerce.extensions.order.constants import PaymentEventTypeName from ecommerce.extensions.payment.exceptions import InvalidBasketError, InvalidSignatureError from ecommerce.extensions.payment.processors.cybersource import Cybersource from ecommerce.extensions.payment.tests.mixins import CybersourceMixin, CybersourceNotificationTestsMixin from ecommerce.extensions.payment.views.cybersource import CybersourceInterstitialView from ecommerce.extensions.test.factories import create_basket from ecommerce.tests.testcases import TestCase JSON = 'application/json' Basket = get_model('basket', 'Basket') Order = get_model('order', 'Order') OrderNumberGenerator = get_class('order.utils', 'OrderNumberGenerator') PaymentEvent = get_model('order', 'PaymentEvent') PaymentProcessorResponse = get_model('payment', 'PaymentProcessorResponse') Selector = get_class('partner.strategy', 'Selector') Source = get_model('payment', 'Source') post_checkout = get_class('checkout.signals', 'post_checkout') class LoginMixin(object): def setUp(self): super(LoginMixin, self).setUp() self.user = self.create_user() self.client.login(username=self.user.username, password=self.password)
import logging import time from django.contrib.sites.models import Site from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import NoReverseMatch, reverse from django.http import HttpResponseRedirect from django.conf import settings from oscar.core.compat import user_is_authenticated from oscar.core.loading import get_class, get_model OrderCreator = get_class('order.utils', 'OrderCreator') Dispatcher = get_class('customer.utils', 'Dispatcher') CheckoutSessionMixin = get_class('checkout.session', 'CheckoutSessionMixin') BillingAddress = get_model('order', 'BillingAddress') ShippingAddress = get_model('order', 'ShippingAddress') OrderNumberGenerator = get_class('order.utils', 'OrderNumberGenerator') PaymentEventType = get_model('order', 'PaymentEventType') PaymentEvent = get_model('order', 'PaymentEvent') PaymentEventQuantity = get_model('order', 'PaymentEventQuantity') UserAddress = get_model('address', 'UserAddress') Basket = get_model('basket', 'Basket') CommunicationEventType = get_model('customer', 'CommunicationEventType') UnableToPlaceOrder = get_class('order.exceptions', 'UnableToPlaceOrder') post_checkout = get_class('checkout.signals', 'post_checkout') # Standard logger for checkout events logger = logging.getLogger('oscar.checkout')
from django.template import RequestContext from django.core.urlresolvers import reverse, resolve from django.utils import simplejson as json from django.db.models import get_model from django.http import HttpResponseRedirect, Http404, HttpResponse from django.views.generic import FormView, View from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ObjectDoesNotExist from extra_views import ModelFormSetView from oscar.core import ajax from oscar.apps.basket.signals import basket_addition, voucher_addition from oscar.templatetags.currency_filters import currency from oscar.core.loading import get_class, get_classes Applicator = get_class('offer.utils', 'Applicator') (BasketLineForm, AddToBasketForm, BasketVoucherForm, SavedLineFormSet, SavedLineForm, ProductSelectionForm) = get_classes( 'basket.forms', ('BasketLineForm', 'AddToBasketForm', 'BasketVoucherForm', 'SavedLineFormSet', 'SavedLineForm', 'ProductSelectionForm')) Repository = get_class('shipping.repository', ('Repository')) def get_messages(basket, offers_before, offers_after, include_buttons=True): """ Return the messages about offer changes """ # Look for changes in offers offers_lost = set(offers_before.keys()).difference(set( offers_after.keys()))
from django.conf import settings from django.contrib import messages from django.utils.html import strip_tags from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from django.utils.translation import ngettext from django.views import generic from oscar.core.loading import get_class, get_model from oscar.core.utils import redirect_to_referrer from oscar.views.generic import BulkEditMixin PageTitleMixin = get_class('customer.mixins', 'PageTitleMixin') Notification = get_model('communication', 'Notification') class NotificationListView(PageTitleMixin, generic.ListView): model = Notification template_name = 'oscar/communication/notifications/list.html' context_object_name = 'notifications' paginate_by = settings.OSCAR_NOTIFICATIONS_PER_PAGE page_title = _("Notifications") active_tab = 'notifications' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx['list_type'] = self.list_type return ctx class InboxView(NotificationListView):
from urllib import unquote, urlencode import pytz from django.conf import settings from django.contrib import messages from django.db import transaction from django.utils.translation import ugettext_lazy as _ from oscar.core.loading import get_class, get_model from ecommerce.courses.utils import mode_for_product from ecommerce.extensions.order.exceptions import AlreadyPlacedOrderException from ecommerce.extensions.order.utils import UserAlreadyPlacedOrder from ecommerce.extensions.payment.utils import embargo_check from ecommerce.referrals.models import Referral Applicator = get_class('offer.applicator', 'Applicator') Basket = get_model('basket', 'Basket') BasketAttribute = get_model('basket', 'BasketAttribute') BasketAttributeType = get_model('basket', 'BasketAttributeType') BUNDLE = 'bundle_identifier' ORGANIZATION_ATTRIBUTE_TYPE = 'organization' StockRecord = get_model('partner', 'StockRecord') OrderLine = get_model('order', 'Line') Refund = get_model('refund', 'Refund') logger = logging.getLogger(__name__) def add_utm_params_to_url(url, params): # utm_params is [(u'utm_content', u'course-v1:IDBx IDB20.1x 1T2017'),... utm_params = [item for item in params if 'utm_' in item[0]]
from django.views.generic import DeleteView, FormView, ListView from oscar.core.loading import get_class, get_classes, get_model from oscar.views import sort_queryset ConditionalOffer = get_model('offer', 'ConditionalOffer') Condition = get_model('offer', 'Condition') Range = get_model('offer', 'Range') Product = get_model('catalogue', 'Product') OrderDiscount = get_model('order', 'OrderDiscount') Benefit = get_model('offer', 'Benefit') MetaDataForm, ConditionForm, BenefitForm, RestrictionsForm, OfferSearchForm \ = get_classes('dashboard.offers.forms', ['MetaDataForm', 'ConditionForm', 'BenefitForm', 'RestrictionsForm', 'OfferSearchForm']) OrderDiscountCSVFormatter = get_class('dashboard.offers.reports', 'OrderDiscountCSVFormatter') class OfferListView(ListView): model = ConditionalOffer context_object_name = 'offers' template_name = 'oscar/dashboard/offers/offer_list.html' form_class = OfferSearchForm paginate_by = settings.OSCAR_DASHBOARD_ITEMS_PER_PAGE def get_queryset(self): self.search_filters = [] qs = self.model._default_manager.all() qs = sort_queryset(qs, self.request, [ 'name', 'offer_type', 'start_datetime', 'end_datetime', 'num_applications', 'total_discount'
from django.conf import settings from django.contrib.sites.models import Site from django.db import transaction from django.utils.translation import gettext_lazy as _ from oscar.apps.order.signals import order_placed from oscar.core.loading import get_class, get_model from . import exceptions Order = get_model('order', 'Order') Line = get_model('order', 'Line') OrderDiscount = get_model('order', 'OrderDiscount') CommunicationEvent = get_model('order', 'CommunicationEvent') CommunicationEventType = get_model('communication', 'CommunicationEventType') Dispatcher = get_class('communication.utils', 'Dispatcher') Surcharge = get_model('order', 'Surcharge') class OrderNumberGenerator(object): """ 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): """ Return an order number for a given basket """ return 100000 + basket.id
from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ObjectDoesNotExist from django import forms from django.db.models import get_model from django.contrib.auth.models import User from django.contrib.auth import forms as auth_forms from django.conf import settings from django.core import validators from django.core.exceptions import ValidationError from django.contrib.sites.models import get_current_site from django.contrib.auth.tokens import default_token_generator from oscar.core.loading import get_profile_class, get_class from oscar.apps.customer.utils import get_password_reset_url Dispatcher = get_class('customer.utils', 'Dispatcher') CommunicationEventType = get_model('customer', 'communicationeventtype') ProductAlert = get_model('customer', 'ProductAlert') def generate_username(): uname = ''.join([random.choice(string.letters + string.digits + '_') for i in range(30)]) try: User.objects.get(username=uname) return generate_username() except User.DoesNotExist: return uname class PasswordResetForm(auth_forms.PasswordResetForm): communication_type_code = "PASSWORD_RESET"
from oscar.core.loading import get_class, get_model from oscar.test.factories import (CategoryFactory, PartnerFactory, ProductAttributeFactory, ProductFactory, create_product) from oscar.test.testcases import WebTestCase, add_permissions Product = get_model('catalogue', 'Product') ProductClass = get_model('catalogue', 'ProductClass') ProductCategory = get_model('catalogue', 'ProductCategory') Category = get_model('catalogue', 'Category') StockRecord = get_model('partner', 'stockrecord') AttributeOptionGroup = get_model('catalogue', 'AttributeOptionGroup') AttributeOption = get_model('catalogue', 'AttributeOption') AttributeOptionGroupForm = get_class('dashboard.catalogue.forms', 'AttributeOptionGroupForm') AttributeOptionFormSet = get_class('dashboard.catalogue.formsets', 'AttributeOptionFormSet') RelatedFieldWidgetWrapper = get_class('dashboard.widgets', 'RelatedFieldWidgetWrapper') class TestCatalogueViews(WebTestCase): is_staff = True def test_exist(self): urls = [ reverse('dashboard:catalogue-product-list'), reverse('dashboard:catalogue-category-list'), reverse('dashboard:stock-alert-list') ]