Esempio n. 1
0
def send_course_purchase_email(sender, order=None, **kwargs):  # pylint: disable=unused-argument
    """Send course purchase notification email when a course is purchased."""
    if waffle.switch_is_active('ENABLE_NOTIFICATIONS'):
        # We do not currently support email sending for orders with more than one item.
        if len(order.lines.all()) == ORDER_LINE_COUNT:
            product = order.lines.first().product
            provider_id = getattr(product.attr, 'credit_provider', None)
            if not provider_id:
                stripped_title = product.title.replace("Seat in ", "", 1)
                stripped_title = stripped_title.replace(
                    "with professional certificate", "")
                stripped_title = stripped_title.replace(
                    "with verified certificate", "")
                send_notification(
                    order.user, 'CREDIT_RECEIPT', {
                        'course_title':
                        stripped_title,
                        'receipt_page_url':
                        get_lms_url('{}?orderNum={}'.format(
                            settings.RECEIPT_PAGE_PATH, order.number)),
                        'credit_hours':
                        str(order.total_excl_tax),
                        'credit_provider':
                        'Credit provider',
                    },
                    threadlocals.get_current_request().site)
                logger.error(
                    'Failed to send credit receipt notification. Credit seat product [%s] has no provider.',
                    product.id)
                return

            elif product.get_product_class().name == 'Seat':
                provider_data = get_provider_data(provider_id)
                if provider_data:
                    send_notification(
                        order.user, 'CREDIT_RECEIPT', {
                            'course_title':
                            product.title,
                            'receipt_page_url':
                            get_lms_url('{}?orderNum={}'.format(
                                settings.RECEIPT_PAGE_PATH, order.number)),
                            'credit_hours':
                            product.attr.credit_hours,
                            'credit_provider':
                            provider_data['display_name'],
                        },
                        threadlocals.get_current_request().site)

        else:
            logger.info(
                'Currently support receipt emails for order with one item.')
Esempio n. 2
0
File: update.py Progetto: rpavez/edd
 def load_update(cls, user=None, path=None):
     """
     Sometimes there will be actions happening outside the context of a request; use this
     factory to create an Update object in those cases.
     :param user: the user responsible for the update; None will be replaced with the
         system user.
     :param path: the path added to the update; it would be a good idea to put e.g. the
         script name and arguments here.
     :return: an Update instance persisted to the database
     """
     User = get_user_model()
     request = get_current_request()
     if request is None:
         mod_by = user
         if mod_by is None:
             mod_by = User.system_user()
         update = cls.objects.create(
             mod_time=arrow.utcnow(),
             mod_by=mod_by,
             path=path,
             origin='localhost',
         )
     else:
         update = cls.load_request_update(request)
     return update
Esempio n. 3
0
    def catalog_contains_product(self, product):
        """
        Retrieve the results from using the catalog contains endpoint for
        catalog service for the catalog id contained in field "course_catalog".
        """
        request = get_current_request()
        partner_code = request.site.siteconfiguration.partner.short_code
        cache_key = get_cache_key(site_domain=request.site.domain,
                                  partner_code=partner_code,
                                  resource='catalogs.contains',
                                  course_id=product.course_id,
                                  catalog_id=self.course_catalog)
        cached_response = TieredCache.get_cached_response(cache_key)
        if cached_response.is_found:
            return cached_response.value

        discovery_api_client = request.site.siteconfiguration.discovery_api_client
        try:
            # GET: /api/v1/catalogs/{catalog_id}/contains?course_run_id={course_run_ids}
            response = discovery_api_client.catalogs(
                self.course_catalog).contains.get(
                    course_run_id=product.course_id)

            TieredCache.set_all_tiers(cache_key, response,
                                      settings.COURSES_API_CACHE_TIMEOUT)
            return response
        except (ReqConnectionError, SlumberBaseException, Timeout) as exc:
            logger.exception(
                '[Code Redemption Failure] Unable to connect to the Discovery Service '
                'for catalog contains endpoint. '
                'Product: %s, Message: %s, Range: %s', product.id, exc,
                self.id)
            raise Exception(
                'Unable to connect to Discovery Service for catalog contains endpoint.'
            ) from exc
Esempio n. 4
0
def filter_students():
    request = get_current_request()
    print(request.META['PATH_INFO'])
    topics = TopicInterest.objects.all()
    students = [t.student for t in topics]

    from urllib.parse import urlparse
    parsed = urlparse(request.META['PATH_INFO'])
    print('scheme  :', parsed.scheme)
    print('netloc  :', parsed.netloc)
    print('path    :', parsed.path)
    print('params  :', parsed.params)
    print('query   :', parsed.query)
    print('fragment:', parsed.fragment)
    print('username:'******'password:'******'hostname:', parsed.hostname)
    print('port    :', parsed.port)
    numbers = re.findall('\d+', parsed.path)
    print('NUMBER ' + str(numbers))
    print('request')
    print(request)
    a = Topic.objects.filter(Q(supervisor=request.user))
    print(a)
    if len(numbers) > 0:
        topic = Topic.objects.get(pk=numbers[0])
        ti = TopicInterest.objects.filter(topic=topic)
        print('ti')
        print(ti)
        print('pk')
    else:
        ti = ""
    return {'topicinterest__in': ti}
Esempio n. 5
0
    def contains_product(self, product):
        """
        Assert if the range contains the product.
        """
        if self.course_catalog:
            request = get_current_request()
            try:
                course_catalog = get_course_catalogs(site=request.site, resource_id=self.course_catalog)
            except (ConnectionError, SlumberBaseException, Timeout):
                raise Exception(
                    'Unable to connect to Course Catalog service for catalog with id [%s].' % self.course_catalog
                )

            response = self.run_catalog_query(product, course_catalog.get('query'))
            # Range can have a catalog query and 'regular' products in it,
            # therefor an OR is used to check for both possibilities.
            return ((response['course_runs'][product.course_id]) or
                    super(Range, self).contains_product(product))  # pylint: disable=bad-super-call
        elif self.catalog_query and self.course_seat_types:
            if product.attr.certificate_type.lower() in self.course_seat_types:  # pylint: disable=unsupported-membership-test
                response = self.run_catalog_query(product)
                # Range can have a catalog query and 'regular' products in it,
                # therefor an OR is used to check for both possibilities.
                return ((response['course_runs'][product.course_id]) or
                        super(Range, self).contains_product(product))  # pylint: disable=bad-super-call
        elif self.catalog:
            return (
                product.id in self.catalog.stock_records.values_list('product', flat=True) or
                super(Range, self).contains_product(product)  # pylint: disable=bad-super-call
            )
        return super(Range, self).contains_product(product)  # pylint: disable=bad-super-call
Esempio n. 6
0
def render_explain_test(explanation: backend.core.visitor.TestExplanationPage):
    context = {
        'foreword': explanation.foreword.split("\n"),
        'url_name_to_go_to': explanation.url_name_to_go_to,
        'btn_text': explanation.btn_text,
    }
    return render(get_current_request(), 'explain_test.html', context)
Esempio n. 7
0
    def run_catalog_query(self, product):
        """
        Retrieve the results from running the query contained in catalog_query field.
        """
        request = get_current_request()
        partner_code = request.site.siteconfiguration.partner.short_code
        cache_key = get_cache_key(
            site_domain=request.site.domain,
            partner_code=partner_code,
            resource='course_runs.contains',
            course_id=product.course_id,
            query=self.catalog_query
        )
        response = cache.get(cache_key)
        if not response:  # pragma: no cover
            try:
                response = request.site.siteconfiguration.course_catalog_api_client.course_runs.contains.get(
                    query=self.catalog_query,
                    course_run_ids=product.course_id,
                    partner=partner_code
                )
                cache.set(cache_key, response, settings.COURSES_API_CACHE_TIMEOUT)
            except:  # pylint: disable=bare-except
                raise Exception('Could not contact Course Catalog Service.')

        return response
Esempio n. 8
0
def render_test_score(test_score: tuple):
    start_score, final_score = test_score
    context = {
        'start_score': start_score,
        'final_score': final_score,
    }
    return render(get_current_request(), 'test.html', context)
Esempio n. 9
0
def send_course_purchase_email(sender, order=None, **kwargs):  # pylint: disable=unused-argument
    """Send course purchase notification email when a course is purchased."""
    if waffle.switch_is_active('ENABLE_NOTIFICATIONS'):
        # We do not currently support email sending for orders with more than one item.
        if len(order.lines.all()) == ORDER_LINE_COUNT:
            product = order.lines.first().product
            provider_id = getattr(product.attr, 'credit_provider', None)
            if not provider_id:
                logger.error(
                    'Failed to send credit receipt notification. Credit seat product [%s] has not provider.', product.id
                )
                return
            elif product.get_product_class().name == 'Seat':
                provider_data = get_provider_data(provider_id)
                if provider_data:
                    send_notification(
                        order.user,
                        'CREDIT_RECEIPT',
                        {
                            'course_title': product.title,
                            'receipt_page_url': get_lms_url(
                                '{}?orderNum={}'.format(settings.RECEIPT_PAGE_PATH, order.number)
                            ),
                            'credit_hours': product.attr.credit_hours,
                            'credit_provider': provider_data['display_name'],
                        },
                        threadlocals.get_current_request().site
                    )

        else:
            logger.info('Currently support receipt emails for order with one item.')
Esempio n. 10
0
    def catalog_contains_product(self, product):
        """
        Retrieve the results from using the catalog contains endpoint for
        catalog service for the catalog id contained in field "course_catalog".
        """
        request = get_current_request()
        partner_code = request.site.siteconfiguration.partner.short_code
        cache_key = get_cache_key(site_domain=request.site.domain,
                                  partner_code=partner_code,
                                  resource='catalogs.contains',
                                  course_id=product.course_id,
                                  catalog_id=self.course_catalog)
        response = cache.get(cache_key)
        if not response:
            discovery_api_client = request.site.siteconfiguration.discovery_api_client
            try:
                # GET: /api/v1/catalogs/{catalog_id}/contains?course_run_id={course_run_ids}
                response = discovery_api_client.catalogs(
                    self.course_catalog).contains.get(
                        course_run_id=product.course_id)
                cache.set(cache_key, response,
                          settings.COURSES_API_CACHE_TIMEOUT)
            except (ConnectionError, SlumberBaseException, Timeout):
                raise Exception(
                    'Unable to connect to Discovery Service for catalog contains endpoint.'
                )

        return response
Esempio n. 11
0
def get_mongo_db_name():
    req = get_current_request()
    if req:
        mapper = get_mapper()
        db = mapper.get_dbname(req)
    else:
        db = settings.DOC_STORE_CONFIG.get("db")
    return db
Esempio n. 12
0
 def test_process_request(self):
     """
     if ThreadLocalMiddleware is enabled in settings, then running the test client
     should trigger the middleware and set the request in thread locals
     """
     client = Client()
     client.get(u'/')
     self.assertEqual(get_current_request().path, u'/')
Esempio n. 13
0
def render_register_visitor(empty_field: bool = False,
                            invalid_code: bool = False):

    context = {
        "empty_field": empty_field,
        "invalid_code": invalid_code,
    }
    return render(get_current_request(), 'register_visitor.html', context)
Esempio n. 14
0
 def test_process_request(self):
     """
     if ThreadLocalMiddleware is enabled in settings, then running the test client
     should trigger the middleware and set the request in thread locals
     """
     client = Client()
     client.get(u'/')
     self.assertEqual(get_current_request().path, u'/')
Esempio n. 15
0
 def all_products(self):
     request = get_current_request()
     if self.catalog_query and self.course_seat_types:
         products = get_seats_from_query(request.site, self.catalog_query, self.course_seat_types)
         return products + list(super(Range, self).all_products())  # pylint: disable=bad-super-call
     if self.catalog:
         catalog_products = [record.product for record in self.catalog.stock_records.all()]
         return catalog_products + list(super(Range, self).all_products())  # pylint: disable=bad-super-call
     return super(Range, self).all_products()  # pylint: disable=bad-super-call
Esempio n. 16
0
    def __init__(self, *args, **kwargs):
        super(MothertongueModelTranslate, self).__init__(*args, **kwargs)
        self._translation_cache = {}

        # Added by Raw Jam 06/11/2015 to prevent issues when editing these models in
        # the admin, with the non default language in use.
        request = get_current_request()
        if request.user.is_staff and "PATH_INFO" in request.META and "/admin/" in request.META['PATH_INFO']:
            self._allow_translate = False
Esempio n. 17
0
def get_now():
    """ """
    # Allow access global request and read a timestamp from query...
    request = get_current_request()
    if request:
        openinghours_now = request.GET.get("openinghours-now")
        if openinghours_now:
            return datetime.datetime.strptime(openinghours_now, "%Y%m%d%H%M%S")
    return datetime.datetime.now()
Esempio n. 18
0
 def test_process_request(self):
     """
     if ThreadLocalMiddleware is enabled in settings, then running the test client
     should trigger the middleware and set the request in thread locals
     """
     response = self.client.get(''.join([reverse('query'), '?query=test']))
     self.assertEqual(response.content.decode('utf8'), u"{'query': 'test'}")
     # No formal way to order tests, so verify request is deleted here.
     self.assertEqual(get_current_request(), None)
 def test_core(self):
     request = get_current_request()
     self.assertDictEqual(
         core(request), {
             'lms_base_url': get_lms_url(),
             'lms_dashboard_url': get_lms_dashboard_url(),
             'platform_name': request.site.name,
             'support_url': SUPPORT_URL
         })
Esempio n. 20
0
    def get_expected_transaction_parameters(self, transaction_uuid, include_level_2_3_details=True):
        """
        Builds expected transaction parameters dictionary
        """
        configuration = settings.PAYMENT_PROCESSOR_CONFIG['edx'][self.processor_name]
        access_key = configuration['access_key']
        profile_id = configuration['profile_id']

        expected = {
            'access_key': access_key,
            'profile_id': profile_id,
            'signed_field_names': '',
            'unsigned_field_names': '',
            'signed_date_time': self.PI_DAY.strftime(ISO_8601_FORMAT),
            'locale': settings.LANGUAGE_CODE,
            'transaction_type': 'sale',
            'reference_number': self.basket.order_number,
            'amount': unicode(self.basket.total_incl_tax),
            'currency': self.basket.currency,
            'consumer_id': self.basket.owner.username,
            'override_custom_receipt_page': '{}?orderNum={}'.format(self.processor.receipt_page_url,
                                                                    self.basket.order_number),
            'override_custom_cancel_page': self.processor.cancel_page_url,
            'merchant_defined_data1': self.course.id,
            'merchant_defined_data2': self.CERTIFICATE_TYPE,
        }

        if include_level_2_3_details:
            expected.update({
                'line_item_count': self.basket.lines.count(),
                'amex_data_taa1': get_current_request().site.name,
                'purchasing_level': '3',
                'user_po': 'BLANK',
            })

            for index, line in enumerate(self.basket.lines.all()):
                expected['item_{}_code'.format(index)] = line.product.get_product_class().slug
                expected['item_{}_discount_amount '.format(index)] = str(line.discount_value)
                expected['item_{}_gross_net_indicator'.format(index)] = 'Y'
                expected['item_{}_name'.format(index)] = line.product.title
                expected['item_{}_quantity'.format(index)] = line.quantity
                expected['item_{}_sku'.format(index)] = line.stockrecord.partner_sku
                expected['item_{}_tax_amount'.format(index)] = str(line.line_tax)
                expected['item_{}_tax_rate'.format(index)] = '0'
                expected['item_{}_total_amount '.format(index)] = str(line.line_price_incl_tax_incl_discounts)
                expected['item_{}_unit_of_measure'.format(index)] = 'ITM'
                expected['item_{}_unit_price'.format(index)] = str(line.unit_price_incl_tax)

        signed_field_names = expected.keys() + ['transaction_uuid']
        expected['signed_field_names'] = ','.join(sorted(signed_field_names))

        # Copy the UUID value so that we can properly generate the signature. We will validate the UUID below.
        expected['transaction_uuid'] = transaction_uuid
        expected['signature'] = self.generate_signature(self.processor.secret_key, expected)

        return expected
Esempio n. 21
0
def get_now():
    """ """
    # Allow access global request and read a timestamp from query...
    # I'm not exactly sure what you were trying to do here so I left it. - JJ
    if "get_current_request" is not None:
        request = get_current_request()
        openinghours_now = request.GET.get("openinghours-now")
        if openinghours_now:
            return datetime.datetime.strptime(openinghours_now, "%Y%m%d%H%M%S")
    return datetime.datetime.now()
Esempio n. 22
0
    def create_order_model(self, user, basket, shipping_address,
                           shipping_method, shipping_charge, billing_address,
                           total, order_number, status, **extra_order_fields):
        """
        Create an order model.

        This override ensures the order's site is set to that of the basket. If the basket has no site, the default
        site is used. The site value can be overridden by setting the `site` kwarg.
        """

        # If a site was not passed in with extra_order_fields,
        # use the basket's site if it has one, else get the site
        # from the current request.
        site = basket.site
        if not site:
            site = get_current_request().site

        order_data = {
            'basket': basket,
            'number': order_number,
            'site': site,
            'currency': total.currency,
            'total_incl_tax': total.incl_tax,
            'total_excl_tax': total.excl_tax,
            'shipping_incl_tax': shipping_charge.incl_tax,
            'shipping_excl_tax': shipping_charge.excl_tax,
            'shipping_method': shipping_method.name,
            'shipping_code': shipping_method.code
        }
        if shipping_address:
            order_data['shipping_address'] = shipping_address
        if billing_address:
            order_data['billing_address'] = billing_address
        if user and user.is_authenticated():
            order_data['user_id'] = user.id
        if status:
            order_data['status'] = status
        if extra_order_fields:
            order_data.update(extra_order_fields)
        order = Order(**order_data)
        order.save()

        try:
            referral = Referral.objects.get(basket=basket)
            referral.order = order
            referral.save()
        except Referral.DoesNotExist:
            logger.debug(
                'Order [%d] has no referral associated with its basket.',
                order.id)
        except Exception:  # pylint: disable=broad-except
            logger.exception('Referral for Order [%d] failed to save.',
                             order.id)

        return order
Esempio n. 23
0
def get_absolute_url(relative_url):
    """
    Computes the absolute URL for the specified relative URL.
    :param relative_url: the relative URL
    :return: the absolute URL
    """
    current_request = get_current_request()
    protocol = 'https://'
    if current_request and not current_request.is_secure():
        protocol = 'http://'
    return protocol + Site.objects.get_current().domain + relative_url
 def test_core(self):
     request = get_current_request()
     self.assertDictEqual(
         core(request),
         {
             'lms_base_url': get_lms_url(),
             'lms_dashboard_url': get_lms_dashboard_url(),
             'platform_name': request.site.name,
             'support_url': SUPPORT_URL
         }
     )
Esempio n. 25
0
def get_current_site():
    """
    Return current site.

    Returns:
         (django.contrib.sites.models.Site): current site
    """
    request = get_current_request()
    if not request:
        return None
    return getattr(request, 'site', None)
Esempio n. 26
0
 def test_core(self):
     request = get_current_request()
     self.assertDictEqual(
         core(request),
         {
             'lms_base_url': get_lms_url(),
             'lms_dashboard_url': get_lms_dashboard_url(),
             'platform_name': request.site.name,
             'support_url': request.site.siteconfiguration.payment_support_url,
         }
     )
Esempio n. 27
0
 def run_catalog_query(self, product):
     """
     Retrieve the results from running the query contained in catalog_query field.
     """
     request = get_current_request()
     try:
         response = request.site.siteconfiguration.course_catalog_api_client.course_runs.contains.get(
             query=self.catalog_query, course_run_ids=product.course_id)
     except:  # pylint: disable=bare-except
         raise Exception('Could not contact Course Catalog Service.')
     return response
Esempio n. 28
0
def get_current_site():
    """
    Return current site.

    Returns:
         (django.contrib.sites.models.Site): current site
    """
    request = get_current_request()
    if not request:
        return None
    return getattr(request, 'site', None)
def get_lms_url(path=''):
    """
    Returns path joined with the appropriate LMS URL root for the current site

    Raises:
        MissingRequestError: If the current ecommerce site is not in threadlocal storage
    """
    request = get_current_request()
    if request:
        return urljoin(request.site.siteconfiguration.lms_url_root, path)
    raise MissingRequestError
Esempio n. 30
0
def send_update_message(receiver_id, sender_id):
    receiver_id = int(receiver_id)
    sender_id = int(sender_id)
    request = get_current_request()
    messages = Message.objects.filter(receiver=request.user, status=False)
    message_data = {}
    message_data['incoming'] = {receiver_id: messages.count()}
    to_user = {}
    to_user['id'] = receiver_id
    to_user['count'] = 0
    message_data[receiver_id] = {sender_id: to_user}
    r.publish('users', json.dumps(message_data, cls=DjangoJSONEncoder))
Esempio n. 31
0
 def get_theme_template_sources():
     """
     Return template sources for the given theme and if request object is None (this would be the case for
     management commands) return template sources for all themes.
     """
     if not get_current_request():
         # if request object is not present, then this method is being called inside a management
         # command and return all theme template sources for compression
         return get_all_theme_template_dirs()
     else:
         # template is being accessed by a view, so return templates sources for current theme
         return get_current_theme_template_dirs()
Esempio n. 32
0
 def all_products(self):
     request = get_current_request()
     if self.catalog_query and self.course_seat_types:
         products = get_seats_from_query(request.site, self.catalog_query,
                                         self.course_seat_types)
         return products + list(super(Range, self).all_products())  # pylint: disable=bad-super-call
     if self.catalog:
         catalog_products = [
             record.product for record in self.catalog.stock_records.all()
         ]
         return catalog_products + list(super(Range, self).all_products())  # pylint: disable=bad-super-call
     return super(Range, self).all_products()  # pylint: disable=bad-super-call
def get_ecommerce_url(path=''):
    """
    Returns path joined with the appropriate ecommerce URL root for the current site

    Raises:
        MissingRequestError: If the current ecommerce site is not in threadlocal storage
    """
    request = get_current_request()
    if request:
        ecommerce_url_root = "{}://{}".format(request.scheme, request.site.domain)
        return urljoin(ecommerce_url_root, path)
    raise MissingRequestError
Esempio n. 34
0
def get_now():
    """
    Allows to access global request and read a timestamp from query.
    """
    if not get_current_request:
        return datetime.datetime.now()
    request = get_current_request()
    if request:
        openinghours_now = request.GET.get('openinghours-now')
        if openinghours_now:
            return datetime.datetime.strptime(openinghours_now, '%Y%m%d%H%M%S')
    return datetime.datetime.now()
Esempio n. 35
0
	def canManage(self, logged_user=None):
		"""
		Is the logged in user a enso user, or manager in the company
		"""

		if logged_user == None:
			logged_user = get_current_request().user

		if not logged_user.isEnsoUser():
			if not logged_user.isManager() or logged_user.company.pk != self.owner.company.pk:
				return False

		return True
Esempio n. 36
0
 def run_catalog_query(self, product):
     """
     Retrieve the results from running the query contained in catalog_query field.
     """
     request = get_current_request()
     try:
         response = request.site.siteconfiguration.course_catalog_api_client.course_runs.contains.get(
             query=self.catalog_query,
             course_run_ids=product.course_id
         )
     except:  # pylint: disable=bare-except
         raise Exception('Could not contact Course Catalog Service.')
     return response
Esempio n. 37
0
def render_challenge(challenge: backend.core.visitor.Challenge,
                     is_failure: bool = None,
                     with_error: str = None):

    context = {
        'question': challenge.question.question_text.split("\n"),
        'answers': challenge.answers,
        'explanation': challenge.question.explanation_text.split("\n"),
        'disclose_answers': challenge.disclose_answers,
        'is_failure': is_failure,
        'error_msg': with_error,
    }
    return render(get_current_request(), 'drill_topic.html', context)
Esempio n. 38
0
File: query.py Progetto: JBEI/edd
def get_absolute_url(relative_url):
    """
    Computes the absolute URL for the specified relative URL.

    :param relative_url: the relative URL
    :return: the absolute URL
    """
    current_request = get_current_request()
    site = Site.objects.get_current()
    protocol = "https"
    if current_request and not current_request.is_secure():
        protocol = "http"
    return f"{protocol}://{site.domain}{relative_url}"
Esempio n. 39
0
 def get_current_user(cls):
     """
     Inspect the threadlocal variable for the current request, and extract
     the current user. If none is found, return the system user.
     """
     User = get_user_model()
     request = get_current_request()
     current = None
     if request is not None:
         current = request.user
     if not isinstance(current, User):
         # any None or AnonymousUser gets replaced with system user
         return User.system_user()
     return current
Esempio n. 40
0
    def test_post_checkout_callback(self):
        """
        When the post_checkout signal is emitted, the receiver should attempt
        to fulfill the newly-placed order and send receipt email.
        """
        httpretty.register_uri(httpretty.GET,
                               get_lms_url('api/credit/v1/providers/ASU'),
                               body='{"display_name": "Hogwarts"}',
                               content_type="application/json")
        toggle_switch('ENABLE_NOTIFICATIONS', True)
        course = Course.objects.create(id='edX/DemoX/Demo_Course',
                                       name='Demo Course')
        seat = course.create_or_update_seat('credit', False, 50, self.partner,
                                            'ASU', None, 2)

        basket = BasketFactory()
        basket.add_product(seat, 1)
        order = factories.create_order(number=1, basket=basket, user=self.user)
        with mock.patch(
                'threadlocals.threadlocals.get_current_request') as mock_gcr:
            mock_gcr.return_value = self.request
            send_course_purchase_email(None, order=order)
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].from_email,
                         self.site_configuration.from_email)
        self.assertEqual(mail.outbox[0].subject, 'Order Receipt')
        self.assertEqual(
            mail.outbox[0].body, '\nPayment confirmation for: {course_title}'
            '\n\nDear {full_name},'
            '\n\nThank you for purchasing {credit_hours} credit hours from {credit_provider} for {course_title}. '
            'A charge will appear on your credit or debit card statement with a company name of "{platform_name}".'
            '\n\nTo receive your course credit, you must also request credit at the {credit_provider} website. '
            'For a link to request credit from {credit_provider}, or to see the status of your credit request, '
            'go to your {platform_name} dashboard.'
            '\n\nTo explore other credit-eligible courses, visit the {platform_name} website. '
            'We add new courses frequently!'
            '\n\nTo view your payment information, visit the following website.'
            '\n{receipt_url}'
            '\n\nThank you. We hope you enjoyed your course!'
            '\nThe {platform_name} team'
            '\n\nYou received this message because you purchased credit hours for {course_title}, '
            'an {platform_name} course.\n'.format(
                course_title=order.lines.first().product.title,
                full_name=self.user.get_full_name(),
                credit_hours=2,
                credit_provider='Hogwarts',
                platform_name=get_current_request().site.name,
                receipt_url=get_lms_url('{}?orderNum={}'.format(
                    settings.RECEIPT_PAGE_PATH, order.number))))
Esempio n. 41
0
    def create_order_model(self, user, basket, shipping_address, shipping_method, shipping_charge, billing_address,
                           total, order_number, status, **extra_order_fields):
        """
        Create an order model.

        This override ensures the order's site is set to that of the basket. If the basket has no site, the default
        site is used. The site value can be overridden by setting the `site` kwarg.
        """

        # If a site was not passed in with extra_order_fields,
        # use the basket's site if it has one, else get the site
        # from the current request.
        site = basket.site
        if not site:
            site = get_current_request().site

        order_data = {'basket': basket,
                      'number': order_number,
                      'site': site,
                      'currency': total.currency,
                      'total_incl_tax': total.incl_tax,
                      'total_excl_tax': total.excl_tax,
                      'shipping_incl_tax': shipping_charge.incl_tax,
                      'shipping_excl_tax': shipping_charge.excl_tax,
                      'shipping_method': shipping_method.name,
                      'shipping_code': shipping_method.code}
        if shipping_address:
            order_data['shipping_address'] = shipping_address
        if billing_address:
            order_data['billing_address'] = billing_address
        if user and user.is_authenticated():
            order_data['user_id'] = user.id
        if status:
            order_data['status'] = status
        if extra_order_fields:
            order_data.update(extra_order_fields)
        order = Order(**order_data)
        order.save()

        try:
            referral = Referral.objects.get(basket=basket)
            referral.order = order
            referral.save()
        except Referral.DoesNotExist:
            logger.debug('Order [%d] has no referral associated with its basket.', order.id)
        except Exception:  # pylint: disable=broad-except
            logger.exception('Referral for Order [%d] failed to save.', order.id)

        return order
Esempio n. 42
0
def get_current_site_theme():
    """
    Return current site theme object. Returns None if theming is disabled.

    Returns:
         (ecommerce.theming.models.SiteTheme): site theme object for the current site.
    """
    # Return None if theming is disabled
    if not is_comprehensive_theming_enabled():
        return None

    request = get_current_request()
    if not request:
        return None
    return getattr(request, 'site_theme', None)
Esempio n. 43
0
def get_current_site_theme():
    """
    Return current site theme object. Returns None if theming is disabled.

    Returns:
         (ecommerce.theming.models.SiteTheme): site theme object for the current site.
    """
    # Return None if theming is disabled
    if not is_comprehensive_theming_enabled():
        return None

    request = get_current_request()
    if not request:
        return None
    return getattr(request, 'site_theme', None)
Esempio n. 44
0
    def test_post_checkout_callback(self):
        """
        When the post_checkout signal is emitted, the receiver should attempt
        to fulfill the newly-placed order and send receipt email.
        """
        httpretty.register_uri(
            httpretty.GET, get_lms_url('api/credit/v1/providers/ASU'),
            body='{"display_name": "Hogwarts"}',
            content_type="application/json"
        )
        toggle_switch('ENABLE_NOTIFICATIONS', True)
        course = Course.objects.create(id='edX/DemoX/Demo_Course', name='Demo Course')
        seat = course.create_or_update_seat('credit', False, 50, self.partner, 'ASU', None, 2)

        basket = BasketFactory()
        basket.add_product(seat, 1)
        order = factories.create_order(number=1, basket=basket, user=self.user)
        with mock.patch('threadlocals.threadlocals.get_current_request') as mock_gcr:
            mock_gcr.return_value = self.request
            send_course_purchase_email(None, order=order)
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].from_email, self.site_configuration.from_email)
        self.assertEqual(mail.outbox[0].subject, 'Order Receipt')
        self.assertEqual(
            mail.outbox[0].body,
            '\nPayment confirmation for: {course_title}'
            '\n\nDear {full_name},'
            '\n\nThank you for purchasing {credit_hours} credit hours from {credit_provider} for {course_title}. '
            'A charge will appear on your credit or debit card statement with a company name of "{platform_name}".'
            '\n\nTo receive your course credit, you must also request credit at the {credit_provider} website. '
            'For a link to request credit from {credit_provider}, or to see the status of your credit request, '
            'go to your {platform_name} dashboard.'
            '\n\nTo explore other credit-eligible courses, visit the {platform_name} website. '
            'We add new courses frequently!'
            '\n\nTo view your payment information, visit the following website.'
            '\n{receipt_url}'
            '\n\nThank you. We hope you enjoyed your course!'
            '\nThe {platform_name} team'
            '\n\nYou received this message because you purchased credit hours for {course_title}, '
            'an {platform_name} course.\n'.format(
                course_title=order.lines.first().product.title,
                full_name=self.user.get_full_name(),
                credit_hours=2,
                credit_provider='Hogwarts',
                platform_name=get_current_request().site.name,
                receipt_url=get_lms_url('{}?orderNum={}'.format(settings.RECEIPT_PAGE_PATH, order.number))
            )
        )
Esempio n. 45
0
def get_now():
    """
    Allows to access global request and read a timestamp from query.
    """
    if not get_current_request:
        return timezone.now()

    request = get_current_request()
    if request:
        openinghours_now = request.GET.get("openinghours-now")

        if openinghours_now:
            return datetime.datetime.strptime(
                timezone.localtime(openinghours_now), "%Y%m%d%H%M%S")

    return timezone.now()
Esempio n. 46
0
    def configuration(self):
        """
        Returns the configuration (set in Django settings) specific to this payment processor.

        Returns:
            dict: Payment processor configuration

        Raises:
            KeyError: If no settings found for this payment processor
            MissingRequestError: if no `request` is available
        """
        request = get_current_request()
        if request:
            partner_short_code = request.site.siteconfiguration.partner.short_code
            return settings.PAYMENT_PROCESSOR_CONFIG[partner_short_code.lower()][self.NAME.lower()]
        raise MissingRequestError
Esempio n. 47
0
def _get_site_configuration():
    """ Retrieve the SiteConfiguration from the current request from the global thread.

    Notes:
        This is a stopgap. Do NOT use this with any expectation that it will remain in place.
        This function WILL be removed.
    """
    warnings.warn('Usage of _get_site_configuration and django-threadlocals is deprecated. '
                  'Use the helper methods on the SiteConfiguration model.', DeprecationWarning)

    request = get_current_request()

    if request:
        return request.site.siteconfiguration

    raise MissingRequestError
Esempio n. 48
0
def _get_site_configuration():
    """ Retrieve the SiteConfiguration from the current request from the global thread.

    Notes:
        This is a stopgap. Do NOT use this with any expectation that it will remain in place.
        This function WILL be removed.
    """
    warnings.warn('Usage of _get_site_configuration and django-threadlocals is deprecated. '
                  'Use the helper methods on the SiteConfiguration model.', DeprecationWarning)

    request = get_current_request()

    if request:
        return request.site.siteconfiguration

    raise MissingRequestError
Esempio n. 49
0
    def order_number(self, basket):
        """
        Returns an order number, determined using the basket's ID and site.

        Arguments:
            basket (Basket)

        Returns:
            string: Order number
        """
        site = basket.site
        if not site:
            site = get_current_request().site
            logger.warning('Basket [%d] is not associated with a Site. Defaulting to Site [%d].', basket.id, site.id)

        partner = site.siteconfiguration.partner
        return self.order_number_from_basket_id(partner, basket.id)
Esempio n. 50
0
    def run_catalog_query(self, product):
        """
        Retrieve the results from running the query contained in catalog_query field.
        """
        cache_key = 'catalog_query_contains [{}] [{}]'.format(self.catalog_query, product.course_id)
        cache_hash = hashlib.md5(cache_key).hexdigest()
        response = cache.get(cache_hash)
        if not response:  # pragma: no cover
            request = get_current_request()
            try:
                response = request.site.siteconfiguration.course_catalog_api_client.course_runs.contains.get(
                    query=self.catalog_query,
                    course_run_ids=product.course_id
                )
                cache.set(cache_hash, response, settings.COURSES_API_CACHE_TIMEOUT)
            except:  # pylint: disable=bare-except
                raise Exception('Could not contact Course Catalog Service.')

        return response
Esempio n. 51
0
    def create_order_model(self, user, basket, shipping_address, shipping_method, shipping_charge, billing_address,
                           total, order_number, status, **extra_order_fields):
        """
        Create an order model.

        This override ensures the order's site is set to that of the basket. If the basket has no site, the default
        site is used. The site value can be overridden by setting the `site` kwarg.
        """

        # If a site was not passed in with extra_order_fields,
        # use the basket's site if it has one, else get the site
        # from the current request.
        site = basket.site
        if not site:
            site = get_current_request().site

        order_data = {'basket': basket,
                      'number': order_number,
                      'site': site,
                      'currency': total.currency,
                      'total_incl_tax': total.incl_tax,
                      'total_excl_tax': total.excl_tax,
                      'shipping_incl_tax': shipping_charge.incl_tax,
                      'shipping_excl_tax': shipping_charge.excl_tax,
                      'shipping_method': shipping_method.name,
                      'shipping_code': shipping_method.code}
        if shipping_address:
            order_data['shipping_address'] = shipping_address
        if billing_address:
            order_data['billing_address'] = billing_address
        if user and user.is_authenticated():
            order_data['user_id'] = user.id
        if status:
            order_data['status'] = status
        if extra_order_fields:
            order_data.update(extra_order_fields)
        order = Order(**order_data)
        order.save()
        return order
Esempio n. 52
0
def is_comprehensive_theming_enabled():
    """
    Returns boolean indicating whether theming is enabled or disabled.

    Example:
        >> is_comprehensive_theming_enabled()
        True

    Returns:
         (bool): True if theming is enabled else False
    """

    # Return False if theming is disabled via Django settings
    if not settings.ENABLE_COMPREHENSIVE_THEMING:
        return False

    # Return False if we're currently processing a request and theming is disabled via runtime switch
    if bool(get_current_request()) and waffle.switch_is_active(settings.DISABLE_THEMING_ON_RUNTIME_SWITCH):
        return False

    # Return True indicating theming is enabled
    return True
Esempio n. 53
0
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            TenantUserModel = get_tenant_user_model()
            request = get_current_request()

            extra_kwargs = {}
            if getattr(settings, 'RESTRICT_TENANT_TO_HOST', False):
                if not request.host_tenant:
                    return
                extra_kwargs['%s__schema_name' % settings.TENANT_USER_TENANT_FK] = request.host_tenant.schema_name

            tenant_user = TenantUserModel.objects.select_related(settings.TENANT_USER_TENANT_FK).get(email=username, **extra_kwargs)
            connection.set_tenant(getattr(tenant_user, settings.TENANT_USER_TENANT_FK))
            user = super(TenantSessionAuthBackend, self).authenticate(username=username, password=password, **kwargs)

            if user:
                request.session['__schema_name__'] = getattr(tenant_user, settings.TENANT_USER_TENANT_FK).schema_name

            return user
        except:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel = get_user_model()
            UserModel().set_password(password)
Esempio n. 54
0
def is_comprehensive_theming_enabled():
    """
    Returns boolean indicating whether comprehensive theming functionality is enabled or disabled.

    Example:
        >> is_comprehensive_theming_enabled()
        True

    Returns:
         (bool): True if comprehensive theming is enabled else False
    """
    if not settings.ENABLE_COMPREHENSIVE_THEMING:
        # Return False if theming is disabled
        return False

    # return False if theming is disabled on runtime and function is called during request processing
    if bool(get_current_request()):
        # check if theming is disabled on runtime
        if waffle.switch_is_active(settings.DISABLE_THEMING_ON_RUNTIME_SWITCH):
            # function called in request processing and theming is disabled on runtime
            return False

    # Theming is enabled
    return True
def send_notification(user, commtype_code, context):
    """Send different notification mail to the user based on the triggering event.

    Args:
    user(obj): 'User' object to whom email is to send
    commtype_code(str): Communication type code
    context(dict): context to be used in the mail

    """

    tracking_id, client_id, ip = parse_tracking_context(user)

    tracking_pixel = 'https://www.google-analytics.com/collect?v=1&t=event&ec=email&ea=open&tid={tracking_id}' \
                     '&cid={client_id}&uip={ip}'.format(tracking_id=tracking_id, client_id=client_id, ip=ip)
    full_name = user.get_full_name()
    context.update({
        'full_name': full_name,
        'platform_name': get_current_request().site.name,
        'tracking_pixel': tracking_pixel,
    })

    try:
        event_type = CommunicationEventType.objects.get(code=commtype_code)
    except CommunicationEventType.DoesNotExist:
        try:
            messages = CommunicationEventType.objects.get_and_render(commtype_code, context)
        except Exception:  # pylint: disable=broad-except
            log.error('Unable to locate a DB entry or templates for communication type [%s]. '
                      'No notification has been sent.', commtype_code)
            return
    else:
        messages = event_type.get_messages(context)

    if messages and (messages['body'] or messages['html']):
        messages['html'] = transform(messages['html'])
        Dispatcher().dispatch_user_messages(user, messages)
Esempio n. 56
0
    def get_transaction_parameters(self, basket, request=None):
        """
        Generate a dictionary of signed parameters CyberSource requires to complete a transaction.

        Arguments:
            basket (Basket): The basket of products being purchased.

        Keyword Arguments:
            request (Request): A Request object which could be used to construct an absolute URL; not
                used by this method.

        Returns:
            dict: CyberSource-specific parameters required to complete a transaction, including a signature.
        """
        parameters = {
            'access_key': self.access_key,
            'profile_id': self.profile_id,
            'transaction_uuid': uuid.uuid4().hex,
            'signed_field_names': '',
            'unsigned_field_names': '',
            'signed_date_time': self.utcnow().strftime(ISO_8601_FORMAT),
            'locale': self.language_code,
            'transaction_type': 'sale',
            'reference_number': basket.order_number,
            'amount': str(basket.total_incl_tax),
            'currency': basket.currency,
            'consumer_id': basket.owner.username,
            'override_custom_receipt_page': '{}?orderNum={}'.format(self.receipt_page_url, basket.order_number),
            'override_custom_cancel_page': self.cancel_page_url,
        }

        # XCOM-274: when internal reporting across all processors is
        # operational, these custom fields will no longer be needed and should
        # be removed.
        single_seat = self.get_single_seat(basket)
        if single_seat:
            parameters['merchant_defined_data1'] = single_seat.attr.course_key
            parameters['merchant_defined_data2'] = getattr(single_seat.attr, 'certificate_type', '')

        # Level 2/3 details
        if self.send_level_2_3_details:
            parameters['amex_data_taa1'] = '{}'.format(get_current_request().site.name)
            parameters['purchasing_level'] = '3'
            parameters['line_item_count'] = basket.lines.count()
            # Note (CCB): This field (purchase order) is required for Visa;
            # but, is not actually used by us/exposed on the order form.
            parameters['user_po'] = 'BLANK'

            for index, line in enumerate(basket.lines.all()):
                parameters['item_{}_code'.format(index)] = line.product.get_product_class().slug
                parameters['item_{}_discount_amount '.format(index)] = str(line.discount_value)
                # Note (CCB): This indicates that the total_amount field below includes tax.
                parameters['item_{}_gross_net_indicator'.format(index)] = 'Y'
                parameters['item_{}_name'.format(index)] = line.product.title
                parameters['item_{}_quantity'.format(index)] = line.quantity
                parameters['item_{}_sku'.format(index)] = line.stockrecord.partner_sku
                parameters['item_{}_tax_amount'.format(index)] = str(line.line_tax)
                parameters['item_{}_tax_rate'.format(index)] = '0'
                parameters['item_{}_total_amount '.format(index)] = str(line.line_price_incl_tax_incl_discounts)
                # Note (CCB): Course seat is not a unit of measure. Use item (ITM).
                parameters['item_{}_unit_of_measure'.format(index)] = 'ITM'
                parameters['item_{}_unit_price'.format(index)] = str(line.unit_price_incl_tax)

        # Sign all fields
        signed_field_names = parameters.keys()
        parameters['signed_field_names'] = ','.join(sorted(signed_field_names))
        parameters['signature'] = self._generate_signature(parameters)

        parameters['payment_page_url'] = self.payment_page_url

        return parameters