Passed
Push — master ( e07a89...15a904 )
by Guangyu
01:53 queued 10s
created

combinedequipmentefficiency.Reporting.on_get()   F

Complexity

Conditions 141

Size

Total Lines 689
Code Lines 517

Duplication

Lines 689
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 517
dl 689
loc 689
rs 0
c 0
b 0
f 0
cc 141
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

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