Skip to content

Commit

Permalink
Merge pull request #458 from Neetuj/billing
Browse files Browse the repository at this point in the history
Adding billing
  • Loading branch information
underscorephil committed Jan 13, 2015
2 parents 3287aef + 7cae91d commit f764db2
Show file tree
Hide file tree
Showing 11 changed files with 454 additions and 4 deletions.
2 changes: 2 additions & 0 deletions SoftLayer/CLI/billing/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""Billing."""
# :license: MIT, see LICENSE for more details.
39 changes: 39 additions & 0 deletions SoftLayer/CLI/billing/info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""List billing details of Account."""
# :license: MIT, see LICENSE for more details.


import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting

import click


@click.command()
@environment.pass_env
def cli(env):
"""List billing details of Account."""
billing = SoftLayer.BillingManager(env.client)
table = formatting.Table(['Name', 'Value'])
info = billing.get_info()
table.add_row(['accountId', info['accountId']])
table.add_row(['id', info['id']])
table.add_row(['paymentTerms', info['paymentTerms']])
table.add_row(['modifyDate', info['modifyDate']])
table.add_row(['anniversaryDayOfMonth', info['anniversaryDayOfMonth']])
table.add_row(['lastFourPaymentCardDigits',
info['lastFourPaymentCardDigits']])
table.add_row(['cardExpirationMonth', info['cardExpirationMonth']])
table.add_row(['cardExpirationYear', info['cardExpirationYear']])
table.add_row(['percentDiscountOnetime', info['percentDiscountOnetime']])
table.add_row(['sparePoolAmount', info['sparePoolAmount']])
table.add_row(['lastPaymentDate', info['lastPaymentDate']])
table.add_row(['createDate', info['createDate']])
table.add_row(['percentDiscountRecurring',
info['percentDiscountRecurring']])
pass_table = formatting.Table(['Name', 'Value'])
result = info['currency']
for key in result.keys():
pass_table.add_row([key, result[key]])
table.add_row(['currency', pass_table])
return table
38 changes: 38 additions & 0 deletions SoftLayer/CLI/billing/list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""List billing information of orders."""
# :license: MIT, see LICENSE for more details.


import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer import utils

import click


@click.command()
@click.option('--start_date', '-f', help='cost incurred from this start date')
@click.option('--end_date', '-e',
help='cost incurred before this end date'
' (default is current time stamp)')
@environment.pass_env
def cli(env, start_date, end_date):
"""List billing information for orders."""
billing = SoftLayer.BillingManager(env.client)
from_date = start_date
to_date = end_date
table = formatting.Table(['Order ID', 'Resource Name', 'Resource Type',
'cost', 'create_date'])
resources = billing.list_resources(from_date, to_date)

for resource in resources:
resource = utils.NestedDict(resource)
table.add_row([
resource['id'],
resource['hostName'],
resource['resourceType'],
resource['cost'],
resource['createDate']
])

return table
25 changes: 25 additions & 0 deletions SoftLayer/CLI/billing/summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""List billing summary."""
# :license: MIT, see LICENSE for more details.


import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting

import click


@click.command()
@environment.pass_env
def cli(env):
"""List billing summary."""
billing = SoftLayer.BillingManager(env.client)
table = formatting.Table(['Name', 'Value'])
result = billing.get_summary()
balance = result['balance']
next_balance = result['nextbalance']
last_bill_date = result['lastbilldate']
table.add_row(['Current Balance', balance])
table.add_row(['Estimated Next Balance', next_balance])
table.add_row(['Last Billing Date', last_bill_date])
return table
5 changes: 5 additions & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
"""

ALL_ROUTES = [
('billing', 'SoftLayer.CLI.billing'),
('billing:list', 'SoftLayer.CLI.billing.list:cli'),
('billing:info', 'SoftLayer.CLI.billing.info:cli'),
('billing:summary', 'SoftLayer.CLI.billing.summary:cli'),

('call-api', 'SoftLayer.CLI.call_api:cli'),

('vs', 'SoftLayer.CLI.virt'),
Expand Down
9 changes: 5 additions & 4 deletions SoftLayer/managers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
:license: MIT, see LICENSE for more details.
"""
# pylint: disable=w0401

from SoftLayer.managers.billing import BillingManager # NOQA
from SoftLayer.managers.cdn import CDNManager # NOQA
from SoftLayer.managers.dns import DNSManager # NOQA
from SoftLayer.managers.firewall import FirewallManager # NOQA
Expand All @@ -25,8 +25,9 @@
from SoftLayer.managers.ticket import TicketManager # NOQA
from SoftLayer.managers.vs import VSManager # NOQA

__all__ = ['DNSManager', 'FirewallManager', 'HardwareManager',
'ImageManager', 'MessagingManager', 'MetadataManager', 'CDNManager',
'NetworkManager', 'SshKeyManager', 'SSLManager', 'TicketManager',
__all__ = ['BillingManager', 'DNSManager', 'FirewallManager',
'HardwareManager', 'ImageManager', 'MessagingManager',
'MetadataManager', 'CDNManager', 'NetworkManager',
'SshKeyManager', 'SSLManager', 'TicketManager',
'VSManager', 'ISCSIManager', 'LoadBalancerManager',
'OrderingManager']
232 changes: 232 additions & 0 deletions SoftLayer/managers/billing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
"""
SoftLayer.billing
~~~~~~~~~~~~
Billing Manager/helpers
:license: MIT, see LICENSE for more details.
"""
import calendar
import datetime

from SoftLayer import utils

import math
import time


class BillingManager(object):
"""Manages Billing details.
:param SoftLayer.managers.orderingManager
"""

def __init__(self, client):
"""init
:param client
:return: billing account info
"""
self.client = client
self.account = self.client['Account']
self.billing_order = self.client['Billing_Order']

def get_info(self):
"""get info
:return: billing account info
"""
result = self.account.getBillingInfo()
return result

def get_balance(self):
"""get balance
:return: billing account info
"""
result = self.account.getBalance()
return result

def get_next_balance(self):
"""get next balance
:return: billing account info
"""
result = self.account.getNextInvoiceTotalAmount()
return result

def get_latest_bill_date(self):
"""get latest balance
:return: billing account info
"""
result = self.account.getLatestBillDate()
return result

def get_summary(self):
"""get summary
:return: billing account info
"""
result = {
'lastbilldate': self.get_latest_bill_date(),
'balance': self.get_balance(),
'nextbalance': self.get_next_balance()
}
return result

def get_next_bill_items(self):
"""get next bill items
:return: billing account info
"""
result = self.account.getAllBillingItems()
return result

def list_resources(self, from_date=None, to_date=None, **kwargs):
"""Retrieve a list of all ordered resources along with their costing.
:param dict \\*\\*kwargs: response-level option (limit)
:returns: Returns a list of dictionaries representing the
matching ordered resorces by a user along with their costing
"""
params = {}
if 'mask' not in kwargs:
items = set([
'order[items[description,billingItem[id,hostName,'
'hourlyRecurringFee,cancellationDate,createDate,'
'laborFee,oneTimeFee,setupFee]]]'
])
params['mask'] = "mask[%s]" % ','.join(items)

_filter = utils.NestedDict({})
user = self.account.getCurrentUser(mask='mask[id]')
_filter['orders']['userRecordId'] = utils.query_filter(user['id'])
date_format = '%Y-%m-%d'

if from_date and to_date:
_filter['orders']['createDate'] = utils.query_filter_date(
from_date, to_date)
elif from_date:
from_date_filter = '>=' + ' ' + from_date
_filter['orders']['createDate'] = utils.query_filter(
from_date_filter)
elif to_date:
to_date_filter = '<=' + ' ' + to_date
_filter['orders']['createDate'] = utils.query_filter(
to_date_filter)
orders = self.account.getOrders(filter=_filter.to_dict())
result = []

for order in orders:
billing_order = self.client['Billing_Order']
params['id'] = order_id = order['id']
items = billing_order.getItems(**params)
cost = float(0.0)
resource_type = ''
flag = 1
hostname = ''
creation_date = ''

for item in items:
if flag == 1:
resource_type = item['description']

if 'Core' in resource_type and flag == 1:
hostname = item['billingItem']['hostName']
flag = 0
usedmonths = 1

creation_date = item['billingItem']['createDate']
cancellation_date = item['billingItem']['cancellationDate']

if 'hourlyRecurringFee' not in item['billingItem']:
create_date = datetime.datetime.strptime(
format_date(
item['billingItem']['createDate']), date_format)
if cancellation_date:
cancel_date = datetime.datetime.strptime(
format_date(
item['billingItem']['cancellationDate']),
date_format)
usedmonths = get_month_delta(create_date, cancel_date)
else:
now = datetime.datetime.strptime(
format_date(str(datetime.datetime.now())),
date_format)
usedmonths = get_month_delta(create_date, now)

usedmonths += 1

cost += float(
billing_order.getOrderTotalOneTime(
id=order['id']
) + billing_order.getOrderTotalRecurring(
id=order['id']
) * usedmonths
)

elif not cancellation_date:
virtual_guest = self.account.getHourlyVirtualGuests(
filter={
'hourlyVirtualGuests': {
'hourlyVirtualGuests': {
'billingItem': {
'id': {
'operation':
item['billingItem']['id']}}}}})
if virtual_guest:
guest = virtual_guest[0]
cost = guest['billingItem']['currentHourlyCharge']

else:
create_date = datetime.datetime.strptime(
format_date(creation_date), date_format)
cancel_date = datetime.datetime.strptime(
format_date(cancellation_date), date_format)
d1_ts = time.mktime(create_date.timetuple())
d2_ts = time.mktime(cancel_date.timetuple())
usedhours = math.ceil(d2_ts - d1_ts)/3600
cost += usedhours * float(
item['billingItem']['hourlyRecurringFee']
) + float(
item['billingItem']['laborFee']
) + float(
item['billingItem']['oneTimeFee']
) + float(
item['billingItem']['setupFee'])
resource = {
'id': order_id,
'resourceType': resource_type,
'hostName': hostname,
'createDate': creation_date,
'cost': cost
}
result.append(resource)
return result


def format_date(date):
"""format date.
:param date: YY-MM-DD
"""
result = date.replace('T', ' ')
return result[0:10]


def get_month_delta(date1, date2):
"""get month
:param date1: YY-MM-DD
:param date2: YY-MM-DD
:return: delta
"""
delta = 0
while True:
mdays = calendar.monthrange(date1.year, date1.month)[1]
date1 += datetime.timedelta(days=mdays)
if date1 <= date2:
delta += 1
else:
break
return delta

0 comments on commit f764db2

Please sign in to comment.