adding api call to get sales orders in a given range
udating the api to be able to return salesorders between a given range, as well as the client/shell to make use of this. Has resulted in a lot of duplicate code, but next patch will go through and clean up a bunch of that, and extract a few validators into either decorators, or at least helper functions. Change-Id: I59ed58c32b8dd4a75babf70df188e965e5e94a16
This commit is contained in:
parent
66a8c0ad78
commit
a0b8ec9b7f
@ -2,15 +2,17 @@ from decorator import decorator
|
||||
import flask
|
||||
import itertools
|
||||
import json
|
||||
from artifice.models import Tenant
|
||||
|
||||
|
||||
def _validate(data, *args, **kwargs):
|
||||
for key in itertools.chain(args, kwargs.keys()):
|
||||
if not key in data:
|
||||
flask.abort(400, json.dumps({'error': 'missing parameter',
|
||||
'param': key}))
|
||||
'param': key}))
|
||||
for key, val in kwargs.iteritems():
|
||||
flask.abort(400, json.dumps({'error': 'validation failed',
|
||||
'param': key}))
|
||||
'param': key}))
|
||||
|
||||
|
||||
def must(*args, **kwargs):
|
||||
@ -47,3 +49,19 @@ def json_must(*args, **kwargs):
|
||||
return func(*iargs)
|
||||
return decorator(dejson, func)
|
||||
return unpack
|
||||
|
||||
|
||||
def validate_tenant_id(tenant_id, session):
|
||||
"""Tenant ID validation that check that the id you passed is valid,
|
||||
and that a tenant with this ID exists.
|
||||
- returns tenant query, or a tuple if validation failure."""
|
||||
if isinstance(tenant_id, unicode):
|
||||
tenant_query = session.query(Tenant).\
|
||||
filter(Tenant.id == tenant_id)
|
||||
if tenant_query.count() == 0:
|
||||
return 400, {"errors": ["No tenant matching ID found."]}
|
||||
elif tenant_id is not None:
|
||||
return 400, {"error": ["tenant must be a unicode string."]}
|
||||
else:
|
||||
return 400, {"missing parameter": {"tenant": "Tenant id."}}
|
||||
return tenant_query[0]
|
||||
|
@ -3,7 +3,7 @@ from flask import Flask, Blueprint
|
||||
from artifice import interface, database, config
|
||||
from artifice.transformers import active_transformers
|
||||
from artifice.rates import RatesFile
|
||||
from artifice.models import SalesOrder, Tenant
|
||||
from artifice.models import SalesOrder
|
||||
from artifice.helpers import convert_to
|
||||
import sqlalchemy
|
||||
from sqlalchemy import create_engine, func
|
||||
@ -12,7 +12,7 @@ from sqlalchemy.pool import NullPool
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
|
||||
from .helpers import returns_json, json_must
|
||||
from .helpers import returns_json, json_must, validate_tenant_id
|
||||
|
||||
|
||||
engine = None
|
||||
@ -224,19 +224,12 @@ def add_costs_for_tenant(tenant, RatesManager):
|
||||
|
||||
def generate_sales_order(draft, tenant_id, end):
|
||||
session = Session()
|
||||
|
||||
if isinstance(tenant_id, unicode):
|
||||
tenant_query = session.query(Tenant).\
|
||||
filter(Tenant.id == tenant_id)
|
||||
if tenant_query.count() == 0:
|
||||
return 400, {"errors": ["No tenant matching ID found."]}
|
||||
elif tenant_id is not None:
|
||||
return 400, {"error": ["tenant must be a unicode string."]}
|
||||
else:
|
||||
return 400, {"missing parameter": {"tenant": "Tenant id."}}
|
||||
|
||||
db = database.Database(session)
|
||||
|
||||
valid_tenant = validate_tenant_id(tenant_id, session)
|
||||
if isinstance(valid_tenant, tuple):
|
||||
return valid_tenant
|
||||
|
||||
rates = RatesFile(config.rates_config)
|
||||
|
||||
# Get the last sales order for this tenant, to establish
|
||||
@ -268,7 +261,7 @@ def generate_sales_order(draft, tenant_id, end):
|
||||
session.commit()
|
||||
|
||||
# Transform the query result into a billable dict.
|
||||
tenant_dict = build_tenant_dict(tenant_query[0], usage, db)
|
||||
tenant_dict = build_tenant_dict(valid_tenant, usage, db)
|
||||
tenant_dict = add_costs_for_tenant(tenant_dict, rates)
|
||||
|
||||
# add sales order range:
|
||||
@ -285,39 +278,22 @@ def generate_sales_order(draft, tenant_id, end):
|
||||
|
||||
def regenerate_sales_order(tenant_id, target):
|
||||
session = Session()
|
||||
|
||||
db = database.Database(session)
|
||||
|
||||
if isinstance(tenant_id, unicode):
|
||||
tenant_query = session.query(Tenant).\
|
||||
filter(Tenant.id == tenant_id)
|
||||
if tenant_query.count() == 0:
|
||||
return 400, {"errors": ["No tenant matching ID found."]}
|
||||
elif tenant_id is not None:
|
||||
return 400, {"error": ["tenant must be a unicode string."]}
|
||||
else:
|
||||
return 400, {"missing parameter": {"tenant": "Tenant id."}}
|
||||
|
||||
if target is not None:
|
||||
try:
|
||||
target = datetime.strptime(target, iso_date)
|
||||
except ValueError:
|
||||
return 400, {"errors": ["date given needs to be in format: " +
|
||||
"y-m-d"]}
|
||||
else:
|
||||
return 400, {"missing parameter": {"date": "target date in format: " +
|
||||
"y-m-d"}}
|
||||
|
||||
rates = RatesFile(config.rates_config)
|
||||
|
||||
valid_tenant = validate_tenant_id(tenant_id, session)
|
||||
if isinstance(valid_tenant, tuple):
|
||||
return valid_tenant
|
||||
|
||||
try:
|
||||
sales_order = db.get_sales_order(tenant_id, target)
|
||||
sales_order = db.get_sales_orders(tenant_id, target, target)
|
||||
except IndexError:
|
||||
return 400, {"errors": ["Given date not in existing sales orders."]}
|
||||
|
||||
usage = db.usage(sales_order.start, sales_order.end, tenant_id)
|
||||
|
||||
# Transform the query result into a billable dict.
|
||||
tenant_dict = build_tenant_dict(tenant_query[0], usage, db)
|
||||
tenant_dict = build_tenant_dict(valid_tenant, usage, db)
|
||||
tenant_dict = add_costs_for_tenant(tenant_dict, rates)
|
||||
|
||||
# add sales order range:
|
||||
@ -327,6 +303,34 @@ def regenerate_sales_order(tenant_id, target):
|
||||
return 200, tenant_dict
|
||||
|
||||
|
||||
def regenerate_sales_order_range(tenant_id, start, end):
|
||||
session = Session()
|
||||
db = database.Database(session)
|
||||
rates = RatesFile(config.rates_config)
|
||||
|
||||
valid_tenant = validate_tenant_id(tenant_id, session)
|
||||
if isinstance(valid_tenant, tuple):
|
||||
return valid_tenant
|
||||
|
||||
sales_orders = db.get_sales_orders(tenant_id, start, end)
|
||||
|
||||
tenants = []
|
||||
for sales_order in sales_orders:
|
||||
usage = db.usage(sales_order.start, sales_order.end, tenant_id)
|
||||
|
||||
# Transform the query result into a billable dict.
|
||||
tenant_dict = build_tenant_dict(valid_tenant, usage, db)
|
||||
tenant_dict = add_costs_for_tenant(tenant_dict, rates)
|
||||
|
||||
# add sales order range:
|
||||
tenant_dict['start'] = str(sales_order.start)
|
||||
tenant_dict['end'] = str(sales_order.end)
|
||||
|
||||
tenants.append(tenant_dict)
|
||||
|
||||
return 200, tenants
|
||||
|
||||
|
||||
@app.route("sales_order", methods=["POST"])
|
||||
@json_must()
|
||||
@returns_json
|
||||
@ -377,8 +381,43 @@ def run_sales_historic_generation():
|
||||
tenant_id = flask.request.json.get("tenant", None)
|
||||
target = flask.request.json.get("date", None)
|
||||
|
||||
if target is not None:
|
||||
try:
|
||||
target = datetime.strptime(target, iso_date)
|
||||
except ValueError:
|
||||
return 400, {"errors": ["date given needs to be in format: " +
|
||||
"y-m-d"]}
|
||||
else:
|
||||
return 400, {"missing parameter": {"date": "target date in format: " +
|
||||
"y-m-d"}}
|
||||
|
||||
return regenerate_sales_order(tenant_id, target)
|
||||
|
||||
|
||||
@app.route("sales_range", methods=["POST"])
|
||||
@json_must()
|
||||
@returns_json
|
||||
def run_sales_historic_range_generation():
|
||||
tenant_id = flask.request.json.get("tenant", None)
|
||||
start = flask.request.json.get("start", None)
|
||||
end = flask.request.json.get("end", None)
|
||||
|
||||
try:
|
||||
if start is not None:
|
||||
start = datetime.strptime(start, iso_date)
|
||||
else:
|
||||
return 400, {"missing parameter": {"start": "start date in format: " +
|
||||
"y-m-d"}}
|
||||
if end is not None:
|
||||
end = datetime.strptime(end, iso_date)
|
||||
else:
|
||||
end = datetime.utcnow()
|
||||
except ValueError:
|
||||
return 400, {"errors": ["dates given need to be in format: " +
|
||||
"y-m-d"]}
|
||||
|
||||
return regenerate_sales_order_range(tenant_id, start, end)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
@ -90,11 +90,11 @@ class Database(object):
|
||||
filter(Resource.id == resource_id)
|
||||
return json.loads(info[0].info)
|
||||
|
||||
def get_sales_order(self, tenant_id, target):
|
||||
def get_sales_orders(self, tenant_id, start, end):
|
||||
query = self.session.query(SalesOrder).\
|
||||
filter(SalesOrder.start <= target, SalesOrder.end >= target).\
|
||||
filter(SalesOrder.start <= end, SalesOrder.end >= start).\
|
||||
filter(SalesOrder.tenant_id == tenant_id)
|
||||
return query[0]
|
||||
return query
|
||||
|
||||
def merge_resource_metadata(self, md_dict, entry):
|
||||
fields = config.collection['metadata_def'].get(md_dict['type'], {})
|
||||
|
@ -65,3 +65,23 @@ class Client(object):
|
||||
print json.dumps(response.json(), indent=2, sort_keys=True)
|
||||
except ConnectionError as e:
|
||||
print e
|
||||
|
||||
def sales_range(self, tenants, start, end):
|
||||
url = self.endpoint + "sales_range"
|
||||
|
||||
for tenant in tenants:
|
||||
data = {"tenant": tenant, "start": start, "end": end}
|
||||
try:
|
||||
response = requests.post(url,
|
||||
headers={"Content-Type":
|
||||
"application/json",
|
||||
"token": self.auth_token},
|
||||
data=json.dumps(data))
|
||||
if response.status_code != 200:
|
||||
raise AttributeError("Sales order cycle failed: " +
|
||||
response.text + " code: " +
|
||||
str(response.status_code))
|
||||
else:
|
||||
print json.dumps(response.json(), indent=2, sort_keys=True)
|
||||
except ConnectionError as e:
|
||||
print e
|
||||
|
@ -82,6 +82,22 @@ if __name__ == '__main__':
|
||||
"-d", "--date", dest="date",
|
||||
help='target search date for sales order.')
|
||||
|
||||
range_parser = subparsers.add_parser(
|
||||
'sales-range',
|
||||
help=('regenerate historic sales orders for given tenants,' +
|
||||
'in a given range'))
|
||||
range_parser.add_argument(
|
||||
"-t", "--tenant", dest="tenants",
|
||||
help='Tenants to create sales drafts for.',
|
||||
action="append", default=[])
|
||||
range_parser.add_argument(
|
||||
"-s", "--start", dest="start",
|
||||
help='start of range for sales orders.')
|
||||
range_parser.add_argument(
|
||||
"-e", "--end", dest="end",
|
||||
help='end of range for sales orders. Defaults to now.',
|
||||
default=None)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
conf = {'api': {'endpoint': 'http://0.0.0.0:8000/',
|
||||
@ -107,3 +123,6 @@ if __name__ == '__main__':
|
||||
|
||||
if args.command == 'sales-historic':
|
||||
client.sales_historic(args.tenants, args.date)
|
||||
|
||||
if args.command == 'sales-range':
|
||||
client.sales_range(args.tenants, args.start, args.end)
|
||||
|
Loading…
x
Reference in New Issue
Block a user