Issues (1656)

myems-api/reports/dashboard.py (3 issues)

1
from datetime import datetime, timedelta, timezone
2
from decimal import Decimal
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
import config
7
from core import utilities
8
from core.useractivity import access_control, api_key_control
9
10
11
class Reporting:
12
    def __init__(self):
13
        """Initializes Class"""
14
        pass
15
16
    @staticmethod
17
    def on_options(req, resp):
18
        _ = req
19
        resp.status = falcon.HTTP_200
20
21
    ####################################################################################################################
22
    # PROCEDURES
23
    # Step 1: valid parameters
24
    # Step 2: query the space
25
    # Step 3: query energy categories
26
    # Step 4: query sensor data
27
    # Step 5: query child spaces
28
    # Step 6: query base period energy input
29
    # Step 7: query base period energy cost
30
    # Step 8: query base period energy output
31
    # Step 9: query reporting period energy input
32
    # Step 10: query reporting period energy cost
33
    # Step 11: query reporting period energy output
34
    # Step 12: query child spaces energy input
35
    # Step 13: query child spaces energy cost
36
    # Step 14: construct the report
37
    ####################################################################################################################
38
    @staticmethod
39
    def on_get(req, resp):
40
        if 'API-KEY' not in req.headers or \
41
                not isinstance(req.headers['API-KEY'], str) or \
42
                len(str.strip(req.headers['API-KEY'])) == 0:
43
            access_control(req)
44
        else:
45
            api_key_control(req)
46
        user_uuid = req.params.get('useruuid')
47
        period_type = req.params.get('periodtype')
48
        base_period_start_datetime_local = req.params.get('baseperiodstartdatetime')
49
        base_period_end_datetime_local = req.params.get('baseperiodenddatetime')
50
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
51
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
52
53
        ################################################################################################################
54
        # Step 1: valid parameters
55
        ################################################################################################################
56
        if user_uuid is None:
57
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_USER_UUID')
58
        else:
59
            user_uuid = str.strip(user_uuid)
60
            if len(user_uuid) != 36:
61
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
62
                                       description='API.INVALID_USER_UUID')
63
64
        if period_type is None:
65
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
66
                                   description='API.INVALID_PERIOD_TYPE')
67
        else:
68
            period_type = str.strip(period_type)
69
            if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
70
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
71
                                       description='API.INVALID_PERIOD_TYPE')
72
73
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
74
        if config.utc_offset[0] == '-':
75
            timezone_offset = -timezone_offset
76
77
        base_start_datetime_utc = None
78
        if base_period_start_datetime_local is not None and len(str.strip(base_period_start_datetime_local)) > 0:
79
            base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
80
            try:
81
                base_start_datetime_utc = datetime.strptime(base_period_start_datetime_local, '%Y-%m-%dT%H:%M:%S')
82
            except ValueError:
83
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
84
                                       description="API.INVALID_BASE_PERIOD_START_DATETIME")
85
            base_start_datetime_utc = \
86
                base_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
87
            # nomalize the start datetime
88
            if config.minutes_to_count == 30 and base_start_datetime_utc.minute >= 30:
89
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
90
            else:
91
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
92
93
        base_end_datetime_utc = None
94
        if base_period_end_datetime_local is not None and len(str.strip(base_period_end_datetime_local)) > 0:
95
            base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
96
            try:
97
                base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
98
            except ValueError:
99
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
100
                                       description="API.INVALID_BASE_PERIOD_END_DATETIME")
101
            base_end_datetime_utc = \
102
                base_end_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
103
104
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
105
                base_start_datetime_utc >= base_end_datetime_utc:
106
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
107
                                   description='API.INVALID_BASE_PERIOD_END_DATETIME')
108
109
        if reporting_period_start_datetime_local is None:
110
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
111
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
112
        else:
113
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
114
            try:
115
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
116
                                                                 '%Y-%m-%dT%H:%M:%S')
117
            except ValueError:
118
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
119
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
120
            reporting_start_datetime_utc = \
121
                reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
122
            # nomalize the start datetime
123
            if config.minutes_to_count == 30 and reporting_start_datetime_utc.minute >= 30:
124
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
125
            else:
126
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
127
128
        if reporting_period_end_datetime_local is None:
129
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
130
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
131
        else:
132
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
133
            try:
134
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
135
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
136
                    timedelta(minutes=timezone_offset)
137
            except ValueError:
138
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
139
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
140
141
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
142
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
143
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
144
145
        ################################################################################################################
146
        # Step 2: query the space
147
        ################################################################################################################
148
149
        cnx_user = mysql.connector.connect(**config.myems_user_db)
150
        cursor_user = cnx_user.cursor()
151
152
        cursor_user.execute(" SELECT id, is_admin, privilege_id "
153
                            " FROM tbl_users "
154
                            " WHERE uuid = %s ", (user_uuid,))
155
        row_user = cursor_user.fetchone()
156
        if row_user is None:
157
            if cursor_user:
158
                cursor_user.close()
159
            if cnx_user:
160
                cnx_user.close()
161
162
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
163
                                   description='API.USER_NOT_FOUND')
164
165
        user = {'id': row_user[0], 'is_admin': row_user[1], 'privilege_id': row_user[2]}
166
        if user['is_admin']:
167
            # todo: make sure the space id is always 1 for admin
168
            space_id = 1
169
        else:
170
            cursor_user.execute(" SELECT data "
171
                                " FROM tbl_privileges "
172
                                " WHERE id = %s ", (user['privilege_id'],))
173
            row_privilege = cursor_user.fetchone()
174
            if row_privilege is None:
175
                if cursor_user:
176
                    cursor_user.close()
177
                if cnx_user:
178
                    cnx_user.close()
179
180
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
181
                                       description='API.USER_PRIVILEGE_NOT_FOUND')
182
183
            privilege_data = json.loads(row_privilege[0])
184
            if 'spaces' not in privilege_data.keys() \
185
                    or privilege_data['spaces'] is None \
186
                    or len(privilege_data['spaces']) == 0:
187
                if cursor_user:
188
                    cursor_user.close()
189
                if cnx_user:
190
                    cnx_user.close()
191
192
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
193
                                       description='API.USER_PRIVILEGE_NOT_FOUND')
194
            # todo: how to deal with multiple spaces in privilege data
195
            space_id = privilege_data['spaces'][0]
196
197
        if cursor_user:
198
            cursor_user.close()
199
        if cnx_user:
200
            cnx_user.close()
201
202
        cnx_system = mysql.connector.connect(**config.myems_system_db)
203
        cursor_system = cnx_system.cursor()
204
205
        cursor_system.execute(" SELECT id, name, area, number_of_occupants, cost_center_id "
206
                              " FROM tbl_spaces "
207
                              " WHERE id = %s ", (space_id,))
208
        row_space = cursor_system.fetchone()
209
        if row_space is None:
210
            if cursor_system:
211
                cursor_system.close()
212
            if cnx_system:
213
                cnx_system.close()
214
215
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND')
216
217
        space = dict()
218
        space['id'] = row_space[0]
219
        space['name'] = row_space[1]
220
        space['area'] = row_space[2]
221
        space['number_of_occupants'] = row_space[3]
222
        space['cost_center_id'] = row_space[4]
223
224
        ################################################################################################################
225
        # Step 3: query energy categories
226
        ################################################################################################################
227
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
228
        cursor_energy = cnx_energy.cursor()
229
230
        cnx_billing = mysql.connector.connect(**config.myems_billing_db)
231
        cursor_billing = cnx_billing.cursor()
232
233
        input_energy_category_set = set()
234
        # query energy categories in base period
235
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
236
                              " FROM tbl_space_input_category_hourly "
237
                              " WHERE space_id = %s "
238
                              "     AND start_datetime_utc >= %s "
239
                              "     AND start_datetime_utc < %s ",
240
                              (space['id'], base_start_datetime_utc, base_end_datetime_utc))
241
        rows_energy_categories = cursor_energy.fetchall()
242
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
243
            for row_energy_category in rows_energy_categories:
244
                input_energy_category_set.add(row_energy_category[0])
245
246
        # query energy categories in reporting period
247
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
248
                              " FROM tbl_space_input_category_hourly "
249
                              " WHERE space_id = %s "
250
                              "     AND start_datetime_utc >= %s "
251
                              "     AND start_datetime_utc < %s ",
252
                              (space['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
253
        rows_energy_categories = cursor_energy.fetchall()
254
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
255
            for row_energy_category in rows_energy_categories:
256
                input_energy_category_set.add(row_energy_category[0])
257
258
        output_energy_category_set = set()
259
        # query output energy categories in base period
260
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
261
                              " FROM tbl_space_output_category_hourly "
262
                              " WHERE space_id = %s "
263
                              "     AND start_datetime_utc >= %s "
264
                              "     AND start_datetime_utc < %s ",
265
                              (space['id'], base_start_datetime_utc, base_end_datetime_utc))
266
        rows_energy_categories = cursor_energy.fetchall()
267
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
268
            for row_energy_category in rows_energy_categories:
269
                output_energy_category_set.add(row_energy_category[0])
270
271
        # query output energy categories in reporting period
272
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
273
                              " FROM tbl_space_output_category_hourly "
274
                              " WHERE space_id = %s "
275
                              "     AND start_datetime_utc >= %s "
276
                              "     AND start_datetime_utc < %s ",
277
                              (space['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
278
        rows_energy_categories = cursor_energy.fetchall()
279
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
280
            for row_energy_category in rows_energy_categories:
281
                output_energy_category_set.add(row_energy_category[0])
282
283
        # query all energy categories
284
        cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e "
285
                              " FROM tbl_energy_categories "
286
                              " ORDER BY id ", )
287
        rows_energy_categories = cursor_system.fetchall()
288
        if rows_energy_categories is None or len(rows_energy_categories) == 0:
289
            if cursor_system:
290
                cursor_system.close()
291
            if cnx_system:
292
                cnx_system.close()
293
294
            if cursor_energy:
295
                cursor_energy.close()
296
            if cnx_energy:
297
                cnx_energy.close()
298
299
            if cursor_billing:
300
                cursor_billing.close()
301
            if cnx_billing:
302
                cnx_billing.close()
303
304
            raise falcon.HTTPError(status=falcon.HTTP_404,
305
                                   title='API.NOT_FOUND',
306
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
307
        energy_category_dict = dict()
308
        for row_energy_category in rows_energy_categories:
309
            energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1],
310
                                                            "unit_of_measure": row_energy_category[2],
311
                                                            "kgce": row_energy_category[3],
312
                                                            "kgco2e": row_energy_category[4]}
313
314
        ################################################################################################################
315
        # Step 4: query sensor data
316
        ################################################################################################################
317
        cnx_system = mysql.connector.connect(**config.myems_system_db)
318
        cursor_system = cnx_system.cursor()
319
320
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
321
        cursor_historical = cnx_historical.cursor()
322
323
        sensor_id_list = list()
324
        sensor_dict = dict()
325
        cursor_system.execute(" SELECT s.id, s.name, s.uuid, s.description "
326
                              " FROM tbl_sensors s, tbl_spaces_sensors ss "
327
                              " WHERE ss.space_id = %s "
328
                              " AND s.id = ss.sensor_id "
329
                              , (space['id'],))
330
        rows_sensors = cursor_system.fetchall()
331
        if rows_sensors is not None and len(rows_sensors) > 0:
332
            for row in rows_sensors:
333
                sensor_id_list.append(row[0])
334
                sensor_dict[row[0]] = dict()
335
                sensor_dict[row[0]]['name'] = row[1]
336
                sensor_dict[row[0]]['description'] = row[2]
337
                sensor_dict[row[0]]['uuid'] = row[3]
338
                sensor_dict[row[0]]['point_name_list'] = list()
339
                sensor_dict[row[0]]['point_unit_list'] = list()
340
                sensor_dict[row[0]]['point_id_list'] = list()
341
        if sensor_id_list is not None and len(sensor_id_list) > 0:
342
            cursor_system.execute(" SELECT sp.sensor_id, p.id, p.name, p.units "
343
                                  " FROM tbl_sensors_points sp, tbl_points p "
344
                                  " WHERE sp.sensor_id in ({}) "
345
                                  " AND sp.point_id = p.id "
346
                                  " ORDER BY p.id ".format(','.join("{0}".format(x) for x in sensor_id_list)))
347
            rows_sensor_points = cursor_system.fetchall()
348
            if rows_sensor_points is not None and len(rows_sensor_points) > 0:
349
                for row in rows_sensor_points:
350
                    sensor_dict[row[0]]['point_id_list'].append(row[1])
351
                    sensor_dict[row[0]]['point_name_list'].append(row[2])
352
                    sensor_dict[row[0]]['point_unit_list'].append(row[3])
353
354
        point_data_dict = dict()
355
        for key in sensor_dict:
356
            if sensor_dict[key]['point_id_list'] is not None and len(sensor_dict[key]['point_id_list']) > 0:
357
                cursor_historical.execute(" SELECT point_id, actual_value "
358
                                          " FROM tbl_analog_value_latest "
359
                                          " WHERE point_id in ({}) "
360
                                          " ORDER BY point_id ".
361
                                          format(','.join("{0}".format(x) for x in sensor_dict[key]['point_id_list'])))
362
                rows_analog_values = cursor_historical.fetchall()
363
                if rows_analog_values is not None and len(rows_analog_values) > 0:
364
                    for row in rows_analog_values:
365
                        point_data_dict[row[0]] = row[1]
366
                
367
                cursor_historical.execute(" SELECT point_id, actual_value "
368
                                          " FROM tbl_digital_value_latest "
369
                                          " WHERE point_id in ({}) "
370
                                          " ORDER BY point_id ".
371
                                          format(','.join("{0}".format(x) for x in sensor_dict[key]['point_id_list'])))
372
                rows_digital_values = cursor_historical.fetchall()
373
                if rows_digital_values is not None and len(rows_digital_values) > 0:
374
                    for row in rows_digital_values:
375
                        point_data_dict[row[0]] = row[1]
376
377
        ################################################################################################################
378
        # Step 5: query child spaces
379
        ################################################################################################################
380
        child_space_list = list()
381
        cursor_system.execute(" SELECT id, name  "
382
                              " FROM tbl_spaces "
383
                              " WHERE parent_space_id = %s "
384
                              " ORDER BY id ", (space['id'], ))
385
        rows_child_spaces = cursor_system.fetchall()
386
        if rows_child_spaces is not None and len(rows_child_spaces) > 0:
387
            for row in rows_child_spaces:
388
                child_space_list.append({"id": row[0], "name": row[1]})
389
390
        ################################################################################################################
391
        # Step 6: query base period energy input
392
        ################################################################################################################
393
        base_input = dict()
394 View Code Duplication
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
395
            for energy_category_id in input_energy_category_set:
396
                kgce = energy_category_dict[energy_category_id]['kgce']
397
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
398
399
                base_input[energy_category_id] = dict()
400
                base_input[energy_category_id]['subtotal'] = Decimal(0.0)
401
                base_input[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
402
                base_input[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
403
404
                cursor_energy.execute(" SELECT SUM(actual_value) "
405
                                      " FROM tbl_space_input_category_hourly "
406
                                      " WHERE space_id = %s "
407
                                      "     AND energy_category_id = %s "
408
                                      "     AND start_datetime_utc >= %s "
409
                                      "     AND start_datetime_utc < %s ",
410
                                      (space['id'],
411
                                       energy_category_id,
412
                                       base_start_datetime_utc,
413
                                       base_end_datetime_utc))
414
                row_space_sum = cursor_energy.fetchone()
415
                if row_space_sum is None or len(row_space_sum) < 1 or row_space_sum[0] is None:
416
                    actual_value = Decimal(0.0)
417
                else:
418
                    actual_value = row_space_sum[0]
419
                base_input[energy_category_id]['subtotal'] = actual_value
420
                base_input[energy_category_id]['subtotal_in_kgce'] = actual_value * kgce
421
                base_input[energy_category_id]['subtotal_in_kgco2e'] = actual_value * kgco2e
422
423
        ################################################################################################################
424
        # Step 7: query base period energy cost
425
        ################################################################################################################
426
        base_cost = dict()
427
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
428
            for energy_category_id in input_energy_category_set:
429
                base_cost[energy_category_id] = dict()
430
                base_cost[energy_category_id]['subtotal'] = Decimal(0.0)
431
432
                cursor_billing.execute(" SELECT SUM(actual_value) "
433
                                       " FROM tbl_space_input_category_hourly "
434
                                       " WHERE space_id = %s "
435
                                       "     AND energy_category_id = %s "
436
                                       "     AND start_datetime_utc >= %s "
437
                                       "     AND start_datetime_utc < %s ",
438
                                       (space['id'],
439
                                        energy_category_id,
440
                                        base_start_datetime_utc,
441
                                        base_end_datetime_utc))
442
                row_space_sum = cursor_billing.fetchone()
443
                if row_space_sum is None or len(row_space_sum) < 1 or row_space_sum[0] is None:
444
                    actual_value = Decimal(0.0)
445
                else:
446
                    actual_value = row_space_sum[0]
447
                base_cost[energy_category_id]['subtotal'] = actual_value
448
449
        ################################################################################################################
450
        # Step 8: query base period energy output
451
        ################################################################################################################
452
        base_output = dict()
453 View Code Duplication
        if output_energy_category_set is not None and len(output_energy_category_set) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
454
            for energy_category_id in output_energy_category_set:
455
                kgce = energy_category_dict[energy_category_id]['kgce']
456
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
457
458
                base_output[energy_category_id] = dict()
459
                base_output[energy_category_id]['subtotal'] = Decimal(0.0)
460
                base_output[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
461
                base_output[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
462
463
                cursor_energy.execute(" SELECT SUM(actual_value) "
464
                                      " FROM tbl_space_output_category_hourly "
465
                                      " WHERE space_id = %s "
466
                                      "     AND energy_category_id = %s "
467
                                      "     AND start_datetime_utc >= %s "
468
                                      "     AND start_datetime_utc < %s ",
469
                                      (space['id'],
470
                                       energy_category_id,
471
                                       base_start_datetime_utc,
472
                                       base_end_datetime_utc))
473
                row_space_sum = cursor_energy.fetchone()
474
                if row_space_sum is None or len(row_space_sum) < 1 or row_space_sum[0] is None:
475
                    actual_value = Decimal(0.0)
476
                else:
477
                    actual_value = row_space_sum[0]
478
                base_output[energy_category_id]['subtotal'] = actual_value
479
                base_output[energy_category_id]['subtotal_in_kgce'] = actual_value * kgce
480
                base_output[energy_category_id]['subtotal_in_kgco2e'] = actual_value * kgco2e
481
482
        ################################################################################################################
483
        # Step 9: query reporting period energy input
484
        ################################################################################################################
485
        reporting_input = dict()
486
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
487
            for energy_category_id in input_energy_category_set:
488
                kgce = energy_category_dict[energy_category_id]['kgce']
489
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
490
491
                reporting_input[energy_category_id] = dict()
492
                reporting_input[energy_category_id]['timestamps'] = list()
493
                reporting_input[energy_category_id]['values'] = list()
494
                reporting_input[energy_category_id]['subtotal'] = Decimal(0.0)
495
                reporting_input[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
496
                reporting_input[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
497
                reporting_input[energy_category_id]['toppeak'] = Decimal(0.0)
498
                reporting_input[energy_category_id]['onpeak'] = Decimal(0.0)
499
                reporting_input[energy_category_id]['midpeak'] = Decimal(0.0)
500
                reporting_input[energy_category_id]['offpeak'] = Decimal(0.0)
501
                reporting_input[energy_category_id]['deep'] = Decimal(0.0)
502
503
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
504
                                      " FROM tbl_space_input_category_hourly "
505
                                      " WHERE space_id = %s "
506
                                      "     AND energy_category_id = %s "
507
                                      "     AND start_datetime_utc >= %s "
508
                                      "     AND start_datetime_utc < %s "
509
                                      " ORDER BY start_datetime_utc ",
510
                                      (space['id'],
511
                                       energy_category_id,
512
                                       reporting_start_datetime_utc,
513
                                       reporting_end_datetime_utc))
514
                rows_space_hourly = cursor_energy.fetchall()
515
516
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
517
                                                                                    reporting_start_datetime_utc,
518
                                                                                    reporting_end_datetime_utc,
519
                                                                                    period_type)
520
                for row_space_periodically in rows_space_periodically:
521
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
522
                                             timedelta(minutes=timezone_offset)
523
                    if period_type == 'hourly':
524
                        current_datetime = current_datetime_local.isoformat()[0:19]
525
                    elif period_type == 'daily':
526
                        current_datetime = current_datetime_local.isoformat()[0:10]
527
                    elif period_type == 'weekly':
528
                        current_datetime = current_datetime_local.isoformat()[0:10]
529
                    elif period_type == 'monthly':
530
                        current_datetime = current_datetime_local.isoformat()[0:7]
531
                    elif period_type == 'yearly':
532
                        current_datetime = current_datetime_local.isoformat()[0:4]
533
534
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
535
                    reporting_input[energy_category_id]['timestamps'].append(current_datetime)
0 ignored issues
show
The variable current_datetime does not seem to be defined for all execution paths.
Loading history...
536
                    reporting_input[energy_category_id]['values'].append(actual_value)
537
                    reporting_input[energy_category_id]['subtotal'] += actual_value
538
                    reporting_input[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
539
                    reporting_input[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
540
541
                energy_category_tariff_dict = utilities.get_energy_category_peak_types(space['cost_center_id'],
542
                                                                                       energy_category_id,
543
                                                                                       reporting_start_datetime_utc,
544
                                                                                       reporting_end_datetime_utc)
545
                for row in rows_space_hourly:
546
                    peak_type = energy_category_tariff_dict.get(row[0], None)
547
                    if peak_type == 'toppeak':
548
                        reporting_input[energy_category_id]['toppeak'] += row[1]
549
                    elif peak_type == 'onpeak':
550
                        reporting_input[energy_category_id]['onpeak'] += row[1]
551
                    elif peak_type == 'midpeak':
552
                        reporting_input[energy_category_id]['midpeak'] += row[1]
553
                    elif peak_type == 'offpeak':
554
                        reporting_input[energy_category_id]['offpeak'] += row[1]
555
                    elif peak_type == 'deep':
556
                        reporting_input[energy_category_id]['deep'] += row[1]
557
558
        ################################################################################################################
559
        # Step 10: query reporting period energy cost
560
        ################################################################################################################
561
        reporting_cost = dict()
562
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
563
            for energy_category_id in input_energy_category_set:
564
565
                reporting_cost[energy_category_id] = dict()
566
                reporting_cost[energy_category_id]['timestamps'] = list()
567
                reporting_cost[energy_category_id]['values'] = list()
568
                reporting_cost[energy_category_id]['subtotal'] = Decimal(0.0)
569
                reporting_cost[energy_category_id]['toppeak'] = Decimal(0.0)
570
                reporting_cost[energy_category_id]['onpeak'] = Decimal(0.0)
571
                reporting_cost[energy_category_id]['midpeak'] = Decimal(0.0)
572
                reporting_cost[energy_category_id]['offpeak'] = Decimal(0.0)
573
                reporting_cost[energy_category_id]['deep'] = Decimal(0.0)
574
575
                cursor_billing.execute(" SELECT start_datetime_utc, actual_value "
576
                                       " FROM tbl_space_input_category_hourly "
577
                                       " WHERE space_id = %s "
578
                                       "     AND energy_category_id = %s "
579
                                       "     AND start_datetime_utc >= %s "
580
                                       "     AND start_datetime_utc < %s "
581
                                       " ORDER BY start_datetime_utc ",
582
                                       (space['id'],
583
                                        energy_category_id,
584
                                        reporting_start_datetime_utc,
585
                                        reporting_end_datetime_utc))
586
                rows_space_hourly = cursor_billing.fetchall()
587
588
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
589
                                                                                    reporting_start_datetime_utc,
590
                                                                                    reporting_end_datetime_utc,
591
                                                                                    period_type)
592
                for row_space_periodically in rows_space_periodically:
593
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
594
                                             timedelta(minutes=timezone_offset)
595
                    if period_type == 'hourly':
596
                        current_datetime = current_datetime_local.isoformat()[0:19]
597
                    elif period_type == 'daily':
598
                        current_datetime = current_datetime_local.isoformat()[0:10]
599
                    elif period_type == 'weekly':
600
                        current_datetime = current_datetime_local.isoformat()[0:10]
601
                    elif period_type == 'monthly':
602
                        current_datetime = current_datetime_local.isoformat()[0:7]
603
                    elif period_type == 'yearly':
604
                        current_datetime = current_datetime_local.isoformat()[0:4]
605
606
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
607
                    reporting_cost[energy_category_id]['timestamps'].append(current_datetime)
608
                    reporting_cost[energy_category_id]['values'].append(actual_value)
609
                    reporting_cost[energy_category_id]['subtotal'] += actual_value
610
611
                energy_category_tariff_dict = utilities.get_energy_category_peak_types(space['cost_center_id'],
612
                                                                                       energy_category_id,
613
                                                                                       reporting_start_datetime_utc,
614
                                                                                       reporting_end_datetime_utc)
615
                for row in rows_space_hourly:
616
                    peak_type = energy_category_tariff_dict.get(row[0], None)
617
                    if peak_type == 'toppeak':
618
                        reporting_cost[energy_category_id]['toppeak'] += row[1]
619
                    elif peak_type == 'onpeak':
620
                        reporting_cost[energy_category_id]['onpeak'] += row[1]
621
                    elif peak_type == 'midpeak':
622
                        reporting_cost[energy_category_id]['midpeak'] += row[1]
623
                    elif peak_type == 'offpeak':
624
                        reporting_cost[energy_category_id]['offpeak'] += row[1]
625
                    elif peak_type == 'deep':
626
                        reporting_cost[energy_category_id]['deep'] += row[1]
627
        ################################################################################################################
628
        # Step 11: query reporting period energy output
629
        ################################################################################################################
630
        reporting_output = dict()
631
        if output_energy_category_set is not None and len(output_energy_category_set) > 0:
632
            for energy_category_id in output_energy_category_set:
633
                kgce = energy_category_dict[energy_category_id]['kgce']
634
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
635
636
                reporting_output[energy_category_id] = dict()
637
                reporting_output[energy_category_id]['timestamps'] = list()
638
                reporting_output[energy_category_id]['values'] = list()
639
                reporting_output[energy_category_id]['subtotal'] = Decimal(0.0)
640
                reporting_output[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
641
                reporting_output[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
642
                reporting_output[energy_category_id]['toppeak'] = Decimal(0.0)
643
                reporting_output[energy_category_id]['onpeak'] = Decimal(0.0)
644
                reporting_output[energy_category_id]['midpeak'] = Decimal(0.0)
645
                reporting_output[energy_category_id]['offpeak'] = Decimal(0.0)
646
                reporting_output[energy_category_id]['deep'] = Decimal(0.0)
647
648
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
649
                                      " FROM tbl_space_output_category_hourly "
650
                                      " WHERE space_id = %s "
651
                                      "     AND energy_category_id = %s "
652
                                      "     AND start_datetime_utc >= %s "
653
                                      "     AND start_datetime_utc < %s "
654
                                      " ORDER BY start_datetime_utc ",
655
                                      (space['id'],
656
                                       energy_category_id,
657
                                       reporting_start_datetime_utc,
658
                                       reporting_end_datetime_utc))
659
                rows_space_hourly = cursor_energy.fetchall()
660
661
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
662
                                                                                    reporting_start_datetime_utc,
663
                                                                                    reporting_end_datetime_utc,
664
                                                                                    period_type)
665
                for row_space_periodically in rows_space_periodically:
666
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
667
                                             timedelta(minutes=timezone_offset)
668
                    if period_type == 'hourly':
669
                        current_datetime = current_datetime_local.isoformat()[0:19]
670
                    elif period_type == 'daily':
671
                        current_datetime = current_datetime_local.isoformat()[0:10]
672
                    elif period_type == 'weekly':
673
                        current_datetime = current_datetime_local.isoformat()[0:10]
674
                    elif period_type == 'monthly':
675
                        current_datetime = current_datetime_local.isoformat()[0:7]
676
                    elif period_type == 'yearly':
677
                        current_datetime = current_datetime_local.isoformat()[0:4]
678
679
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else \
680
                        row_space_periodically[1]
681
                    reporting_output[energy_category_id]['timestamps'].append(current_datetime)
682
                    reporting_output[energy_category_id]['values'].append(actual_value)
683
                    reporting_output[energy_category_id]['subtotal'] += actual_value
684
                    reporting_output[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
685
                    reporting_output[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
686
687
                energy_category_tariff_dict = utilities.get_energy_category_peak_types(space['cost_center_id'],
688
                                                                                       energy_category_id,
689
                                                                                       reporting_start_datetime_utc,
690
                                                                                       reporting_end_datetime_utc)
691
                for row in rows_space_hourly:
692
                    peak_type = energy_category_tariff_dict.get(row[0], None)
693
                    if peak_type == 'toppeak':
694
                        reporting_output[energy_category_id]['toppeak'] += row[1]
695
                    elif peak_type == 'onpeak':
696
                        reporting_output[energy_category_id]['onpeak'] += row[1]
697
                    elif peak_type == 'midpeak':
698
                        reporting_output[energy_category_id]['midpeak'] += row[1]
699
                    elif peak_type == 'offpeak':
700
                        reporting_output[energy_category_id]['offpeak'] += row[1]
701
                    elif peak_type == 'deep':
702
                        reporting_output[energy_category_id]['deep'] += row[1]
703
704
        ################################################################################################################
705
        # Step 12: query child spaces energy input
706
        ################################################################################################################
707
        child_space_input = dict()
708
709
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
710
            for energy_category_id in input_energy_category_set:
711
                child_space_input[energy_category_id] = dict()
712
                child_space_input[energy_category_id]['child_space_names'] = list()
713
                child_space_input[energy_category_id]['subtotals'] = list()
714
                child_space_input[energy_category_id]['subtotals_in_kgce'] = list()
715
                child_space_input[energy_category_id]['subtotals_in_kgco2e'] = list()
716
                kgce = energy_category_dict[energy_category_id]['kgce']
717
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
718
                for child_space in child_space_list:
719
                    child_space_input[energy_category_id]['child_space_names'].append(child_space['name'])
720
                    subtotal = 0
721
                    subtotal_list = list()
722
723
                    cursor_energy.execute(" SELECT start_datetime_utc, actual_value"
724
                                          " FROM tbl_space_input_category_hourly "
725
                                          " WHERE space_id = %s "
726
                                          "     AND energy_category_id = %s "
727
                                          "     AND start_datetime_utc >= %s "
728
                                          "     AND start_datetime_utc < %s "
729
                                          " ORDER BY start_datetime_utc ",
730
                                          (child_space['id'],
731
                                           energy_category_id,
732
                                           reporting_start_datetime_utc,
733
                                           reporting_end_datetime_utc))
734
                    row_subtotal = cursor_energy.fetchall() 
735
                    rows_space_periodically = utilities.aggregate_hourly_data_by_period(row_subtotal,
736
                                                                                        reporting_start_datetime_utc,
737
                                                                                        reporting_end_datetime_utc,
738
                                                                                        period_type)
739
740
                    for row_space_periodically in rows_space_periodically:
741
                        actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
742
                        subtotal_list.append(actual_value)
743
                        subtotal += actual_value
744
745
                    child_space_input[energy_category_id]['subtotals'].append(subtotal_list)
746
                    child_space_input[energy_category_id]['subtotals_in_kgce'].append(subtotal * kgce)
747
                    child_space_input[energy_category_id]['subtotals_in_kgco2e'].append(subtotal * kgco2e)
748
749
        ################################################################################################################
750
        # Step 13: query child spaces energy cost
751
        ################################################################################################################
752
        child_space_cost = dict()
753
754
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
755
            for energy_category_id in input_energy_category_set:
756
                child_space_cost[energy_category_id] = dict()
757
                child_space_cost[energy_category_id]['child_space_names'] = list()
758
                child_space_cost[energy_category_id]['subtotals'] = list()
759
                for child_space in child_space_list:
760
                    child_space_cost[energy_category_id]['child_space_names'].append(child_space['name'])
761
                    subtotal_list = list()
762
763
                    cursor_billing.execute(" SELECT start_datetime_utc, actual_value"
764
                                           " FROM tbl_space_input_category_hourly "
765
                                           " WHERE space_id = %s "
766
                                           "     AND energy_category_id = %s "
767
                                           "     AND start_datetime_utc >= %s "
768
                                           "     AND start_datetime_utc < %s "
769
                                           " ORDER BY start_datetime_utc ",
770
                                           (child_space['id'],
771
                                            energy_category_id,
772
                                            reporting_start_datetime_utc,
773
                                            reporting_end_datetime_utc))
774
                    row_subtotal = cursor_billing.fetchall() 
775
                    rows_space_periodically = utilities.aggregate_hourly_data_by_period(row_subtotal,
776
                                                                                        reporting_start_datetime_utc,
777
                                                                                        reporting_end_datetime_utc,
778
                                                                                        period_type)
779
780
                    for row_space_periodically in rows_space_periodically:
781
                        actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
782
                        subtotal_list.append(actual_value)
783
784
                    child_space_cost[energy_category_id]['subtotals'].append(subtotal_list)
785
786
        ################################################################################################################
787
        # Step 14: construct the report
788
        ################################################################################################################
789
        if cursor_system:
790
            cursor_system.close()
791
        if cnx_system:
792
            cnx_system.close()
793
794
        if cursor_energy:
795
            cursor_energy.close()
796
        if cnx_energy:
797
            cnx_energy.close()
798
799
        if cursor_billing:
800
            cursor_billing.close()
801
        if cnx_billing:
802
            cnx_billing.close()
803
804
        result = dict()
805
806
        result['space'] = dict()
807
        result['space']['id'] = space['id']
808
        result['space']['name'] = space['name']
809
        result['space']['area'] = space['area']
810
        result['space']['number_of_occupants'] = space['number_of_occupants']
811
812
        result['base_period_input'] = dict()
813
        result['base_period_input']['names'] = list()
814
        result['base_period_input']['units'] = list()
815
        result['base_period_input']['subtotals'] = list()
816
        result['base_period_input']['subtotals_in_kgce'] = list()
817
        result['base_period_input']['subtotals_in_kgco2e'] = list()
818
        result['base_period_input']['total_in_kgce'] = Decimal(0.0)
819
        result['base_period_input']['total_in_kgco2e'] = Decimal(0.0)
820
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
821
            for energy_category_id in input_energy_category_set:
822
                result['base_period_input']['names'].append(
823
                    energy_category_dict[energy_category_id]['name'])
824
                result['base_period_input']['units'].append(
825
                    energy_category_dict[energy_category_id]['unit_of_measure'])
826
                result['base_period_input']['subtotals'].append(
827
                    base_input[energy_category_id]['subtotal'])
828
                result['base_period_input']['subtotals_in_kgce'].append(
829
                    base_input[energy_category_id]['subtotal_in_kgce'])
830
                result['base_period_input']['subtotals_in_kgco2e'].append(
831
                    base_input[energy_category_id]['subtotal_in_kgco2e'])
832
                result['base_period_input']['total_in_kgce'] += \
833
                    base_input[energy_category_id]['subtotal_in_kgce']
834
                result['base_period_input']['total_in_kgco2e'] += \
835
                    base_input[energy_category_id]['subtotal_in_kgco2e']
836
        
837
        result['sensor'] = dict()
838
        result['point'] = dict()
839
        result['sensor'] = sensor_dict
840
        result['point'] = point_data_dict
841
842
        result['base_period_cost'] = dict()
843
        result['base_period_cost']['names'] = list()
844
        result['base_period_cost']['units'] = list()
845
        result['base_period_cost']['subtotals'] = list()
846
        result['base_period_cost']['total'] = Decimal(0.0)
847
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
848
            for energy_category_id in input_energy_category_set:
849
                result['base_period_cost']['names'].append(
850
                    energy_category_dict[energy_category_id]['name'])
851
                result['base_period_cost']['units'].append(config.currency_unit)
852
                result['base_period_cost']['subtotals'].append(
853
                    base_cost[energy_category_id]['subtotal'])
854
                result['base_period_cost']['total'] += base_cost[energy_category_id]['subtotal']
855
856
        result['base_period_output'] = dict()
857
        result['base_period_output']['names'] = list()
858
        result['base_period_output']['units'] = list()
859
        result['base_period_output']['subtotals'] = list()
860
        result['base_period_output']['subtotals_in_kgce'] = list()
861
        result['base_period_output']['subtotals_in_kgco2e'] = list()
862
        result['base_period_output']['total_in_kgce'] = Decimal(0.0)
863
        result['base_period_output']['total_in_kgco2e'] = Decimal(0.0)
864
        if output_energy_category_set is not None and len(output_energy_category_set) > 0:
865
            for energy_category_id in output_energy_category_set:
866
                result['base_period_output']['names'].append(
867
                    energy_category_dict[energy_category_id]['name'])
868
                result['base_period_output']['units'].append(
869
                    energy_category_dict[energy_category_id]['unit_of_measure'])
870
                result['base_period_output']['subtotals'].append(
871
                    base_output[energy_category_id]['subtotal'])
872
                result['base_period_output']['subtotals_in_kgce'].append(
873
                    base_output[energy_category_id]['subtotal_in_kgce'])
874
                result['base_period_output']['subtotals_in_kgco2e'].append(
875
                    base_output[energy_category_id]['subtotal_in_kgco2e'])
876
                result['base_period_output']['total_in_kgce'] += \
877
                    base_output[energy_category_id]['subtotal_in_kgce']
878
                result['base_period_output']['total_in_kgco2e'] += \
879
                    base_output[energy_category_id]['subtotal_in_kgco2e']
880
881
        result['reporting_period_input'] = dict()
882
        result['reporting_period_input']['names'] = list()
883
        result['reporting_period_input']['energy_category_ids'] = list()
884
        result['reporting_period_input']['units'] = list()
885
        result['reporting_period_input']['timestamps'] = list()
886
        result['reporting_period_input']['values'] = list()
887
        result['reporting_period_input']['subtotals'] = list()
888
        result['reporting_period_input']['subtotals_in_kgce'] = list()
889
        result['reporting_period_input']['subtotals_in_kgco2e'] = list()
890
        result['reporting_period_input']['toppeaks'] = list()
891
        result['reporting_period_input']['onpeaks'] = list()
892
        result['reporting_period_input']['midpeaks'] = list()
893
        result['reporting_period_input']['offpeaks'] = list()
894
        result['reporting_period_input']['deeps'] = list()
895
        result['reporting_period_input']['increment_rates'] = list()
896
        result['reporting_period_input']['total_in_kgce'] = Decimal(0.0)
897
        result['reporting_period_input']['total_in_kgco2e'] = Decimal(0.0)
898
        result['reporting_period_input']['increment_rate_in_kgce'] = Decimal(0.0)
899
        result['reporting_period_input']['increment_rate_in_kgco2e'] = Decimal(0.0)
900
901
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
902
            for energy_category_id in input_energy_category_set:
903
                result['reporting_period_input']['names'].append(energy_category_dict[energy_category_id]['name'])
904
                result['reporting_period_input']['energy_category_ids'].append(energy_category_id)
905
                result['reporting_period_input']['units'].append(
906
                    energy_category_dict[energy_category_id]['unit_of_measure'])
907
                result['reporting_period_input']['timestamps'].append(
908
                    reporting_input[energy_category_id]['timestamps'])
909
                result['reporting_period_input']['values'].append(
910
                    reporting_input[energy_category_id]['values'])
911
                result['reporting_period_input']['subtotals'].append(
912
                    reporting_input[energy_category_id]['subtotal'])
913
                result['reporting_period_input']['subtotals_in_kgce'].append(
914
                    reporting_input[energy_category_id]['subtotal_in_kgce'])
915
                result['reporting_period_input']['subtotals_in_kgco2e'].append(
916
                    reporting_input[energy_category_id]['subtotal_in_kgco2e'])
917
                result['reporting_period_input']['toppeaks'].append(
918
                    reporting_input[energy_category_id]['toppeak'])
919
                result['reporting_period_input']['onpeaks'].append(
920
                    reporting_input[energy_category_id]['onpeak'])
921
                result['reporting_period_input']['midpeaks'].append(
922
                    reporting_input[energy_category_id]['midpeak'])
923
                result['reporting_period_input']['offpeaks'].append(
924
                    reporting_input[energy_category_id]['offpeak'])
925
                result['reporting_period_input']['deeps'].append(
926
                    reporting_input[energy_category_id]['deep'])
927
                result['reporting_period_input']['increment_rates'].append(
928
                    (reporting_input[energy_category_id]['subtotal'] -
929
                     base_input[energy_category_id]['subtotal']) /
930
                    base_input[energy_category_id]['subtotal']
931
                    if base_input[energy_category_id]['subtotal'] > 0.0 else None)
932
                result['reporting_period_input']['total_in_kgce'] += \
933
                    reporting_input[energy_category_id]['subtotal_in_kgce']
934
                result['reporting_period_input']['total_in_kgco2e'] += \
935
                    reporting_input[energy_category_id]['subtotal_in_kgco2e']
936
937
        result['reporting_period_input']['increment_rate_in_kgce'] = \
938
            (result['reporting_period_input']['total_in_kgce'] - result['base_period_input']['total_in_kgce']) / \
939
            result['base_period_input']['total_in_kgce'] \
940
            if result['base_period_input']['total_in_kgce'] > Decimal(0.0) else None
941
942
        result['reporting_period_input']['increment_rate_in_kgco2e'] = \
943
            (result['reporting_period_input']['total_in_kgco2e'] - result['base_period_input']['total_in_kgco2e']) / \
944
            result['base_period_input']['total_in_kgco2e'] \
945
            if result['base_period_input']['total_in_kgco2e'] > Decimal(0.0) else None
946
947
        result['reporting_period_cost'] = dict()
948
        result['reporting_period_cost']['names'] = list()
949
        result['reporting_period_cost']['energy_category_ids'] = list()
950
        result['reporting_period_cost']['units'] = list()
951
        result['reporting_period_cost']['timestamps'] = list()
952
        result['reporting_period_cost']['values'] = list()
953
        result['reporting_period_cost']['subtotals'] = list()
954
        result['reporting_period_cost']['toppeaks'] = list()
955
        result['reporting_period_cost']['onpeaks'] = list()
956
        result['reporting_period_cost']['midpeaks'] = list()
957
        result['reporting_period_cost']['offpeaks'] = list()
958
        result['reporting_period_cost']['deeps'] = list()
959
        result['reporting_period_cost']['increment_rates'] = list()
960
        result['reporting_period_cost']['total'] = Decimal(0.0)
961
        result['reporting_period_cost']['total_increment_rate'] = Decimal(0.0)
962
        result['reporting_period_cost']['total_unit'] = config.currency_unit
963
964
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
965
            for energy_category_id in input_energy_category_set:
966
                result['reporting_period_cost']['names'].append(energy_category_dict[energy_category_id]['name'])
967
                result['reporting_period_cost']['energy_category_ids'].append(energy_category_id)
968
                result['reporting_period_cost']['units'].append(config.currency_unit)
969
                result['reporting_period_cost']['timestamps'].append(
970
                    reporting_cost[energy_category_id]['timestamps'])
971
                result['reporting_period_cost']['values'].append(
972
                    reporting_cost[energy_category_id]['values'])
973
                result['reporting_period_cost']['subtotals'].append(
974
                    reporting_cost[energy_category_id]['subtotal'])
975
                result['reporting_period_cost']['toppeaks'].append(
976
                    reporting_cost[energy_category_id]['toppeak'])
977
                result['reporting_period_cost']['onpeaks'].append(
978
                    reporting_cost[energy_category_id]['onpeak'])
979
                result['reporting_period_cost']['midpeaks'].append(
980
                    reporting_cost[energy_category_id]['midpeak'])
981
                result['reporting_period_cost']['offpeaks'].append(
982
                    reporting_cost[energy_category_id]['offpeak'])
983
                result['reporting_period_cost']['deeps'].append(
984
                    reporting_cost[energy_category_id]['deep'])
985
                result['reporting_period_cost']['increment_rates'].append(
986
                    (reporting_cost[energy_category_id]['subtotal'] -
987
                     base_cost[energy_category_id]['subtotal']) /
988
                    base_cost[energy_category_id]['subtotal']
989
                    if base_cost[energy_category_id]['subtotal'] > 0.0 else None)
990
                result['reporting_period_cost']['total'] += reporting_cost[energy_category_id]['subtotal']
991
992
        result['reporting_period_cost']['total_increment_rate'] = \
993
            (result['reporting_period_cost']['total'] - result['base_period_cost']['total']) / \
994
            result['reporting_period_cost']['total'] \
995
            if result['reporting_period_cost']['total'] > Decimal(0.0) else None
996
997
        result['reporting_period_output'] = dict()
998
        result['reporting_period_output']['names'] = list()
999
        result['reporting_period_output']['energy_category_ids'] = list()
1000
        result['reporting_period_output']['units'] = list()
1001
        result['reporting_period_output']['timestamps'] = list()
1002
        result['reporting_period_output']['values'] = list()
1003
        result['reporting_period_output']['subtotals'] = list()
1004
        result['reporting_period_output']['subtotals_in_kgce'] = list()
1005
        result['reporting_period_output']['subtotals_in_kgco2e'] = list()
1006
        result['reporting_period_output']['toppeaks'] = list()
1007
        result['reporting_period_output']['onpeaks'] = list()
1008
        result['reporting_period_output']['midpeaks'] = list()
1009
        result['reporting_period_output']['offpeaks'] = list()
1010
        result['reporting_period_output']['deeps'] = list()
1011
        result['reporting_period_output']['increment_rates'] = list()
1012
        result['reporting_period_output']['total_in_kgce'] = Decimal(0.0)
1013
        result['reporting_period_output']['total_in_kgco2e'] = Decimal(0.0)
1014
        result['reporting_period_output']['increment_rate_in_kgce'] = Decimal(0.0)
1015
        result['reporting_period_output']['increment_rate_in_kgco2e'] = Decimal(0.0)
1016
1017
        if output_energy_category_set is not None and len(output_energy_category_set) > 0:
1018
            for energy_category_id in output_energy_category_set:
1019
                result['reporting_period_output']['names'].append(energy_category_dict[energy_category_id]['name'])
1020
                result['reporting_period_output']['energy_category_ids'].append(energy_category_id)
1021
                result['reporting_period_output']['units'].append(
1022
                    energy_category_dict[energy_category_id]['unit_of_measure'])
1023
                result['reporting_period_output']['timestamps'].append(
1024
                    reporting_output[energy_category_id]['timestamps'])
1025
                result['reporting_period_output']['values'].append(
1026
                    reporting_output[energy_category_id]['values'])
1027
                result['reporting_period_output']['subtotals'].append(
1028
                    reporting_output[energy_category_id]['subtotal'])
1029
                result['reporting_period_output']['subtotals_in_kgce'].append(
1030
                    reporting_output[energy_category_id]['subtotal_in_kgce'])
1031
                result['reporting_period_output']['subtotals_in_kgco2e'].append(
1032
                    reporting_output[energy_category_id]['subtotal_in_kgco2e'])
1033
                result['reporting_period_output']['toppeaks'].append(
1034
                    reporting_output[energy_category_id]['toppeak'])
1035
                result['reporting_period_output']['onpeaks'].append(
1036
                    reporting_output[energy_category_id]['onpeak'])
1037
                result['reporting_period_output']['midpeaks'].append(
1038
                    reporting_output[energy_category_id]['midpeak'])
1039
                result['reporting_period_output']['offpeaks'].append(
1040
                    reporting_output[energy_category_id]['offpeak'])
1041
                result['reporting_period_output']['deeps'].append(
1042
                    reporting_output[energy_category_id]['deep'])
1043
                result['reporting_period_output']['increment_rates'].append(
1044
                    (reporting_output[energy_category_id]['subtotal'] -
1045
                     base_output[energy_category_id]['subtotal']) /
1046
                    base_output[energy_category_id]['subtotal']
1047
                    if base_output[energy_category_id]['subtotal'] > 0.0 else None)
1048
                result['reporting_period_output']['total_in_kgce'] += \
1049
                    reporting_output[energy_category_id]['subtotal_in_kgce']
1050
                result['reporting_period_output']['total_in_kgco2e'] += \
1051
                    reporting_output[energy_category_id]['subtotal_in_kgco2e']
1052
        result['reporting_period_output']['increment_rate_in_kgce'] = \
1053
            (result['reporting_period_output']['total_in_kgce'] - result['base_period_input']['total_in_kgce']) / \
1054
            result['base_period_output']['total_in_kgce'] \
1055
            if result['reporting_period_output']['total_in_kgce'] > Decimal(0.0) else None
1056
1057
        result['reporting_period_output']['increment_rate_in_kgco2e'] = \
1058
            (result['reporting_period_output']['total_in_kgco2e'] - result['base_period_output']['total_in_kgco2e']) / \
1059
            result['base_period_output']['total_in_kgco2e'] \
1060
            if result['base_period_output']['total_in_kgco2e'] > Decimal(0.0) else None
1061
1062
        result['child_space_input'] = dict()
1063
        result['child_space_input']['energy_category_names'] = list()  # 1D array [energy category]
1064
        result['child_space_input']['units'] = list()  # 1D array [energy category]
1065
        result['child_space_input']['child_space_names_array'] = list()  # 2D array [energy category][child space]
1066
        result['child_space_input']['subtotals_array'] = list()  # 2D array [energy category][child space]
1067
        result['child_space_input']['subtotals_in_kgce_array'] = list()  # 2D array [energy category][child space]
1068
        result['child_space_input']['subtotals_in_kgco2e_array'] = list()  # 2D array [energy category][child space]
1069
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
1070
            for energy_category_id in input_energy_category_set:
1071
                result['child_space_input']['energy_category_names'].append(
1072
                    energy_category_dict[energy_category_id]['name'])
1073
                result['child_space_input']['units'].append(
1074
                    energy_category_dict[energy_category_id]['unit_of_measure'])
1075
                result['child_space_input']['child_space_names_array'].append(
1076
                    child_space_input[energy_category_id]['child_space_names'])
1077
                result['child_space_input']['subtotals_array'].append(
1078
                    child_space_input[energy_category_id]['subtotals'])
1079
                result['child_space_input']['subtotals_in_kgce_array'].append(
1080
                    child_space_input[energy_category_id]['subtotals_in_kgce'])
1081
                result['child_space_input']['subtotals_in_kgco2e_array'].append(
1082
                    child_space_input[energy_category_id]['subtotals_in_kgco2e'])
1083
1084
        result['child_space_cost'] = dict()
1085
        result['child_space_cost']['energy_category_names'] = list()  # 1D array [energy category]
1086
        result['child_space_cost']['units'] = list()  # 1D array [energy category]
1087
        result['child_space_cost']['child_space_names_array'] = list()  # 2D array [energy category][child space]
1088
        result['child_space_cost']['subtotals_array'] = list()  # 2D array [energy category][child space]
1089
        if input_energy_category_set is not None and len(input_energy_category_set) > 0:
1090
            for energy_category_id in input_energy_category_set:
1091
                result['child_space_cost']['energy_category_names'].append(
1092
                    energy_category_dict[energy_category_id]['name'])
1093
                result['child_space_cost']['units'].append(config.currency_unit)
1094
                result['child_space_cost']['child_space_names_array'].append(
1095
                    child_space_cost[energy_category_id]['child_space_names'])
1096
                result['child_space_cost']['subtotals_array'].append(
1097
                    child_space_cost[energy_category_id]['subtotals'])
1098
1099
        resp.text = json.dumps(result)
1100