reports.spaceproduction.Reporting.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
from datetime import datetime, timedelta, timezone
2
from decimal import Decimal
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
import config
7
from core import utilities
8
from core.useractivity import access_control, api_key_control
9
10
11
class Reporting:
12
    def __init__(self):
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        _ = req
18
        resp.status = falcon.HTTP_200
19
20
    ####################################################################################################################
21
    # PROCEDURES
22
    # Step 1: valid parameters
23
    # Step 2: query reporting period production
24
    # Step 3: construct the report
25
    ####################################################################################################################
26
    @staticmethod
27
    def on_get(req, resp):
28
        if 'API-KEY' not in req.headers or \
29
                not isinstance(req.headers['API-KEY'], str) or \
30
                len(str.strip(req.headers['API-KEY'])) == 0:
31
            access_control(req)
32
        else:
33
            api_key_control(req)
34
        space_id = req.params.get('spaceid')
35
        product_id = req.params.get('productid')
36
        period_type = req.params.get('periodtype')
37
        base_period_start_datetime_local = req.params.get('baseperiodstartdatetime')
38
        base_period_end_datetime_local = req.params.get('baseperiodenddatetime')
39
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
40
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
41
        language = req.params.get('language')
42
        quick_mode = req.params.get('quickmode')
43
44
        ################################################################################################################
45
        # Step 1: valid parameters
46
        ################################################################################################################
47
        if space_id is None:
48
            raise falcon.HTTPError(status=falcon.HTTP_400,
49
                                   title='API.BAD_REQUEST',
50
                                   description='API.INVALID_SPACE_ID')
51
        
52
        if space_id is not None:
53
            space_id = str.strip(space_id)
54
            if not space_id.isdigit() or int(space_id) <= 0:
55
                raise falcon.HTTPError(status=falcon.HTTP_400,
56
                                       title='API.BAD_REQUEST',
57
                                       description='API.INVALID_SPACE_ID')
58
            
59
        if product_id is None:
60
            raise falcon.HTTPError(status=falcon.HTTP_400,
61
                                   title='API.BAD_REQUEST',
62
                                   description='API.INVALID_PRODUCT_ID')
63
        
64
        if product_id is not None:
65
            product_id = str.strip(product_id)
66
            if not product_id.isdigit() or int(product_id) <= 0:
67
                raise falcon.HTTPError(status=falcon.HTTP_400,
68
                                       title='API.BAD_REQUEST',
69
                                       description='API.INVALID_PRODUCT_ID')
70
            
71
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
72
        if config.utc_offset[0] == '-':
73
            timezone_offset = -timezone_offset
74
75
        base_start_datetime_utc = None
76
        if base_period_start_datetime_local is not None and len(str.strip(base_period_start_datetime_local)) > 0:
77
            base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
78
            try:
79
                base_start_datetime_utc = datetime.strptime(base_period_start_datetime_local, '%Y-%m-%dT%H:%M:%S')
80
            except ValueError:
81
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
82
                                       description='API.INVALID_BASE_PERIOD_START_DATETIME')
83
            base_start_datetime_utc = \
84
                base_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
85
            # nomalize the start datetime
86
            if config.minutes_to_count == 30 and base_start_datetime_utc.minute >= 30:
87
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
88
            else:
89
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
90
91
        base_end_datetime_utc = None
92
        if base_period_end_datetime_local is not None or len(str.strip(base_period_end_datetime_local)) > 0:
93
            base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
94
            try:
95
                base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
96
            except ValueError:
97
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
98
                                       description='API.INVALID_BASE_PERIOD_END_DATETIME')
99
            base_end_datetime_utc = \
100
                base_end_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
101
            
102
        if reporting_period_start_datetime_local is None:
103
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
104
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
105
        else:
106
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
107
            try:
108
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
109
                                                                 '%Y-%m-%dT%H:%M:%S')
110
            except ValueError:
111
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
112
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
113
            reporting_start_datetime_utc = \
114
                reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
115
            # nomalize the start datetime
116
            if config.minutes_to_count == 30 and reporting_start_datetime_utc.minute >= 30:
117
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
118
            else:
119
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
120
121
        if reporting_period_end_datetime_local is None:
122
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
123
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
124
        else:
125
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
126
            try:
127
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
128
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
129
                                             timedelta(minutes=timezone_offset)
130
            except ValueError:
131
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
132
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
133
134
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
135
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
136
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
137
138
        if period_type is None:
139
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
140
                                   description='API.INVALID_PERIOD_TYPE')
141
        else:
142
            period_type = str.strip(period_type)
143
            if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
144
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
145
                                       description='API.INVALID_PERIOD_TYPE')
146
        
147
        is_quick_mode = False
148
        if quick_mode is not None and \
149
            len(str.strip(quick_mode)) > 0 and \
150
                str.lower(str.strip(quick_mode)) in ('true', 't', 'on', 'yes', 'y'):
151
            is_quick_mode = True
152
        
153
        cnx_system = mysql.connector.connect(**config.myems_system_db)
154
        cursor_system = cnx_system.cursor()
155
        
156
        cursor_system.execute(" SELECT name, area, number_of_occupants, cost_center_id "
157
                              " FROM tbl_spaces "
158
                              " WHERE id = %s ", (space_id,))
159
        row = cursor_system.fetchone()
160
161
        if row is None:
162
            if cursor_system:
163
                cursor_system.close()
164
            if cnx_system:
165
                cnx_system.close()
166
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
167
                                   description='API.SPACE_NOT_FOUND')
168
        else:
169
            space_name = row[0]
170
            space_area = row[1]
171
            space_center_id = row[2]
172
            space_number_of_occupants = row[3]
173
174
        cnx_production = mysql.connector.connect(**config.myems_production_db)
175
        cursor_production = cnx_production.cursor()
176
        
177
        cursor_production.execute(" SELECT name "
178
                                  " FROM tbl_products "
179
                                  " WHERE id = %s ", (product_id,))
180
        row = cursor_production.fetchone()
181
182
        if row is None:
183
            if cursor_production:
184
                cursor_production.close()
185
            if cnx_production:
186
                cnx_production.close()
187
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
188
                                   description='API.PRODUCT_NOT_FOUND')
189
        else:
190
            product_name = row[0]
191
192
        ################################################################################################################
193
        # Step 2: query base period production
194
        ################################################################################################################
195
        base_date_list = list()
196
        base_daily_values = list()
197
198
        cnx_production = mysql.connector.connect(**config.myems_production_db)
199
        cursor_production = cnx_production.cursor()
200
201
        query = (" SELECT start_datetime_utc, product_count "
202
                 " FROM tbl_space_hourly "
203
                 " WHERE space_id = %s "
204
                 " AND product_id = %s "
205
                 " AND start_datetime_utc >= %s "
206
                 " AND start_datetime_utc < %s "
207
                 " ORDER BY start_datetime_utc ")
208
        cursor_production.execute(query, (space_id,
209
                                          product_id,
210
                                          base_start_datetime_utc,
211
                                          base_end_datetime_utc))
212
        rows_space_production_hourly = cursor_production.fetchall()
213
214
        start_datetime_utc = base_start_datetime_utc.replace(tzinfo=None)
215
        end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=None)
216
217
        start_datetime_local = start_datetime_utc + timedelta(hours=int(config.utc_offset[1:3]))
218
        current_datetime_utc = start_datetime_local.replace(hour=0) - timedelta(hours=int(config.utc_offset[1:3]))
219
220 View Code Duplication
        while current_datetime_utc <= end_datetime_utc:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
221
            flag = True
222
            subtotal = Decimal(0.0)
223
            for row in rows_space_production_hourly:
224
                if current_datetime_utc <= row[0] < current_datetime_utc + timedelta(days=1):
225
                    flag = False
226
                    subtotal += row[1]
227
            if flag:
228
                subtotal = None
229
            current_datetime = start_datetime_local.isoformat()[0:10]
230
231
            base_date_list.append(current_datetime)
232
            base_daily_values.append(subtotal)
233
            current_datetime_utc += timedelta(days=1)
234
            start_datetime_local += timedelta(days=1)
235
236
        ################################################################################################################
237
        # Step 3: query energy categories
238
        ################################################################################################################
239
        cnx_system = mysql.connector.connect(**config.myems_system_db)
240
        cursor_system = cnx_system.cursor()
241
242
        cnx_billing = mysql.connector.connect(**config.myems_billing_db)
243
        cursor_billing = cnx_billing.cursor()
244
245
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
246
        cursor_historical = cnx_historical.cursor()
247
248
        energy_category_set = set()
249
        # query energy categories in base period
250
        cursor_billing.execute(" SELECT DISTINCT(energy_category_id) "
251
                               " FROM tbl_space_input_category_hourly "
252
                               " WHERE space_id = %s "
253
                               "     AND start_datetime_utc >= %s "
254
                               "     AND start_datetime_utc < %s ",
255
                               (space_id, base_start_datetime_utc, base_end_datetime_utc))
256
        rows_energy_categories = cursor_billing.fetchall()
257
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
258
            for row_energy_category in rows_energy_categories:
259
                energy_category_set.add(row_energy_category[0])
260
261
        # query energy categories in reporting period
262
        cursor_billing.execute(" SELECT DISTINCT(energy_category_id) "
263
                               " FROM tbl_space_input_category_hourly "
264
                               " WHERE space_id = %s "
265
                               "     AND start_datetime_utc >= %s "
266
                               "     AND start_datetime_utc < %s ",
267
                               (space_id, reporting_start_datetime_utc, reporting_end_datetime_utc))
268
        rows_energy_categories = cursor_billing.fetchall()
269
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
270
            for row_energy_category in rows_energy_categories:
271
                energy_category_set.add(row_energy_category[0])
272
273
        # query all energy categories in base period and reporting period
274
        cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e "
275
                              " FROM tbl_energy_categories "
276
                              " ORDER BY id ", )
277
        rows_energy_categories = cursor_system.fetchall()
278
        if rows_energy_categories is None or len(rows_energy_categories) == 0:
279
            if cursor_system:
280
                cursor_system.close()
281
            if cnx_system:
282
                cnx_system.close()
283
284
            if cursor_billing:
285
                cursor_billing.close()
286
            if cnx_billing:
287
                cnx_billing.close()
288
289
            if cursor_historical:
290
                cursor_historical.close()
291
            if cnx_historical:
292
                cnx_historical.close()
293
            raise falcon.HTTPError(status=falcon.HTTP_404,
294
                                   title='API.NOT_FOUND',
295
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
296
        energy_category_dict = dict()
297
        for row_energy_category in rows_energy_categories:
298
            if row_energy_category[0] in energy_category_set:
299
                energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1],
300
                                                                "unit_of_measure": row_energy_category[2],
301
                                                                "kgce": row_energy_category[3],
302
                                                                "kgco2e": row_energy_category[4]}
303
304
        ################################################################################################################
305
        # Step 4: query reporting period production
306
        ################################################################################################################
307
        reporting_date_list = list()
308
        reporting_daily_values = list()
309
310
        cnx_production = mysql.connector.connect(**config.myems_production_db)
311
        cursor_production = cnx_production.cursor()
312
313
        query = (" SELECT start_datetime_utc, product_count "
314
                 " FROM tbl_space_hourly "
315
                 " WHERE space_id = %s "
316
                 " AND product_id = %s "
317
                 " AND start_datetime_utc >= %s "
318
                 " AND start_datetime_utc < %s "
319
                 " ORDER BY start_datetime_utc ")
320
        cursor_production.execute(query, (space_id,
321
                                          product_id,
322
                                          reporting_start_datetime_utc,
323
                                          reporting_end_datetime_utc))
324
        rows_space_production_hourly = cursor_production.fetchall()
325
326
        start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=None)
327
        end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=None)
328
329
        start_datetime_local = start_datetime_utc + timedelta(hours=int(config.utc_offset[1:3]))
330
        current_datetime_utc = start_datetime_local.replace(hour=0) - timedelta(hours=int(config.utc_offset[1:3]))
331
332 View Code Duplication
        while current_datetime_utc <= end_datetime_utc:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
333
            flag = True
334
            subtotal = Decimal(0.0)
335
            for row in rows_space_production_hourly:
336
                if current_datetime_utc <= row[0] < current_datetime_utc + timedelta(days=1):
337
                    flag = False
338
                    subtotal += row[1]
339
            if flag:
340
                subtotal = None
341
            current_datetime = start_datetime_local.isoformat()[0:10]
342
343
            reporting_date_list.append(current_datetime)
344
            reporting_daily_values.append(subtotal)
345
            current_datetime_utc += timedelta(days=1)
346
            start_datetime_local += timedelta(days=1)
347
348
        query = (" SELECT name, unit_of_measure, tag, standard_product_coefficient "
349
                 " FROM tbl_products "
350
                 " WHERE id = %s ")
351
        cursor_production.execute(query, (product_id,))
352
        row_product = cursor_production.fetchone()
353
        product_dict = dict()
354
        product_dict['name'] = row_product[0]
355
        product_dict['unit'] = row_product[1]
356
        product_dict['tag'] = row_product[2]
357
        product_dict['coefficient'] = row_product[3]
358
        
359
        ################################################################################################################
360
        # Step 5: query base period production
361
        ################################################################################################################
362
        base_date_list = list()
363
        base_daily_values = list()
364
365
        cnx_production = mysql.connector.connect(**config.myems_production_db)
366
        cursor_production = cnx_production.cursor()
367
368
        query = (" SELECT start_datetime_utc, product_count "
369
                 " FROM tbl_space_hourly "
370
                 " WHERE space_id = %s "
371
                 " AND product_id = %s "
372
                 " AND start_datetime_utc >= %s "
373
                 " AND start_datetime_utc < %s "
374
                 " ORDER BY start_datetime_utc ")
375
        cursor_production.execute(query, (space_id,
376
                                          product_id,
377
                                          base_start_datetime_utc,
378
                                          base_end_datetime_utc))
379
        rows_space_production_hourly = cursor_production.fetchall()
380
        start_datetime_utc = base_start_datetime_utc.replace(tzinfo=None)
381
        end_datetime_utc = base_end_datetime_utc.replace(tzinfo=None)
382
383
        start_datetime_local = start_datetime_utc + timedelta(hours=int(config.utc_offset[1:3]))
384
        current_datetime_utc = start_datetime_local.replace(hour=0) - timedelta(hours=int(config.utc_offset[1:3]))
385
386 View Code Duplication
        while current_datetime_utc <= end_datetime_utc:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
387
            flag = True
388
            subtotal = Decimal(0.0)
389
            for row in rows_space_production_hourly:
390
                if current_datetime_utc <= row[0] < current_datetime_utc + timedelta(days=1):
391
                    flag = False
392
                    subtotal += row[1]
393
            if flag:
394
                subtotal = None
395
            current_datetime = start_datetime_local.isoformat()[0:10]
396
397
            base_date_list.append(current_datetime)
398
            base_daily_values.append(subtotal)
399
            current_datetime_utc += timedelta(days=1)
400
            start_datetime_local += timedelta(days=1)
401
402
        ################################################################################################################
403
        # Step 6: query base period energy consumption
404
        ################################################################################################################
405
        base = dict()
406
        if energy_category_set is not None and len(energy_category_set) > 0:
407
            for energy_category_id in energy_category_set:
408
                kgce = energy_category_dict[energy_category_id]['kgce']
409
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
410
411
                base[energy_category_id] = dict()
412
                base[energy_category_id]['timestamps'] = list()
413
                base[energy_category_id]['values'] = list()
414
                base[energy_category_id]['subtotal'] = Decimal(0.0)
415
                base[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
416
                base[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
417
418
                cursor_billing.execute(" SELECT start_datetime_utc, actual_value "
419
                                       " FROM tbl_space_input_category_hourly "
420
                                       " WHERE space_id = %s "
421
                                       "     AND energy_category_id = %s "
422
                                       "     AND start_datetime_utc >= %s "
423
                                       "     AND start_datetime_utc < %s "
424
                                       " ORDER BY start_datetime_utc ",
425
                                       (space_id,
426
                                        energy_category_id,
427
                                        base_start_datetime_utc,
428
                                        base_end_datetime_utc))
429
                rows_space_hourly = cursor_billing.fetchall()
430
431
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
432
                                                                                    base_start_datetime_utc,
433
                                                                                    base_end_datetime_utc,
434
                                                                                    period_type)
435
                for row_space_periodically in rows_space_periodically:
436
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
437
                                             timedelta(minutes=timezone_offset)
438
                    if period_type == 'hourly':
439
                        current_datetime = current_datetime_local.isoformat()[0:19]
440
                    elif period_type == 'daily':
441
                        current_datetime = current_datetime_local.isoformat()[0:10]
442
                    elif period_type == 'weekly':
443
                        current_datetime = current_datetime_local.isoformat()[0:10]
444
                    elif period_type == 'monthly':
445
                        current_datetime = current_datetime_local.isoformat()[0:7]
446
                    elif period_type == 'yearly':
447
                        current_datetime = current_datetime_local.isoformat()[0:4]
448
449
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
450
                    base[energy_category_id]['timestamps'].append(current_datetime)
0 ignored issues
show
introduced by
The variable current_datetime does not seem to be defined in case the while loop on line 220 is not entered. Are you sure this can never be the case?
Loading history...
451
                    base[energy_category_id]['values'].append(actual_value)
452
                    base[energy_category_id]['subtotal'] += actual_value
453
                    base[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
454
                    base[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
455
456
        ################################################################################################################
457
        # Step 7: query reporting period energy consumption
458
        ################################################################################################################
459
        reporting = dict()
460
        if energy_category_set is not None and len(energy_category_set) > 0:
461
            for energy_category_id in energy_category_set:
462
                kgce = energy_category_dict[energy_category_id]['kgce']
463
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
464
465
                reporting[energy_category_id] = dict()
466
                reporting[energy_category_id]['timestamps'] = list()
467
                reporting[energy_category_id]['values'] = list()
468
                reporting[energy_category_id]['subtotal'] = Decimal(0.0)
469
                reporting[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
470
                reporting[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
471
472
                cursor_billing.execute(" SELECT start_datetime_utc, actual_value "
473
                                       " FROM tbl_space_input_category_hourly "
474
                                       " WHERE space_id = %s "
475
                                       "     AND energy_category_id = %s "
476
                                       "     AND start_datetime_utc >= %s "
477
                                       "     AND start_datetime_utc < %s "
478
                                       " ORDER BY start_datetime_utc ",
479
                                       (space_id,
480
                                        energy_category_id,
481
                                        reporting_start_datetime_utc,
482
                                        reporting_end_datetime_utc))
483
                rows_space_hourly = cursor_billing.fetchall()
484
485
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
486
                                                                                    reporting_start_datetime_utc,
487
                                                                                    reporting_end_datetime_utc,
488
                                                                                    period_type)
489
                for row_space_periodically in rows_space_periodically:
490
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
491
                                             timedelta(minutes=timezone_offset)
492
                    if period_type == 'hourly':
493
                        current_datetime = current_datetime_local.isoformat()[0:19]
494
                    elif period_type == 'daily':
495
                        current_datetime = current_datetime_local.isoformat()[0:10]
496
                    elif period_type == 'weekly':
497
                        current_datetime = current_datetime_local.isoformat()[0:10]
498
                    elif period_type == 'monthly':
499
                        current_datetime = current_datetime_local.isoformat()[0:7]
500
                    elif period_type == 'yearly':
501
                        current_datetime = current_datetime_local.isoformat()[0:4]
502
503
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
504
                    reporting[energy_category_id]['timestamps'].append(current_datetime)
505
                    reporting[energy_category_id]['values'].append(actual_value)
506
                    reporting[energy_category_id]['subtotal'] += actual_value
507
                    reporting[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
508
                    reporting[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
509
510
        ################################################################################################################
511
        # Step 8: construct the report
512
        ################################################################################################################
513
        if cursor_system:
514
            cursor_system.close()
515
        if cnx_system:
516
            cnx_system.disconnect()
517
518
        if cursor_production:
519
            cursor_production.close()
520
        if cnx_production:
521
            cnx_production.disconnect()
522
523
        if cursor_billing:
524
            cursor_billing.close()
525
        if cnx_billing:
526
            cnx_billing.close()
527
528
        if cursor_historical:
529
            cursor_historical.close()
530
        if cnx_historical:
531
            cnx_historical.close()
532
533
        reporting_result_values = []
534
        base_result_values = []
535
        result = dict()
536
        
537
        result['space'] = dict()
538
        result['space']['name'] = space_name
539
        result['space']['area'] = space_area
540
        result['space']['number_of_occupants'] = space_number_of_occupants
541
542
        result['base_period'] = dict()
543
        result['base_period']['names'] = list()
544
        result['base_period']['units'] = list()
545
        result['base_period']['timestamps'] = list()
546
        result['base_period']['values'] = list()
547
        result['base_period']['subtotals'] = list()
548
        result['base_period']['total'] = Decimal(0.0)
549
        result['base_period']['subtotals_in_kgce'] = list()
550
        result['base_period']['subtotals_in_kgco2e'] = list()
551
        result['base_period']['total_in_kgce'] = Decimal(0.0)
552
        result['base_period']['total_in_kgco2e'] = Decimal(0.0)
553
554
        if energy_category_set is not None and len(energy_category_set) > 0:
555
            for energy_category_id in energy_category_set:
556
                result['base_period']['names'].append(energy_category_dict[energy_category_id]['name'])
557
                result['base_period']['units'].append(config.currency_unit)
558
                result['base_period']['timestamps'].append(base[energy_category_id]['timestamps'])
559
                result['base_period']['values'].append(base[energy_category_id]['values'])
560
                result['base_period']['subtotals'].append(base[energy_category_id]['subtotal'])
561
                result['base_period']['total'] += base[energy_category_id]['subtotal']
562
                result['base_period']['subtotals_in_kgce'].append(base[energy_category_id]['subtotal_in_kgce'])
563
                result['base_period']['subtotals_in_kgco2e'].append(base[energy_category_id]['subtotal_in_kgco2e'])
564
                result['base_period']['total_in_kgce'] += base[energy_category_id]['subtotal_in_kgce']
565
                result['base_period']['total_in_kgco2e'] += base[energy_category_id]['subtotal_in_kgco2e']
566
567
        result['reporting_period'] = dict()
568
        result['reporting_period']['names'] = list()
569
        result['reporting_period']['energy_category_ids'] = list()
570
        result['reporting_period']['units'] = list()
571
        result['reporting_period']['timestamps'] = list()
572
        result['reporting_period']['values'] = list()
573
        result['reporting_period']['subtotals'] = list()
574
        result['reporting_period']['total'] = Decimal(0.0)
575
        result['reporting_period']['subtotals_in_kgce'] = list()
576
        result['reporting_period']['subtotals_in_kgco2e'] = list()
577
        result['reporting_period']['subtotals_per_unit_area'] = list()
578
        result['reporting_period']['subtotals_per_capita'] = list()
579
        result['reporting_period']['total_in_kgce'] = Decimal(0.0)
580
        result['reporting_period']['total_in_kgco2e'] = Decimal(0.0)
581
        result['reporting_period']['total_unit'] = config.currency_unit
582
        result['reporting_period']['rates'] = list()
583
        result['reporting_period']['increment_rates'] = list()
584
        result['reporting_period']['increment_rate_in_kgce'] = Decimal(0.0)
585
        result['reporting_period']['increment_rate_in_kgco2e'] = Decimal(0.0)
586
587
        if energy_category_set is not None and len(energy_category_set) > 0:
588
            for energy_category_id in energy_category_set:
589
                result['reporting_period']['names'].append(energy_category_dict[energy_category_id]['name'])
590
                result['reporting_period']['energy_category_ids'].append(energy_category_id)
591
                result['reporting_period']['units'].append(config.currency_unit)
592
                result['reporting_period']['timestamps'].append(reporting[energy_category_id]['timestamps'])
593
                result['reporting_period']['values'].append(reporting[energy_category_id]['values'])
594
                result['reporting_period']['subtotals'].append(reporting[energy_category_id]['subtotal'])
595
                result['reporting_period']['total'] += reporting[energy_category_id]['subtotal']
596
                result['reporting_period']['subtotals_in_kgce'].append(
597
                    reporting[energy_category_id]['subtotal_in_kgce'])
598
                result['reporting_period']['subtotals_in_kgco2e'].append(
599
                    reporting[energy_category_id]['subtotal_in_kgco2e'])
600
                result['reporting_period']['total_in_kgce'] += reporting[energy_category_id]['subtotal_in_kgce']
601
                result['reporting_period']['total_in_kgco2e'] += reporting[energy_category_id]['subtotal_in_kgco2e']
602
                result['reporting_period']['increment_rates'].append(
603
                    (reporting[energy_category_id]['subtotal'] - base[energy_category_id]['subtotal']) /
604
                    base[energy_category_id]['subtotal']
605
                    if base[energy_category_id]['subtotal'] > 0.0 else None)
606
                
607
        reporting_period_total_production = 0
608
        for date, daily_value in zip(reporting_date_list, reporting_daily_values):
609
            reporting_period_total_production += daily_value if daily_value is not None else 0
610
611
        base_period_total_production = 0
612
        for date, daily_value in zip(base_date_list, base_daily_values):
613
            base_period_total_production += daily_value if daily_value is not None else 0
614
615
        result['reporting_period']['total_in_kgco2e_per_prodution'] = \
616
            result['reporting_period']['total_in_kgce'] / reporting_period_total_production \
617
            if reporting_period_total_production > 0.0 else None
618
619
        result['reporting_period']['increment_rate_in_kgce'] = \
620
            (result['reporting_period']['total_in_kgce'] - result['base_period']['total_in_kgce']) / \
621
            result['base_period']['total_in_kgce'] \
622
            if result['base_period']['total_in_kgce'] > Decimal(0.0) else None
623
624
        result['reporting_period']['total_in_kgce_per_prodution'] = \
625
            result['reporting_period']['total_in_kgco2e'] / reporting_period_total_production \
626
            if reporting_period_total_production > 0.0 else None
627
628
        result['reporting_period']['increment_rate_in_kgco2e'] = \
629
            (result['reporting_period']['total_in_kgco2e'] - result['base_period']['total_in_kgco2e']) / \
630
            result['base_period']['total_in_kgco2e'] \
631
            if result['base_period']['total_in_kgco2e'] > Decimal(0.0) else None
632
        
633
        rates = list()
634
        result['base_production'] = dict()
635
        result['base_production']['timestamps'] = base_date_list
636
        result['base_production']['values'] = base_daily_values
637
638
        result['reporting_production'] = dict()
639
        result['reporting_production']['timestamps'] = reporting_date_list
640
        result['reporting_production']['values'] = reporting_daily_values
641
        for base, reporting in zip(base_daily_values, reporting_daily_values):
642
            rate = (reporting - base) / base \
643
                if reporting is not None and base is not None and base > 0 and reporting > 0 else 0
644
            rates.append(rate)
645
        result['reporting_production']['rates'] = rates
646
647
        result['reporting_result_values'] = reporting_result_values
648
        result['reporting_total_production'] = reporting_period_total_production
649
        result['base_result_values'] = base_result_values
650
        result['base_total_production'] = base_period_total_production
651
        result['product'] = product_dict
652
        resp.text = json.dumps(result)
653