Issues (1656)

myems-api/reports/combinedequipmentefficiency.py (7 issues)

1
import re
2
from datetime import datetime, timedelta, timezone
3
from decimal import Decimal
4
import falcon
5
import mysql.connector
6
import simplejson as json
7
import config
8
import excelexporters.combinedequipmentefficiency
9
from core import utilities
10
from core.useractivity import access_control, api_key_control
11
12
13
class Reporting:
14
    def __init__(self):
15
        """"Initializes Reporting"""
16
        pass
17
18
    @staticmethod
19
    def on_options(req, resp):
20
        _ = req
21
        resp.status = falcon.HTTP_200
22
23
    ####################################################################################################################
24
    # PROCEDURES
25
    # Step 1: valid parameters
26
    # Step 2: query the combined equipment
27
    # Step 3: query energy categories
28
    # Step 4: query associated points
29
    # Step 5: query associated equipments
30
    # Step 6: query associated fractions
31
    # Step 7: query fractions' numerator and denominator
32
    # Step 8: calculate base period fractions
33
    # Step 9: calculate reporting period fractions
34
    # Step 10: query associated points data
35
    # Step 11: query associated equipments energy input
36
    # Step 12: 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
        print(req.params)
47
        combined_equipment_id = req.params.get('combinedequipmentid')
48
        combined_equipment_uuid = req.params.get('combinedequipmentuuid')
49
        period_type = req.params.get('periodtype')
50
        base_period_start_datetime_local = req.params.get('baseperiodstartdatetime')
51
        base_period_end_datetime_local = req.params.get('baseperiodenddatetime')
52
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
53
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
54
        language = req.params.get('language')
55
        quick_mode = req.params.get('quickmode')
56
57
        ################################################################################################################
58
        # Step 1: valid parameters
59
        ################################################################################################################
60
        if combined_equipment_id is None and combined_equipment_uuid is None:
61
            raise falcon.HTTPError(status=falcon.HTTP_400,
62
                                   title='API.BAD_REQUEST',
63
                                   description='API.INVALID_COMBINED_EQUIPMENT_ID')
64
65
        if combined_equipment_id is not None:
66
            combined_equipment_id = str.strip(combined_equipment_id)
67
            if not combined_equipment_id.isdigit() or int(combined_equipment_id) <= 0:
68
                raise falcon.HTTPError(status=falcon.HTTP_400,
69
                                       title='API.BAD_REQUEST',
70
                                       description='API.INVALID_COMBINED_EQUIPMENT_ID')
71
72
        if combined_equipment_uuid is not None:
73
            regex = re.compile(r'^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
74
            match = regex.match(str.strip(combined_equipment_uuid))
75
            if not bool(match):
76
                raise falcon.HTTPError(status=falcon.HTTP_400,
77
                                       title='API.BAD_REQUEST',
78
                                       description='API.INVALID_COMBINED_EQUIPMENT_UUID')
79
80
        if period_type is None:
81
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
82
                                   description='API.INVALID_PERIOD_TYPE')
83
        else:
84
            period_type = str.strip(period_type)
85
            if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
86
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
87
                                       description='API.INVALID_PERIOD_TYPE')
88
89
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
90
        if config.utc_offset[0] == '-':
91
            timezone_offset = -timezone_offset
92
93
        base_start_datetime_utc = None
94
        if base_period_start_datetime_local is not None and len(str.strip(base_period_start_datetime_local)) > 0:
95
            base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
96
            try:
97
                base_start_datetime_utc = datetime.strptime(base_period_start_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_START_DATETIME")
101
            base_start_datetime_utc = \
102
                base_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
103
            # nomalize the start datetime
104
            if config.minutes_to_count == 30 and base_start_datetime_utc.minute >= 30:
105
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
106
            else:
107
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
108
109
        base_end_datetime_utc = None
110
        if base_period_end_datetime_local is not None and len(str.strip(base_period_end_datetime_local)) > 0:
111
            base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
112
            try:
113
                base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
114
            except ValueError:
115
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
116
                                       description="API.INVALID_BASE_PERIOD_END_DATETIME")
117
            base_end_datetime_utc = \
118
                base_end_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
119
120
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
121
                base_start_datetime_utc >= base_end_datetime_utc:
122
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
123
                                   description='API.INVALID_BASE_PERIOD_END_DATETIME')
124
125
        if reporting_period_start_datetime_local is None:
126
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
127
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
128
        else:
129
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
130
            try:
131
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
132
                                                                 '%Y-%m-%dT%H:%M:%S')
133
            except ValueError:
134
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
135
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
136
            reporting_start_datetime_utc = \
137
                reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
138
            # nomalize the start datetime
139
            if config.minutes_to_count == 30 and reporting_start_datetime_utc.minute >= 30:
140
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
141
            else:
142
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
143
144
        if reporting_period_end_datetime_local is None:
145
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
146
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
147
        else:
148
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
149
            try:
150
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
151
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
152
                                             timedelta(minutes=timezone_offset)
153
            except ValueError:
154
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
155
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
156
157
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
158
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
159
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
160
        # if turn quick mode on, do not return parameters data and excel file
161
        is_quick_mode = False
162
        if quick_mode is not None and \
163
            len(str.strip(quick_mode)) > 0 and \
164
                str.lower(str.strip(quick_mode)) in ('true', 't', 'on', 'yes', 'y'):
165
            is_quick_mode = True
166
167
        ################################################################################################################
168
        # Step 2: query the combined equipment
169
        ################################################################################################################
170
        cnx_system = mysql.connector.connect(**config.myems_system_db)
171
        cursor_system = cnx_system.cursor()
172
173
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
174
        cursor_energy = cnx_energy.cursor()
175
176
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
177
        cursor_historical = cnx_historical.cursor()
178
179
        if combined_equipment_id is not None:
180
            cursor_system.execute(" SELECT id, name, cost_center_id "
181
                                  " FROM tbl_combined_equipments "
182
                                  " WHERE id = %s ", (combined_equipment_id,))
183
            row_combined_equipment = cursor_system.fetchone()
184
        elif combined_equipment_uuid is not None:
185
            cursor_system.execute(" SELECT id, name, cost_center_id "
186
                                  " FROM tbl_combined_equipments "
187
                                  " WHERE uuid = %s ", (combined_equipment_uuid,))
188
            row_combined_equipment = cursor_system.fetchone()
189
190 View Code Duplication
        if row_combined_equipment is None:
0 ignored issues
show
The variable row_combined_equipment does not seem to be defined for all execution paths.
Loading history...
This code seems to be duplicated in your project.
Loading history...
191
            if cursor_system:
192
                cursor_system.close()
193
            if cnx_system:
194
                cnx_system.close()
195
196
            if cursor_energy:
197
                cursor_energy.close()
198
            if cnx_energy:
199
                cnx_energy.close()
200
201
            if cursor_historical:
202
                cursor_historical.close()
203
            if cnx_historical:
204
                cnx_historical.close()
205
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
206
                                   description='API.COMBINED_EQUIPMENT_NOT_FOUND')
207
208
        combined_equipment = dict()
209
        combined_equipment['id'] = row_combined_equipment[0]
210
        combined_equipment['name'] = row_combined_equipment[1]
211
        combined_equipment['cost_center_id'] = row_combined_equipment[2]
212
213
        ################################################################################################################
214
        # Step 3: query energy categories
215
        ################################################################################################################
216
        energy_category_set = set()
217
        # query energy categories in base period
218
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
219
                              " FROM tbl_combined_equipment_input_category_hourly "
220
                              " WHERE combined_equipment_id = %s "
221
                              "     AND start_datetime_utc >= %s "
222
                              "     AND start_datetime_utc < %s ",
223
                              (combined_equipment['id'], base_start_datetime_utc, base_end_datetime_utc))
224
        rows_energy_categories = cursor_energy.fetchall()
225
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
226
            for row_energy_category in rows_energy_categories:
227
                energy_category_set.add(row_energy_category[0])
228
229
        # query energy categories in reporting period
230
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
231
                              " FROM tbl_combined_equipment_input_category_hourly "
232
                              " WHERE combined_equipment_id = %s "
233
                              "     AND start_datetime_utc >= %s "
234
                              "     AND start_datetime_utc < %s ",
235
                              (combined_equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
236
        rows_energy_categories = cursor_energy.fetchall()
237
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
238
            for row_energy_category in rows_energy_categories:
239
                energy_category_set.add(row_energy_category[0])
240
241
        # query all energy categories in base period and reporting period
242
        cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e "
243
                              " FROM tbl_energy_categories "
244
                              " ORDER BY id ", )
245
        rows_energy_categories = cursor_system.fetchall()
246
        if rows_energy_categories is None or len(rows_energy_categories) == 0:
247
            if cursor_system:
248
                cursor_system.close()
249
            if cnx_system:
250
                cnx_system.close()
251
252
            if cursor_energy:
253
                cursor_energy.close()
254
            if cnx_energy:
255
                cnx_energy.close()
256
257
            if cursor_historical:
258
                cursor_historical.close()
259
            if cnx_historical:
260
                cnx_historical.close()
261
            raise falcon.HTTPError(status=falcon.HTTP_404,
262
                                   title='API.NOT_FOUND',
263
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
264
        energy_category_dict = dict()
265
        for row_energy_category in rows_energy_categories:
266
            if row_energy_category[0] in energy_category_set:
267
                energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1],
268
                                                                "unit_of_measure": row_energy_category[2],
269
                                                                "kgce": row_energy_category[3],
270
                                                                "kgco2e": row_energy_category[4]}
271
272
        ################################################################################################################
273
        # Step 4: query associated points
274
        ################################################################################################################
275
        point_list = list()
276
        cursor_system.execute(" SELECT p.id, ep.name, p.units, p.object_type  "
277
                              " FROM tbl_combined_equipments e, tbl_combined_equipments_parameters ep, tbl_points p "
278
                              " WHERE e.id = %s AND e.id = ep.combined_equipment_id AND ep.parameter_type = 'point' "
279
                              "       AND ep.point_id = p.id "
280
                              " ORDER BY p.id ", (combined_equipment['id'],))
281
        rows_points = cursor_system.fetchall()
282
        if rows_points is not None and len(rows_points) > 0:
283
            for row in rows_points:
284
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
285
286
        ################################################################################################################
287
        # Step 5: query associated equipments
288
        ################################################################################################################
289
        associated_equipment_list = list()
290
        cursor_system.execute(" SELECT e.id, e.name "
291
                              " FROM tbl_equipments e,tbl_combined_equipments_equipments ee"
292
                              " WHERE ee.combined_equipment_id = %s AND e.id = ee.equipment_id"
293
                              " ORDER BY id ", (combined_equipment['id'],))
294
        rows_associated_equipments = cursor_system.fetchall()
295
        if rows_associated_equipments is not None and len(rows_associated_equipments) > 0:
296
            for row in rows_associated_equipments:
297
                associated_equipment_list.append({"id": row[0], "name": row[1]})
298
299
        ################################################################################################################
300
        # Step 6: query associated fractions
301
        ################################################################################################################
302
        fraction_list = list()
303
        cursor_system.execute(" SELECT id, name, numerator_meter_uuid, denominator_meter_uuid  "
304
                              " FROM tbl_combined_equipments_parameters "
305
                              " WHERE combined_equipment_id = %s AND parameter_type = 'fraction' ",
306
                              (combined_equipment['id'],))
307
        rows_fractions = cursor_system.fetchall()
308
        if rows_fractions is not None and len(rows_fractions) > 0:
309
            for row in rows_fractions:
310
                fraction_list.append({"id": row[0],
311
                                      "name": row[1],
312
                                      "numerator_meter_uuid": row[2],
313
                                      "denominator_meter_uuid": row[3],
314
                                      })
315
316
        ################################################################################################################
317
        # Step 7: query fractions' numerator and denominator
318
        ################################################################################################################
319
        # get all meters
320
        meter_dict = dict()
321
        query = (" SELECT m.uuid, m.id, m.name, ec.unit_of_measure "
322
                 " FROM tbl_meters m, tbl_energy_categories ec "
323
                 " WHERE m.energy_category_id  = ec.id ")
324
        cursor_system.execute(query)
325
        rows_meters = cursor_system.fetchall()
326
327
        if rows_meters is not None and len(rows_meters) > 0:
328
            for row in rows_meters:
329
                meter_dict[row[0]] = {'id': row[1], 'name': row[2], 'unit': row[3]}
330
        # get all offline meters
331
        offline_meter_dict = dict()
332
        query = (" SELECT m.uuid, m.id, m.name, ec.unit_of_measure "
333
                 " FROM tbl_offline_meters m, tbl_energy_categories ec "
334
                 " WHERE m.energy_category_id  = ec.id ")
335
        cursor_system.execute(query)
336
        rows_offline_meters = cursor_system.fetchall()
337
338
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
339
            for row in rows_offline_meters:
340
                offline_meter_dict[row[0]] = {'id': row[1], 'name': row[2], 'unit': row[3]}
341
        # get all virtual meters
342
        virtual_meter_dict = dict()
343
        query = (" SELECT m.uuid, m.id, m.name, ec.unit_of_measure "
344
                 " FROM tbl_virtual_meters m, tbl_energy_categories ec "
345
                 " WHERE m.energy_category_id  = ec.id ")
346
        cursor_system.execute(query)
347
        rows_virtual_meters = cursor_system.fetchall()
348
349
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
350
            for row in rows_virtual_meters:
351
                virtual_meter_dict[row[0]] = {'id': row[1], 'name': row[2], 'unit': row[3]}
352
353 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
354
            for i in range(len(fraction_list)):
355
                if fraction_list[i]['numerator_meter_uuid'] in offline_meter_dict:
356
                    fraction_list[i]['numerator_meter_id'] = \
357
                        offline_meter_dict[fraction_list[i]['numerator_meter_uuid']]['id']
358
                    fraction_list[i]['numerator_meter_name'] = \
359
                        offline_meter_dict[fraction_list[i]['numerator_meter_uuid']]['name']
360
                    fraction_list[i]['numerator_meter_unit'] = \
361
                        offline_meter_dict[fraction_list[i]['numerator_meter_uuid']]['unit']
362
                    fraction_list[i]['numerator_meter_type'] = 'offline_meter'
363
                elif fraction_list[i]['numerator_meter_uuid'] in virtual_meter_dict:
364
                    fraction_list[i]['numerator_meter_id'] = \
365
                        virtual_meter_dict[fraction_list[i]['numerator_meter_uuid']]['id']
366
                    fraction_list[i]['numerator_meter_name'] = \
367
                        virtual_meter_dict[fraction_list[i]['numerator_meter_uuid']]['name']
368
                    fraction_list[i]['numerator_meter_unit'] = \
369
                        virtual_meter_dict[fraction_list[i]['numerator_meter_uuid']]['unit']
370
                    fraction_list[i]['numerator_meter_type'] = 'virtual_meter'
371
                elif fraction_list[i]['numerator_meter_uuid'] in meter_dict:
372
                    fraction_list[i]['numerator_meter_id'] = \
373
                        meter_dict[fraction_list[i]['numerator_meter_uuid']]['id']
374
                    fraction_list[i]['numerator_meter_name'] = \
375
                        meter_dict[fraction_list[i]['numerator_meter_uuid']]['name']
376
                    fraction_list[i]['numerator_meter_unit'] = \
377
                        meter_dict[fraction_list[i]['numerator_meter_uuid']]['unit']
378
                    fraction_list[i]['numerator_meter_type'] = 'meter'
379
                else:
380
                    del fraction_list[i]
381
                    continue
382
383
                if fraction_list[i]['denominator_meter_uuid'] in offline_meter_dict:
384
                    fraction_list[i]['denominator_meter_id'] = \
385
                        offline_meter_dict[fraction_list[i]['denominator_meter_uuid']]['id']
386
                    fraction_list[i]['denominator_meter_name'] = \
387
                        offline_meter_dict[fraction_list[i]['denominator_meter_uuid']]['name']
388
                    fraction_list[i]['denominator_meter_unit'] = \
389
                        offline_meter_dict[fraction_list[i]['denominator_meter_uuid']]['unit']
390
                    fraction_list[i]['denominator_meter_type'] = 'offline_meter'
391
                elif fraction_list[i]['denominator_meter_uuid'] in virtual_meter_dict:
392
                    fraction_list[i]['denominator_meter_id'] = \
393
                        virtual_meter_dict[fraction_list[i]['denominator_meter_uuid']]['id']
394
                    fraction_list[i]['denominator_meter_name'] = \
395
                        virtual_meter_dict[fraction_list[i]['denominator_meter_uuid']]['name']
396
                    fraction_list[i]['denominator_meter_unit'] = \
397
                        virtual_meter_dict[fraction_list[i]['denominator_meter_uuid']]['unit']
398
                    fraction_list[i]['denominator_meter_type'] = 'virtual_meter'
399
                elif fraction_list[i]['denominator_meter_uuid'] in meter_dict:
400
                    fraction_list[i]['denominator_meter_id'] = \
401
                        meter_dict[fraction_list[i]['denominator_meter_uuid']]['id']
402
                    fraction_list[i]['denominator_meter_name'] = \
403
                        meter_dict[fraction_list[i]['denominator_meter_uuid']]['name']
404
                    fraction_list[i]['denominator_meter_unit'] = \
405
                        meter_dict[fraction_list[i]['denominator_meter_uuid']]['unit']
406
                    fraction_list[i]['denominator_meter_type'] = 'meter'
407
                else:
408
                    del fraction_list[i]
409
                    continue
410
411
        ################################################################################################################
412
        # Step 8: calculate base period fractions
413
        ################################################################################################################
414
        base = dict()
415 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
416
            for fraction in fraction_list:
417
                base[fraction['id']] = dict()
418
                base[fraction['id']]['name'] = fraction['name']
419
                base[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \
420
                    fraction['denominator_meter_unit']
421
                base[fraction['id']]['numerator_timestamps'] = list()
422
                base[fraction['id']]['numerator_values'] = list()
423
                base[fraction['id']]['numerator_cumulation'] = Decimal(0.0)
424
                base[fraction['id']]['denominator_timestamps'] = list()
425
                base[fraction['id']]['denominator_values'] = list()
426
                base[fraction['id']]['denominator_cumulation'] = Decimal(0.0)
427
                base[fraction['id']]['timestamps'] = list()
428
                base[fraction['id']]['values'] = list()
429
                base[fraction['id']]['cumulation'] = Decimal(0.0)
430
                # query numerator meter output
431
                if fraction['numerator_meter_type'] == 'meter':
432
                    query = (" SELECT start_datetime_utc, actual_value "
433
                             " FROM tbl_meter_hourly "
434
                             " WHERE meter_id = %s "
435
                             " AND start_datetime_utc >= %s "
436
                             " AND start_datetime_utc < %s "
437
                             " ORDER BY start_datetime_utc ")
438
                elif fraction['numerator_meter_type'] == 'offline_meter':
439
                    query = (" SELECT start_datetime_utc, actual_value "
440
                             " FROM tbl_offline_meter_hourly "
441
                             " WHERE offline_meter_id = %s "
442
                             " AND start_datetime_utc >= %s "
443
                             " AND start_datetime_utc < %s "
444
                             " ORDER BY start_datetime_utc ")
445
                elif fraction['numerator_meter_type'] == 'virtual_meter':
446
                    query = (" SELECT start_datetime_utc, actual_value "
447
                             " FROM tbl_virtual_meter_hourly "
448
                             " WHERE virtual_meter_id = %s "
449
                             " AND start_datetime_utc >= %s "
450
                             " AND start_datetime_utc < %s "
451
                             " ORDER BY start_datetime_utc ")
452
453
                cursor_energy.execute(query, (fraction['numerator_meter_id'],
454
                                              base_start_datetime_utc,
455
                                              base_end_datetime_utc))
456
                rows_numerator_meter_hourly = cursor_energy.fetchall()
457
458
                rows_numerator_meter_periodically = \
459
                    utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly,
460
                                                              base_start_datetime_utc,
461
                                                              base_end_datetime_utc,
462
                                                              period_type)
463
                # query denominator meter input
464
                if fraction['denominator_meter_type'] == 'meter':
465
                    query = (" SELECT start_datetime_utc, actual_value "
466
                             " FROM tbl_meter_hourly "
467
                             " WHERE meter_id = %s "
468
                             " AND start_datetime_utc >= %s "
469
                             " AND start_datetime_utc < %s "
470
                             " ORDER BY start_datetime_utc ")
471
                elif fraction['denominator_meter_type'] == 'offline_meter':
472
                    query = (" SELECT start_datetime_utc, actual_value "
473
                             " FROM tbl_offline_meter_hourly "
474
                             " WHERE offline_meter_id = %s "
475
                             " AND start_datetime_utc >= %s "
476
                             " AND start_datetime_utc < %s "
477
                             " ORDER BY start_datetime_utc ")
478
                elif fraction['denominator_meter_type'] == 'virtual_meter':
479
                    query = (" SELECT start_datetime_utc, actual_value "
480
                             " FROM tbl_virtual_meter_hourly "
481
                             " WHERE virtual_meter_id = %s "
482
                             " AND start_datetime_utc >= %s "
483
                             " AND start_datetime_utc < %s "
484
                             " ORDER BY start_datetime_utc ")
485
486
                cursor_energy.execute(query, (fraction['denominator_meter_id'],
487
                                              base_start_datetime_utc,
488
                                              base_end_datetime_utc))
489
                rows_denominator_meter_hourly = cursor_energy.fetchall()
490
491
                rows_denominator_meter_periodically = \
492
                    utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly,
493
                                                              base_start_datetime_utc,
494
                                                              base_end_datetime_utc,
495
                                                              period_type)
496
497
                for row_numerator_meter_periodically in rows_numerator_meter_periodically:
498
                    current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
499
                                             timedelta(minutes=timezone_offset)
500
                    if period_type == 'hourly':
501
                        current_datetime = current_datetime_local.isoformat()[0:19]
502
                    elif period_type == 'daily':
503
                        current_datetime = current_datetime_local.isoformat()[0:10]
504
                    elif period_type == 'weekly':
505
                        current_datetime = current_datetime_local.isoformat()[0:10]
506
                    elif period_type == 'monthly':
507
                        current_datetime = current_datetime_local.isoformat()[0:7]
508
                    elif period_type == 'yearly':
509
                        current_datetime = current_datetime_local.isoformat()[0:4]
510
511
                    actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \
512
                        else row_numerator_meter_periodically[1]
513
514
                    base[fraction['id']]['numerator_timestamps'].append(current_datetime)
0 ignored issues
show
The variable current_datetime does not seem to be defined for all execution paths.
Loading history...
515
                    base[fraction['id']]['numerator_values'].append(actual_value)
516
                    base[fraction['id']]['numerator_cumulation'] += actual_value
517
518
                for row_denominator_meter_periodically in rows_denominator_meter_periodically:
519
                    current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
520
                                             timedelta(minutes=timezone_offset)
521
                    if period_type == 'hourly':
522
                        current_datetime = current_datetime_local.isoformat()[0:19]
523
                    elif period_type == 'daily':
524
                        current_datetime = current_datetime_local.isoformat()[0:10]
525
                    elif period_type == 'weekly':
526
                        current_datetime = current_datetime_local.isoformat()[0:10]
527
                    elif period_type == 'monthly':
528
                        current_datetime = current_datetime_local.isoformat()[0:7]
529
                    elif period_type == 'yearly':
530
                        current_datetime = current_datetime_local.isoformat()[0:4]
531
532
                    actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \
533
                        else row_denominator_meter_periodically[1]
534
535
                    base[fraction['id']]['denominator_timestamps'].append(current_datetime)
536
                    base[fraction['id']]['denominator_values'].append(actual_value)
537
                    base[fraction['id']]['denominator_cumulation'] += actual_value
538
539
                for i in range(len(base[fraction['id']]['denominator_timestamps'])):
540
                    timestamp = base[fraction['id']]['denominator_timestamps'][i]
541
                    base[fraction['id']]['timestamps'].append(timestamp)
542
                    value = (base[fraction['id']]['numerator_values'][i] /
543
                             base[fraction['id']]['denominator_values'][i]) \
544
                        if base[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0)
545
                    base[fraction['id']]['values'].append(value)
546
547
                cumulation = (base[fraction['id']]['numerator_cumulation'] /
548
                              base[fraction['id']]['denominator_cumulation']) \
549
                    if base[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0)
550
                base[fraction['id']]['cumulation'] = cumulation
551
552
        ################################################################################################################
553
        # Step 9: calculate reporting period fractions
554
        ################################################################################################################
555
        reporting = dict()
556 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
557
            for fraction in fraction_list:
558
                reporting[fraction['id']] = dict()
559
                reporting[fraction['id']]['name'] = fraction['name']
560
                reporting[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \
561
                    fraction['denominator_meter_unit']
562
563
                reporting[fraction['id']]['numerator_name'] = fraction['numerator_meter_name']
564
                reporting[fraction['id']]['numerator_unit'] = fraction['numerator_meter_unit']
565
                reporting[fraction['id']]['denominator_name'] = fraction['denominator_meter_name']
566
                reporting[fraction['id']]['denominator_unit'] = fraction['denominator_meter_unit']
567
568
                reporting[fraction['id']]['numerator_timestamps'] = list()
569
                reporting[fraction['id']]['numerator_values'] = list()
570
                reporting[fraction['id']]['numerator_cumulation'] = Decimal(0.0)
571
                reporting[fraction['id']]['denominator_timestamps'] = list()
572
                reporting[fraction['id']]['denominator_values'] = list()
573
                reporting[fraction['id']]['denominator_cumulation'] = Decimal(0.0)
574
                reporting[fraction['id']]['timestamps'] = list()
575
                reporting[fraction['id']]['values'] = list()
576
                reporting[fraction['id']]['cumulation'] = Decimal(0.0)
577
                # query numerator meter output
578
                if fraction['numerator_meter_type'] == 'meter':
579
                    query = (" SELECT start_datetime_utc, actual_value "
580
                             " FROM tbl_meter_hourly "
581
                             " WHERE meter_id = %s "
582
                             " AND start_datetime_utc >= %s "
583
                             " AND start_datetime_utc < %s "
584
                             " ORDER BY start_datetime_utc ")
585
                elif fraction['numerator_meter_type'] == 'offline_meter':
586
                    query = (" SELECT start_datetime_utc, actual_value "
587
                             " FROM tbl_offline_meter_hourly "
588
                             " WHERE offline_meter_id = %s "
589
                             " AND start_datetime_utc >= %s "
590
                             " AND start_datetime_utc < %s "
591
                             " ORDER BY start_datetime_utc ")
592
                elif fraction['numerator_meter_type'] == 'virtual_meter':
593
                    query = (" SELECT start_datetime_utc, actual_value "
594
                             " FROM tbl_virtual_meter_hourly "
595
                             " WHERE virtual_meter_id = %s "
596
                             " AND start_datetime_utc >= %s "
597
                             " AND start_datetime_utc < %s "
598
                             " ORDER BY start_datetime_utc ")
599
600
                cursor_energy.execute(query, (fraction['numerator_meter_id'],
601
                                              reporting_start_datetime_utc,
602
                                              reporting_end_datetime_utc))
603
                rows_numerator_meter_hourly = cursor_energy.fetchall()
604
605
                rows_numerator_meter_periodically = \
606
                    utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly,
607
                                                              reporting_start_datetime_utc,
608
                                                              reporting_end_datetime_utc,
609
                                                              period_type)
610
                # query denominator meter input
611
                if fraction['denominator_meter_type'] == 'meter':
612
                    query = (" SELECT start_datetime_utc, actual_value "
613
                             " FROM tbl_meter_hourly "
614
                             " WHERE meter_id = %s "
615
                             " AND start_datetime_utc >= %s "
616
                             " AND start_datetime_utc < %s "
617
                             " ORDER BY start_datetime_utc ")
618
                elif fraction['denominator_meter_type'] == 'offline_meter':
619
                    query = (" SELECT start_datetime_utc, actual_value "
620
                             " FROM tbl_offline_meter_hourly "
621
                             " WHERE offline_meter_id = %s "
622
                             " AND start_datetime_utc >= %s "
623
                             " AND start_datetime_utc < %s "
624
                             " ORDER BY start_datetime_utc ")
625
                elif fraction['denominator_meter_type'] == 'virtual_meter':
626
                    query = (" SELECT start_datetime_utc, actual_value "
627
                             " FROM tbl_virtual_meter_hourly "
628
                             " WHERE virtual_meter_id = %s "
629
                             " AND start_datetime_utc >= %s "
630
                             " AND start_datetime_utc < %s "
631
                             " ORDER BY start_datetime_utc ")
632
633
                cursor_energy.execute(query, (fraction['denominator_meter_id'],
634
                                              reporting_start_datetime_utc,
635
                                              reporting_end_datetime_utc))
636
                rows_denominator_meter_hourly = cursor_energy.fetchall()
637
638
                rows_denominator_meter_periodically = \
639
                    utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly,
640
                                                              reporting_start_datetime_utc,
641
                                                              reporting_end_datetime_utc,
642
                                                              period_type)
643
644
                for row_numerator_meter_periodically in rows_numerator_meter_periodically:
645
                    current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
646
                                             timedelta(minutes=timezone_offset)
647
                    if period_type == 'hourly':
648
                        current_datetime = current_datetime_local.isoformat()[0:19]
649
                    elif period_type == 'daily':
650
                        current_datetime = current_datetime_local.isoformat()[0:10]
651
                    elif period_type == 'weekly':
652
                        current_datetime = current_datetime_local.isoformat()[0:10]
653
                    elif period_type == 'monthly':
654
                        current_datetime = current_datetime_local.isoformat()[0:7]
655
                    elif period_type == 'yearly':
656
                        current_datetime = current_datetime_local.isoformat()[0:4]
657
658
                    actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \
659
                        else row_numerator_meter_periodically[1]
660
661
                    reporting[fraction['id']]['numerator_timestamps'].append(current_datetime)
662
                    reporting[fraction['id']]['numerator_values'].append(actual_value)
663
                    reporting[fraction['id']]['numerator_cumulation'] += actual_value
664
665
                for row_denominator_meter_periodically in rows_denominator_meter_periodically:
666
                    current_datetime_local = row_denominator_meter_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_denominator_meter_periodically[1] is None \
680
                        else row_denominator_meter_periodically[1]
681
682
                    reporting[fraction['id']]['denominator_timestamps'].append(current_datetime)
683
                    reporting[fraction['id']]['denominator_values'].append(actual_value)
684
                    reporting[fraction['id']]['denominator_cumulation'] += actual_value
685
686
                for i in range(len(reporting[fraction['id']]['denominator_timestamps'])):
687
                    timestamp = reporting[fraction['id']]['denominator_timestamps'][i]
688
                    reporting[fraction['id']]['timestamps'].append(timestamp)
689
                    value = reporting[fraction['id']]['numerator_values'][i] / \
690
                        reporting[fraction['id']]['denominator_values'][i] \
691
                        if reporting[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0)
692
                    reporting[fraction['id']]['values'].append(value)
693
694
                cumulation = (reporting[fraction['id']]['numerator_cumulation'] /
695
                              reporting[fraction['id']]['denominator_cumulation']) \
696
                    if reporting[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0)
697
                reporting[fraction['id']]['cumulation'] = cumulation
698
699
        ################################################################################################################
700
        # Step 10: query associated points data
701
        ################################################################################################################
702
        parameters_data = dict()
703
        parameters_data['names'] = list()
704
        parameters_data['timestamps'] = list()
705
        parameters_data['values'] = list()
706
        if not is_quick_mode:
707
            for point in point_list:
708
                point_values = []
709
                point_timestamps = []
710
                if point['object_type'] == 'ENERGY_VALUE':
711
                    query = (" SELECT utc_date_time, actual_value "
712
                             " FROM tbl_energy_value "
713
                             " WHERE point_id = %s "
714
                             "       AND utc_date_time BETWEEN %s AND %s "
715
                             " ORDER BY utc_date_time ")
716
                    cursor_historical.execute(query, (point['id'],
717
                                                      reporting_start_datetime_utc,
718
                                                      reporting_end_datetime_utc))
719
                    rows = cursor_historical.fetchall()
720
721
                    if rows is not None and len(rows) > 0:
722
                        for row in rows:
723
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
724
                                                     timedelta(minutes=timezone_offset)
725
                            current_datetime = current_datetime_local.isoformat()[0:19]
726
                            point_timestamps.append(current_datetime)
727
                            point_values.append(row[1])
728
                elif point['object_type'] == 'ANALOG_VALUE':
729
                    query = (" SELECT utc_date_time, actual_value "
730
                             " FROM tbl_analog_value "
731
                             " WHERE point_id = %s "
732
                             "       AND utc_date_time BETWEEN %s AND %s "
733
                             " ORDER BY utc_date_time ")
734
                    cursor_historical.execute(query, (point['id'],
735
                                                      reporting_start_datetime_utc,
736
                                                      reporting_end_datetime_utc))
737
                    rows = cursor_historical.fetchall()
738
739
                    if rows is not None and len(rows) > 0:
740
                        for row in rows:
741
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
742
                                                     timedelta(minutes=timezone_offset)
743
                            current_datetime = current_datetime_local.isoformat()[0:19]
744
                            point_timestamps.append(current_datetime)
745
                            point_values.append(row[1])
746
                elif point['object_type'] == 'DIGITAL_VALUE':
747
                    query = (" SELECT utc_date_time, actual_value "
748
                             " FROM tbl_digital_value "
749
                             " WHERE point_id = %s "
750
                             "       AND utc_date_time BETWEEN %s AND %s "
751
                             " ORDER BY utc_date_time ")
752
                    cursor_historical.execute(query, (point['id'],
753
                                                      reporting_start_datetime_utc,
754
                                                      reporting_end_datetime_utc))
755
                    rows = cursor_historical.fetchall()
756
757
                    if rows is not None and len(rows) > 0:
758
                        for row in rows:
759
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
760
                                                     timedelta(minutes=timezone_offset)
761
                            current_datetime = current_datetime_local.isoformat()[0:19]
762
                            point_timestamps.append(current_datetime)
763
                            point_values.append(row[1])
764
765
                parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
766
                parameters_data['timestamps'].append(point_timestamps)
767
                parameters_data['values'].append(point_values)
768
769
        ################################################################################################################
770
        # Step 11: query associated equipments energy input
771
        ################################################################################################################
772
        associated_equipment_data = dict()
773
774
        if energy_category_set is not None and len(energy_category_set) > 0:
775
            for energy_category_id in energy_category_set:
776
                associated_equipment_data[energy_category_id] = dict()
777
                associated_equipment_data[energy_category_id]['associated_equipment_names'] = list()
778
                associated_equipment_data[energy_category_id]['subtotals'] = list()
779
                for associated_equipment in associated_equipment_list:
780
                    associated_equipment_data[energy_category_id]['associated_equipment_names'].append(
781
                        associated_equipment['name'])
782
783
                    cursor_energy.execute(" SELECT SUM(actual_value) "
784
                                          " FROM tbl_equipment_input_category_hourly "
785
                                          " WHERE equipment_id = %s "
786
                                          "     AND energy_category_id = %s "
787
                                          "     AND start_datetime_utc >= %s "
788
                                          "     AND start_datetime_utc < %s ",
789
                                          (associated_equipment['id'],
790
                                           energy_category_id,
791
                                           reporting_start_datetime_utc,
792
                                           reporting_end_datetime_utc))
793
                    row_subtotal = cursor_energy.fetchone()
794
795
                    subtotal = Decimal(0.0) if (row_subtotal is None or row_subtotal[0] is None) else row_subtotal[0]
796
                    associated_equipment_data[energy_category_id]['subtotals'].append(subtotal)
797
798
        ################################################################################################################
799
        # Step 12: construct the report
800
        ################################################################################################################
801
        if cursor_system:
802
            cursor_system.close()
803
        if cnx_system:
804
            cnx_system.close()
805
806
        if cursor_energy:
807
            cursor_energy.close()
808
        if cnx_energy:
809
            cnx_energy.close()
810
811
        result = dict()
812
813
        result['combined_equipment'] = dict()
814
        result['combined_equipment']['name'] = combined_equipment['name']
815
816
        result['base_period_efficiency'] = dict()
817
        result['base_period_efficiency']['timestamps'] = list()
818
        result['base_period_efficiency']['values'] = list()
819
        result['base_period_efficiency']['cumulations'] = list()
820
        result['base_period_efficiency']['numerator_timestamps'] = list()
821
        result['base_period_efficiency']['numerator_values'] = list()
822
        result['base_period_efficiency']['numerator_cumulations'] = list()
823
        result['base_period_efficiency']['denominator_timestamps'] = list()
824
        result['base_period_efficiency']['denominator_values'] = list()
825
        result['base_period_efficiency']['denominator_cumulations'] = list()
826
827
        result['reporting_period_efficiency'] = dict()
828
        result['reporting_period_efficiency']['names'] = list()
829
        result['reporting_period_efficiency']['units'] = list()
830
831
        result['reporting_period_efficiency']['numerator_names'] = list()
832
        result['reporting_period_efficiency']['numerator_units'] = list()
833
        result['reporting_period_efficiency']['denominator_names'] = list()
834
        result['reporting_period_efficiency']['denominator_units'] = list()
835
836
        result['reporting_period_efficiency']['timestamps'] = list()
837
        result['reporting_period_efficiency']['values'] = list()
838
        result['reporting_period_efficiency']['rates'] = list()
839
840
        result['reporting_period_efficiency']['numerator_timestamps'] = list()
841
        result['reporting_period_efficiency']['numerator_values'] = list()
842
        result['reporting_period_efficiency']['numerator_rates'] = list()
843
        result['reporting_period_efficiency']['denominator_timestamps'] = list()
844
        result['reporting_period_efficiency']['denominator_values'] = list()
845
        result['reporting_period_efficiency']['denominator_rates'] = list()
846
847
        result['reporting_period_efficiency']['cumulations'] = list()
848
849
        result['reporting_period_efficiency']['numerator_cumulations'] = list()
850
        result['reporting_period_efficiency']['denominator_cumulations'] = list()
851
852
        result['reporting_period_efficiency']['increment_rates'] = list()
853
854
        result['reporting_period_efficiency']['increment_rates_num'] = list()
855
        result['reporting_period_efficiency']['increment_rates_den'] = list()
856
857 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
858
            for fraction in fraction_list:
859
                result['base_period_efficiency']['timestamps'].append(base[fraction['id']]['timestamps'])
860
                result['base_period_efficiency']['values'].append(base[fraction['id']]['values'])
861
                result['base_period_efficiency']['cumulations'].append(base[fraction['id']]['cumulation'])
862
                result['base_period_efficiency']['numerator_timestamps'] \
863
                    .append(base[fraction['id']]['numerator_timestamps'])
864
                result['base_period_efficiency']['numerator_values'] \
865
                    .append(base[fraction['id']]['numerator_values'])
866
                result['base_period_efficiency']['numerator_cumulations'] \
867
                    .append(base[fraction['id']]['numerator_cumulation'])
868
                result['base_period_efficiency']['denominator_timestamps'] \
869
                    .append(base[fraction['id']]['denominator_timestamps'])
870
                result['base_period_efficiency']['denominator_values'] \
871
                    .append(base[fraction['id']]['denominator_values'])
872
                result['base_period_efficiency']['denominator_cumulations']. \
873
                    append(base[fraction['id']]['denominator_cumulation'])
874
                result['reporting_period_efficiency']['names'].append(reporting[fraction['id']]['name'])
875
                result['reporting_period_efficiency']['units'].append(reporting[fraction['id']]['unit'])
876
877
                result['reporting_period_efficiency']['numerator_names'].append(
878
                    reporting[fraction['id']]['numerator_name'])
879
                result['reporting_period_efficiency']['numerator_units'].append(
880
                    reporting[fraction['id']]['numerator_unit'])
881
                result['reporting_period_efficiency']['denominator_names'].append(
882
                    reporting[fraction['id']]['denominator_name'])
883
                result['reporting_period_efficiency']['denominator_units'].append(
884
                    reporting[fraction['id']]['denominator_unit'])
885
886
                result['reporting_period_efficiency']['timestamps'].append(reporting[fraction['id']]['timestamps'])
887
                result['reporting_period_efficiency']['values'].append(reporting[fraction['id']]['values'])
888
889
                result['reporting_period_efficiency']['numerator_timestamps'].append(
890
                    reporting[fraction['id']]['numerator_timestamps'])
891
                result['reporting_period_efficiency']['numerator_values'].append(
892
                    reporting[fraction['id']]['numerator_values'])
893
                result['reporting_period_efficiency']['denominator_timestamps'].append(
894
                    reporting[fraction['id']]['denominator_timestamps'])
895
                result['reporting_period_efficiency']['denominator_values'].append(
896
                    reporting[fraction['id']]['denominator_values'])
897
898
                result['reporting_period_efficiency']['cumulations'].append(reporting[fraction['id']]['cumulation'])
899
900
                result['reporting_period_efficiency']['numerator_cumulations'].append(
901
                    reporting[fraction['id']]['numerator_cumulation'])
902
                result['reporting_period_efficiency']['denominator_cumulations'].append(
903
                    reporting[fraction['id']]['denominator_cumulation'])
904
905
                result['reporting_period_efficiency']['increment_rates'].append(
906
                    (reporting[fraction['id']]['cumulation'] - base[fraction['id']]['cumulation']) /
907
                    base[fraction['id']]['cumulation'] if base[fraction['id']]['cumulation'] > Decimal(0.0) else None)
908
909
                result['reporting_period_efficiency']['increment_rates_num'].append(
910
                    (reporting[fraction['id']]['numerator_cumulation'] - base[fraction['id']]['numerator_cumulation']) /
911
                    base[fraction['id']]['numerator_cumulation']
912
                    if base[fraction['id']]['numerator_cumulation'] > Decimal(0.0) else None)
913
                result['reporting_period_efficiency']['increment_rates_den'].append(
914
                    (reporting[fraction['id']]['denominator_cumulation'] -
915
                     base[fraction['id']]['denominator_cumulation']) /
916
                    base[fraction['id']]['denominator_cumulation']
917
                    if base[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else None)
918
919
                rate = list()
920
                for index, value in enumerate(reporting[fraction['id']]['values']):
921
                    if index < len(base[fraction['id']]['values']) \
922
                            and base[fraction['id']]['values'][index] != 0 and value != 0:
923
                        rate.append((value - base[fraction['id']]['values'][index])
924
                                    / base[fraction['id']]['values'][index])
925
                    else:
926
                        rate.append(None)
927
                result['reporting_period_efficiency']['rates'].append(rate)
928
929
                numerator_rate = list()
930
                for index, value in enumerate(reporting[fraction['id']]['numerator_values']):
931
                    if index < len(base[fraction['id']]['numerator_values']) \
932
                            and base[fraction['id']]['numerator_values'][index] != 0 and value != 0:
933
                        numerator_rate.append((value - base[fraction['id']]['numerator_values'][index])
934
                                              / base[fraction['id']]['numerator_values'][index])
935
                    else:
936
                        numerator_rate.append(None)
937
                result['reporting_period_efficiency']['numerator_rates'].append(numerator_rate)
938
939
                denominator_rate = list()
940
                for index, value in enumerate(reporting[fraction['id']]['denominator_values']):
941
                    if index < len(base[fraction['id']]['denominator_values']) \
942
                            and base[fraction['id']]['denominator_values'][index] != 0 and value != 0:
943
                        denominator_rate.append((value - base[fraction['id']]['denominator_values'][index])
944
                                                / base[fraction['id']]['denominator_values'][index])
945
                    else:
946
                        denominator_rate.append(None)
947
                result['reporting_period_efficiency']['denominator_rates'].append(denominator_rate)
948
949
        result['parameters'] = {
950
            "names": parameters_data['names'],
951
            "timestamps": parameters_data['timestamps'],
952
            "values": parameters_data['values']
953
        }
954
        result['associated_equipment'] = dict()
955
        result['associated_equipment']['energy_category_names'] = list()
956
        result['associated_equipment']['units'] = list()
957
        result['associated_equipment']['associated_equipment_names_array'] = list()
958
        result['associated_equipment']['subtotals_array'] = list()
959
        if energy_category_set is not None and len(energy_category_set) > 0:
960
            for energy_category_id in energy_category_set:
961
                result['associated_equipment']['energy_category_names'].append(
962
                    energy_category_dict[energy_category_id]['name'])
963
                result['associated_equipment']['units'].append(
964
                    energy_category_dict[energy_category_id]['unit_of_measure'])
965
                result['associated_equipment']['associated_equipment_names_array'].append(
966
                    associated_equipment_data[energy_category_id]['associated_equipment_names'])
967
                result['associated_equipment']['subtotals_array'].append(
968
                    associated_equipment_data[energy_category_id]['subtotals'])
969
970
        # export result to Excel file and then encode the file to base64 string
971
        result['excel_bytes_base64'] = None
972
        if not is_quick_mode:
973
            result['excel_bytes_base64'] = \
974
                excelexporters.combinedequipmentefficiency.export(result,
975
                                                                  combined_equipment['name'],
976
                                                                  base_period_start_datetime_local,
977
                                                                  base_period_end_datetime_local,
978
                                                                  reporting_period_start_datetime_local,
979
                                                                  reporting_period_end_datetime_local,
980
                                                                  period_type,
981
                                                                  language)
982
983
        resp.text = json.dumps(result)
984