Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions dynatademand/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,33 @@ def get_sources(self):
'get_sources',
)
return self._api_get('/sources')

def reconcile_project(self, project_id, file, message):
'''
Sends a reconciliation request
'''
"""
# Awaiting valid body & path schemas
self.validator.validate_request(
'update_line_item',
path_data={
'extProjectId': '{}'.format(project_id),
},
request_body={
'file': file,
'message': message,
},
)
"""
self._check_authentication()
url = '{}{}'.format(self.base_url, '/projects/{}/reconcile'.format(project_id))
request_headers = {
'Authorization': 'Bearer {}'.format(self._access_token),
'Content-Type': "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
}
response = requests.post(url=url, data=file, headers=request_headers)
if response.status_code > 399:
raise DemandAPIError('Demand API request to {} failed with status {}. Response: {}'.format(
url, response.status_code, response.content
))
return response.json()
11 changes: 11 additions & 0 deletions dynatademand/schemas/request/body/reconcile_project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"type": "object",
"properties": {
"file": {
"type": "file"
},
"message": {
"type": "string"
}
}
}
12 changes: 12 additions & 0 deletions dynatademand/schemas/request/path/reconcile_project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"type": "object",
"properties": {
"extProjectId": {
"type": "string",
"required": true
}
},
"required": [
"extProjectId"
]
}
1 change: 1 addition & 0 deletions dynatademand/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
'update_project': ['path', 'body', ],
'buy_project': ['path', 'body', ],
'get_project_detailed_report': ['path', ],
'reconcile_project': ['path', ],

# Invoices
'get_invoice': ['path', ],
Expand Down
Binary file not shown.
29 changes: 28 additions & 1 deletion tests/test_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def test_close_project(self):

@responses.activate
def test_update_project(self):
# Tests creating a project. This also tests validating the project data as part of `api.create_project`.
# Tests updating a project.
with open('./tests/test_files/update_project.json', 'r') as update_project_file:
update_project_data = json.load(update_project_file)

Expand All @@ -133,3 +133,30 @@ def test_update_project(self):
with self.assertRaises(DemandAPIError):
self.api.update_project(24, update_project_data)
self.assertEqual(len(responses.calls), 2)

@responses.activate
def test_reconcile_project(self):
# Tests reconciling a project.
message = 'testing reconciliation'
with open('./tests/test_files/Data+Quality+Request+Template.xlsx', 'rb') as file:
# Success response
responses.add(
responses.POST,
'{}/sample/v1/projects/24/reconcile'.format(BASE_HOST),
json={'status': {'message': 'success'}},
status=200)
# Error message included
responses.add(
responses.POST,
'{}/sample/v1/projects/24/reconcile'.format(BASE_HOST),
json={'status': {'message': 'error'}},
status=400)

# Test successful response.
self.api.reconcile_project(24, file, message)
self.assertEqual(len(responses.calls), 1)

# Test response with error included.
with self.assertRaises(DemandAPIError):
self.api.reconcile_project(24, file, message)
self.assertEqual(len(responses.calls), 2)