Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit Template Report Submission Endpoint #4411

Merged
merged 8 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
27 changes: 27 additions & 0 deletions seed/audit_template/audit_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,33 @@ def get_building_xml(self, audit_template_building_id, token):

return response, ""

def get_submission(self, audit_template_submission_id, report_format='pdf'):
# supporting 'PDF' and 'XML' formats only for now

token, message = self.get_api_token()
if not token:
return None, message

# validate format
if report_format.lower() not in ['xml', 'pdf']:
report_format = 'pdf'

# set headers
headers = {'accept': 'application/pdf'}
if report_format.lower() == 'xml':
headers = {'accept': 'application/xml'}

url = f'{self.API_URL}/rp/submissions/{audit_template_submission_id}.{report_format}?token={token}'
try:
response = requests.request("GET", url, headers=headers)

if response.status_code != 200:
return None, f'Expected 200 response from Audit Template get_submission but got {response.status_code}: {response.content}'
except Exception as e:
return None, f'Unexpected error from Audit Template: {e}'

return response, ""

def get_buildings(self, cycle_id):
token, message = self.get_api_token()
if not token:
Expand Down
16 changes: 16 additions & 0 deletions seed/tests/test_audit_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def setUp(self):

self.get_building_url = reverse('api:v3:audit_template-get-building-xml', args=['1'])
self.get_buildings_url = reverse('api:v3:audit_template-get-buildings')
self.get_submission_url = reverse('api:v3:audit_template-get-submission', args=['1'])

self.good_authenticate_response = mock.Mock()
self.good_authenticate_response.status_code = 200
Expand All @@ -57,6 +58,11 @@ def setUp(self):
self.good_get_building_response.status_code = 200
self.good_get_building_response.text = "building response"

self.good_get_submission_response = mock.Mock()
self.good_get_submission_response.status_code = 200
self.good_get_submission_response.text = "submission response"
self.good_get_submission_response.content = "submission response"

self.bad_get_building_response = mock.Mock()
self.bad_get_building_response.status_code = 400
self.bad_get_building_response.content = "bad building response"
Expand All @@ -71,6 +77,16 @@ def test_get_building_xml_from_audit_template(self, mock_request):
self.assertEqual(200, response.status_code, response.content)
self.assertEqual(response.content, b"building response")

@mock.patch('requests.request')
def test_get_submission_from_audit_template(self, mock_request):
# -- Act
mock_request.side_effect = [self.good_authenticate_response, self.good_get_submission_response]
response = self.client.get(self.get_submission_url, data={"organization_id": self.org.id})

# -- Assert
self.assertEqual(200, response.status_code, response.content)
self.assertEqual(response.content, b"submission response")

@mock.patch('requests.request')
def test_get_building_xml_from_audit_template_org_has_no_at_token(self, mock_request):
# -- Setup
Expand Down
38 changes: 37 additions & 1 deletion seed/views/v3/audit_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,49 @@


class AuditTemplateViewSet(viewsets.ViewSet, OrgMixin):
@swagger_auto_schema(manual_parameters=[AutoSchemaHelper.query_org_id_field()])
@has_perm_class('can_view_data')
@action(detail=True, methods=['GET'])
def get_submission(self, request, pk):
"""
Fetches a Report Submission (XML or PDF) from Audit Template (only)
"""

# get report format or default to pdf
default_report_format = 'pdf'
report_format = request.query_params.get('report_format', default_report_format)

valid_file_formats = ['xml', 'pdf']
if report_format.lower() not in valid_file_formats:
message = f"The report_format specified is invalid. Must be one of: {valid_file_formats}."
return JsonResponse({
'success': False,
'message': message
}, status=400)

# retrieve report
at = AuditTemplate(self.get_organization(self.request))
response, message = at.get_submission(pk, report_format)

if response is None:
return JsonResponse({
'success': False,
'message': message
}, status=400)
if report_format.lower() == 'xml':
return HttpResponse(response.text)
else:
response2 = HttpResponse(response.content)
response2.headers["Content-Type"] = 'application/pdf'
response2.headers["Content-Disposition"] = f'attachment; filename="at_submission_{pk}.pdf"'
return response2

@swagger_auto_schema(manual_parameters=[AutoSchemaHelper.query_org_id_field()])
@has_perm_class('can_view_data')
@action(detail=True, methods=['GET'])
def get_building_xml(self, request, pk):
"""
Fetches a Building XML for an Audit Template property and updates the corresponding PropertyView
Fetches a Building XML for an Audit Template property (only)
"""
at = AuditTemplate(self.get_organization(self.request))
response, message = at.get_building(pk)
Expand Down
Loading