Skip to content

Commit f5bd076

Browse files
haneslingerkflemin
andauthored
Add AL to insights page charts (#4948)
* Add AL ro insights page * Lint * Fix test --------- Co-authored-by: Katherine Fleming <2205659+kflemin@users.noreply.github.com>
1 parent 64bd3e3 commit f5bd076

File tree

3 files changed

+129
-12
lines changed

3 files changed

+129
-12
lines changed

seed/static/seed/js/controllers/inventory_reports_controller.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ angular.module('SEED.controller.inventory_reports', []).controller('inventory_re
9494
// for (const key in $scope.potential_level_instances) {
9595
// $scope.potential_level_instances[key].name = path_to_string($scope.potential_level_instances[key].path);
9696
// }
97+
const group_by_level = $scope.level_names[new_level_instance_depth];
98+
$scope.xAxisVars.splice($scope.xAxisVars.length - 1, 1, {
99+
name: group_by_level,
100+
label: group_by_level,
101+
varName: group_by_level,
102+
axisLabel: group_by_level
103+
});
97104
$scope.access_level_instance_id = null;
98105
$scope.setModified();
99106
};
@@ -296,6 +303,13 @@ angular.module('SEED.controller.inventory_reports', []).controller('inventory_re
296303

297304
$scope.level_name_index = JSON.parse(localStorage.getItem(localStorageALIndex)) || '0';
298305
const new_level_instance_depth = parseInt($scope.level_name_index, 10) + parseInt(users_depth, 10);
306+
const group_by_level = $scope.level_names[new_level_instance_depth];
307+
$scope.xAxisVars.push({
308+
name: group_by_level,
309+
label: group_by_level,
310+
varName: group_by_level,
311+
axisLabel: group_by_level
312+
});
299313
$scope.potential_level_instances = access_level_instances_by_depth[new_level_instance_depth];
300314
$scope.access_level_instance_id = JSON.parse(localStorage.getItem(localStorageALIID)) || parseInt($scope.users_access_level_instance_id, 10);
301315
}
@@ -707,7 +721,7 @@ angular.module('SEED.controller.inventory_reports', []).controller('inventory_re
707721
};
708722

709723
// new agg chart
710-
const the_data = _.orderBy($scope.aggChartData.chartData, ['y'], ['acs']);
724+
const the_data = $scope.aggChartData.chartData;
711725
$scope.barChart.data.labels = the_data.map((a) => a.y);
712726
$scope.barChart.data.datasets[0].data = the_data.map((a) => a.x);
713727
// add the colors to the datapoints, need to create a hash map first

seed/tests/test_reports.py

+82-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
from xlrd import open_workbook
1111

1212
from seed.models import ASSESSED_RAW, Column, Property, PropertyState, PropertyView
13-
from seed.test_helpers.fake import FakeCycleFactory
14-
from seed.tests.util import DataMappingBaseTestCase
13+
from seed.test_helpers.fake import (
14+
FakeCycleFactory,
15+
FakePropertyFactory,
16+
FakePropertyViewFactory,
17+
)
18+
from seed.tests.util import AccessLevelBaseTestCase, DataMappingBaseTestCase
1519

1620

1721
class ExportReport(DataMappingBaseTestCase):
@@ -120,6 +124,25 @@ def test_report_aggregated(self):
120124

121125
assert response.json()["aggregated_data"]["property_counts"] == [{"yr_e": "2015", "num_properties": 5, "num_properties_w-data": 5}]
122126

127+
def test_report_aggregated_count(self):
128+
url = reverse("api:v3:organizations-report-aggregated", args=[self.org.pk])
129+
data = {
130+
"cycle_ids": [self.cycle.id, self.cycle_2.id],
131+
"x_var": "Count",
132+
"y_var": "site_eui",
133+
"access_level_instance_id": self.org.root.id,
134+
}
135+
response = self.client.get(url, data)
136+
assert response.json()["aggregated_data"]["property_counts"] == [
137+
{"yr_e": "2016", "num_properties": 5, "num_properties_w-data": 5},
138+
{"yr_e": "2015", "num_properties": 5, "num_properties_w-data": 5},
139+
]
140+
141+
data["cycle_ids"] = [self.cycle.id]
142+
response = self.client.get(url, data)
143+
144+
assert response.json()["aggregated_data"]["property_counts"] == [{"yr_e": "2015", "num_properties": 5, "num_properties_w-data": 5}]
145+
123146
def test_report_missing_arg(self):
124147
url = reverse("api:v3:organizations-report-aggregated", args=[self.org.pk])
125148
data = {
@@ -130,3 +153,60 @@ def test_report_missing_arg(self):
130153
response = self.client.get(url, data)
131154

132155
assert response.status_code == 400
156+
157+
158+
class ExportReportALITests(AccessLevelBaseTestCase):
159+
def setUp(self):
160+
super().setUp()
161+
self.cycle = self.cycle_factory.get_cycle()
162+
self.property_factory = FakePropertyFactory(organization=self.org)
163+
self.property_view_factory = FakePropertyViewFactory(organization=self.org, cycle=self.cycle)
164+
165+
# two alis on the same level, "child"
166+
self.kid_1 = self.child_level_instance
167+
self.kid_2 = self.org.add_new_access_level_instance(self.org.root.id, "kid_2")
168+
169+
# two properties in each level
170+
self.property_1 = self.property_factory.get_property(access_level_instance=self.kid_1)
171+
self.view_1 = self.property_view_factory.get_property_view(prprty=self.property_1, site_eui=30)
172+
self.property_2 = self.property_factory.get_property(access_level_instance=self.kid_1)
173+
self.view_2 = self.property_view_factory.get_property_view(prprty=self.property_2, site_eui=40)
174+
175+
self.property_3 = self.property_factory.get_property(access_level_instance=self.kid_2)
176+
self.view_3 = self.property_view_factory.get_property_view(prprty=self.property_3, site_eui=50)
177+
self.property_4 = self.property_factory.get_property(access_level_instance=self.kid_2)
178+
self.view_4 = self.property_view_factory.get_property_view(prprty=self.property_4, site_eui=60)
179+
180+
def test_report_aggregated_with_access_level(self):
181+
url = reverse("api:v3:organizations-report-aggregated", args=[self.org.pk])
182+
data = {
183+
"cycle_ids": [self.cycle.id],
184+
"x_var": "site_eui",
185+
"y_var": "child",
186+
"access_level_instance_id": self.org.root.id,
187+
}
188+
189+
response = self.client.get(url, data)
190+
self.assertListEqual(
191+
response.json()["aggregated_data"]["chart_data"],
192+
[{"y": "kid_2", "x": 55.0, "yr_e": "2016"}, {"y": "child", "x": 35.0, "yr_e": "2016"}],
193+
)
194+
195+
def test_report_with_access_level(self):
196+
url = reverse("api:v3:organizations-report", args=[self.org.pk])
197+
data = {
198+
"cycle_ids": [self.cycle.id],
199+
"x_var": "child",
200+
"y_var": "site_eui",
201+
}
202+
response = self.client.get(url, data)
203+
204+
self.assertListEqual(
205+
response.json()["data"]["chart_data"],
206+
[
207+
{"id": self.view_1.id, "x": "child", "y": 30.0, "yr_e": "2016"},
208+
{"id": self.view_2.id, "x": "child", "y": 40.0, "yr_e": "2016"},
209+
{"id": self.view_3.id, "x": "kid_2", "y": 50.0, "yr_e": "2016"},
210+
{"id": self.view_4.id, "x": "kid_2", "y": 60.0, "yr_e": "2016"},
211+
],
212+
)

seed/views/v3/organizations.py

+32-9
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,11 @@ def setup_report_data(self, organization_id, access_level_instance, cycles, x_va
880880

881881
# annotate properties with fields
882882
def get_column_model_field(column):
883-
if column.is_extra_data:
883+
if column in Organization.objects.get(pk=organization_id).access_level_names:
884+
return F("property__access_level_instance__path__" + column)
885+
elif column == "Count":
886+
return Value(1)
887+
elif column.is_extra_data:
884888
return F("state__extra_data__" + column.column_name)
885889
elif column.derived_column:
886890
return F("state__derived_data__" + column.column_name)
@@ -892,8 +896,6 @@ def get_column_model_field(column):
892896
"x": get_column_model_field(x_var),
893897
"y": get_column_model_field(y_var),
894898
}
895-
if x_var == "Count":
896-
fields["x"] = Value(1)
897899
for k, v in fields.items():
898900
all_property_views = all_property_views.annotate(**{k: v})
899901

@@ -968,9 +970,20 @@ def report(self, request, pk=None):
968970
{"status": "error", "message": f"Missing params: {', '.join(missing_params)}"}, status=status.HTTP_400_BAD_REQUEST
969971
)
970972

973+
# x could be an access level, else its a column
974+
access_level_names = Organization.objects.get(pk=pk).access_level_names
975+
if params["x_var"] not in access_level_names:
976+
x_var = Column.objects.get(column_name=params["x_var"], organization=pk, table_name="PropertyState")
977+
else:
978+
x_var = params["x_var"]
979+
980+
# y could be count, else its a column
981+
if params["y_var"] != "Count":
982+
y_var = Column.objects.get(column_name=params["y_var"], organization=pk, table_name="PropertyState")
983+
else:
984+
y_var = params["y_var"]
985+
971986
cycles = Cycle.objects.filter(id__in=params["cycle_ids"])
972-
x_var = Column.objects.get(column_name=params["x_var"], organization=pk, table_name="PropertyState")
973-
y_var = Column.objects.get(column_name=params["y_var"], organization=pk, table_name="PropertyState")
974987
report_data = self.setup_report_data(pk, ali, cycles, x_var, y_var, filter_group_id)
975988
data = self.get_raw_report_data(pk, cycles, report_data["all_property_views"], report_data["field_data"])
976989
axis_data = self.get_axis_data(
@@ -1033,10 +1046,20 @@ def report_aggregated(self, request, pk=None):
10331046
{"status": "error", "message": f"Missing params: {', '.join(missing_params)}"}, status=status.HTTP_400_BAD_REQUEST
10341047
)
10351048

1036-
# get data
1049+
# X could be count, else its a column
1050+
if params["x_var"] != "Count":
1051+
x_var = Column.objects.get(column_name=params["x_var"], organization=pk, table_name="PropertyState")
1052+
else:
1053+
x_var = params["x_var"]
1054+
1055+
# y could be an access level, else its a column
1056+
access_level_names = Organization.objects.get(pk=pk).access_level_names
1057+
if params["y_var"] not in access_level_names:
1058+
y_var = Column.objects.get(column_name=params["y_var"], organization=pk, table_name="PropertyState")
1059+
else:
1060+
y_var = params["y_var"]
1061+
10371062
cycles = Cycle.objects.filter(id__in=params["cycle_ids"])
1038-
x_var = Column.objects.get(column_name=params["x_var"], organization=pk, table_name="PropertyState")
1039-
y_var = Column.objects.get(column_name=params["y_var"], organization=pk, table_name="PropertyState")
10401063
report_data = self.setup_report_data(pk, ali, cycles, x_var, y_var, filter_group_id)
10411064
data = self.get_raw_report_data(pk, cycles, report_data["all_property_views"], report_data["field_data"])
10421065
chart_data = []
@@ -1102,7 +1125,7 @@ def discrete_aggregate_data(self, yr_e, buildings, bins, count=False):
11021125

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

1105-
return results
1128+
return sorted(results, key=lambda d: d["x"], reverse=True)
11061129

11071130
@swagger_auto_schema(
11081131
manual_parameters=[

0 commit comments

Comments
 (0)