Example #1
0
 def test_calculate_credit_cost_for_new_session(self):
     self.assertEqual(
         MessageCost.calculate_credit_cost(
             decimal.Decimal('1.0'), decimal.Decimal('10.0'),
             decimal.Decimal('2.0'), session_created=True),
         decimal.Decimal('33.0'))
     self.assertEqual(
         MessageCost.calculate_credit_cost(
             decimal.Decimal('5.0'), decimal.Decimal('20.0'),
             decimal.Decimal('2.0'), session_created=True),
         decimal.Decimal('84.0'))
Example #2
0
 def test_calculate_credit_cost(self):
     self.assertEqual(
         MessageCost.calculate_credit_cost(
             decimal.Decimal('1.0'), decimal.Decimal('10.0'),
             decimal.Decimal('2.0'), session_created=False),
         decimal.Decimal('11.0'))
     self.assertEqual(
         MessageCost.calculate_credit_cost(
             decimal.Decimal('5.0'), decimal.Decimal('20.0'),
             decimal.Decimal('2.0'), session_created=False),
         decimal.Decimal('60.0'))
Example #3
0
 def test_calculate_message_credit_cost_with_context(self):
     context = decimal.Context()
     self.assertEqual(
         MessageCost.calculate_message_credit_cost(
             decimal.Decimal('1.0'), QUANTIZATION_EXPONENT,
             context=context),
         decimal.Decimal('10.0'))
     self.assertEqual(context.flags[decimal.Inexact], 1)
     self.assertEqual(context.flags[decimal.Rounded], 1)
Example #4
0
 def test_apply_markup_and_convert_to_credits_with_context(self):
     context = decimal.Context()
     self.assertEqual(
         MessageCost.apply_markup_and_convert_to_credits(
             decimal.Decimal('1.0'), QUANTIZATION_EXPONENT,
             context=context),
         decimal.Decimal('10.0'))
     self.assertEqual(context.flags[decimal.Inexact], 1)
     self.assertEqual(context.flags[decimal.Rounded], 1)
Example #5
0
    def get_cost(self, account_number, tag_pool_name, message_direction, session_created):
        """Return the message cost"""
        query = """
            SELECT t.account_number, t.tag_pool_name, t.message_direction,
                   t.message_cost, t.session_cost, t.markup_percent
            FROM (SELECT a.account_number, t.name AS tag_pool_name,
                         c.message_direction, c.message_cost,
                         c.session_cost, c.markup_percent
                  FROM billing_messagecost c
                  INNER JOIN billing_tagpool t ON (c.tag_pool_id = t.id)
                  INNER JOIN billing_account a ON (c.account_id = a.id)
                  WHERE a.account_number = %(account_number)s
                  AND t.name = %(tag_pool_name)s
                  AND c.message_direction = %(message_direction)s
                  UNION
                  SELECT NULL AS account_number, t.name AS tag_pool_name,
                         c.message_direction, c.message_cost,
                         c.session_cost, c.markup_percent
                  FROM billing_messagecost c
                  INNER JOIN billing_tagpool t ON (c.tag_pool_id = t.id)
                  WHERE c.account_id IS NULL
                  AND t.name = %(tag_pool_name)s
                  AND c.message_direction = %(message_direction)s
                  UNION
                  SELECT NULL AS account_number, NULL AS tag_pool_name,
                         c.message_direction, c.message_cost,
                         c.session_cost, c.markup_percent
                  FROM billing_messagecost c
                  WHERE c.account_id IS NULL
                  AND c.tag_pool_id IS NULL
                  AND c.message_direction = %(message_direction)s
            ) as t
            ORDER BY t.account_number
            LIMIT 1
            """

        params = {
            "account_number": account_number,
            "tag_pool_name": tag_pool_name,
            "message_direction": message_direction,
        }

        result = yield self._connection_pool.runQuery(query, params)
        if len(result) > 0:
            message_cost = result[0]
            message_cost["credit_amount"] = MessageCost.calculate_credit_cost(
                message_cost["message_cost"],
                message_cost["markup_percent"],
                message_cost["session_cost"],
                session_created=session_created,
            )

            defer.returnValue(message_cost)
        else:
            defer.returnValue(None)
Example #6
0
    def clean(self):
        """
        Check that:

        * the resulting message credit cost does not underflow to zero.
        * the resulting session credit cost does not underflow to zero.
        * that if the tag pool is not set, neither is the account (
          this is because our message cost lookup currently ignore
          such message costs)
        """
        cleaned_data = super(MessageCostForm, self).clean()
        message_cost = cleaned_data.get('message_cost')
        session_cost = cleaned_data.get('session_cost')
        markup_percent = cleaned_data.get('markup_percent')

        if message_cost and markup_percent:
            context = Context()
            credit_cost = MessageCost.calculate_message_credit_cost(
                message_cost, markup_percent, context=context)
            if cost_rounded_to_zero(credit_cost, context):
                raise forms.ValidationError(
                    "The resulting cost per message (in credits) was rounded"
                    " to 0.")

        if session_cost and markup_percent:
            context = Context()
            session_credit_cost = MessageCost.calculate_session_credit_cost(
                session_cost, markup_percent, context=context)
            if cost_rounded_to_zero(session_credit_cost, context):
                raise forms.ValidationError(
                    "The resulting cost per session (in credits) was rounded"
                    " to 0.")

        if not cleaned_data.get("tag_pool") and cleaned_data.get("account"):
            raise forms.ValidationError(
                "Message costs with an empty tag pool value and a non-empty"
                " account value are not currently supported by the billing"
                " API's message cost look up.")

        return cleaned_data
Example #7
0
    def test_transaction(self):
        yield self.create_api_user(email="[email protected]")
        account = yield self.create_api_account(email="[email protected]",
                                                account_number="11111")

        # Set the message cost
        yield self.create_api_cost(
            tag_pool_name="test_pool2",
            message_direction="Inbound",
            message_cost=0.6, session_cost=0.3,
            markup_percent=10.0)

        credit_amount = MessageCost.calculate_credit_cost(
            decimal.Decimal('0.6'), decimal.Decimal('10.0'),
            decimal.Decimal('0.3'), session_created=False)

        credit_amount_for_session = MessageCost.calculate_credit_cost(
            decimal.Decimal('0.6'), decimal.Decimal('10.0'),
            decimal.Decimal('0.3'), session_created=True)

        # Create a transaction
        yield self.create_api_transaction(
            account_number=account['account_number'],
            message_id='msg-id-1',
            tag_pool_name="test_pool2",
            tag_name="12345",
            message_direction="Inbound",
            session_created=False)

        # Make sure there was a transaction created
        [transaction] = yield self.get_api_transaction_list(
            account["account_number"])
        del (transaction['id'], transaction['created'],
             transaction['last_modified'])
        self.assertEqual(transaction, {
            u'account_number': account['account_number'],
            u'message_id': 'msg-id-1',
            u'credit_amount': -credit_amount,
            u'credit_factor': decimal.Decimal('10.000000'),
            u'markup_percent': decimal.Decimal('10.000000'),
            u'message_cost': decimal.Decimal('0.6'),
            u'message_direction': u'Inbound',
            u'session_cost': decimal.Decimal('0.3'),
            u'session_created': False,
            u'status': u'Completed',
            u'tag_name': u'12345',
            u'tag_pool_name': u'test_pool2'
        })

        # Get the account and make sure the credit balance was updated
        account = yield self.get_api_account(account["account_number"])
        self.assertEqual(account['credit_balance'], -credit_amount)

        # Create a transaction (with session_created=True)
        yield self.create_api_transaction(
            account_number=account['account_number'],
            message_id='msg-id-2',
            tag_pool_name="test_pool2",
            tag_name="12345",
            message_direction="Inbound",
            session_created=True)

        # Make sure there was a transaction created (with session_created=True)
        [transaction, _] = yield self.get_api_transaction_list(
            account["account_number"])
        del (transaction['id'], transaction['created'],
             transaction['last_modified'])
        self.assertEqual(transaction, {
            u'account_number': account['account_number'],
            u'message_id': 'msg-id-2',
            u'credit_amount': -credit_amount_for_session,
            u'credit_factor': decimal.Decimal('10.000000'),
            u'markup_percent': decimal.Decimal('10.000000'),
            u'message_cost': decimal.Decimal('0.6'),
            u'message_direction': u'Inbound',
            u'session_cost': decimal.Decimal('0.3'),
            u'session_created': True,
            u'status': u'Completed',
            u'tag_name': u'12345',
            u'tag_pool_name': u'test_pool2'
        })

        # Get the account and make sure the credit balance was updated
        account = yield self.get_api_account(account["account_number"])
        self.assertEqual(account['credit_balance'],
                         -(credit_amount + credit_amount_for_session))

        # Test override of cost by cost for specific account
        yield self.create_api_cost(
            account_number=account["account_number"],
            tag_pool_name="test_pool2",
            message_direction="Inbound",
            message_cost=9.0, session_cost=7.0,
            markup_percent=11.0)

        transaction = yield self.create_api_transaction(
            account_number=account['account_number'],
            message_id='msg-id-3',
            tag_pool_name="test_pool2",
            tag_name="12345",
            message_direction="Inbound",
            session_created=False)

        credit_amount = MessageCost.calculate_credit_cost(
            decimal.Decimal('9.0'), decimal.Decimal('11.0'),
            decimal.Decimal('7.0'), session_created=False)

        del (transaction['id'], transaction['created'],
             transaction['last_modified'])
        self.assertEqual(transaction, {
            u'account_number': account['account_number'],
            u'message_id': 'msg-id-3',
            u'credit_amount': -credit_amount,
            u'credit_factor': decimal.Decimal('10.0'),
            u'markup_percent': decimal.Decimal('11.0'),
            u'message_cost': decimal.Decimal('9.0'),
            u'message_direction': u'Inbound',
            u'session_cost': decimal.Decimal('7.0'),
            u'session_created': False,
            u'status': u'Completed',
            u'tag_name': u'12345',
            u'tag_pool_name': u'test_pool2',
        })

        # Test fallback to default cost
        yield self.create_api_cost(
            message_direction="Outbound",
            message_cost=0.1, session_cost=0.2,
            markup_percent=12.0)

        yield self.create_api_user(email="[email protected]")
        account = yield self.create_api_account(
            email="[email protected]", account_number="arbitrary-user")

        transaction = yield self.create_api_transaction(
            account_number="arbitrary-user",
            message_id='msg-id-4',
            tag_pool_name="some-random-pool",
            tag_name="erk",
            message_direction="Outbound",
            session_created=False)

        credit_amount = MessageCost.calculate_credit_cost(
            decimal.Decimal('0.1'), decimal.Decimal('12.0'),
            decimal.Decimal('0.2'), session_created=False)

        del (transaction['id'], transaction['created'],
             transaction['last_modified'])
        self.assertEqual(transaction, {
            u'account_number': 'arbitrary-user',
            u'message_id': 'msg-id-4',
            u'credit_amount': -credit_amount,
            u'credit_factor': decimal.Decimal('10.0'),
            u'markup_percent': decimal.Decimal('12.0'),
            u'message_cost': decimal.Decimal('0.1'),
            u'message_direction': u'Outbound',
            u'session_cost': decimal.Decimal('0.2'),
            u'session_created': False,
            u'status': u'Completed',
            u'tag_name': u'erk',
            u'tag_pool_name': u'some-random-pool',
        })

        # Test that message direction is correctly checked for
        # in the fallback case.
        try:
            yield self.create_api_transaction(
                account_number="arbitrary-user",
                message_id='msg-id-4',
                tag_pool_name="some-random-pool",
                tag_name="erk",
                message_direction="Inbound",
                session_created=False)
        except ApiCallError, e:
            self.assertEqual(e.response.responseCode, 500)
            self.assertEqual(
                e.message,
                "Unable to determine Inbound message cost for account"
                " arbitrary-user and tag pool some-random-pool")
Example #8
0
 def test_calculate_session_credit_cost(self):
     self.assertEqual(
         MessageCost.calculate_session_credit_cost(
             decimal.Decimal('1.0'), decimal.Decimal('50.0')),
         decimal.Decimal('15.0'))
Example #9
0
 def test_apply_markup_and_convert_to_credits(self):
     self.assertEqual(
         MessageCost.apply_markup_and_convert_to_credits(
             decimal.Decimal('1.0'), decimal.Decimal('50.0')),
         decimal.Decimal('15.0'))