Skip to content
This repository has been archived by the owner on Jun 12, 2018. It is now read-only.

Commit

Permalink
Merge branch 'develop' into feature/issue-1163-update-billing-dispatc…
Browse files Browse the repository at this point in the history
…her-to-send-provider-information

Conflicts:
	go/vumitools/billing_worker.py
	go/vumitools/tests/test_billing_worker.py
  • Loading branch information
justinvdm committed Jan 29, 2015
2 parents 4892d66 + 1ca59e2 commit 1d29160
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 63 deletions.
4 changes: 3 additions & 1 deletion go/billing/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ class MessageCostAdmin(admin.ModelAdmin):
'markup_percent', 'message_credit_cost',
'storage_credit_cost', 'session_credit_cost')

search_fields = ('tag_pool__name', 'account__account_number')
search_fields = (
'tag_pool__name', 'tag_pool__description', 'account__account_number',
'account__user__email', 'account__description')
list_filter = ('tag_pool', 'message_direction')
form = MessageCostForm

Expand Down
92 changes: 50 additions & 42 deletions go/billing/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,17 @@ def render_POST(self, request):
message_id = data.get('message_id', None)
tag_pool_name = data.get('tag_pool_name', None)
tag_name = data.get('tag_name', None)
provider = data.get('provider', None)
message_direction = data.get('message_direction', None)
session_created = data.get('session_created', None)
transaction_type = data.get('transaction_type', None)

if all((account_number, message_id, tag_pool_name, tag_name,
message_direction, session_created is not None)):
d = self.create_transaction(
account_number, message_id, tag_pool_name, tag_name,
message_direction, session_created)
provider, message_direction,
session_created, transaction_type)

d.addCallbacks(self._render_to_json, self._handle_error,
callbackArgs=[request], errbackArgs=[request])
Expand All @@ -141,47 +145,43 @@ def render_POST(self, request):
return NOT_DONE_YET

@defer.inlineCallbacks
def get_cost(self, account_number, tag_pool_name, message_direction,
session_created):
def get_cost(self, account_number, tag_pool_name, provider,
message_direction, session_created):
"""Return the message cost"""
query = """
SELECT t.account_number, t.tag_pool_name, t.message_direction,
SELECT t.account_number, t.tag_pool_name,
t.provider, t.message_direction,
t.message_cost, t.storage_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.storage_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.storage_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.storage_cost,
c.session_cost, c.markup_percent
c.provider, c.message_direction,
c.message_cost, c.storage_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
LEFT OUTER JOIN billing_tagpool t ON (c.tag_pool_id = t.id)
LEFT OUTER JOIN billing_account a ON (c.account_id = a.id)
WHERE
(a.account_number = %(account_number)s OR
c.account_id IS NULL)
AND
(t.name = %(tag_pool_name)s OR c.tag_pool_id IS NULL)
AND
(c.provider = %(provider)s OR c.provider IS NULL)
AND
(c.message_direction = %(message_direction)s)
) as t
ORDER BY t.account_number
ORDER BY
t.account_number NULLS LAST,
t.tag_pool_name NULLS LAST,
t.provider NULLS LAST
LIMIT 1
"""
"""

params = {
'account_number': account_number,
'tag_pool_name': tag_pool_name,
'message_direction': message_direction
'provider': provider,
'message_direction': message_direction,
}

result = yield self._connection_pool.runQuery(query, params)
Expand All @@ -201,10 +201,11 @@ def get_cost(self, account_number, tag_pool_name, message_direction,
@defer.inlineCallbacks
def create_transaction_interaction(self, cursor, account_number,
message_id, tag_pool_name, tag_name,
message_direction, session_created):
provider, message_direction,
session_created, transaction_type):
"""Create a new transaction for the given ``account_number``"""
# Get the message cost
result = yield self.get_cost(account_number, tag_pool_name,
result = yield self.get_cost(account_number, tag_pool_name, provider,
message_direction, session_created)
if result is None:
raise BillingError(
Expand All @@ -230,25 +231,28 @@ def create_transaction_interaction(self, cursor, account_number,
# Create a new transaction
query = """
INSERT INTO billing_transaction
(account_number, message_id,
(account_number, message_id, transaction_type,
tag_pool_name, tag_name,
message_direction, message_cost, storage_cost,
provider, message_direction,
message_cost, storage_cost,
session_created, session_cost, markup_percent,
message_credits, storage_credits, session_credits,
credit_factor, credit_amount, status, created, last_modified)
VALUES
(%(account_number)s, %(message_id)s,
(%(account_number)s, %(message_id)s, %(transaction_type)s,
%(tag_pool_name)s, %(tag_name)s,
%(message_direction)s, %(message_cost)s, %(storage_cost)s,
%(provider)s, %(message_direction)s,
%(message_cost)s, %(storage_cost)s,
%(session_created)s, %(session_cost)s, %(markup_percent)s,
%(message_credits)s, %(storage_credits)s, %(session_credits)s,
%(credit_factor)s, %(credit_amount)s,
'Completed', now(),
now())
RETURNING id, account_number, message_id,
RETURNING id, account_number, message_id, transaction_type,
tag_pool_name, tag_name,
message_direction, message_cost, storage_cost,
session_cost, session_created, markup_percent,
provider, message_direction,
message_cost, storage_cost, session_cost,
session_created, markup_percent,
message_credits, storage_credits, session_credits,
credit_factor, credit_amount, status,
created, last_modified
Expand All @@ -257,8 +261,10 @@ def create_transaction_interaction(self, cursor, account_number,
params = {
'account_number': account_number,
'message_id': message_id,
'transaction_type': transaction_type,
'tag_pool_name': tag_pool_name,
'tag_name': tag_name,
'provider': provider,
'message_direction': message_direction,
'message_cost': message_cost,
'storage_cost': storage_cost,
Expand Down Expand Up @@ -389,11 +395,13 @@ def ceil_percent(n):

@defer.inlineCallbacks
def create_transaction(self, account_number, message_id, tag_pool_name,
tag_name, message_direction, session_created):
tag_name, provider, message_direction,
session_created, transaction_type):
"""Create a new transaction for the given ``account_number``"""
result = yield self._connection_pool.runInteraction(
self.create_transaction_interaction, account_number, message_id,
tag_pool_name, tag_name, message_direction, session_created)
tag_pool_name, tag_name, provider, message_direction,
session_created, transaction_type)

defer.returnValue(result)

Expand Down
14 changes: 12 additions & 2 deletions go/billing/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ def get_transactions(account, statement):


def get_message_transactions(transactions):
transactions = transactions.filter(
transaction_type=Transaction.TRANSACTION_TYPE_MESSAGE)

transactions = transactions.values(
'tag_pool_name',
'tag_name',
Expand All @@ -65,6 +68,9 @@ def get_message_transactions(transactions):


def get_storage_transactions(transactions):
transactions = transactions.filter(
transaction_type=Transaction.TRANSACTION_TYPE_MESSAGE)

transactions = transactions.values(
'storage_cost',
'storage_credits')
Expand All @@ -78,7 +84,9 @@ def get_storage_transactions(transactions):


def get_session_transactions(transactions):
transactions = transactions.filter(session_created=True)
transactions = transactions.filter(
session_created=True,
transaction_type=Transaction.TRANSACTION_TYPE_MESSAGE)

transactions = transactions.values(
'tag_pool_name',
Expand Down Expand Up @@ -166,8 +174,10 @@ def get_channel_type(transaction, tagpools):
def get_message_description(transaction):
if transaction['message_direction'] == MessageCost.DIRECTION_INBOUND:
return 'Messages received'
else:
elif transaction['message_direction'] == MessageCost.DIRECTION_OUTBOUND:
return 'Messages sent'
else:
return None


def make_message_item(statement, transaction, tagpools):
Expand Down
111 changes: 101 additions & 10 deletions go/billing/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,21 @@ def setUp(self):

return BillingApiTestCase.setUp(self)

def create_api_transaction(self, account_number, message_id, tag_pool_name,
tag_name, message_direction, session_created):
def create_api_transaction(self, **kwargs):
"""
Create a transaction record via the billing API.
"""
content = {
'account_number': account_number,
'message_id': message_id,
'tag_pool_name': tag_pool_name,
'tag_name': tag_name,
'message_direction': message_direction,
'session_created': session_created,
'account_number': self.account.account_number,
'message_id': 'msg-id-1',
'tag_pool_name': 'pool1',
'tag_name': 'tag1',
'message_direction': MessageCost.DIRECTION_INBOUND,
'session_created': False,
'provider': None,
'transaction_type': Transaction.TRANSACTION_TYPE_MESSAGE
}
content.update(kwargs)
return self.call_api('post', 'transactions', content=content)

def assert_model(self, model, **kw):
Expand Down Expand Up @@ -281,7 +283,8 @@ def test_transaction(self):
tag_pool_name='pool1',
tag_name='tag1',
message_direction=MessageCost.DIRECTION_INBOUND,
session_created=False)
session_created=False,
transaction_type=Transaction.TRANSACTION_TYPE_MESSAGE)

# Make sure there was a transaction created
transaction = Transaction.objects.latest('created')
Expand All @@ -303,7 +306,8 @@ def test_transaction(self):
storage_credits=get_storage_credits(0.5, 10.0),
session_credits=get_session_credits(0.3, 10.0),
status=Transaction.STATUS_COMPLETED,
message_direction=MessageCost.DIRECTION_INBOUND)
message_direction=MessageCost.DIRECTION_INBOUND,
transaction_type=Transaction.TRANSACTION_TYPE_MESSAGE)

# Get the account and make sure the credit balance was updated
account = Account.objects.get(id=account.id)
Expand Down Expand Up @@ -481,3 +485,90 @@ def test_transaction(self):
("Unable to find billing account unknown-account while"
" checking credit balance. Message was Outbound to/from"
" tag pool pool2.",))

@inlineCallbacks
def test_transaction_provider(self):
mk_message_cost(tag_pool=self.pool1)

transaction = yield self.create_api_transaction(
account_number=self.account.account_number,
provider='mtn')

self.assertEqual(transaction['provider'], 'mtn')

self.assert_model(
model=Transaction.objects.latest('created'),
provider='mtn')

@inlineCallbacks
def test_transaction_provider_none(self):
mk_message_cost(tag_pool=self.pool1)

yield self.create_api_transaction(
account_number=self.account.account_number,
provider=None)

self.assert_model(
model=Transaction.objects.latest('created'),
provider=None)

@inlineCallbacks
def test_transaction_provider_cost(self):
mk_message_cost(
tag_pool=self.pool1,
message_cost=0.8,
provider=None)

mk_message_cost(
tag_pool=self.pool1,
message_cost=0.7,
provider='vodacom')

mk_message_cost(
tag_pool=self.pool1,
message_cost=0.6,
provider='mtn')

yield self.create_api_transaction(
account_number=self.account.account_number,
provider='mtn')

self.assert_model(
model=Transaction.objects.latest('created'),
message_cost=Decimal('0.6'))

yield self.create_api_transaction(
account_number=self.account.account_number,
provider='vodacom')

self.assert_model(
model=Transaction.objects.latest('created'),
message_cost=Decimal('0.7'))

@inlineCallbacks
def test_transaction_provider_fallback_cost(self):
mk_message_cost(
tag_pool=self.pool1,
message_cost=0.8,
provider=None)

mk_message_cost(
tag_pool=self.pool1,
message_cost=0.6,
provider='mtn')

yield self.create_api_transaction(
account_number=self.account.account_number,
provider='unknown')

self.assert_model(
model=Transaction.objects.latest('created'),
message_cost=Decimal('0.8'))

yield self.create_api_transaction(
account_number=self.account.account_number,
provider=None)

self.assert_model(
model=Transaction.objects.latest('created'),
message_cost=Decimal('0.8'))
Loading

0 comments on commit 1d29160

Please sign in to comment.