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.')
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
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
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}
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
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)
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
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)
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.')
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
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
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'/')
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)
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 __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
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()
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 })
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
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()
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
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 } )
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 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, } )
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
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
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))
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()
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
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()
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
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
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)
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}"
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
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))))
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
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)
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)) ) )
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()
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
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
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)
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
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
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
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)
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)
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