Skip to content

Commit

Permalink
Download capability of audit template xml file (#4950)
Browse files Browse the repository at this point in the history
* add download of audit template xml file

* debug statements

* add Electricity meter type to buildingsync mapping

* remove debug statements
  • Loading branch information
kflemin authored Mar 10, 2025
1 parent f5bd076 commit 9cfb899
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 3 deletions.
1 change: 1 addition & 0 deletions seed/analysis_pipelines/better/buildingsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
SEED_TO_BSYNC_RESOURCE_TYPE = {
Meter.ELECTRICITY_GRID: "Electricity",
Meter.ELECTRICITY_UNKNOWN: "Electricity",
Meter.ELECTRICITY: "Electricity",
Meter.NATURAL_GAS: "Natural gas",
Meter.DIESEL: "Diesel",
Meter.PROPANE: "Propane",
Expand Down
4 changes: 3 additions & 1 deletion seed/audit_template/audit_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def batch_export_to_audit_template(self, view_ids):

return progress_data.result(), []

def export_to_audit_template(self, state, token):
def export_to_audit_template(self, state, token, file_only=False):
url = f"{self.API_URL}/building_sync/upload"
display_field = getattr(state, self.org.property_display_field)

Expand All @@ -242,6 +242,8 @@ def export_to_audit_template(self, state, token):

if not xml_string:
return None, messages
if file_only:
return xml_string, messages
except Exception as e:
return None, ["error", f"{display_field}: Unexpected error creating building xml {e}"]

Expand Down
23 changes: 23 additions & 0 deletions seed/static/seed/js/controllers/inventory_detail_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,29 @@ angular.module('SEED.controller.inventory_detail', []).controller('inventory_det
});
};

$scope.export_building_sync_at_file = () => {
$http
.get(
'/api/v3/audit_template/export_buildingsync_at_file/',
{
params: {
view_id: $stateParams.view_id,
organization_id: $scope.organization.id
}
}
)
.then(
(response) => {
const blob2 = new Blob([response.data], { type: 'application/xml;charset=utf-8;' });
const filename = `buildingsync_at_property_${$stateParams.view_id}.xml`;
saveAs(blob2, filename);
},
(err) => {
$scope.download_error_message = err.data ? err.data : err.toString();
}
);
};

$scope.unpair_property_from_taxlot = (property_id) => {
pairing_service.unpair_property_from_taxlot($scope.inventory.view_id, property_id);
$state.reload();
Expand Down
4 changes: 4 additions & 0 deletions seed/static/seed/partials/inventory_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ <h1>{$:: (inventory_type === 'taxlots' ? 'Tax Lot Detail' : 'Property Detail') |
<a ng-click="export_building_sync_xlsx()">Export BuildingSync (Excel)</a>
</li>

<li ng-if="::inventory_type === 'properties'" role="menuitem">
<a ng-click="export_building_sync_at_file()">Export Audit Template File (XML)</a>
</li>

<li ng-if="::inventory_type === 'properties'" role="menuitem">
<a ng-click="open_export_to_audit_template_modal()">Export to Audit Template</a>
</li>
Expand Down
37 changes: 36 additions & 1 deletion seed/views/v3/audit_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

from django.http import HttpResponse, JsonResponse
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets
from rest_framework import status, viewsets
from rest_framework.decorators import action

from seed.audit_template.audit_template import AuditTemplate
from seed.lib.superperms.orgs.decorators import has_perm_class
from seed.models import PropertyView
from seed.utils.api import OrgMixin
from seed.utils.api_schema import AutoSchemaHelper

Expand Down Expand Up @@ -100,6 +101,40 @@ def batch_export_to_audit_template(self, request):
return JsonResponse({"success": False, "message": message or "Unexpected Error"}, status=400)
return JsonResponse(progress_data)

@swagger_auto_schema(
manual_parameters=[
AutoSchemaHelper.query_org_id_field(),
AutoSchemaHelper.query_integer_field("view_id", required=True, description="Property View ID to retrieve"),
]
)
@has_perm_class("can_modify_data")
@action(detail=False, methods=["GET"])
def export_buildingsync_at_file(self, request):
"""
Return the BuildingSync XML file that would be sent over to Audit Template.
Mostly for testing or manual upload.
"""
pk = request.GET.get("view_id", None)
org_id = self.get_organization(self.request)

try:
property_view = PropertyView.objects.select_related("state").get(pk=pk, cycle__organization_id=org_id)
except PropertyView.DoesNotExist:
return JsonResponse(
{"success": False, "message": f"Cannot match a PropertyView with pk={pk}"}, status=status.HTTP_400_BAD_REQUEST
)

try:
at = AuditTemplate(self.get_organization(request))
xml, message = at.export_to_audit_template(property_view.state, None, file_only=True)
if xml:
return HttpResponse(xml, content_type="application/xml")
else:
return JsonResponse({"success": False, "message": message or "Unexpected Error"}, status=400)

except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@swagger_auto_schema(
manual_parameters=[AutoSchemaHelper.query_org_id_field()],
request_body=AutoSchemaHelper.schema_factory(
Expand Down
3 changes: 2 additions & 1 deletion seed/views/v3/organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,8 @@ def discrete_aggregate_data(self, yr_e, buildings, bins, count=False):

results.append({"y": bin, "x": x, "yr_e": yr_e})

return sorted(results, key=lambda d: d["x"], reverse=True)
# return sorted(results, key=lambda d: d["x"], reverse=True)
return sorted(results, key=lambda d: d["x"] if not None else -np.inf, reverse=True)

@swagger_auto_schema(
manual_parameters=[
Expand Down

0 comments on commit 9cfb899

Please sign in to comment.