예제 #1
0
 def handle(self, *args, **options):
     billables_created = 0
     for domain in Domain.get_all():
         key = [domain.name, 'SMSLog']
         start_date = [datetime.datetime(2014, 1, 1).isoformat()]
         end_date = [datetime.datetime(2014, 1, 24).isoformat()]
         sms_docs = SMSLog.get_db().view('sms/by_domain',
                                         reduce=False,
                                         startkey=key + start_date,
                                         endkey=key + end_date + [{}])
         for sms_doc in sms_docs:
             sms_log = SMSLog.get(sms_doc['id'])
             try:
                 if sms_log.phone_number is not None:
                     parse_phone_number(sms_log.phone_number)
             except PhoneNumberParseException:
                 billables = SmsBillable.objects.filter(log_id=sms_log._id)
                 if len(billables) == 0:
                     SmsBillable.create(sms_log)
                     billables_created += 1
                     print 'created SmsBillable for invalid number %s in domain %s, id=%s'\
                           % (sms_log.phone_number, domain.name, sms_log._id)
                 elif len(billables) > 1:
                     print "Warning: >1 SmsBillable exists for SMSLog with id=%" % sms_log._id
     print 'Number of SmsBillables created: %d' % billables_created
     print 'Completed retrobilling.'
예제 #2
0
def arbitrary_sms_billables_for_domain(domain, message_month_date, num_sms, direction=None, multipart_count=1):
    from corehq.apps.smsbillables.models import SmsBillable, SmsGatewayFee, SmsUsageFee

    direction = direction or random.choice(DIRECTIONS)

    gateway_fee = SmsGatewayFee.create_new('MACH', direction, Decimal(0.5))
    usage_fee = SmsUsageFee.create_new(direction, Decimal(0.25))

    _, last_day_message = calendar.monthrange(message_month_date.year, message_month_date.month)

    billables = []
    for _ in range(0, num_sms):
        sms_billable = SmsBillable(
            gateway_fee=gateway_fee,
            usage_fee=usage_fee,
            log_id=data_gen.arbitrary_unique_name()[:50],
            phone_number=data_gen.random_phonenumber(),
            domain=domain,
            direction=direction,
            date_sent=datetime.date(message_month_date.year, message_month_date.month,
                                    random.randint(1, last_day_message)),
            multipart_count=multipart_count,
        )
        sms_billable.save()
        billables.append(sms_billable)
    return billables
    def handle(self, *args, **options):
        num_sms = 0

        start_datetime = datetime.datetime(*str_to_int_tuple(args[0:6]))
        end_datetime = datetime.datetime(*str_to_int_tuple(args[6:12]))

        for domain in Domain.get_all():
            key = [domain.name, 'SMSLog']
            sms_docs = SMSLog.get_db().view('sms/by_domain',
                                            reduce=False,
                                            startkey=key + [start_datetime.isoformat()],
                                            endkey=key + [end_datetime.isoformat(), {}],
            )

            for sms_doc in sms_docs:
                sms_log = SMSLog.get(sms_doc['id'])
                if options.get('create', False):
                    SmsBillable.create(sms_log)
                    print 'Created billable for SMSLog %s in domain %s from %s' \
                          % (sms_doc['id'], domain.name, sms_log.date)
                else:
                    print 'Found SMSLog %s in domain %s from %s' \
                          % (sms_doc['id'], domain.name, sms_log.date)
                num_sms += 1

        print 'Number of SMSs in datetime range: %d' % num_sms
예제 #4
0
파일: tasks.py 프로젝트: jmaina/commcare-hq
def store_billable(msg):
    if msg._id and not SmsBillable.objects.filter(log_id=msg._id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        for _ in range(int(math.ceil(float(len(msg.text)) / msg_length))):
            SmsBillable.create(msg)
예제 #5
0
    def test_twilio_multipart_usage_charge(self):
        self.apply_direction_fee()
        twilio_backend = SQLTwilioBackend.objects.create(
            name='TWILIO',
            is_global=True,
            hq_api_id=SQLTwilioBackend.get_api_id(),
            couch_id='global_backend',
        )
        twilio_backend.set_extra_fields(
            account_sid='sid',
            auth_token='token',
        )
        twilio_backend.save()

        messages = generator.arbitrary_messages_by_backend_and_direction(
            {twilio_backend.hq_api_id: twilio_backend.couch_id}
        )
        for message in messages:
            FakeTwilioMessageFactory.add_num_segments_for_message(message.backend_message_id, randint(1, 10))
            FakeTwilioMessageFactory.add_price_for_message(message.backend_message_id, generator.arbitrary_fee())

        for message in messages:
            multipart_count = randint(1, 10)  # Should be ignored
            billable = SmsBillable.create(message, multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.usage_charge,
                (
                    self.least_specific_fees[message.direction]
                    * FakeTwilioMessageFactory.get_num_segments_for_message(
                        message.backend_message_id
                    )
                )
            )
예제 #6
0
    def test_non_global_backends_with_direct_provider_fees(
            self, mock_log_smsbillables_error):
        bootstrap_twilio_gateway(apps)
        bootstrap_infobip_gateway(apps)
        bootstrap_usage_fees(apps)
        backends = generator.arbitrary_non_global_with_direct_fees_backends()
        for backend in backends:
            messages = [
                message for phone_number in
                [generator.arbitrary_phone_number() for _ in range(10)]
                for message in
                generator.arbitrary_messages_by_backend_and_direction(
                    {backend.hq_api_id: backend.couch_id},
                    phone_number=phone_number)
            ]
            for msg_log in messages:
                FakeMessageFactory.add_price_for_message(
                    msg_log.backend_message_id, generator.arbitrary_fee())

            for msg_log in messages:
                multipart_count = randint(1, 10)  # Should be ignored
                billable = SmsBillable.create(msg_log,
                                              multipart_count=multipart_count)
                self.assertIsNotNone(billable)
                self.assertIsNone(billable.gateway_fee)
                self.assertEqual(billable.gateway_charge, 0)

            self.assertEqual(mock_log_smsbillables_error.call_count, 0)
예제 #7
0
    def test_prefix_fees(self):
        self.create_prefix_gateway_fees()

        for phone_number, prefix in generator.arbitrary_phone_numbers_and_prefixes(
                self.country_code_and_prefixes):
            messages = generator.arbitrary_messages_by_backend_and_direction(
                {
                    random_key: self.backend_ids[random_key]
                    for random_key in [choice(self.backend_ids.keys())]
                },
                phone_number=phone_number,
            )

            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                try:
                    self.assertEqual(
                        billable.gateway_charge,
                        self.prefix_fees[billable.direction]
                        [billable.gateway_fee.criteria.backend_api_id][
                            phone_number[:-10]][prefix][msg_log.backend_id])
                except AssertionError:
                    raise Exception("Phone number: %s, " % phone_number +
                                    "given prefix: %s, " % prefix +
                                    "found prefix: %s" %
                                    billable.gateway_fee.criteria.prefix)
예제 #8
0
    def test_twilio_global_backend(self):
        add_twilio_gateway_fee(apps)
        twilio_backend = SQLTwilioBackend.objects.create(
            name='TWILIO',
            is_global=True,
            hq_api_id=SQLTwilioBackend.get_api_id(),
            couch_id='global_backend',
        )
        twilio_backend.set_extra_fields(
            account_sid='sid',
            auth_token='token',
        )
        twilio_backend.save()

        messages = [
            message for phone_number in
            [generator.arbitrary_phone_number() for _ in range(10)] for message
            in generator.arbitrary_messages_by_backend_and_direction(
                {twilio_backend.hq_api_id: twilio_backend.couch_id},
                phone_number=phone_number)
        ]
        for msg_log in messages:
            FakeTwilioMessageFactory.add_price_for_message(
                msg_log.backend_message_id, generator.arbitrary_fee())

        for msg_log in messages:
            multipart_count = randint(1, 10)  # Should be ignored
            billable = SmsBillable.create(msg_log,
                                          multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertIsNotNone(billable.gateway_fee)
            self.assertEqual(
                billable.gateway_charge,
                FakeTwilioMessageFactory.get_price_for_message(
                    msg_log.backend_message_id))
예제 #9
0
    def test_twilio_domain_level_backend(self, mock_log_smsbillables_error):
        add_twilio_gateway_fee(apps)
        bootstrap_usage_fees(apps)
        twilio_backend = SQLTwilioBackend.objects.create(
            name='TWILIO',
            is_global=False,
            hq_api_id=SQLTwilioBackend.get_api_id(),
            couch_id='domain_backend',
        )
        twilio_backend.set_extra_fields(
            account_sid='sid',
            auth_token='token',
        )
        twilio_backend.save()

        messages = [
            message
            for phone_number in [generator.arbitrary_phone_number() for _ in range(10)]
            for message in generator.arbitrary_messages_by_backend_and_direction(
                {twilio_backend.hq_api_id: twilio_backend.couch_id}, phone_number=phone_number
            )
        ]
        for msg_log in messages:
            FakeTwilioMessageFactory.add_price_for_message(msg_log.backend_message_id, generator.arbitrary_fee())

        for msg_log in messages:
            multipart_count = randint(1, 10)  # Should be ignored
            billable = SmsBillable.create(msg_log, multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertIsNone(billable.gateway_fee)
            self.assertEqual(billable.gateway_charge, 0)

        self.assertEqual(mock_log_smsbillables_error.call_count, 0)
예제 #10
0
    def test_twilio_multipart_usage_charge(self):
        self.apply_direction_fee()
        twilio_backend = SQLTwilioBackend.objects.create(
            name='TWILIO',
            is_global=True,
            hq_api_id=SQLTwilioBackend.get_api_id(),
            couch_id='global_backend',
        )
        twilio_backend.set_extra_fields(
            account_sid='sid',
            auth_token='token',
        )
        twilio_backend.save()

        messages = generator.arbitrary_messages_by_backend_and_direction(
            {twilio_backend.hq_api_id: twilio_backend.couch_id})
        for message in messages:
            FakeTwilioMessageFactory.add_num_segments_for_message(
                message.backend_message_id, randint(1, 10))
            FakeTwilioMessageFactory.add_price_for_message(
                message.backend_message_id, generator.arbitrary_fee())

        for message in messages:
            multipart_count = randint(1, 10)  # Should be ignored
            billable = SmsBillable.create(message,
                                          multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.usage_charge,
                (self.least_specific_fees[message.direction] *
                 FakeTwilioMessageFactory.get_num_segments_for_message(
                     message.backend_message_id)))
예제 #11
0
    def test_prefix_fees(self):
        self.create_prefix_gateway_fees()

        for phone_number, prefix in generator.arbitrary_phone_numbers_and_prefixes(
            self.country_code_and_prefixes
        ):
            messages = generator.arbitrary_messages_by_backend_and_direction(
                {
                    random_key: self.backend_ids[random_key]
                    for random_key in [choice(self.backend_ids.keys())]
                },
                phone_number=phone_number,
            )

            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                try:
                    self.assertEqual(
                        billable.gateway_charge,
                        self.prefix_fees
                        [billable.direction]
                        [billable.gateway_fee.criteria.backend_api_id]
                        [phone_number[:-10]]
                        [prefix]
                        [msg_log.backend_id]
                    )
                except AssertionError:
                    raise Exception(
                        "Phone number: %s, " % phone_number
                        + "given prefix: %s, " % prefix
                        + "found prefix: %s" % billable.gateway_fee.criteria.prefix
                    )
예제 #12
0
    def test_only_direction(self):
        self.apply_direction_fee()
        messages = generator.arbitrary_messages_by_backend_and_direction(self.backend_ids)

        for message in messages:
            billable = SmsBillable.create(message)
            self.assertIsNotNone(billable)
            self.assertEqual(billable.usage_charge, self.least_specific_fees[message.direction])
예제 #13
0
def store_billable(self, msg):
    if not isinstance(msg, SMS):
        raise Exception("Expected msg to be an SMS")

    if msg.couch_id and not SmsBillable.objects.filter(log_id=msg.couch_id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        try:
            SmsBillable.create(
                msg,
                multipart_count=int(math.ceil(float(len(msg.text)) / msg_length)),
            )
        except RetryBillableTaskException as e:
            self.retry(exc=e)
예제 #14
0
    def test_only_direction(self):
        self.apply_direction_fee()
        messages = generator.arbitrary_messages_by_backend_and_direction(
            self.backend_ids)

        for message in messages:
            billable = SmsBillable.create(message)
            self.assertIsNotNone(billable)
            self.assertEqual(billable.usage_charge,
                             self.least_specific_fees[message.direction])
예제 #15
0
    def test_least_specific_fees(self):
        self.create_least_specific_gateway_fees()

        for msg_log in self.message_logs:
            billable = SmsBillable.create(msg_log)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.gateway_charge,
                self.least_specific_fees[billable.direction][
                    billable.gateway_fee.criteria.backend_api_id])
예제 #16
0
    def test_least_specific_fees(self):
        self.create_least_specific_gateway_fees()

        for msg_log in self.message_logs:
            billable = SmsBillable.create(msg_log)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.gateway_charge,
                self.least_specific_fees[billable.direction][billable.gateway_fee.criteria.backend_api_id]
            )
예제 #17
0
def store_billable(self, msg):
    if not isinstance(msg, SMS):
        raise Exception("Expected msg to be an SMS")

    if msg.couch_id and not SmsBillable.objects.filter(log_id=msg.couch_id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        try:
            SmsBillable.create(
                msg,
                multipart_count=int(math.ceil(len(msg.text) / msg_length)),
            )
        except RetryBillableTaskException as e:
            self.retry(exc=e)
예제 #18
0
    def test_domain_and_direction(self):
        self.apply_direction_fee()
        self.apply_direction_and_domain_fee()

        for direction, domain_fee in self.most_specific_fees.items():
            for domain in domain_fee:
                messages = generator.arbitrary_messages_by_backend_and_direction(self.backend_ids, domain=domain)
                for message in messages:
                    billable = SmsBillable.create(message)
                    self.assertIsNotNone(billable)
                    self.assertEqual(billable.usage_charge, self.most_specific_fees[message.direction][domain])
예제 #19
0
    def handle(self, start_datetime, end_datetime, **options):
        num_sms = 0

        for domain in Domain.get_all():
            result = SMS.by_domain(
                domain.name,
                start_date=start_datetime,
                end_date=end_datetime,
            )

            for sms_log in result:
                if options.get('create', False):
                    SmsBillable.create(sms_log)
                    print('Created billable for SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date))
                else:
                    print('Found SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date))
                num_sms += 1

        print('Number of SMSs in datetime range: %d' % num_sms)
예제 #20
0
    def handle(self, start_datetime, end_datetime, **options):
        num_sms = 0

        for domain in Domain.get_all():
            result = SMS.by_domain(
                domain.name,
                start_date=start_datetime,
                end_date=end_datetime,
            )

            for sms_log in result:
                if options.get('create', False):
                    SmsBillable.create(sms_log)
                    print('Created billable for SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date))
                else:
                    print('Found SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date))
                num_sms += 1

        print('Number of SMSs in datetime range: %d' % num_sms)
예제 #21
0
def arbitrary_sms_billables_for_domain(domain, direction, message_month_date, num_sms):
    from corehq.apps.smsbillables.models import SmsBillable, SmsGatewayFee, SmsUsageFee
    from corehq.apps.smsbillables import generator as sms_gen

    gateway_fee = SmsGatewayFee.create_new('MACH', direction, sms_gen.arbitrary_fee())
    usage_fee = SmsUsageFee.create_new(direction, sms_gen.arbitrary_fee())

    _, last_day_message = calendar.monthrange(message_month_date.year, message_month_date.month)

    for _ in range(0, num_sms):
        sms_billable = SmsBillable(
            gateway_fee=gateway_fee,
            usage_fee=usage_fee,
            log_id=data_gen.arbitrary_unique_name()[:50],
            phone_number=data_gen.random_phonenumber(),
            domain=domain,
            direction=direction,
            date_sent=datetime.date(message_month_date.year, message_month_date.month,
                                    random.randint(1, last_day_message)),
        )
        sms_billable.save()
예제 #22
0
    def test_log_no_usage_fee(self):
        self.apply_direction_fee()
        self.apply_direction_and_domain_fee()

        for direction, domain_fee in self.most_specific_fees.items():
            for domain in domain_fee:
                messages = generator.arbitrary_messages_by_backend_and_direction(
                    self.backend_ids, domain=domain, directions=["X", "Y"]
                )
                for message in messages:
                    billable = SmsBillable.create(message)
                    self.assertIsNotNone(billable)
                    self.assertIsNone(billable.usage_fee)
예제 #23
0
    def test_multipart_gateway_charge(self):
        self.create_least_specific_gateway_fees()

        for msg_log in self.message_logs:
            multipart_count = randint(1, 10)
            billable = SmsBillable.create(msg_log, multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.gateway_charge,
                self.least_specific_fees
                [billable.direction]
                [billable.gateway_fee.criteria.backend_api_id] * multipart_count
            )
예제 #24
0
    def handle(self, *args, **options):
        num_sms = 0

        start_datetime = datetime.datetime(*str_to_int_tuple(args[0:6]))
        end_datetime = datetime.datetime(*str_to_int_tuple(args[6:12]))

        for domain in Domain.get_all():
            result = SMS.by_domain(domain.name,
                                   start_date=start_datetime,
                                   end_date=end_datetime)

            for sms_log in result:
                if options.get('create', False):
                    SmsBillable.create(sms_log)
                    print 'Created billable for SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date)
                else:
                    print 'Found SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date)
                num_sms += 1

        print 'Number of SMSs in datetime range: %d' % num_sms
예제 #25
0
    def test_multipart_gateway_charge(self):
        self.create_least_specific_gateway_fees()

        for msg_log in self.message_logs:
            multipart_count = randint(1, 10)
            billable = SmsBillable.create(msg_log,
                                          multipart_count=multipart_count)
            self.assertIsNotNone(billable)
            self.assertEqual(
                billable.gateway_charge,
                self.least_specific_fees[billable.direction][
                    billable.gateway_fee.criteria.backend_api_id] *
                multipart_count)
예제 #26
0
 def sms_billables(self):
     datespan = DateSpan(DateSentFilter.get_start_date(self.request),
                         DateSentFilter.get_end_date(self.request))
     selected_billables = SmsBillable.get_billables_sent_between(datespan)
     if DateCreatedFilter.use_filter(self.request):
         date_span = DateSpan(
             DateCreatedFilter.get_start_date(self.request),
             DateCreatedFilter.get_end_date(self.request))
         selected_billables = SmsBillable.filter_selected_billables_by_date(
             selected_billables, date_span)
     show_billables = ShowBillablesFilter.get_value(self.request,
                                                    self.domain)
     if show_billables:
         selected_billables = SmsBillable.filter_selected_billables_show_billables(
             selected_billables,
             show_billables,
         )
     account_name = NameFilter.get_value(self.request, self.domain)
     if account_name:
         selected_billables = SmsBillable.filter_selected_billables_by_account(
             selected_billables, account_name)
     domain = DomainFilter.get_value(self.request, self.domain)
     if domain:
         selected_billables = selected_billables.filter(domain=domain, )
     has_gateway_fee = HasGatewayFeeFilter.get_value(
         self.request, self.domain)
     if has_gateway_fee:
         if has_gateway_fee == HasGatewayFeeFilter.YES:
             selected_billables = selected_billables.exclude(
                 gateway_fee=None)
         else:
             selected_billables = selected_billables.filter(
                 gateway_fee=None)
     gateway_type = GatewayTypeFilter.get_value(self.request, self.domain)
     if gateway_type:
         selected_billables = selected_billables.filter(
             gateway_fee__criteria__backend_api_id=gateway_type, )
     return selected_billables
예제 #27
0
def store_billable(self, msg):
    if not isinstance(msg, SMS):
        raise Exception("Expected msg to be an SMS")

    if msg.couch_id and not SmsBillable.objects.filter(log_id=msg.couch_id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        try:
            SmsBillable.create(
                msg,
                multipart_count=int(math.ceil(len(msg.text) / msg_length)),
            )
        except RetryBillableTaskException as e:
            self.retry(exc=e)
        except DeliveredBillableException:
            # don't retry, but do raise error for logging purposes and make sure
            # the original message's ID is associated with the error
            # (the backend ID is stored with it already)
            raise DeliveredBillableException(f"msg_couch_id={msg.couch_id}")
예제 #28
0
    def test_no_matching_fee(self):
        self.create_least_specific_gateway_fees()
        self.create_country_code_gateway_fees()
        self.create_instance_gateway_fees()
        self.create_most_specific_gateway_fees()

        phone_numbers = [generator.arbitrary_phone_number() for i in range(10)]
        for phone_number in phone_numbers:
            messages = generator.arbitrary_messages_by_backend_and_direction(self.backend_ids,
                                                                             phone_number=phone_number,
                                                                             directions=['X', 'Y'])
            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                self.assertIsNone(billable.gateway_fee)
예제 #29
0
    def handle(self, *args, **options):
        num_sms = 0

        start_datetime = datetime.datetime(*str_to_int_tuple(args[0:6]))
        end_datetime = datetime.datetime(*str_to_int_tuple(args[6:12]))

        for domain in Domain.get_all():
            result = SMS.by_domain(
                domain.name,
                start_date=start_datetime,
                end_date=end_datetime
            )

            for sms_log in result:
                if options.get('create', False):
                    SmsBillable.create(sms_log)
                    print 'Created billable for SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date)
                else:
                    print 'Found SMS %s in domain %s from %s' \
                          % (sms_log.couch_id, domain.name, sms_log.date)
                num_sms += 1

        print 'Number of SMSs in datetime range: %d' % num_sms
예제 #30
0
def store_billable(self, msg):
    if not isinstance(msg, SMS):
        raise Exception("Expected msg to be an SMS")

    if msg.couch_id and not SmsBillable.objects.filter(log_id=msg.couch_id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        try:
            SmsBillable.create(
                msg,
                multipart_count=int(math.ceil(len(msg.text) / msg_length)),
            )
        except RetryBillableTaskException as e:
            self.retry(exc=e)
        except DataError:
            from corehq.util.soft_assert import soft_assert
            _soft_assert = soft_assert(to='{}@{}'.format('jemord', 'dimagi.com'))
            _soft_assert(len(msg.domain) < 25, "Domain name too long: " + msg.domain)
            raise
예제 #31
0
def store_billable(self, msg):
    if not isinstance(msg, SMS):
        raise Exception("Expected msg to be an SMS")

    if msg.couch_id and not SmsBillable.objects.filter(log_id=msg.couch_id).exists():
        try:
            msg.text.encode('iso-8859-1')
            msg_length = 160
        except UnicodeEncodeError:
            # This string contains unicode characters, so the allowed
            # per-sms message length is shortened
            msg_length = 70
        try:
            SmsBillable.create(
                msg,
                multipart_count=int(math.ceil(float(len(msg.text)) / msg_length)),
            )
        except RetryBillableTaskException as e:
            self.retry(exc=e)
        except DataError:
            from corehq.util.soft_assert import soft_assert
            _soft_assert = soft_assert(to='{}@{}'.format('jemord', 'dimagi.com'))
            _soft_assert(msg.domain < 25, "Domain name too long: " + msg.domain)
            raise
예제 #32
0
def arbitrary_sms_billables_for_domain(domain, message_month_date, num_sms, direction=None, multipart_count=1):
    direction = direction or random.choice(DIRECTIONS)

    gateway_fee = SmsGatewayFee.create_new('MACH', direction, Decimal(0.5))
    usage_fee = SmsUsageFee.create_new(direction, Decimal(0.25))

    _, last_day_message = calendar.monthrange(message_month_date.year, message_month_date.month)

    billables = []
    for _ in range(0, num_sms):
        sms_billable = SmsBillable(
            gateway_fee=gateway_fee,
            usage_fee=usage_fee,
            log_id=data_gen.arbitrary_unique_name()[:50],
            phone_number=data_gen.random_phonenumber(),
            domain=domain,
            direction=direction,
            date_sent=datetime.date(message_month_date.year, message_month_date.month,
                                    random.randint(1, last_day_message)),
            multipart_count=multipart_count,
        )
        sms_billable.save()
        billables.append(sms_billable)
    return billables
예제 #33
0
    def test_log_no_usage_fee(self):
        self.apply_direction_fee()
        self.apply_direction_and_domain_fee()

        for direction, domain_fee in self.most_specific_fees.items():
            for domain in domain_fee:
                messages = generator.arbitrary_messages_by_backend_and_direction(
                    self.backend_ids,
                    domain=domain,
                    directions=['X', 'Y'],
                )
                for message in messages:
                    billable = SmsBillable.create(message)
                    self.assertIsNotNone(billable)
                    self.assertIsNone(billable.usage_fee)
예제 #34
0
    def test_no_matching_fee(self):
        self.create_least_specific_gateway_fees()
        self.create_country_code_gateway_fees()
        self.create_instance_gateway_fees()
        self.create_most_specific_gateway_fees()

        phone_numbers = [generator.arbitrary_phone_number() for i in range(10)]
        for phone_number in phone_numbers:
            messages = generator.arbitrary_messages_by_backend_and_direction(self.backend_ids,
                                                                             phone_number=phone_number,
                                                                             directions=['X', 'Y'])
            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                self.assertIsNone(billable.gateway_fee)
예제 #35
0
    def test_instance_fees(self):
        self.create_least_specific_gateway_fees()
        self.create_country_code_gateway_fees()
        self.create_instance_gateway_fees()

        phone_numbers = [generator.arbitrary_phone_number() for i in range(10)]
        for phone_number in phone_numbers:
            messages = generator.arbitrary_messages_by_backend_and_direction(
                self.backend_ids, phone_number=phone_number)
            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                self.assertEqual(
                    billable.gateway_charge,
                    self.instance_fees[billable.direction][
                        billable.gateway_fee.criteria.backend_api_id][1])
예제 #36
0
    def test_domain_and_direction(self):
        self.apply_direction_fee()
        self.apply_direction_and_domain_fee()

        for direction, domain_fee in self.most_specific_fees.items():
            for domain in domain_fee:
                messages = generator.arbitrary_messages_by_backend_and_direction(
                    self.backend_ids,
                    domain=domain,
                )
                for message in messages:
                    billable = SmsBillable.create(message)
                    self.assertIsNotNone(billable)
                    self.assertEqual(
                        billable.usage_charge,
                        self.most_specific_fees[message.direction][domain])
예제 #37
0
    def test_country_code_fees(self):
        self.create_least_specific_gateway_fees()
        self.create_country_code_gateway_fees()

        phone_numbers = [generator.arbitrary_phone_number() for i in range(10)]
        for phone_number in phone_numbers:
            messages = generator.arbitrary_messages_by_backend_and_direction(self.backend_ids,
                                                                             phone_number=phone_number)
            for msg_log in messages:
                billable = SmsBillable.create(msg_log)
                self.assertIsNotNone(billable)
                self.assertEqual(
                    billable.gateway_charge,
                    self.country_code_fees[billable.direction]
                    [billable.gateway_fee.criteria.backend_api_id]
                    [int(phone_number[:-10])]
                )
예제 #38
0
    def test_fee_for_non_global_backend(self):
        self.create_least_specific_gateway_fees()

        private_backend_ids = generator.arbitrary_non_global_backend_ids()
        messages = generator.arbitrary_messages_by_backend_and_direction(
            private_backend_ids)
        arbitrary_message = messages[randint(0, len(messages) - 1)]

        toggles.ENABLE_INCLUDE_SMS_GATEWAY_CHARGING.set(
            arbitrary_message.domain, True, toggles.NAMESPACE_DOMAIN)
        billable = SmsBillable.create(arbitrary_message)
        toggles.ENABLE_INCLUDE_SMS_GATEWAY_CHARGING.set(
            arbitrary_message.domain, False, toggles.NAMESPACE_DOMAIN)

        self.assertIsNotNone(billable)
        self.assertIsNotNone(billable.gateway_fee)
        self.assertEqual(billable.gateway_charge,
                         self.least_specific_fees[billable.direction]
                         [billable.gateway_fee.criteria.backend_api_id])
 def _get_updated_billable(self, old_billable, updated_currency):
     new_billable = SmsBillable(
         log_id=old_billable.log_id,
         phone_number=old_billable.phone_number,
         direction=old_billable.direction,
         date_sent=old_billable.date_sent,
         domain=old_billable.domain,
         multipart_count=old_billable.multipart_count
     )
     new_billable.gateway_fee = old_billable.gateway_fee
     new_billable.gateway_fee_conversion_rate = updated_currency.rate_to_default
     new_billable.usage_fee = old_billable.usage_fee
     new_billable.save()
     return new_billable
예제 #40
0
    def create_smsbillable(self, date, show_billable=True, gateway_fee=None):
        text = (
            "This is text that will be displayed in a test text message in the "
            "test interface class in Enterprise.")
        self.msg = self.create_fake_sms(self.backend.hq_api_id,
                                        self.backend.couch_id, text, date)

        smsbillable = SmsBillable.create(
            self.msg,
            multipart_count=int(math.ceil(len(self.msg.text) / 160)),
        )
        #The is_valid property is queried to display "active" billables
        smsbillable.is_valid = show_billable
        if gateway_fee:
            smsbillable.gateway_fee = SmsGatewayFee.create_new(
                self.backend.hq_api_id, self.msg.direction, gateway_fee)
        else:
            smsbillable.gateway_fee = None
        smsbillable.save()
        SmsBillable.objects.filter(id=smsbillable.id).update(date_created=date)
        return smsbillable
예제 #41
0
    def test_multipart_usage_charge_for_backends_with_direct_fees(self):
        self.apply_direction_fee()
        backends = generator.arbitrary_with_direct_fees_backends()
        for backend in backends:
            messages = generator.arbitrary_messages_by_backend_and_direction(
                {backend.hq_api_id: backend.couch_id})
            for message in messages:
                FakeMessageFactory.add_num_segments_for_message(
                    message.backend_message_id, randint(1, 10))
                FakeMessageFactory.add_price_for_message(
                    message.backend_message_id, generator.arbitrary_fee())

            for message in messages:
                multipart_count = randint(1, 10)  # Should be ignored
                billable = SmsBillable.create(message,
                                              multipart_count=multipart_count)
                self.assertIsNotNone(billable)
                self.assertEqual(
                    billable.usage_charge,
                    (self.least_specific_fees[message.direction] *
                     FakeMessageFactory.get_num_segments_for_message(
                         message.backend_message_id)))
예제 #42
0
def store_billable(msg):
    SmsBillable.create(msg)
예제 #43
0
def store_billable(msg):
    if not SmsBillable.objects.filter(log_id=msg._id).exists():
        for _ in range(int(math.ceil(float(len(msg.text)) / 160))):
            SmsBillable.create(msg)
예제 #44
0
def store_billable(msg):
    if not SmsBillable.objects.filter(log_id=msg._id).exists():
        for _ in range(int(math.ceil(float(len(msg.text)) / 160))):
            SmsBillable.create(msg)