reports.equipmentefficiency   F
last analyzed

Complexity

Total Complexity 143

Size/Duplication

Total Lines 715
Duplicated Lines 98.32 %

Importance

Changes 0
Metric Value
eloc 524
dl 703
loc 715
rs 2
c 0
b 0
f 0
wmc 143

3 Methods

Rating   Name   Duplication   Size   Complexity  
A Reporting.__init__() 3 3 1
F Reporting.on_get() 678 680 141
A Reporting.on_options() 3 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like reports.equipmentefficiency often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import falcon
2
import simplejson as json
3
import mysql.connector
4
import config
5
from datetime import datetime, timedelta, timezone
6
from core import utilities
7
from decimal import Decimal
8
9
10 View Code Duplication
class Reporting:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
11
    @staticmethod
12
    def __init__():
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        resp.status = falcon.HTTP_200
18
19
    ####################################################################################################################
20
    # PROCEDURES
21
    # Step 1: valid parameters
22
    # Step 2: query the equipment
23
    # Step 3: query energy categories
24
    # Step 4: query associated constants
25
    # Step 4: query associated points
26
    # Step 5: query associated fractions
27
    # Step 5: query base period energy input
28
    # Step 6: query base period energy output
29
    # Step 7: query reporting period energy input
30
    # Step 8: query reporting period energy output
31
    # Step 9: query tariff data
32
    # Step 10: query associated points data
33
    # Step 11: construct the report
34
    ####################################################################################################################
35
    @staticmethod
36
    def on_get(req, resp):
37
        print(req.params)
38
        equipment_id = req.params.get('equipmentid')
39
        period_type = req.params.get('periodtype')
40
        base_start_datetime_local = req.params.get('baseperiodstartdatetime')
41
        base_end_datetime_local = req.params.get('baseperiodenddatetime')
42
        reporting_start_datetime_local = req.params.get('reportingperiodstartdatetime')
43
        reporting_end_datetime_local = req.params.get('reportingperiodenddatetime')
44
45
        ################################################################################################################
46
        # Step 1: valid parameters
47
        ################################################################################################################
48
        if equipment_id is None:
49
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_EQUIPMENT_ID')
50
        else:
51
            equipment_id = str.strip(equipment_id)
52
            if not equipment_id.isdigit() or int(equipment_id) <= 0:
53
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_EQUIPMENT_ID')
54
55
        if period_type is None:
56
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
57
        else:
58
            period_type = str.strip(period_type)
59
            if period_type not in ['hourly', 'daily', 'monthly', 'yearly']:
60
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
61
62
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
63
        if config.utc_offset[0] == '-':
64
            timezone_offset = -timezone_offset
65
66
        base_start_datetime_utc = None
67
        if base_start_datetime_local is not None and len(str.strip(base_start_datetime_local)) > 0:
68
            base_start_datetime_local = str.strip(base_start_datetime_local)
69
            try:
70
                base_start_datetime_utc = datetime.strptime(base_start_datetime_local,
71
                                                            '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
72
                    timedelta(minutes=timezone_offset)
73
            except ValueError:
74
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
75
                                       description="API.INVALID_BASE_PERIOD_START_DATETIME")
76
77
        base_end_datetime_utc = None
78
        if base_end_datetime_local is not None and len(str.strip(base_end_datetime_local)) > 0:
79
            base_end_datetime_local = str.strip(base_end_datetime_local)
80
            try:
81
                base_end_datetime_utc = datetime.strptime(base_end_datetime_local,
82
                                                          '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
83
                    timedelta(minutes=timezone_offset)
84
            except ValueError:
85
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
86
                                       description="API.INVALID_BASE_PERIOD_END_DATETIME")
87
88
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
89
                base_start_datetime_utc >= base_end_datetime_utc:
90
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
91
                                   description='API.INVALID_BASE_PERIOD_END_DATETIME')
92
93
        if reporting_start_datetime_local is None:
94
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
95
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
96
        else:
97
            reporting_start_datetime_local = str.strip(reporting_start_datetime_local)
98
            try:
99
                reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local,
100
                                                                 '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
101
                    timedelta(minutes=timezone_offset)
102
            except ValueError:
103
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
104
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
105
106
        if reporting_end_datetime_local is None:
107
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
108
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
109
        else:
110
            reporting_end_datetime_local = str.strip(reporting_end_datetime_local)
111
            try:
112
                reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local,
113
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
114
                    timedelta(minutes=timezone_offset)
115
            except ValueError:
116
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
117
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
118
119
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
120
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
121
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
122
123
        ################################################################################################################
124
        # Step 2: query the equipment
125
        ################################################################################################################
126
        cnx_system = mysql.connector.connect(**config.myems_system_db)
127
        cursor_system = cnx_system.cursor()
128
129
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
130
        cursor_energy = cnx_energy.cursor()
131
132
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
133
        cursor_historical = cnx_historical.cursor()
134
135
        cursor_system.execute(" SELECT id, name, cost_center_id "
136
                              " FROM tbl_equipments "
137
                              " WHERE id = %s ", (equipment_id,))
138
        row_equipment = cursor_system.fetchone()
139
        if row_equipment is None:
140
            if cursor_system:
141
                cursor_system.close()
142
            if cnx_system:
143
                cnx_system.disconnect()
144
145
            if cursor_energy:
146
                cursor_energy.close()
147
            if cnx_energy:
148
                cnx_energy.disconnect()
149
150
            if cnx_historical:
151
                cnx_historical.close()
152
            if cursor_historical:
153
                cursor_historical.disconnect()
154
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND')
155
156
        equipment = dict()
157
        equipment['id'] = row_equipment[0]
158
        equipment['name'] = row_equipment[1]
159
        equipment['cost_center_id'] = row_equipment[2]
160
161
        ################################################################################################################
162
        # Step 3: query input energy categories and output energy categories
163
        ################################################################################################################
164
        energy_category_set_input = set()
165
        energy_category_set_output = set()
166
        # query input energy categories in base period
167
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
168
                              " FROM tbl_equipment_input_category_hourly "
169
                              " WHERE equipment_id = %s "
170
                              "     AND start_datetime_utc >= %s "
171
                              "     AND start_datetime_utc < %s ",
172
                              (equipment['id'], base_start_datetime_utc, base_end_datetime_utc))
173
        rows_energy_categories = cursor_energy.fetchall()
174
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
175
            for row_energy_category in rows_energy_categories:
176
                energy_category_set_input.add(row_energy_category[0])
177
178
        # query input energy categories in reporting period
179
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
180
                              " FROM tbl_equipment_input_category_hourly "
181
                              " WHERE equipment_id = %s "
182
                              "     AND start_datetime_utc >= %s "
183
                              "     AND start_datetime_utc < %s ",
184
                              (equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
185
        rows_energy_categories = cursor_energy.fetchall()
186
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
187
            for row_energy_category in rows_energy_categories:
188
                energy_category_set_input.add(row_energy_category[0])
189
190
        # query output energy categories in base period
191
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
192
                              " FROM tbl_equipment_output_category_hourly "
193
                              " WHERE equipment_id = %s "
194
                              "     AND start_datetime_utc >= %s "
195
                              "     AND start_datetime_utc < %s ",
196
                              (equipment['id'], base_start_datetime_utc, base_end_datetime_utc))
197
        rows_energy_categories = cursor_energy.fetchall()
198
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
199
            for row_energy_category in rows_energy_categories:
200
                energy_category_set_output.add(row_energy_category[0])
201
202
        # query output energy categories in reporting period
203
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
204
                              " FROM tbl_equipment_output_category_hourly "
205
                              " WHERE equipment_id = %s "
206
                              "     AND start_datetime_utc >= %s "
207
                              "     AND start_datetime_utc < %s ",
208
                              (equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
209
        rows_energy_categories = cursor_energy.fetchall()
210
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
211
            for row_energy_category in rows_energy_categories:
212
                energy_category_set_output.add(row_energy_category[0])
213
214
        # query properties of all energy categories above
215
        cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e "
216
                              " FROM tbl_energy_categories "
217
                              " ORDER BY id ", )
218
        rows_energy_categories = cursor_system.fetchall()
219
        if rows_energy_categories is None or len(rows_energy_categories) == 0:
220
            if cursor_system:
221
                cursor_system.close()
222
            if cnx_system:
223
                cnx_system.disconnect()
224
225
            if cursor_energy:
226
                cursor_energy.close()
227
            if cnx_energy:
228
                cnx_energy.disconnect()
229
230
            if cnx_historical:
231
                cnx_historical.close()
232
            if cursor_historical:
233
                cursor_historical.disconnect()
234
            raise falcon.HTTPError(falcon.HTTP_404,
235
                                   title='API.NOT_FOUND',
236
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
237
        energy_category_dict = dict()
238
        for row_energy_category in rows_energy_categories:
239
            if row_energy_category[0] in energy_category_set_input or \
240
                    row_energy_category[0] in energy_category_set_output:
241
                energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1],
242
                                                                "unit_of_measure": row_energy_category[2],
243
                                                                "kgce": row_energy_category[3],
244
                                                                "kgco2e": row_energy_category[4]}
245
246
        ################################################################################################################
247
        # Step 4: query associated points
248
        ################################################################################################################
249
        point_list = list()
250
        cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type  "
251
                              " FROM tbl_equipments e, tbl_equipments_parameters ep, tbl_points p "
252
                              " WHERE e.id = %s AND e.id = ep.equipment_id AND ep.parameter_type = 'point' "
253
                              "       AND ep.point_id = p.id "
254
                              " ORDER BY p.id ", (equipment['id'],))
255
        rows_points = cursor_system.fetchall()
256
        if rows_points is not None and len(rows_points) > 0:
257
            for row in rows_points:
258
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
259
260
        ################################################################################################################
261
        # Step 5: query base period energy input
262
        ################################################################################################################
263
        base_input = dict()
264
        if energy_category_set_input is not None and len(energy_category_set_input) > 0:
265
            for energy_category_id in energy_category_set_input:
266
                base_input[energy_category_id] = dict()
267
                base_input[energy_category_id]['timestamps'] = list()
268
                base_input[energy_category_id]['values'] = list()
269
                base_input[energy_category_id]['subtotal'] = Decimal(0.0)
270
271
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
272
                                      " FROM tbl_equipment_input_category_hourly "
273
                                      " WHERE equipment_id = %s "
274
                                      "     AND energy_category_id = %s "
275
                                      "     AND start_datetime_utc >= %s "
276
                                      "     AND start_datetime_utc < %s "
277
                                      " ORDER BY start_datetime_utc ",
278
                                      (equipment['id'],
279
                                       energy_category_id,
280
                                       base_start_datetime_utc,
281
                                       base_end_datetime_utc))
282
                rows_equipment_hourly = cursor_energy.fetchall()
283
284
                rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly,
285
                                                                                        base_start_datetime_utc,
286
                                                                                        base_end_datetime_utc,
287
                                                                                        period_type)
288
                for row_equipment_periodically in rows_equipment_periodically:
289
                    current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \
290
                                             timedelta(minutes=timezone_offset)
291
                    if period_type == 'hourly':
292
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
293
                    elif period_type == 'daily':
294
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
295
                    elif period_type == 'monthly':
296
                        current_datetime = current_datetime_local.strftime('%Y-%m')
297
                    elif period_type == 'yearly':
298
                        current_datetime = current_datetime_local.strftime('%Y')
299
300
                    actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \
301
                        else row_equipment_periodically[1]
302
                    base_input[energy_category_id]['timestamps'].append(current_datetime)
0 ignored issues
show
introduced by
The variable current_datetime does not seem to be defined for all execution paths.
Loading history...
303
                    base_input[energy_category_id]['values'].append(actual_value)
304
                    base_input[energy_category_id]['subtotal'] += actual_value
305
306
        ################################################################################################################
307
        # Step 6: query base period energy output
308
        ################################################################################################################
309
        base_output = dict()
310
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
311
            for energy_category_id in energy_category_set_output:
312
                base_output[energy_category_id] = dict()
313
                base_output[energy_category_id]['timestamps'] = list()
314
                base_output[energy_category_id]['values'] = list()
315
                base_output[energy_category_id]['subtotal'] = Decimal(0.0)
316
317
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
318
                                      " FROM tbl_equipment_output_category_hourly "
319
                                      " WHERE equipment_id = %s "
320
                                      "     AND energy_category_id = %s "
321
                                      "     AND start_datetime_utc >= %s "
322
                                      "     AND start_datetime_utc < %s "
323
                                      " ORDER BY start_datetime_utc ",
324
                                      (equipment['id'],
325
                                       energy_category_id,
326
                                       base_start_datetime_utc,
327
                                       base_end_datetime_utc))
328
                rows_equipment_hourly = cursor_energy.fetchall()
329
330
                rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly,
331
                                                                                        base_start_datetime_utc,
332
                                                                                        base_end_datetime_utc,
333
                                                                                        period_type)
334
                for row_equipment_periodically in rows_equipment_periodically:
335
                    current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \
336
                                             timedelta(minutes=timezone_offset)
337
                    if period_type == 'hourly':
338
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
339
                    elif period_type == 'daily':
340
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
341
                    elif period_type == 'monthly':
342
                        current_datetime = current_datetime_local.strftime('%Y-%m')
343
                    elif period_type == 'yearly':
344
                        current_datetime = current_datetime_local.strftime('%Y')
345
346
                    actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \
347
                        else row_equipment_periodically[1]
348
                    base_output[energy_category_id]['timestamps'].append(current_datetime)
349
                    base_output[energy_category_id]['values'].append(actual_value)
350
                    base_output[energy_category_id]['subtotal'] += actual_value
351
        ################################################################################################################
352
        # Step 7: query reporting period energy input
353
        ################################################################################################################
354
        reporting_input = dict()
355
        if energy_category_set_input is not None and len(energy_category_set_input) > 0:
356
            for energy_category_id in energy_category_set_input:
357
358
                reporting_input[energy_category_id] = dict()
359
                reporting_input[energy_category_id]['timestamps'] = list()
360
                reporting_input[energy_category_id]['values'] = list()
361
                reporting_input[energy_category_id]['subtotal'] = Decimal(0.0)
362
363
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
364
                                      " FROM tbl_equipment_input_category_hourly "
365
                                      " WHERE equipment_id = %s "
366
                                      "     AND energy_category_id = %s "
367
                                      "     AND start_datetime_utc >= %s "
368
                                      "     AND start_datetime_utc < %s "
369
                                      " ORDER BY start_datetime_utc ",
370
                                      (equipment['id'],
371
                                       energy_category_id,
372
                                       reporting_start_datetime_utc,
373
                                       reporting_end_datetime_utc))
374
                rows_equipment_hourly = cursor_energy.fetchall()
375
376
                rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly,
377
                                                                                        reporting_start_datetime_utc,
378
                                                                                        reporting_end_datetime_utc,
379
                                                                                        period_type)
380
                for row_equipment_periodically in rows_equipment_periodically:
381
                    current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \
382
                                             timedelta(minutes=timezone_offset)
383
                    if period_type == 'hourly':
384
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
385
                    elif period_type == 'daily':
386
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
387
                    elif period_type == 'monthly':
388
                        current_datetime = current_datetime_local.strftime('%Y-%m')
389
                    elif period_type == 'yearly':
390
                        current_datetime = current_datetime_local.strftime('%Y')
391
392
                    actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \
393
                        else row_equipment_periodically[1]
394
                    reporting_input[energy_category_id]['timestamps'].append(current_datetime)
395
                    reporting_input[energy_category_id]['values'].append(actual_value)
396
                    reporting_input[energy_category_id]['subtotal'] += actual_value
397
398
        ################################################################################################################
399
        # Step 8: query reporting period energy output
400
        ################################################################################################################
401
        reporting_output = dict()
402
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
403
            for energy_category_id in energy_category_set_output:
404
405
                reporting_output[energy_category_id] = dict()
406
                reporting_output[energy_category_id]['timestamps'] = list()
407
                reporting_output[energy_category_id]['values'] = list()
408
                reporting_output[energy_category_id]['subtotal'] = Decimal(0.0)
409
410
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
411
                                      " FROM tbl_equipment_output_category_hourly "
412
                                      " WHERE equipment_id = %s "
413
                                      "     AND energy_category_id = %s "
414
                                      "     AND start_datetime_utc >= %s "
415
                                      "     AND start_datetime_utc < %s "
416
                                      " ORDER BY start_datetime_utc ",
417
                                      (equipment['id'],
418
                                       energy_category_id,
419
                                       reporting_start_datetime_utc,
420
                                       reporting_end_datetime_utc))
421
                rows_equipment_hourly = cursor_energy.fetchall()
422
423
                rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly,
424
                                                                                        reporting_start_datetime_utc,
425
                                                                                        reporting_end_datetime_utc,
426
                                                                                        period_type)
427
                for row_equipment_periodically in rows_equipment_periodically:
428
                    current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \
429
                                             timedelta(minutes=timezone_offset)
430
                    if period_type == 'hourly':
431
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
432
                    elif period_type == 'daily':
433
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
434
                    elif period_type == 'monthly':
435
                        current_datetime = current_datetime_local.strftime('%Y-%m')
436
                    elif period_type == 'yearly':
437
                        current_datetime = current_datetime_local.strftime('%Y')
438
439
                    actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \
440
                        else row_equipment_periodically[1]
441
                    reporting_output[energy_category_id]['timestamps'].append(current_datetime)
442
                    reporting_output[energy_category_id]['values'].append(actual_value)
443
                    reporting_output[energy_category_id]['subtotal'] += actual_value
444
445
        ################################################################################################################
446
        # Step 9: query tariff data
447
        ################################################################################################################
448
        parameters_data = dict()
449
        parameters_data['names'] = list()
450
        parameters_data['timestamps'] = list()
451
        parameters_data['values'] = list()
452
        if energy_category_set_input is not None and len(energy_category_set_input) > 0:
453
            for energy_category_id in energy_category_set_input:
454
                energy_category_tariff_dict = utilities.get_energy_category_tariffs(equipment['cost_center_id'],
455
                                                                                    energy_category_id,
456
                                                                                    reporting_start_datetime_utc,
457
                                                                                    reporting_end_datetime_utc)
458
                tariff_timestamp_list = list()
459
                tariff_value_list = list()
460
                for k, v in energy_category_tariff_dict.items():
461
                    # convert k from utc to local
462
                    k = k + timedelta(minutes=timezone_offset)
463
                    tariff_timestamp_list.append(k.isoformat()[0:19][0:19])
464
                    tariff_value_list.append(v)
465
466
                parameters_data['names'].append('TARIFF-' + energy_category_dict[energy_category_id]['name'])
467
                parameters_data['timestamps'].append(tariff_timestamp_list)
468
                parameters_data['values'].append(tariff_value_list)
469
470
        ################################################################################################################
471
        # Step 10: query associated sensors and points data
472
        ################################################################################################################
473
        for point in point_list:
474
            point_values = []
475
            point_timestamps = []
476
            if point['object_type'] == 'ANALOG_VALUE':
477
                query = (" SELECT utc_date_time, actual_value "
478
                         " FROM tbl_analog_value "
479
                         " WHERE point_id = %s "
480
                         "       AND utc_date_time BETWEEN %s AND %s "
481
                         " ORDER BY utc_date_time ")
482
                cursor_historical.execute(query, (point['id'],
483
                                                  reporting_start_datetime_utc,
484
                                                  reporting_end_datetime_utc))
485
                rows = cursor_historical.fetchall()
486
487
                if rows is not None and len(rows) > 0:
488
                    for row in rows:
489
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
490
                                                 timedelta(minutes=timezone_offset)
491
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
492
                        point_timestamps.append(current_datetime)
493
                        point_values.append(row[1])
494
495
            elif point['object_type'] == 'ENERGY_VALUE':
496
                query = (" SELECT utc_date_time, actual_value "
497
                         " FROM tbl_energy_value "
498
                         " WHERE point_id = %s "
499
                         "       AND utc_date_time BETWEEN %s AND %s "
500
                         " ORDER BY utc_date_time ")
501
                cursor_historical.execute(query, (point['id'],
502
                                                  reporting_start_datetime_utc,
503
                                                  reporting_end_datetime_utc))
504
                rows = cursor_historical.fetchall()
505
506
                if rows is not None and len(rows) > 0:
507
                    for row in rows:
508
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
509
                                                 timedelta(minutes=timezone_offset)
510
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
511
                        point_timestamps.append(current_datetime)
512
                        point_values.append(row[1])
513
            elif point['object_type'] == 'DIGITAL_VALUE':
514
                query = (" SELECT utc_date_time, actual_value "
515
                         " FROM tbl_digital_value "
516
                         " WHERE point_id = %s "
517
                         "       AND utc_date_time BETWEEN %s AND %s ")
518
                cursor_historical.execute(query, (point['id'],
519
                                                  reporting_start_datetime_utc,
520
                                                  reporting_end_datetime_utc))
521
                rows = cursor_historical.fetchall()
522
523
                if rows is not None and len(rows) > 0:
524
                    for row in rows:
525
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
526
                                                 timedelta(minutes=timezone_offset)
527
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
528
                        point_timestamps.append(current_datetime)
529
                        point_values.append(row[1])
530
531
            parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
532
            parameters_data['timestamps'].append(point_timestamps)
533
            parameters_data['values'].append(point_values)
534
535
        ################################################################################################################
536
        # Step 11: construct the report
537
        ################################################################################################################
538
        if cursor_system:
539
            cursor_system.close()
540
        if cnx_system:
541
            cnx_system.disconnect()
542
543
        if cursor_energy:
544
            cursor_energy.close()
545
        if cnx_energy:
546
            cnx_energy.disconnect()
547
548
        result = dict()
549
550
        result['equipment'] = dict()
551
        result['equipment']['name'] = equipment['name']
552
553
        result['base_period_input'] = dict()
554
        result['base_period_input']['names'] = list()
555
        result['base_period_input']['units'] = list()
556
        result['base_period_input']['timestamps'] = list()
557
        result['base_period_input']['values'] = list()
558
        result['base_period_input']['subtotals'] = list()
559
        if energy_category_set_input is not None and len(energy_category_set_input) > 0:
560
            for energy_category_id in energy_category_set_input:
561
                result['base_period_input']['names'].append(energy_category_dict[energy_category_id]['name'])
562
                result['base_period_input']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure'])
563
                result['base_period_input']['timestamps'].append(base_input[energy_category_id]['timestamps'])
564
                result['base_period_input']['values'].append(base_input[energy_category_id]['values'])
565
                result['base_period_input']['subtotals'].append(base_input[energy_category_id]['subtotal'])
566
567
        result['base_period_output'] = dict()
568
        result['base_period_output']['names'] = list()
569
        result['base_period_output']['units'] = list()
570
        result['base_period_output']['timestamps'] = list()
571
        result['base_period_output']['values'] = list()
572
        result['base_period_output']['subtotals'] = list()
573
574
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
575
            for energy_category_id in energy_category_set_output:
576
                result['base_period_output']['names'].append(energy_category_dict[energy_category_id]['name'])
577
                result['base_period_output']['units'].append(
578
                    energy_category_dict[energy_category_id]['unit_of_measure'])
579
                result['base_period_output']['timestamps'].append(base_output[energy_category_id]['timestamps'])
580
                result['base_period_output']['values'].append(base_output[energy_category_id]['values'])
581
                result['base_period_output']['subtotals'].append(base_output[energy_category_id]['subtotal'])
582
583
        result['base_period_efficiency'] = dict()
584
        result['base_period_efficiency']['names'] = list()
585
        result['base_period_efficiency']['units'] = list()
586
        result['base_period_efficiency']['timestamps'] = list()
587
        result['base_period_efficiency']['values'] = list()
588
        result['base_period_efficiency']['cumulations'] = list()
589
590
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
591
            for energy_category_id_output in energy_category_set_output:
592
                for energy_category_id_input in energy_category_set_input:
593
                    result['base_period_efficiency']['names'].append(
594
                        energy_category_dict[energy_category_id_output]['name'] + '/' +
595
                        energy_category_dict[energy_category_id_input]['name'])
596
                    result['base_period_efficiency']['units'].append(
597
                        energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' +
598
                        energy_category_dict[energy_category_id_input]['unit_of_measure'])
599
                    result['base_period_efficiency']['timestamps'].append(
600
                        base_output[energy_category_id_output]['timestamps'])
601
                    efficiency_values = list()
602
                    for i in range(len(base_output[energy_category_id_output]['timestamps'])):
603
                        efficiency_values.append((base_output[energy_category_id_output]['values'][i] /
604
                                                  base_input[energy_category_id_input]['values'][i])
605
                                                 if base_input[energy_category_id_input]['values'][i] > Decimal(0.0)
606
                                                 else None)
607
                    result['base_period_efficiency']['values'].append(efficiency_values)
608
609
                    base_cumulation = (base_output[energy_category_id_output]['subtotal'] /
610
                                       base_input[energy_category_id_input]['subtotal']) if \
611
                        base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None
612
                    result['base_period_efficiency']['cumulations'].append(base_cumulation)
613
614
        result['reporting_period_input'] = dict()
615
        result['reporting_period_input']['names'] = list()
616
        result['reporting_period_input']['energy_category_ids'] = list()
617
        result['reporting_period_input']['units'] = list()
618
        result['reporting_period_input']['timestamps'] = list()
619
        result['reporting_period_input']['values'] = list()
620
        result['reporting_period_input']['subtotals'] = list()
621
        result['reporting_period_input']['increment_rates'] = list()
622
623
        if energy_category_set_input is not None and len(energy_category_set_input) > 0:
624
            for energy_category_id in energy_category_set_input:
625
                result['reporting_period_input']['names'].append(energy_category_dict[energy_category_id]['name'])
626
                result['reporting_period_input']['energy_category_ids'].append(energy_category_id)
627
                result['reporting_period_input']['units'].append(
628
                    energy_category_dict[energy_category_id]['unit_of_measure'])
629
                result['reporting_period_input']['timestamps'].append(
630
                    reporting_input[energy_category_id]['timestamps'])
631
                result['reporting_period_input']['values'].append(
632
                    reporting_input[energy_category_id]['values'])
633
                result['reporting_period_input']['subtotals'].append(
634
                    reporting_input[energy_category_id]['subtotal'])
635
                result['reporting_period_input']['increment_rates'].append(
636
                    (reporting_input[energy_category_id]['subtotal'] -
637
                     base_input[energy_category_id]['subtotal']) /
638
                    base_input[energy_category_id]['subtotal']
639
                    if base_input[energy_category_id]['subtotal'] > 0.0 else None)
640
641
        result['reporting_period_output'] = dict()
642
        result['reporting_period_output']['names'] = list()
643
        result['reporting_period_output']['energy_category_ids'] = list()
644
        result['reporting_period_output']['units'] = list()
645
        result['reporting_period_output']['timestamps'] = list()
646
        result['reporting_period_output']['values'] = list()
647
        result['reporting_period_output']['subtotals'] = list()
648
        result['reporting_period_output']['increment_rates'] = list()
649
650
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
651
            for energy_category_id in energy_category_set_output:
652
                result['reporting_period_output']['names'].append(energy_category_dict[energy_category_id]['name'])
653
                result['reporting_period_output']['energy_category_ids'].append(energy_category_id)
654
                result['reporting_period_output']['units'].append(
655
                    energy_category_dict[energy_category_id]['unit_of_measure'])
656
                result['reporting_period_output']['timestamps'].append(
657
                    reporting_output[energy_category_id]['timestamps'])
658
                result['reporting_period_output']['values'].append(reporting_output[energy_category_id]['values'])
659
                result['reporting_period_output']['subtotals'].append(reporting_output[energy_category_id]['subtotal'])
660
                result['reporting_period_output']['increment_rates'].append(
661
                    (reporting_output[energy_category_id]['subtotal'] -
662
                     base_output[energy_category_id]['subtotal']) /
663
                    base_output[energy_category_id]['subtotal']
664
                    if base_output[energy_category_id]['subtotal'] > 0.0 else None)
665
666
        result['reporting_period_efficiency'] = dict()
667
        result['reporting_period_efficiency']['names'] = list()
668
        result['reporting_period_efficiency']['units'] = list()
669
        result['reporting_period_efficiency']['timestamps'] = list()
670
        result['reporting_period_efficiency']['values'] = list()
671
        result['reporting_period_efficiency']['cumulations'] = list()
672
        result['reporting_period_efficiency']['increment_rates'] = list()
673
674
        if energy_category_set_output is not None and len(energy_category_set_output) > 0:
675
            for energy_category_id_output in energy_category_set_output:
676
                for energy_category_id_input in energy_category_set_input:
677
                    result['reporting_period_efficiency']['names'].append(
678
                        energy_category_dict[energy_category_id_output]['name'] + '/' +
679
                        energy_category_dict[energy_category_id_input]['name'])
680
                    result['reporting_period_efficiency']['units'].append(
681
                        energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' +
682
                        energy_category_dict[energy_category_id_input]['unit_of_measure'])
683
                    result['reporting_period_efficiency']['timestamps'].append(
684
                        reporting_output[energy_category_id_output]['timestamps'])
685
                    efficiency_values = list()
686
                    for i in range(len(reporting_output[energy_category_id_output]['timestamps'])):
687
                        efficiency_values.append((reporting_output[energy_category_id_output]['values'][i] /
688
                                                 reporting_input[energy_category_id_input]['values'][i])
689
                                                 if reporting_input[energy_category_id_input]['values'][i] >
690
                                                 Decimal(0.0) else None)
691
                    result['reporting_period_efficiency']['values'].append(efficiency_values)
692
693
                    base_cumulation = (base_output[energy_category_id_output]['subtotal'] /
694
                                       base_input[energy_category_id_input]['subtotal']) if \
695
                        base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None
696
697
                    reporting_cumulation = (reporting_output[energy_category_id_output]['subtotal'] /
698
                                            reporting_input[energy_category_id_input]['subtotal']) if \
699
                        reporting_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None
700
701
                    result['reporting_period_efficiency']['cumulations'].append(reporting_cumulation)
702
                    result['reporting_period_efficiency']['increment_rates'].append(
703
                        ((reporting_cumulation - base_cumulation) / base_cumulation if (base_cumulation is not None and
704
                                                                                        base_cumulation > Decimal(0.0))
705
                         else None)
706
                    )
707
708
        result['parameters'] = {
709
            "names": parameters_data['names'],
710
            "timestamps": parameters_data['timestamps'],
711
            "values": parameters_data['values']
712
        }
713
714
        resp.body = json.dumps(result)
715