def create_data(self, voucher_type, max_uses, assignments): """ Create vouchers, offers and offer assignments. """ codes = {assignment['code'] for assignment in assignments} emails = sorted({assignment['user_email'] for assignment in assignments}) quantity = len(codes) voucher_types = (Voucher.MULTI_USE, Voucher.ONCE_PER_CUSTOMER, Voucher.MULTI_USE_PER_CUSTOMER) num_of_offers = quantity if voucher_type in voucher_types else 1 offers = [] for __ in range(num_of_offers): offers.append(factories.EnterpriseOfferFactory(max_global_applications=max_uses)) coupon = self.create_coupon(quantity=quantity, voucher_type=voucher_type) for index, info in enumerate(zip(coupon.attr.coupon_vouchers.vouchers.all(), codes)): voucher, code = info voucher.code = code voucher.offers.add(offers[index] if len(offers) > 1 else offers[0]) voucher.save() data = {'codes': codes, 'emails': emails} serializer = CouponCodeAssignmentSerializer(data=data, context={'coupon': coupon}) if serializer.is_valid(): serializer.save() assignments = serializer.data
def test_send_assignment_email_error(self, mock_email): """ Test that we log an appropriate message if the code assignment email cannot be sent. """ mock_email.side_effect = Exception('Ignore me - assignment') serializer = CouponCodeAssignmentSerializer(data=self.data, context={'coupon': self.coupon}) expected = [ ( self.LOGGER_NAME, 'ERROR', '[Offer Assignment] Email for offer_assignment_id: {} with greeting \'{}\' and closing \'{}\' raised ' 'exception: {}'.format( self.offer_assignment.id, self.GREETING, self.CLOSING, repr(Exception('Ignore me - assignment')) ) ), ] with LogCapture(self.LOGGER_NAME) as log: serializer._trigger_email_sending_task( # pylint: disable=protected-access greeting=self.GREETING, closing=self.CLOSING, assigned_offer=self.offer_assignment, voucher_usage_type=Voucher.MULTI_USE_PER_CUSTOMER ) log.check_present(*expected)
def test_send_assigned_offer_email_args_with_enterprise_url( self, mock_assign_email): """ Test that the code_expiration_date passed is equal to coupon batch end date """ serializer = CouponCodeAssignmentSerializer( data=self.data, context={'coupon': self.coupon}) serializer._trigger_email_sending_task( # pylint: disable=protected-access subject=self.SUBJECT, greeting=self.GREETING, closing=self.CLOSING, assigned_offer=self.offer_assignment, voucher_usage_type=Voucher.MULTI_USE_PER_CUSTOMER, base_enterprise_url=self.BASE_ENTERPRISE_URL, ) expected_expiration_date = self.coupon.attr.coupon_vouchers.vouchers.first( ).end_datetime assert mock_assign_email.call_count == 1 assign_email_args = mock_assign_email.call_args[1] assert assign_email_args['subject'] == self.SUBJECT assert assign_email_args['greeting'] == self.GREETING assert assign_email_args['closing'] == self.CLOSING assert assign_email_args[ 'learner_email'] == self.offer_assignment.user_email assert assign_email_args[ 'offer_assignment_id'] == self.offer_assignment.id assert assign_email_args['code'] == self.offer_assignment.code assert assign_email_args[ 'code_expiration_date'] == expected_expiration_date.strftime( '%d %B, %Y %H:%M %Z') assert assign_email_args[ 'base_enterprise_url'] == self.BASE_ENTERPRISE_URL
def assign(self, request, pk): # pylint: disable=unused-argument """ Assign users by email to codes within the Coupon. """ coupon = self.get_object() self._validate_coupon_availablity( coupon, 'Coupon is not available for code assignment') subject = request.data.pop('template_subject', '') greeting = request.data.pop('template_greeting', '') closing = request.data.pop('template_closing', '') template_id = request.data.pop('template_id', None) template = OfferAssignmentEmailTemplates.get_template(template_id) enterprise_customer = coupon.attr.enterprise_customer_uuid self._validate_email_fields(subject, greeting, closing) serializer = CouponCodeAssignmentSerializer(data=request.data, context={ 'coupon': coupon, 'subject': subject, 'greeting': greeting, 'closing': closing, }) if serializer.is_valid(): serializer.save() # Create a record of the email sent self._create_offer_assignment_email_sent_record( enterprise_customer, ASSIGN, template) return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def assign(self, request, pk): # pylint: disable=unused-argument """ Assign users by email to codes within the Coupon. """ coupon = self.get_object() self._validate_coupon_availablity( coupon, 'Coupon is not available for code assignment') subject = request.data.pop('template_subject', '') greeting = request.data.pop('template_greeting', '') closing = request.data.pop('template_closing', '') template_id = request.data.pop('template_id', None) sender_id = request.user.lms_user_id self._validate_email_fields(subject, greeting, closing) serializer = CouponCodeAssignmentSerializer(data=request.data, context={ 'coupon': coupon, 'subject': subject, 'greeting': greeting, 'closing': closing, 'template_id': template_id, 'sender_id': sender_id, 'site': request.site }) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def test_enterprise_customer_coupon_redemption_for_no_offer_assignment(self): """ Verify the warning message appears on redemption if coupon does not have any offer assignments for the user. """ expected_message = ( 'This code is not valid with your email. ' 'Please login with the correct email assigned ' 'to the code or contact your Learning Manager ' 'for additional questions.' ) code, coupon = self.prepare_enterprise_data( benefit_value=5, consent_enabled=False, catalog=self.catalog, enterprise_customer_catalog=ENTERPRISE_CUSTOMER_CATALOG ) self.mock_assignable_enterprise_condition_calls(ENTERPRISE_CUSTOMER_CATALOG) self.mock_enterprise_learner_api_for_learner_with_no_enterprise() self.mock_enterprise_learner_post_api() self.mock_course_run_detail_endpoint(self.course, discovery_api_url=self.site_configuration.discovery_api_url) data = {'codes': [code], 'emails': ['*****@*****.**']} serializer = CouponCodeAssignmentSerializer(data=data, context={'coupon': coupon}) if serializer.is_valid(): serializer.save() response = self.client.get(self.redeem_url_with_params(code=code), follow=True) messages = [] messages += response.context['messages'] self.assertEqual(messages[0].tags, 'warning') self.assertEqual(messages[0].message, expected_message)
def test_send_assignment_email_error(self, mock_email): """ Test that we log an appropriate message if the code assignment email cannot be sent. """ mock_email.side_effect = Exception('Ignore me - assignment') serializer = CouponCodeAssignmentSerializer( data=self.code_assignment_serializer_data, context={'coupon': self.coupon}) expected = [ (self.LOGGER_NAME, 'ERROR', '[Offer Assignment] Email for offer_assignment_id: {} with subject \'{}\', greeting \'{}\' closing ' '\'{}\' and attachments {}, raised exception: {}'.format( self.offer_assignment.id, self.SUBJECT, self.GREETING, self.CLOSING, self.ATTACHMENTS, repr(Exception('Ignore me - assignment')))), ] with LogCapture(self.LOGGER_NAME) as log: serializer._trigger_email_sending_task( # pylint: disable=protected-access subject=self.SUBJECT, greeting=self.GREETING, closing=self.CLOSING, assigned_offer=self.offer_assignment, voucher_usage_type=Voucher.MULTI_USE_PER_CUSTOMER, sender_alias=self.SENDER_ALIAS, reply_to=self.REPLY_TO, attachments=self.ATTACHMENTS, ) log.check_present(*expected)
def assign(self, request, pk): # pylint: disable=unused-argument """ Assign users by email to codes within the Coupon. """ coupon = self.get_object() serializer = CouponCodeAssignmentSerializer(data=request.data, context={'coupon': coupon}) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def test_send_assigned_offer_email_args(self, mock_assign_email): """ Test that the code_expiration_date passed is equal to coupon batch end date """ serializer = CouponCodeAssignmentSerializer(data=self.data, context={'coupon': self.coupon}) serializer._trigger_email_sending_task( # pylint: disable=protected-access greeting=self.GREETING, closing=self.CLOSING, assigned_offer=self.offer_assignment, voucher_usage_type=Voucher.MULTI_USE_PER_CUSTOMER ) expected_expiration_date = self.coupon.attr.coupon_vouchers.vouchers.first().end_datetime mock_assign_email.assert_called_with( greeting=self.GREETING, closing=self.CLOSING, offer_assignment_id=self.offer_assignment.id, learner_email=self.offer_assignment.user_email, code=self.offer_assignment.code, redemptions_remaining=mock.ANY, code_expiration_date=expected_expiration_date.strftime('%d %B, %Y') )