Reporting.on_get()   F
last analyzed

Complexity

Conditions 43

Size

Total Lines 271
Code Lines 195

Duplication

Lines 271
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 195
dl 271
loc 271
rs 0
c 0
b 0
f 0
cc 43
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 reports.photovoltaicpowerstationitemenergy.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 re
2
from datetime import datetime, timedelta, timezone
3
from decimal import Decimal
4
import falcon
5
import mysql.connector
6
import simplejson as json
7
from core import utilities
8
import config
9
from core.useractivity import access_control, api_key_control
10
11
12 View Code Duplication
class Reporting:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
13
    def __init__(self):
14
        """Initializes Class"""
15
        pass
16
17
    @staticmethod
18
    def on_options(req, resp):
19
        _ = req
20
        resp.status = falcon.HTTP_200
21
22
    ####################################################################################################################
23
    # PROCEDURES
24
    # Step 1: valid parameters
25
    # Step 2: query the energy storage power station
26
    # Step 3: query generation energy data in 7 days
27
    # Step 5: query generation energy data in this month
28
    # Step 7: query generation energy data in this year
29
    # Step 9: construct the report
30
    ####################################################################################################################
31
    @staticmethod
32
    def on_get(req, resp):
33
        if 'API-KEY' not in req.headers or \
34
                not isinstance(req.headers['API-KEY'], str) or \
35
                len(str.strip(req.headers['API-KEY'])) == 0:
36
            access_control(req)
37
        else:
38
            api_key_control(req)
39
        # this procedure accepts energy storage power station id or uuid
40
        photovoltaic_power_station_id = req.params.get('id')
41
        photovoltaic_power_station_uuid = req.params.get('uuid')
42
43
        ################################################################################################################
44
        # Step 1: valid parameters
45
        ################################################################################################################
46
        if photovoltaic_power_station_id is None and photovoltaic_power_station_uuid is None:
47
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
48
                                   description='API.INVALID_photovoltaic_POWER_STATION_ID')
49
50
        if photovoltaic_power_station_id is not None:
51
            photovoltaic_power_station_id = str.strip(photovoltaic_power_station_id)
52
            if not photovoltaic_power_station_id.isdigit() or int(photovoltaic_power_station_id) <= 0:
53
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
54
                                       description='API.INVALID_photovoltaic_POWER_STATION_ID')
55
56
        if photovoltaic_power_station_uuid is not None:
57
            regex = re.compile(r'^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
58
            match = regex.match(str.strip(photovoltaic_power_station_uuid))
59
            if not bool(match):
60
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
61
                                       description='API.INVALID_photovoltaic_POWER_STATION_UUID')
62
63
        ################################################################################################################
64
        # Step 2: query the energy storage power station
65
        ################################################################################################################
66
        cnx_system_db = mysql.connector.connect(**config.myems_system_db)
67
        cursor_system_db = cnx_system_db.cursor()
68
        # Get Spaces associated with energy storage power stations
69
        query = (" SELECT se.photovoltaic_power_station_id, s.name "
70
                 " FROM tbl_spaces s, tbl_spaces_photovoltaic_power_stations se "
71
                 " WHERE se.space_id = s.id ")
72
        cursor_system_db.execute(query)
73
        rows_spaces = cursor_system_db.fetchall()
74
75
        space_dict = dict()
76
        if rows_spaces is not None and len(rows_spaces) > 0:
77
            for row in rows_spaces:
78
                space_dict[row[0]] = row[1]
79
        print(space_dict)
80
        # Get energy storage power station
81
        if photovoltaic_power_station_id is not None:
82
            query = (" SELECT id, name, uuid, "
83
                     "        address, latitude, longitude, rated_capacity, rated_power, "
84
                     "        contact_id, cost_center_id "
85
                     " FROM tbl_photovoltaic_power_stations "
86
                     " WHERE id = %s ")
87
            cursor_system_db.execute(query, (photovoltaic_power_station_id,))
88
            row = cursor_system_db.fetchone()
89
        elif photovoltaic_power_station_uuid is not None:
90
            query = (" SELECT id, name, uuid, "
91
                     "        address, latitude, longitude, rated_capacity, rated_power, "
92
                     "        contact_id, cost_center_id "
93
                     " FROM tbl_photovoltaic_power_stations "
94
                     " WHERE uuid = %s ")
95
            cursor_system_db.execute(query, (photovoltaic_power_station_uuid,))
96
            row = cursor_system_db.fetchone()
97
98
        if row is None:
0 ignored issues
show
introduced by
The variable row does not seem to be defined for all execution paths.
Loading history...
99
            cursor_system_db.close()
100
            cnx_system_db.close()
101
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
102
                                   description='API.photovoltaic_POWER_STATION_NOT_FOUND')
103
        else:
104
            photovoltaic_power_station_id = row[0]
105
            photovoltaic_power_station = {
106
                "id": row[0],
107
                "name": row[1],
108
                "uuid": row[2],
109
                "address": row[3],
110
                "space_name": space_dict.get(row[0]),
111
                "latitude": row[4],
112
                "longitude": row[5],
113
                "rated_capacity": row[6],
114
                "rated_power": row[7]
115
            }
116
117
        ################################################################################################################
118
        # Step 3: query generation energy data in 7 days
119
        ################################################################################################################
120
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
121
        if config.utc_offset[0] == '-':
122
            timezone_offset = -timezone_offset
123
        reporting = dict()
124
        reporting['generation_7_days'] = dict()
125
        reporting['generation_this_month'] = dict()
126
        reporting['generation_this_year'] = dict()
127
128
        end_datetime_utc = datetime.utcnow()
129
        end_datetime_local = datetime.utcnow() + timedelta(minutes=timezone_offset)
130
        period_type = 'daily'
131
        start_datetime_local = end_datetime_local.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=6)
132
        start_datetime_utc = start_datetime_local - timedelta(minutes=timezone_offset)
133
        print('start_datetime_local:' + start_datetime_local.isoformat())
134
        print('end_datetime_local:' + end_datetime_local.isoformat())
135
        print('start_datetime_utc:' + start_datetime_utc.isoformat())
136
        print('end_datetime_utc:' + end_datetime_utc.isoformat())
137
138
        cnx_energy_db = mysql.connector.connect(**config.myems_energy_db)
139
        cursor_energy_db = cnx_energy_db.cursor()
140
141
        reporting['generation_7_days'] = dict()
142
        reporting['generation_7_days']['timestamps_array'] = list()
143
        reporting['generation_7_days']['values_array'] = list()
144
145
        timestamps = list()
146
        values = list()
147
        query = (" SELECT start_datetime_utc, actual_value "
148
                 " FROM tbl_photovoltaic_power_station_generation_hourly "
149
                 " WHERE photovoltaic_power_station_id = %s "
150
                 " AND start_datetime_utc >= %s "
151
                 " AND start_datetime_utc < %s "
152
                 " ORDER BY start_datetime_utc ")
153
        cursor_energy_db.execute(query, (photovoltaic_power_station_id, start_datetime_utc, end_datetime_utc))
154
        rows_generation_hourly = cursor_energy_db.fetchall()
155
156
        rows_generation_periodically = utilities.aggregate_hourly_data_by_period(rows_generation_hourly,
157
                                                                                 start_datetime_utc,
158
                                                                                 end_datetime_utc,
159
                                                                                 period_type)
160
        for row_generation_periodically in rows_generation_periodically:
161
            current_datetime_local = row_generation_periodically[0].replace(tzinfo=timezone.utc) + \
162
                                     timedelta(minutes=timezone_offset)
163
            if period_type == 'hourly':
164
                current_datetime = current_datetime_local.isoformat()[0:19]
165
            elif period_type == 'daily':
166
                current_datetime = current_datetime_local.isoformat()[0:10]
167
            elif period_type == 'weekly':
168
                current_datetime = current_datetime_local.isoformat()[0:10]
169
            elif period_type == 'monthly':
170
                current_datetime = current_datetime_local.isoformat()[0:7]
171
            elif period_type == 'yearly':
172
                current_datetime = current_datetime_local.isoformat()[0:4]
173
174
            actual_value = Decimal(0.0) if row_generation_periodically[1] is None else row_generation_periodically[1]
175
            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...
176
            values.append(actual_value)
177
        reporting['generation_7_days']['timestamps_array'].append(timestamps)
178
        reporting['generation_7_days']['values_array'].append(values)
179
180
        ################################################################################################################
181
        # Step 5: query generation energy data in this month
182
        ################################################################################################################
183
        end_datetime_utc = datetime.utcnow()
184
        end_datetime_local = datetime.utcnow() + timedelta(minutes=timezone_offset)
185
        period_type = 'daily'
186
        start_datetime_local = end_datetime_local.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
187
        start_datetime_utc = start_datetime_local - timedelta(minutes=timezone_offset)
188
        print('start_datetime_local:' + start_datetime_local.isoformat())
189
        print('end_datetime_local:' + end_datetime_local.isoformat())
190
        print('start_datetime_utc:' + start_datetime_utc.isoformat())
191
        print('end_datetime_utc:' + end_datetime_utc.isoformat())
192
193
        reporting['generation_this_month'] = dict()
194
        reporting['generation_this_month']['timestamps_array'] = list()
195
        reporting['generation_this_month']['values_array'] = list()
196
197
        timestamps = list()
198
        values = list()
199
        query = (" SELECT start_datetime_utc, actual_value "
200
                 " FROM tbl_photovoltaic_power_station_generation_hourly "
201
                 " WHERE photovoltaic_power_station_id = %s "
202
                 " AND start_datetime_utc >= %s "
203
                 " AND start_datetime_utc < %s "
204
                 " ORDER BY start_datetime_utc ")
205
        cursor_energy_db.execute(query, (photovoltaic_power_station['id'], start_datetime_utc, end_datetime_utc))
206
        rows_generation_hourly = cursor_energy_db.fetchall()
207
208
        rows_generation_periodically = utilities.aggregate_hourly_data_by_period(rows_generation_hourly,
209
                                                                                 start_datetime_utc,
210
                                                                                 end_datetime_utc,
211
                                                                                 period_type)
212
213
        for row_generation_periodically in rows_generation_periodically:
214
            current_datetime_local = row_generation_periodically[0].replace(tzinfo=timezone.utc) + \
215
                                     timedelta(minutes=timezone_offset)
216
            if period_type == 'hourly':
217
                current_datetime = current_datetime_local.isoformat()[0:19]
218
            elif period_type == 'daily':
219
                current_datetime = current_datetime_local.isoformat()[0:10]
220
            elif period_type == 'weekly':
221
                current_datetime = current_datetime_local.isoformat()[0:10]
222
            elif period_type == 'monthly':
223
                current_datetime = current_datetime_local.isoformat()[0:7]
224
            elif period_type == 'yearly':
225
                current_datetime = current_datetime_local.isoformat()[0:4]
226
227
            actual_value = Decimal(0.0) if row_generation_periodically[1] is None else row_generation_periodically[1]
228
            timestamps.append(current_datetime)
229
            values.append(actual_value)
230
        reporting['generation_this_month']['timestamps_array'].append(timestamps)
231
        reporting['generation_this_month']['values_array'].append(values)
232
233
        ################################################################################################################
234
        # Step 7: query generation energy data in this year
235
        ################################################################################################################
236
        end_datetime_utc = datetime.utcnow()
237
        end_datetime_local = datetime.utcnow() + timedelta(minutes=timezone_offset)
238
        period_type = 'monthly'
239
        start_datetime_local = end_datetime_local.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
240
        start_datetime_utc = start_datetime_local - timedelta(minutes=timezone_offset)
241
        print('start_datetime_local:' + start_datetime_local.isoformat())
242
        print('end_datetime_local:' + end_datetime_local.isoformat())
243
        print('start_datetime_utc:' + start_datetime_utc.isoformat())
244
        print('end_datetime_utc:' + end_datetime_utc.isoformat())
245
246
        reporting['generation_this_year'] = dict()
247
        reporting['generation_this_year']['timestamps_array'] = list()
248
        reporting['generation_this_year']['values_array'] = list()
249
250
        timestamps = list()
251
        values = list()
252
        query = (" SELECT start_datetime_utc, actual_value "
253
                 " FROM tbl_photovoltaic_power_station_generation_hourly "
254
                 " WHERE photovoltaic_power_station_id = %s "
255
                 " AND start_datetime_utc >= %s "
256
                 " AND start_datetime_utc < %s "
257
                 " ORDER BY start_datetime_utc ")
258
        cursor_energy_db.execute(query, (photovoltaic_power_station['id'], start_datetime_utc, end_datetime_utc))
259
        rows_generation_hourly = cursor_energy_db.fetchall()
260
261
        rows_generation_periodically = utilities.aggregate_hourly_data_by_period(rows_generation_hourly,
262
                                                                                 start_datetime_utc,
263
                                                                                 end_datetime_utc,
264
                                                                                 period_type)
265
        for row_generation_periodically in rows_generation_periodically:
266
            current_datetime_local = row_generation_periodically[0].replace(tzinfo=timezone.utc) + \
267
                                     timedelta(minutes=timezone_offset)
268
            if period_type == 'hourly':
269
                current_datetime = current_datetime_local.isoformat()[0:19]
270
            elif period_type == 'daily':
271
                current_datetime = current_datetime_local.isoformat()[0:10]
272
            elif period_type == 'weekly':
273
                current_datetime = current_datetime_local.isoformat()[0:10]
274
            elif period_type == 'monthly':
275
                current_datetime = current_datetime_local.isoformat()[0:7]
276
            elif period_type == 'yearly':
277
                current_datetime = current_datetime_local.isoformat()[0:4]
278
279
            actual_value = Decimal(0.0) if row_generation_periodically[1] is None else row_generation_periodically[1]
280
            timestamps.append(current_datetime)
281
            values.append(actual_value)
282
        reporting['generation_this_year']['timestamps_array'].append(timestamps)
283
        reporting['generation_this_year']['values_array'].append(values)
284
285
        ################################################################################################################
286
        # Step 9: construct the report
287
        ################################################################################################################
288
        if cursor_system_db:
289
            cursor_system_db.close()
290
        if cnx_system_db:
291
            cnx_system_db.close()
292
293
        if cursor_energy_db:
294
            cursor_energy_db.close()
295
        if cnx_energy_db:
296
            cnx_energy_db.close()
297
298
        result = dict()
299
        result['photovoltaic_power_station'] = photovoltaic_power_station
300
        result['reporting'] = reporting
301
        resp.text = json.dumps(result)
302