Skip to content

Commit 5034f88

Browse files
Merge pull request #62 from JaviCerveraIngram/CPS-34-reporting-usage-files
CPS-34-reporting-usage-files
2 parents 4d3954d + ad6298c commit 5034f88

File tree

10 files changed

+55
-17
lines changed

10 files changed

+55
-17
lines changed

connect/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __init__(self, api_url=None, api_key=None, products=None, file=None):
5757

5858
# Initialize
5959
self._api_key = api_key
60-
self._api_url = api_url
60+
self._api_url = api_url if api_url.endswith('/') else api_url + '/'
6161
self._products = [products] \
6262
if isinstance(products, str) \
6363
else products or []

connect/models/asset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Asset(BaseModel):
4747
- new: First purchase requested.
4848
- processing: Until first purchase request is either completed or rejected.
4949
- active: After the first purchase request is completed.
50-
NOTE: Asset stays active regardless of any other requests except cancel.
50+
NOTE: Asset stays active regardless of any other requests except cancel.
5151
- rejected: Asset becomes rejected once the first purchase request is rejected.
5252
- terminated: Asset becomes terminated once the 'cancel' request type is fulfilled.
5353
- suspended: Asset becomes suspended once 'suspend' request type is fulfilled.

connect/models/schemas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ def make_object(self, data):
368368

369369
class ServerErrorResponseSchema(Schema):
370370
error_code = fields.Str()
371-
params = fields.Dict()
371+
params = fields.Dict(allow_none=True)
372372
errors = fields.List(fields.Str())
373373

374374
@post_load
@@ -556,7 +556,7 @@ def make_object(self, data):
556556

557557

558558
class UsageRecordSchema(BaseSchema):
559-
record_id = fields.Str()
559+
usage_record_id = fields.Str()
560560
item_search_criteria = fields.Str()
561561
item_search_value = fields.Str()
562562
quantity = fields.Int()

connect/models/usage.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ class UsageRecord(BaseModel):
149149

150150
_schema = UsageRecordSchema()
151151

152-
record_id = None # type: str
153-
""" (str) Record id. """
152+
usage_record_id = None # type: str
153+
""" (str) Usage record id. """
154154

155155
item_search_criteria = None # type: str
156156
""" (str) Item search criteria. """

connect/resources/automation_engine.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ def filters(self, status='pending', **kwargs):
1818
# type: (str, Dict[str, Any]) -> Dict[str, Any]
1919
return super(AutomationEngine, self).filters(status=status, **kwargs)
2020

21-
def process(self):
22-
# type: () -> None
23-
for request in self.list():
21+
def process(self, filters=None):
22+
# type: (Dict[str, Any]) -> None
23+
for request in self.list(filters):
2424
self.dispatch(request)
2525

2626
def dispatch(self, request):

connect/resources/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,12 @@ def _check_and_pack_response(response):
102102
)
103103

104104
if not response.ok:
105-
error = ServerErrorResponse.deserialize(response.text)
105+
try:
106+
error = ServerErrorResponse.deserialize(response.text)
107+
except ValueError:
108+
error = None
109+
if not error or not error.error_code:
110+
error = ServerErrorResponse(errors=[response.text])
106111
raise ServerError(error)
107112

108113
return response.text, response.status_code

connect/resources/fulfillment_automation.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@ class FulfillmentAutomation(AutomationEngine):
3939

4040
def filters(self, status='pending', **kwargs):
4141
"""
42+
Returns the default set of filters for Fulfillment request, plus any others that you might
43+
specify. The allowed filters are:
44+
45+
- status
46+
- created
47+
- id (List support)
48+
- type (purchase|renew|change|cancel)
49+
- asset.id (asset_id) - (List support)
50+
- asset.product.id (product_id)
51+
- asset.product.name - (List support)
52+
- asset.hub.id
53+
- asset.connection.hub.name - (List support)
54+
- asset.connection.provider.id
55+
- asset.connection.provider.name - (List support)
56+
- asset.connection.vendor.name - (List support)
57+
- asset.tiers.customer.id (Customer ID)
58+
- asset.tiers.tier1.id
59+
- asset.tiers.tier2.id
60+
- asset.connection.type (test|production|preview)
61+
4262
:param str status: Status of the requests. Default: ``'pending'``.
4363
:param dict[str,Any] kwargs: Additional filters to add to the default ones.
4464
:return: The set of filters for this resource.

connect/resources/usage_automation.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class UsageAutomation(AutomationEngine):
2424
"""
2525

2626
__metaclass__ = ABCMeta
27-
resource = 'usage/files'
27+
resource = 'listings'
2828
model_class = UsageFile
2929

3030
def filters(self, status='draft', **kwargs):
@@ -104,7 +104,7 @@ def submit_usage(self, usage_file, usage_records):
104104
def _get_usage_template_download_location(self, product_id):
105105
# type: (str) -> str
106106
try:
107-
response, _ = self._api.get(url='{}/usage/products/{}/template/'
107+
response, _ = self._api.get(url='{}usage/products/{}/template/'
108108
.format(self.config.api_url, product_id))
109109
response_dict = json.loads(response)
110110
return response_dict['template_link']
@@ -127,7 +127,8 @@ def _create_usage_file(self, usage_file):
127127
if not usage_file.description:
128128
# Could be because description is empty or None, so make sure it is empty
129129
usage_file.description = ''
130-
response, _ = self._api.post(json=usage_file.json)
130+
response, _ = self._api.post(url='{}usage/files/'
131+
.format(self.config.api_url), json=usage_file.json)
131132
return self.model_class.deserialize(response)
132133

133134
def _upload_usage_records(self, usage_file, usage_records):
@@ -152,7 +153,7 @@ def _create_spreadsheet(usage_records):
152153
sheet['H1'] = 'asset_search_value'
153154
for index, record in enumerate(usage_records):
154155
row = str(index + 2)
155-
sheet['A' + row] = record.record_id
156+
sheet['A' + row] = record.usage_record_id
156157
sheet['B' + row] = record.item_search_criteria
157158
sheet['C' + row] = record.item_search_value
158159
sheet['D' + row] = record.quantity
@@ -172,7 +173,7 @@ def _upload_spreadsheet(self, usage_file, spreadsheet):
172173
file_contents = tmp.read()
173174

174175
# Setup request
175-
url = self._api.get_url(usage_file.id + '/upload/')
176+
url = '{}usage/files/{}/upload/'.format(self.config.api_url, usage_file.id)
176177
headers = self._api.headers
177178
headers['Accept'] = 'application/json'
178179
del headers['Content-Type'] # This must NOT be set for multipart post requests
@@ -182,7 +183,7 @@ def _upload_spreadsheet(self, usage_file, spreadsheet):
182183
# Post request
183184
try:
184185
content, status = self._api.post(
185-
path=usage_file.id + '/upload/',
186+
url=url,
186187
headers=headers,
187188
files=multipart)
188189
except requests.RequestException as ex:

connect/resources/usage_file_automation.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ class UsageFileAutomation(AutomationEngine):
2121
resource = 'usage/files'
2222
model_class = UsageFile
2323

24+
def filters(self, status='ready', **kwargs):
25+
"""
26+
:param str status: Status of the requests. Default: ``'ready'``.
27+
:param dict[str,Any] kwargs: Additional filters to add to the default ones.
28+
:return: The set of filters for this resource.
29+
:rtype: dict[str,Any]
30+
"""
31+
filters = super(UsageFileAutomation, self).filters(status, **kwargs)
32+
if self.config.products:
33+
filters['product__id'] = ','.join(self.config.products)
34+
return filters
35+
2436
def dispatch(self, request):
2537
# type: (UsageFile) -> str
2638
try:

tests/test_usage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_get_usage_template_ok(get_mock):
5353
assert resource.get_usage_template(Product(id='PRD-638-321-603')) == b'template_contents'
5454
get_mock.assert_has_calls([
5555
call(
56-
url='http://localhost:8080/api/public/v1//usage/products/PRD-638-321-603/template/',
56+
url='http://localhost:8080/api/public/v1/usage/products/PRD-638-321-603/template/',
5757
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'}),
5858
call('...')
5959
])

0 commit comments

Comments
 (0)