Skip to content

Commit

Permalink
Remaining Service Life table update (#4805)
Browse files Browse the repository at this point in the history
* Fix rsl table

* added bsync and federal bps measures

* lint

* precommit

* Fixed tkbl redirect bug, added response schema, removed unused code

---------

Co-authored-by: Hannah Eslinger <[email protected]>
Co-authored-by: Alex Swindler <[email protected]>
  • Loading branch information
3 people authored Sep 23, 2024
1 parent 67135ac commit 6e5cf57
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 644 deletions.
2 changes: 2 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ pyotp==2.9.0

# This dependency can be removed once a version newer than 8.5.0 has been released that fixes Django autoreload
importlib_metadata==8.4.0

tkbl==0.6
4 changes: 2 additions & 2 deletions seed/analysis_pipelines/element_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
analysis_pipeline_task,
task_create_analysis_property_views,
)
from seed.lib.tkbl.tkbl import scope_one_emission_codes
from seed.lib.tkbl.tkbl import SCOPE_ONE_EMISSION_CODES
from seed.lib.uniformat.uniformat import uniformat_data
from seed.models import Analysis, AnalysisPropertyView, Column, Element

Expand Down Expand Up @@ -142,7 +142,7 @@ def _create_element_columns(analysis):
"description": data["code"] if "definition" not in data else data["code"] + ": " + data["definition"],
}
for data in uniformat_data
if data["code"] in scope_one_emission_codes
if data["code"] in SCOPE_ONE_EMISSION_CODES
}

for code, col in column_meta_by_code.items():
Expand Down
4 changes: 2 additions & 2 deletions seed/analysis_pipelines/upgrade_recommendation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
analysis_pipeline_task,
task_create_analysis_property_views,
)
from seed.lib.tkbl.tkbl import scope_one_emission_codes
from seed.lib.tkbl.tkbl import SCOPE_ONE_EMISSION_CODES
from seed.models import Analysis, AnalysisMessage, AnalysisPropertyView, Column, Element

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -159,7 +159,7 @@ def get_value(name):
return "NO DER project recommended"

# if did not hit ff_fired_equipment_rsl_threshold and ff_fired_equipment_rsl_threshold or condition_index_threshold
lowest_RSL = elements.filter(code__code__in=scope_one_emission_codes).order_by("remaining_service_life").first()
lowest_RSL = elements.filter(code__code__in=SCOPE_ONE_EMISSION_CODES).order_by("remaining_service_life").first()
if lowest_RSL is None:
return "NO DER project recommended"
lowest_RSL = lowest_RSL.remaining_service_life
Expand Down
615 changes: 1 addition & 614 deletions seed/lib/tkbl/tkbl.py

Large diffs are not rendered by default.

11 changes: 0 additions & 11 deletions seed/serializers/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from rest_framework import serializers
from rest_framework.fields import ChoiceField

from seed.lib.tkbl.tkbl import tkbl_data
from seed.lib.uniformat.uniformat import uniformat_codes
from seed.models import Element, Uniformat

Expand Down Expand Up @@ -63,13 +62,3 @@ def update(self, instance, validated_data):
validated_data["property_id"] = self.context["request"].parser_context["kwargs"]["property_pk"]
validated_data["element_id"] = validated_data.pop("id", None)
return super().update(instance, validated_data)


class ElementPropertyTKBLSerializer(ElementPropertySerializer):
tkbl = serializers.SerializerMethodField()

def get_tkbl(self, element):
return {
"estcp": tkbl_data["estcp"].get(element.code.code, []),
"sftool": tkbl_data["sftool"].get(element.code.code, []),
}
2 changes: 1 addition & 1 deletion seed/static/seed/js/services/element_service.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ angular.module('SEED.service.element', []).factory('element_service', [

// Return Technology Knowledge Base Library guidance for a given property
get_tkbl: (organization_id, property_id) => $http
.get(`/api/v3/properties/${property_id}/elements/tkbl`, {
.get(`/api/v3/properties/${property_id}/elements/tkbl/`, {
params: { organization_id }
}).then(({ data }) => data)
})
Expand Down
22 changes: 14 additions & 8 deletions seed/static/seed/partials/inventory_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,6 @@ <h2 ng-if="::inventory_type==='properties'"><i class="fa-regular fa-map"></i> {$
</table>
</div>
</div>
<br />
<br />

<div ng-if="::inventory_type==='properties'">
<!-- Elements Section -->
Expand Down Expand Up @@ -389,10 +387,10 @@ <h2><i class="fa-solid fa-atom"></i>{$:: 'Property Elements' | translate $}<span
</div>
</div>

<div class="section" ng-if="::tkbl.length > 0">
<div ng-if="::tkbl.length > 0">
<div class="section_header_container" style="margin-top: 20px; border-bottom: 0">
<div class="section_header fixed_height_short has_no_padding">
<div class="section_action_container left" style="width: 50%">
<div class="section_action_container" style="width: 75%">
<h2><i class="fa-solid fa-atom"></i>{$:: 'Building Performance Standard (BPS) Compliance Pathway Support' | translate $}</h2>
</div>
</div>
Expand Down Expand Up @@ -420,19 +418,27 @@ <h2><i class="fa-solid fa-atom"></i>{$:: 'Building Performance Standard (BPS) Co
<td>
<ul ng-if="element.tkbl.sftool.length > 0">
<li ng-repeat="entry in ::element.tkbl.sftool">
<a ng-href="{$:: entry.url $}" target="_blank" rel="noopener noreferrer">{$:: entry.name $}</a>
<a ng-href="{$:: entry.url $}" target="_blank" rel="noopener noreferrer">{$:: entry.subcategory $}</a>
</li>
</ul>
</td>
<td>
<ul ng-if="element.tkbl.estcp.length > 0">
<li ng-repeat="entry in ::element.tkbl.estcp">
<a ng-href="{$:: entry.url $}" target="_blank" rel="noopener noreferrer">{$:: entry.name $}</a>
<a ng-href="{$:: entry.url $}" target="_blank" rel="noopener noreferrer">{$:: entry.title $}</a>
</li>
</ul>
</td>
<td></td>
<td></td>
<td>
<ul ng-if="element.tkbl.bsync_measures.length > 0">
<li ng-repeat="entry in ::element.tkbl.bsync_measures">{$:: entry $}</li>
</ul>
</td>
<td class="col-sm-4">
<ul ng-if="element.tkbl.federal_bps_measures.length > 0">
<li class="elements-wrap" ng-repeat="entry in ::element.tkbl.federal_bps_measures">{$:: entry $}</li>
</ul>
</td>
<td></td>
</tr>
</tbody>
Expand Down
6 changes: 6 additions & 0 deletions seed/static/seed/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5673,3 +5673,9 @@ tags-input .tags .tag-item {
font-size: bold;
}
}

.elements-wrap {
word-wrap: break-word;
white-space: normal;
min-width: 350px;
}
74 changes: 68 additions & 6 deletions seed/views/v3/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
See also https://github.com/SEED-platform/seed/blob/main/LICENSE.md
"""

import json

from django.db import IntegrityError
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.renderers import JSONRenderer
from tkbl import bsync_by_uniformat_code, federal_bps_by_uniformat_code, filter_by_uniformat_code

from seed.decorators import ajax_request_class
from seed.lib.superperms.orgs.decorators import has_hierarchy_access, has_perm_class
from seed.lib.superperms.orgs.models import AccessLevelInstance
from seed.lib.tkbl.tkbl import scope_one_emission_codes
from seed.lib.tkbl.tkbl import SCOPE_ONE_EMISSION_CODES
from seed.models import Element
from seed.serializers.elements import ElementPropertySerializer, ElementPropertyTKBLSerializer, ElementSerializer
from seed.serializers.elements import ElementPropertySerializer, ElementSerializer
from seed.utils.api import api_endpoint_class
from seed.utils.api_schema import swagger_auto_schema_org_query_param
from seed.utils.api_schema import AutoSchemaHelper, swagger_auto_schema_org_query_param
from seed.utils.viewsets import SEEDOrgNoPatchOrOrgCreateModelViewSet, SEEDOrgReadOnlyModelViewSet


Expand Down Expand Up @@ -119,12 +123,70 @@ def create(self, request, *args, **kwargs):
except IntegrityError as e:
return JsonResponse({"status": "error", "message": str(e)}, status=status.HTTP_400_BAD_REQUEST)

@swagger_auto_schema_org_query_param
@swagger_auto_schema(
manual_parameters=[AutoSchemaHelper.query_org_id_field()],
responses={
200: AutoSchemaHelper.schema_factory(
[
{
"code": "string",
"remaining_service_life": "number",
"description": "string",
"tkbl": {
"sftool": [
{
"category": "string",
"subcategory": "string",
"uniformat code": "string",
"uniformat description": "string",
"url": "string",
"title": "string",
}
],
"estcp": [
{
"category": "string",
"subcategory": "string",
"uniformat code": "string",
"uniformat description": "string",
"url": "string",
"title": "string",
}
],
"bsync_measures": ["string"],
"federal_bps_measures": ["string"],
},
}
]
)
},
)
@api_endpoint_class
@ajax_request_class
@has_perm_class("requires_viewer")
@has_hierarchy_access(property_id_kwarg="property_pk")
@action(detail=False, methods=["GET"])
def tkbl(self, request, *args, **kwargs):
tkbl_elements = self.get_queryset().filter(code__code__in=scope_one_emission_codes).order_by("remaining_service_life")[:3]
return ElementPropertyTKBLSerializer(tkbl_elements, many=True).data
"""
Technologies Knowledge Base Library recommendations for Elements belonging to a Property with the lowest remaining service life
"""

tkbl_elements = self.get_queryset().filter(code__code__in=SCOPE_ONE_EMISSION_CODES).order_by("remaining_service_life")[:3]

results = []
for e in tkbl_elements:
links = json.loads(filter_by_uniformat_code(e.code.code))
sftool_links = [link for link in links if link["category"] != "ESTCP"]
estcp_links = [link for link in links if link["category"] == "ESTCP"]
bsync = [x["eem_name"] for x in bsync_by_uniformat_code(e.code.code)]
federal_bps = [x["Federal BPS Prescriptive Measures"] for x in federal_bps_by_uniformat_code(e.code.code)]
results.append(
{
"code": e.code.code,
"remaining_service_life": e.remaining_service_life,
"description": e.description,
"tkbl": {"sftool": sftool_links, "estcp": estcp_links, "bsync_measures": bsync, "federal_bps_measures": federal_bps},
}
)

return results

0 comments on commit 6e5cf57

Please sign in to comment.