core.virtualmeter.VirtualMeterCollection.on_get()   F
last analyzed

Complexity

Conditions 23

Size

Total Lines 128
Code Lines 98

Duplication

Lines 50
Ratio 39.06 %

Importance

Changes 0
Metric Value
cc 23
eloc 98
nop 2
dl 50
loc 128
rs 0
c 0
b 0
f 0

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 core.virtualmeter.VirtualMeterCollection.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
import uuid
6
7
8
class VirtualMeterCollection:
9
    @staticmethod
10
    def __init__():
11
        pass
12
13
    @staticmethod
14
    def on_options(req, resp):
15
        resp.status = falcon.HTTP_200
16
17
    @staticmethod
18
    def on_get(req, resp):
19
        cnx = mysql.connector.connect(**config.myems_system_db)
20
        cursor = cnx.cursor(dictionary=True)
21
22
        query = (" SELECT id, name, uuid "
23
                 " FROM tbl_energy_categories ")
24
        cursor.execute(query)
25
        rows_energy_categories = cursor.fetchall()
26
27
        energy_category_dict = dict()
28
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
29
            for row in rows_energy_categories:
30
                energy_category_dict[row['id']] = {"id": row['id'],
31
                                                   "name": row['name'],
32
                                                   "uuid": row['uuid']}
33
34
        query = (" SELECT id, name, uuid "
35
                 " FROM tbl_energy_items ")
36
        cursor.execute(query)
37
        rows_energy_items = cursor.fetchall()
38
39
        energy_item_dict = dict()
40
        if rows_energy_items is not None and len(rows_energy_items) > 0:
41
            for row in rows_energy_items:
42
                energy_item_dict[row['id']] = {"id": row['id'],
43
                                               "name": row['name'],
44
                                               "uuid": row['uuid']}
45
46
        query = (" SELECT id, name, uuid "
47
                 " FROM tbl_cost_centers ")
48
        cursor.execute(query)
49
        rows_cost_centers = cursor.fetchall()
50
51
        cost_center_dict = dict()
52
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
53
            for row in rows_cost_centers:
54
                cost_center_dict[row['id']] = {"id": row['id'],
55
                                               "name": row['name'],
56
                                               "uuid": row['uuid']}
57
58
        query = (" SELECT id, name, uuid, energy_category_id, is_counted, "
59
                 "        energy_item_id, cost_center_id, description "
60
                 " FROM tbl_virtual_meters "
61
                 " ORDER BY id ")
62
        cursor.execute(query)
63
        rows_virtual_meters = cursor.fetchall()
64
65
        result = list()
66
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
67
            for row in rows_virtual_meters:
68
                energy_category = energy_category_dict.get(row['energy_category_id'], None)
69
                energy_item = energy_item_dict.get(row['energy_item_id'], None)
70
                cost_center = cost_center_dict.get(row['cost_center_id'], None)
71
                meta_result = {"id": row['id'],
72
                               "name": row['name'],
73
                               "uuid": row['uuid'],
74
                               "energy_category": energy_category,
75
                               "is_counted": True if row['is_counted'] else False,
76
                               "energy_item": energy_item,
77
                               "cost_center": cost_center,
78
                               "description": row['description'],
79
                               "expression": {}}
80
81
                expression = dict()
82
                query_expression = (" SELECT e.id, e.uuid, e.equation "
83
                                    " FROM tbl_expressions e "
84
                                    " WHERE e.virtual_meter_id = %s ")
85
                cursor.execute(query_expression, (row['id'],))
86
                row_expression = cursor.fetchone()
87
88 View Code Duplication
                if row_expression is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
89
                    expression = {'id': row_expression['id'],
90
                                  'uuid': row_expression['uuid'],
91
                                  'equation': row_expression['equation'],
92
                                  'variables': []}
93
94
                    query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
95
                                       " FROM tbl_expressions e, tbl_variables v "
96
                                       " WHERE e.id = %s AND v.expression_id = e.id "
97
                                       " ORDER BY v.name ")
98
                    cursor.execute(query_variables, (row_expression['id'],))
99
                    rows_variables = cursor.fetchall()
100
                    if rows_variables is not None:
101
                        for row_variable in rows_variables:
102
                            if row_variable['meter_type'].lower() == 'meter':
103
                                query_meter = (" SELECT m.name "
104
                                               " FROM tbl_meters m "
105
                                               " WHERE m.id = %s ")
106
                                cursor.execute(query_meter, (row_variable['meter_id'],))
107
                                row_meter = cursor.fetchone()
108
                                if row_meter is not None:
109
                                    expression['variables'].append({'id': row_variable['id'],
110
                                                                    'name': row_variable['name'],
111
                                                                    'meter_type': row_variable['meter_type'],
112
                                                                    'meter_id': row_variable['meter_id'],
113
                                                                    'meter_name': row_meter['name']})
114
                            elif row_variable['meter_type'].lower() == 'offline_meter':
115
                                query_meter = (" SELECT m.name "
116
                                               " FROM tbl_offline_meters m "
117
                                               " WHERE m.id = %s ")
118
                                cursor.execute(query_meter, (row_variable['meter_id'],))
119
                                row_meter = cursor.fetchone()
120
                                if row_meter is not None:
121
                                    expression['variables'].append({'id': row_variable['id'],
122
                                                                    'name': row_variable['name'],
123
                                                                    'meter_type': row_variable['meter_type'],
124
                                                                    'meter_id': row_variable['meter_id'],
125
                                                                    'meter_name': row_meter['name']})
126
                            elif row_variable['meter_type'].lower() == 'virtual_meter':
127
                                query_meter = (" SELECT m.name "
128
                                               " FROM tbl_virtual_meters m "
129
                                               " WHERE m.id = %s ")
130
                                cursor.execute(query_meter, (row_variable['meter_id'],))
131
                                row_meter = cursor.fetchone()
132
                                if row_meter is not None:
133
                                    expression['variables'].append({'id': row_variable['id'],
134
                                                                    'name': row_variable['name'],
135
                                                                    'meter_type': row_variable['meter_type'],
136
                                                                    'meter_id': row_variable['meter_id'],
137
                                                                    'meter_name': row_meter['name']})
138
139
                meta_result['expression'] = expression
140
                result.append(meta_result)
141
142
        cursor.close()
143
        cnx.disconnect()
144
        resp.body = json.dumps(result)
145
146
    @staticmethod
147
    def on_post(req, resp):
148
        """Handles POST requests"""
149
        try:
150
            raw_json = req.stream.read().decode('utf-8')
151
        except Exception as ex:
152
            raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', description=ex)
153
154
        new_values = json.loads(raw_json)
155
156
        if 'name' not in new_values['data'].keys() or \
157
                not isinstance(new_values['data']['name'], str) or \
158
                len(str.strip(new_values['data']['name'])) == 0:
159
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
160
                                   description='API.INVALID_VIRTUAL_METER_NAME')
161
        name = str.strip(new_values['data']['name'])
162
163
        if 'energy_category_id' not in new_values['data'].keys() or new_values['data']['energy_category_id'] <= 0:
164
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
165
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
166
        energy_category_id = new_values['data']['energy_category_id']
167
168
        if 'is_counted' not in new_values['data'].keys() or not isinstance(new_values['data']['is_counted'], bool):
169
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
170
                                   description='API.INVALID_IS_COUNTED_VALUE')
171
        is_counted = new_values['data']['is_counted']
172
173
        if 'cost_center_id' not in new_values['data'].keys() or \
174
                not isinstance(new_values['data']['cost_center_id'], int) or \
175
                new_values['data']['cost_center_id'] <= 0:
176
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
177
                                       description='API.INVALID_COST_CENTER_ID')
178
179
        cost_center_id = new_values['data']['cost_center_id']
180
181
        if 'energy_item_id' in new_values['data'].keys() and \
182
                new_values['data']['energy_item_id'] is not None:
183
            if not isinstance(new_values['data']['energy_item_id'], int) or \
184
                    new_values['data']['energy_item_id'] <= 0:
185
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
186
                                       description='API.INVALID_ENERGY_ITEM_ID')
187
            energy_item_id = new_values['data']['energy_item_id']
188
        else:
189
            energy_item_id = None
190
191
        if 'description' in new_values['data'].keys() and \
192
                new_values['data']['description'] is not None and \
193
                len(str(new_values['data']['description'])) > 0:
194
            description = str.strip(new_values['data']['description'])
195
        else:
196
            description = None
197
198
        if 'expression' not in new_values['data'].keys():
199
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
200
                                   description='API.INVALID_EXPRESSION_OBJECT')
201
202
        if 'equation' not in new_values['data']['expression'].keys() \
203
                or len(new_values['data']['expression']['equation']) == 0:
204
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
205
                                   description='API.INVALID_EQUATION_IN_EXPRESSION')
206
        # todo: validate equation with more rules
207
208
        if 'variables' not in new_values['data']['expression'].keys() \
209
                or len(new_values['data']['expression']['variables']) == 0:
210
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
211
                                   description='API.EMPTY_VARIABLES_ARRAY')
212
213
        for variable in new_values['data']['expression']['variables']:
214
            if 'name' not in variable.keys() or \
215
                    len(variable['name']) == 0:
216
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
217
                                       description='API.INVALID_VARIABLE_NAME')
218
            if 'meter_type' not in variable.keys() or \
219
                    len(variable['meter_type']) == 0 or \
220
                    variable['meter_type'].lower() not in ['meter', 'offline_meter', 'virtual_meter']:
221
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
222
                                       description='API.INVALID_VARIABLE_METER_TYPE')
223
            if 'meter_id' not in variable.keys() or \
224
                    variable['meter_id'] <= 0:
225
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
226
                                       description='API.INVALID_VARIABLE_METER_ID')
227
228
        cnx = mysql.connector.connect(**config.myems_system_db)
229
        cursor = cnx.cursor()
230
231
        cursor.execute(" SELECT name "
232
                       " FROM tbl_virtual_meters "
233
                       " WHERE name = %s ", (name,))
234
        if cursor.fetchone() is not None:
235
            cursor.close()
236
            cnx.disconnect()
237
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
238
                                   description='API.VIRTUAL_METER_NAME_IS_ALREADY_IN_USE')
239
240
        cursor.execute(" SELECT name "
241
                       " FROM tbl_energy_categories "
242
                       " WHERE id = %s ",
243
                       (energy_category_id,))
244
        if cursor.fetchone() is None:
245
            cursor.close()
246
            cnx.disconnect()
247
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
248
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
249
250
        cursor.execute(" SELECT name "
251
                       " FROM tbl_cost_centers "
252
                       " WHERE id = %s ",
253
                       (new_values['data']['cost_center_id'],))
254
        row = cursor.fetchone()
255
        if row is None:
256
            cursor.close()
257
            cnx.disconnect()
258
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
259
                                   description='API.COST_CENTER_NOT_FOUND')
260
261 View Code Duplication
        if energy_item_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
262
            cursor.execute(" SELECT name, energy_category_id "
263
                           " FROM tbl_energy_items "
264
                           " WHERE id = %s ",
265
                           (new_values['data']['energy_item_id'],))
266
            row = cursor.fetchone()
267
            if row is None:
268
                cursor.close()
269
                cnx.disconnect()
270
                raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
271
                                       description='API.ENERGY_ITEM_NOT_FOUND')
272
            else:
273
                if row[1] != energy_category_id:
274
                    cursor.close()
275
                    cnx.disconnect()
276
                    raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST',
277
                                           description='API.ENERGY_ITEM_IS_NOT_BELONG_TO_ENERGY_CATEGORY')
278
279
        for variable in new_values['data']['expression']['variables']:
280 View Code Duplication
            if variable['meter_type'].lower() == 'meter':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
281
                cursor.execute(" SELECT name "
282
                               " FROM tbl_meters "
283
                               " WHERE id = %s ", (variable['meter_id'],))
284
                if cursor.fetchone() is None:
285
                    cursor.close()
286
                    cnx.disconnect()
287
                    raise falcon.HTTPError(falcon.HTTP_404,
288
                                           title='API.NOT_FOUND',
289
                                           description='API.METER_OF_VARIABLE_NOT_FOUND')
290
            elif variable['meter_type'].lower() == 'offline_meter':
291
                cursor.execute(" SELECT name "
292
                               " FROM tbl_offline_meters "
293
                               " WHERE id = %s ", (variable['meter_id'],))
294
                if cursor.fetchone() is None:
295
                    cursor.close()
296
                    cnx.disconnect()
297
                    raise falcon.HTTPError(falcon.HTTP_404,
298
                                           title='API.NOT_FOUND',
299
                                           description='API.OFFLINE_METER_OF_VARIABLE_NOT_FOUND')
300
            elif variable['meter_type'].lower() == 'virtual_meter':
301
                cursor.execute(" SELECT name "
302
                               " FROM tbl_virtual_meters "
303
                               " WHERE id = %s ", (variable['meter_id'],))
304
                if cursor.fetchone() is None:
305
                    cursor.close()
306
                    cnx.disconnect()
307
                    raise falcon.HTTPError(falcon.HTTP_404,
308
                                           title='API.NOT_FOUND',
309
                                           description='API.VIRTUAL_METER_OF_VARIABLE_NOT_FOUND')
310
311
        add_values = (" INSERT INTO tbl_virtual_meters "
312
                      "     (name, uuid, energy_category_id, is_counted, "
313
                      "      cost_center_id, energy_item_id, description) "
314
                      " VALUES (%s, %s, %s, %s, %s, %s, %s) ")
315
        cursor.execute(add_values, (name,
316
                                    str(uuid.uuid4()),
317
                                    energy_category_id,
318
                                    is_counted,
319
                                    cost_center_id,
320
                                    energy_item_id,
321
                                    description))
322
        new_id = cursor.lastrowid
323
        cnx.commit()
324
325
        cursor.execute(" SELECT id "
326
                       " FROM tbl_expressions "
327
                       " WHERE virtual_meter_id = %s ", (new_id,))
328
        row_expression = cursor.fetchone()
329
        if row_expression is not None:
330
            # delete variables
331
            cursor.execute(" DELETE FROM tbl_variables WHERE expression_id = %s ", (row_expression[0],))
332
            # delete expression
333
            cursor.execute(" DELETE FROM tbl_expressions WHERE id = %s ", (row_expression[0],))
334
            cnx.commit()
335
336
        # add expression
337
        add_values = (" INSERT INTO tbl_expressions (uuid, virtual_meter_id, equation) "
338
                      " VALUES (%s, %s, %s) ")
339
        cursor.execute(add_values, (str(uuid.uuid4()),
340
                                    new_id,
341
                                    new_values['data']['expression']['equation'].lower()))
342
        new_expression_id = cursor.lastrowid
343
        cnx.commit()
344
345
        # add variables
346
        for variable in new_values['data']['expression']['variables']:
347
            add_values = (" INSERT INTO tbl_variables (name, expression_id, meter_type, meter_id) "
348
                          " VALUES (%s, %s, %s, %s) ")
349
            cursor.execute(add_values, (variable['name'].lower(),
350
                                        new_expression_id,
351
                                        variable['meter_type'],
352
                                        variable['meter_id'],))
353
            cnx.commit()
354
355
        cursor.close()
356
        cnx.disconnect()
357
358
        resp.status = falcon.HTTP_201
359
        resp.location = '/virtualmeters/' + str(new_id)
360
361
362
class VirtualMeterItem:
363
    @staticmethod
364
    def __init__():
365
        pass
366
367
    @staticmethod
368
    def on_options(req, resp, id_):
369
        resp.status = falcon.HTTP_200
370
371
    @staticmethod
372
    def on_get(req, resp, id_):
373
        if not id_.isdigit() or int(id_) <= 0:
374
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
375
                                   description='API.INVALID_VIRTUAL_METER_ID')
376
377
        cnx = mysql.connector.connect(**config.myems_system_db)
378
        cursor = cnx.cursor(dictionary=True)
379
380
        query = (" SELECT id, name, uuid "
381
                 " FROM tbl_energy_categories ")
382
        cursor.execute(query)
383
        rows_energy_categories = cursor.fetchall()
384
385
        energy_category_dict = dict()
386
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
387
            for row in rows_energy_categories:
388
                energy_category_dict[row['id']] = {"id": row['id'],
389
                                                   "name": row['name'],
390
                                                   "uuid": row['uuid']}
391
392
        query = (" SELECT id, name, uuid, energy_category_id "
393
                 " FROM tbl_energy_items ")
394
        cursor.execute(query)
395
        rows_energy_items = cursor.fetchall()
396
397
        energy_item_dict = dict()
398
        if rows_energy_items is not None and len(rows_energy_items) > 0:
399
            for row in rows_energy_items:
400
                energy_item_dict[row['id']] = {"id": row['id'],
401
                                               "name": row['name'],
402
                                               "uuid": row['uuid']}
403
404
        query = (" SELECT id, name, uuid "
405
                 " FROM tbl_cost_centers ")
406
        cursor.execute(query)
407
        rows_cost_centers = cursor.fetchall()
408
409
        cost_center_dict = dict()
410
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
411
            for row in rows_cost_centers:
412
                cost_center_dict[row['id']] = {"id": row['id'],
413
                                               "name": row['name'],
414
                                               "uuid": row['uuid']}
415
416
        query = (" SELECT id, name, uuid, energy_category_id, is_counted, "
417
                 "        energy_item_id, cost_center_id, description "
418
                 " FROM tbl_virtual_meters "
419
                 " WHERE id = %s ")
420
        cursor.execute(query, (id_,))
421
        row = cursor.fetchone()
422
        if row is None:
423
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
424
                                   description='API.VIRTUAL_METER_NOT_FOUND')
425
        else:
426
            energy_category = energy_category_dict.get(row['energy_category_id'], None)
427
            energy_item = energy_item_dict.get(row['energy_item_id'], None)
428
            cost_center = cost_center_dict.get(row['cost_center_id'], None)
429
            meta_result = {"id": row['id'],
430
                           "name": row['name'],
431
                           "uuid": row['uuid'],
432
                           "energy_category": energy_category,
433
                           "is_counted": True if row['is_counted'] else False,
434
                           "energy_item": energy_item,
435
                           "cost_center": cost_center,
436
                           "description": row['description'],
437
                           "expression": {}}
438
439
        expression = dict()
440
        query_expression = (" SELECT e.id, e.uuid, e.equation "
441
                            " FROM tbl_expressions e "
442
                            " WHERE e.virtual_meter_id = %s ")
443
        cursor.execute(query_expression, (id_,))
444
        row_expression = cursor.fetchone()
445
446 View Code Duplication
        if row_expression is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
447
            expression = {'id': row_expression['id'],
448
                          'uuid': row_expression['uuid'],
449
                          'equation': row_expression['equation'],
450
                          'variables': []}
451
452
            query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
453
                               " FROM tbl_expressions e, tbl_variables v "
454
                               " WHERE e.id = %s AND v.expression_id = e.id "
455
                               " ORDER BY v.name ")
456
            cursor.execute(query_variables, (row_expression['id'],))
457
            rows_variables = cursor.fetchall()
458
            if rows_variables is not None:
459
                for row_variable in rows_variables:
460
                    if row_variable['meter_type'].lower() == 'meter':
461
                        query_meter = (" SELECT m.name "
462
                                       " FROM tbl_meters m "
463
                                       " WHERE m.id = %s ")
464
                        cursor.execute(query_meter, (row_variable['meter_id'],))
465
                        row_meter = cursor.fetchone()
466
                        if row_meter is not None:
467
                            expression['variables'].append({'id': row_variable['id'],
468
                                                            'name': row_variable['name'],
469
                                                            'meter_type': row_variable['meter_type'],
470
                                                            'meter_id': row_variable['meter_id'],
471
                                                            'meter_name': row_meter['name']})
472
                    elif row_variable['meter_type'].lower() == 'offline_meter':
473
                        query_meter = (" SELECT m.name "
474
                                       " FROM tbl_offline_meters m "
475
                                       " WHERE m.id = %s ")
476
                        cursor.execute(query_meter, (row_variable['meter_id'],))
477
                        row_meter = cursor.fetchone()
478
                        if row_meter is not None:
479
                            expression['variables'].append({'id': row_variable['id'],
480
                                                            'name': row_variable['name'],
481
                                                            'meter_type': row_variable['meter_type'],
482
                                                            'meter_id': row_variable['meter_id'],
483
                                                            'meter_name': row_meter['name']})
484
                    elif row_variable['meter_type'].lower() == 'virtual_meter':
485
                        query_meter = (" SELECT m.name "
486
                                       " FROM tbl_virtual_meters m "
487
                                       " WHERE m.id = %s ")
488
                        cursor.execute(query_meter, (row_variable['meter_id'],))
489
                        row_meter = cursor.fetchone()
490
                        if row_meter is not None:
491
                            expression['variables'].append({'id': row_variable['id'],
492
                                                            'name': row_variable['name'],
493
                                                            'meter_type': row_variable['meter_type'],
494
                                                            'meter_id': row_variable['meter_id'],
495
                                                            'meter_name': row_meter['name']})
496
497
        meta_result['expression'] = expression
498
499
        cursor.close()
500
        cnx.disconnect()
501
        resp.body = json.dumps(meta_result)
502
503
    @staticmethod
504
    def on_delete(req, resp, id_):
505
        if not id_.isdigit() or int(id_) <= 0:
506
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
507
                                   description='API.INVALID_VIRTUAL_METER_ID')
508
509
        cnx = mysql.connector.connect(**config.myems_system_db)
510
        cursor = cnx.cursor()
511
512
        cursor.execute(" SELECT uuid "
513
                       " FROM tbl_virtual_meters "
514
                       " WHERE id = %s ", (id_,))
515
        row = cursor.fetchone()
516
        if row is None:
517
            cursor.close()
518
            cnx.disconnect()
519
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
520
                                   description='API.VIRTUAL_METER_NOT_FOUND')
521
        else:
522
            virtual_meter_uuid = row[0]
523
524
        # check relations with other virtual meters
525
        cursor.execute(" SELECT vm.name "
526
                       " FROM tbl_variables va, tbl_expressions ex, tbl_virtual_meters vm "
527
                       " WHERE va.meter_id = %s AND va.meter_type = 'virtual_meter' AND va.expression_id = ex.id "
528
                       " AND ex.virtual_meter_id = vm.id ",
529
                       (id_,))
530
        row_virtual_meter = cursor.fetchone()
531
        if row_virtual_meter is not None:
532
            cursor.close()
533
            cnx.disconnect()
534
            raise falcon.HTTPError(falcon.HTTP_400,
535
                                   title='API.BAD_REQUEST',
536
                                   description='API.THERE_IS_RELATION_WITH_OTHER_VIRTUAL_METERS')
537
538
        # check relation with spaces
539
        cursor.execute(" SELECT id "
540
                       " FROM tbl_spaces_virtual_meters "
541
                       " WHERE virtual_meter_id = %s ", (id_,))
542
        rows_spaces = cursor.fetchall()
543
        if rows_spaces is not None and len(rows_spaces) > 0:
544
            cursor.close()
545
            cnx.disconnect()
546
            raise falcon.HTTPError(falcon.HTTP_400,
547
                                   title='API.BAD_REQUEST',
548
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
549
550
        # check relation with combined equipments
551
        cursor.execute(" SELECT combined_equipment_id "
552
                       " FROM tbl_combined_equipments_virtual_meters "
553
                       " WHERE virtual_meter_id = %s ",
554
                       (id_,))
555
        rows_combined_equipments = cursor.fetchall()
556
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
557
            cursor.close()
558
            cnx.disconnect()
559
            raise falcon.HTTPError(falcon.HTTP_400,
560
                                   title='API.BAD_REQUEST',
561
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENTS')
562
563
        # check relation with combined equipment parameters
564
        cursor.execute(" SELECT combined_equipment_id "
565
                       " FROM tbl_combined_equipments_parameters "
566
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s",
567
                       (virtual_meter_uuid, virtual_meter_uuid,))
568
        rows_combined_equipments = cursor.fetchall()
569
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
570
            cursor.close()
571
            cnx.disconnect()
572
            raise falcon.HTTPError(falcon.HTTP_400,
573
                                   title='API.BAD_REQUEST',
574
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENT_PARAMETERS')
575
576
        # check relation with equipments
577
        cursor.execute(" SELECT equipment_id "
578
                       " FROM tbl_equipments_virtual_meters "
579
                       " WHERE virtual_meter_id = %s ", (id_,))
580
        rows_equipments = cursor.fetchall()
581
        if rows_equipments is not None and len(rows_equipments) > 0:
582
            cursor.close()
583
            cnx.disconnect()
584
            raise falcon.HTTPError(falcon.HTTP_400,
585
                                   title='API.BAD_REQUEST',
586
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENTS')
587
588
        # check relation with equipment parameters
589
        cursor.execute(" SELECT equipment_id "
590
                       " FROM tbl_equipments_parameters "
591
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s",
592
                       (virtual_meter_uuid, virtual_meter_uuid,))
593
        rows_equipments = cursor.fetchall()
594
        if rows_equipments is not None and len(rows_equipments) > 0:
595
            cursor.close()
596
            cnx.disconnect()
597
            raise falcon.HTTPError(falcon.HTTP_400,
598
                                   title='API.BAD_REQUEST',
599
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENT_PARAMETERS')
600
601
        # check relations with tenants
602
        cursor.execute(" SELECT tenant_id "
603
                       " FROM tbl_tenants_virtual_meters "
604
                       " WHERE virtual_meter_id = %s ", (id_,))
605
        rows_tenants = cursor.fetchall()
606
        if rows_tenants is not None and len(rows_tenants) > 0:
607
            cursor.close()
608
            cnx.disconnect()
609
            raise falcon.HTTPError(falcon.HTTP_400,
610
                                   title='API.BAD_REQUEST',
611
                                   description='API.THERE_IS_RELATION_WITH_TENANTS')
612
613
        # check relations with stores
614
        cursor.execute(" SELECT store_id "
615
                       " FROM tbl_stores_virtual_meters "
616
                       " WHERE virtual_meter_id = %s ", (id_,))
617
        rows_stores = cursor.fetchall()
618
        if rows_stores is not None and len(rows_stores) > 0:
619
            cursor.close()
620
            cnx.disconnect()
621
            raise falcon.HTTPError(falcon.HTTP_400,
622
                                   title='API.BAD_REQUEST',
623
                                   description='API.THERE_IS_RELATION_WITH_STORES')
624
625
        # check relations with shopfloors
626
        cursor.execute(" SELECT shopfloor_id "
627
                       " FROM tbl_shopfloors_virtual_meters "
628
                       " WHERE virtual_meter_id = %s ", (id_,))
629
        rows_shopfloors = cursor.fetchall()
630
        if rows_shopfloors is not None and len(rows_shopfloors) > 0:
631
            cursor.close()
632
            cnx.disconnect()
633
            raise falcon.HTTPError(falcon.HTTP_400,
634
                                   title='API.BAD_REQUEST',
635
                                   description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
636
637
        cursor.execute(" SELECT id "
638
                       " FROM tbl_expressions "
639
                       " WHERE virtual_meter_id = %s ", (id_,))
640
        row_expression = cursor.fetchone()
641
        if row_expression is not None:
642
            # delete variables
643
            cursor.execute(" DELETE FROM tbl_variables WHERE expression_id = %s ", (row_expression[0],))
644
            # delete expression
645
            cursor.execute(" DELETE FROM tbl_expressions WHERE id = %s ", (row_expression[0],))
646
            cnx.commit()
647
648
        # check relation with energy flow diagram links
649
        cursor.execute(" SELECT id "
650
                       " FROM tbl_energy_flow_diagrams_links "
651
                       " WHERE meter_uuid = %s ", (virtual_meter_uuid,))
652
        rows_links = cursor.fetchall()
653
        if rows_links is not None and len(rows_links) > 0:
654
            cursor.close()
655
            cnx.disconnect()
656
            raise falcon.HTTPError(falcon.HTTP_400,
657
                                   title='API.BAD_REQUEST',
658
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_FLOW_DIAGRAM_LINKS')
659
660
        cursor.execute(" DELETE FROM tbl_virtual_meters WHERE id = %s ", (id_,))
661
        cnx.commit()
662
663
        cursor.close()
664
        cnx.disconnect()
665
666
        resp.status = falcon.HTTP_204
667
668
    @staticmethod
669
    def on_put(req, resp, id_):
670
        """Handles PUT requests"""
671
        try:
672
            raw_json = req.stream.read().decode('utf-8')
673
        except Exception as ex:
674
            raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=ex)
675
676
        if not id_.isdigit() or int(id_) <= 0:
677
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
678
                                   description='API.INVALID_VIRTUAL_METER_ID')
679
680
        new_values = json.loads(raw_json)
681
682
        if 'name' not in new_values['data'].keys() or \
683
                not isinstance(new_values['data']['name'], str) or \
684
                len(str.strip(new_values['data']['name'])) == 0:
685
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
686
                                   description='API.INVALID_VIRTUAL_METER_NAME')
687
        name = str.strip(new_values['data']['name'])
688
689
        if 'energy_category_id' not in new_values['data'].keys() or new_values['data']['energy_category_id'] <= 0:
690
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
691
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
692
        energy_category_id = new_values['data']['energy_category_id']
693
694
        if 'is_counted' not in new_values['data'].keys() or not isinstance(new_values['data']['is_counted'], bool):
695
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
696
                                   description='API.INVALID_IS_COUNTED_VALUE')
697
        is_counted = new_values['data']['is_counted']
698
699
        if 'cost_center_id' not in new_values['data'].keys() or \
700
                not isinstance(new_values['data']['cost_center_id'], int) or \
701
                new_values['data']['cost_center_id'] <= 0:
702
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
703
                                       description='API.INVALID_COST_CENTER_ID')
704
705
        cost_center_id = new_values['data']['cost_center_id']
706
707
        if 'energy_item_id' in new_values['data'].keys() and \
708
                new_values['data']['energy_item_id'] is not None:
709
            if not isinstance(new_values['data']['energy_item_id'], int) or \
710
                    new_values['data']['energy_item_id'] <= 0:
711
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
712
                                       description='API.INVALID_ENERGY_ITEM_ID')
713
            energy_item_id = new_values['data']['energy_item_id']
714
        else:
715
            energy_item_id = None
716
717
        if 'description' in new_values['data'].keys() and \
718
                new_values['data']['description'] is not None and \
719
                len(str(new_values['data']['description'])) > 0:
720
            description = str.strip(new_values['data']['description'])
721
        else:
722
            description = None
723
724
        if 'expression' not in new_values['data'].keys():
725
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
726
                                   description='API.INVALID_EXPRESSION_OBJECT')
727
728
        if 'equation' not in new_values['data']['expression'].keys() \
729
                or len(new_values['data']['expression']['equation']) == 0:
730
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
731
                                   description='API.INVALID_EQUATION_IN_EXPRESSION')
732
        # todo: validate equation with more rules
733
734
        if 'variables' not in new_values['data']['expression'].keys() \
735
                or len(new_values['data']['expression']['variables']) == 0:
736
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
737
                                   description='API.EMPTY_VARIABLES_ARRAY')
738
739
        for variable in new_values['data']['expression']['variables']:
740
            if 'name' not in variable.keys() or \
741
                    len(variable['name']) == 0:
742
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
743
                                       description='API.INVALID_VARIABLE_NAME')
744
            if 'meter_type' not in variable.keys() or \
745
                len(variable['meter_type']) == 0 or \
746
                    variable['meter_type'].lower() not in ['meter', 'offline_meter', 'virtual_meter']:
747
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
748
                                       description='API.INVALID_VARIABLE_METER_TYPE')
749
            if 'meter_id' not in variable.keys() or \
750
                    variable['meter_id'] <= 0:
751
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
752
                                       description='API.INVALID_VARIABLE_METER_ID')
753
754
        cnx = mysql.connector.connect(**config.myems_system_db)
755
        cursor = cnx.cursor()
756
757
        cursor.execute(" SELECT name "
758
                       " FROM tbl_virtual_meters "
759
                       " WHERE id = %s ", (id_,))
760
        if cursor.fetchone() is None:
761
            cursor.close()
762
            cnx.disconnect()
763
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
764
                                   description='API.VIRTUAL_METER_NOT_FOUND')
765
766
        cursor.execute(" SELECT name "
767
                       " FROM tbl_virtual_meters "
768
                       " WHERE name = %s AND id != %s ", (name, id_))
769
        if cursor.fetchone() is not None:
770
            cursor.close()
771
            cnx.disconnect()
772
            raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST',
773
                                   description='API.VIRTUAL_METER_NAME_IS_ALREADY_IN_USE')
774
775
        cursor.execute(" SELECT name "
776
                       " FROM tbl_energy_categories "
777
                       " WHERE id = %s ",
778
                       (energy_category_id,))
779
        if cursor.fetchone() is None:
780
            cursor.close()
781
            cnx.disconnect()
782
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
783
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
784
785
        cursor.execute(" SELECT name "
786
                       " FROM tbl_cost_centers "
787
                       " WHERE id = %s ",
788
                       (new_values['data']['cost_center_id'],))
789
        row = cursor.fetchone()
790
        if row is None:
791
            cursor.close()
792
            cnx.disconnect()
793
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
794
                                   description='API.COST_CENTER_NOT_FOUND')
795
796 View Code Duplication
        if energy_item_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
797
            cursor.execute(" SELECT name, energy_category_id "
798
                           " FROM tbl_energy_items "
799
                           " WHERE id = %s ",
800
                           (new_values['data']['energy_item_id'],))
801
            row = cursor.fetchone()
802
            if row is None:
803
                cursor.close()
804
                cnx.disconnect()
805
                raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
806
                                       description='API.ENERGY_ITEM_NOT_FOUND')
807
            else:
808
                if row[1] != energy_category_id:
809
                    cursor.close()
810
                    cnx.disconnect()
811
                    raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST',
812
                                           description='API.ENERGY_ITEM_IS_NOT_BELONG_TO_ENERGY_CATEGORY')
813
814
        for variable in new_values['data']['expression']['variables']:
815 View Code Duplication
            if variable['meter_type'].lower() == 'meter':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
816
                cursor.execute(" SELECT name "
817
                               " FROM tbl_meters "
818
                               " WHERE id = %s ", (variable['meter_id'],))
819
                if cursor.fetchone() is None:
820
                    cursor.close()
821
                    cnx.disconnect()
822
                    raise falcon.HTTPError(falcon.HTTP_404,
823
                                           title='API.NOT_FOUND',
824
                                           description='API.METER_OF_VARIABLE_NOT_FOUND')
825
            elif variable['meter_type'].lower() == 'offline_meter':
826
                cursor.execute(" SELECT name "
827
                               " FROM tbl_offline_meters "
828
                               " WHERE id = %s ", (variable['meter_id'],))
829
                if cursor.fetchone() is None:
830
                    cursor.close()
831
                    cnx.disconnect()
832
                    raise falcon.HTTPError(falcon.HTTP_404,
833
                                           title='API.NOT_FOUND',
834
                                           description='API.OFFLINE_METER_OF_VARIABLE_NOT_FOUND')
835
            elif variable['meter_type'].lower() == 'virtual_meter':
836
                cursor.execute(" SELECT name "
837
                               " FROM tbl_virtual_meters "
838
                               " WHERE id = %s ", (variable['meter_id'],))
839
                if cursor.fetchone() is None:
840
                    cursor.close()
841
                    cnx.disconnect()
842
                    raise falcon.HTTPError(falcon.HTTP_404,
843
                                           title='API.NOT_FOUND',
844
                                           description='API.VIRTUAL_METER_OF_VARIABLE_NOT_FOUND')
845
846
        update_row = (" UPDATE tbl_virtual_meters "
847
                      " SET name = %s, energy_category_id = %s, is_counted = %s, "
848
                      "     cost_center_id = %s, energy_item_id = %s, description = %s "
849
                      " WHERE id = %s ")
850
        cursor.execute(update_row, (name,
851
                                    energy_category_id,
852
                                    is_counted,
853
                                    cost_center_id,
854
                                    energy_item_id,
855
                                    description,
856
                                    id_,))
857
        cnx.commit()
858
859
        cursor.execute(" SELECT id "
860
                       " FROM tbl_expressions "
861
                       " WHERE virtual_meter_id = %s ", (id_,))
862
        row_expression = cursor.fetchone()
863
        if row_expression is not None:
864
            # delete variables
865
            cursor.execute(" DELETE FROM tbl_variables WHERE expression_id = %s ", (row_expression[0],))
866
            # delete expression
867
            cursor.execute(" DELETE FROM tbl_expressions WHERE id = %s ", (row_expression[0],))
868
            cnx.commit()
869
870
        # add expression
871
        add_values = (" INSERT INTO tbl_expressions (uuid, virtual_meter_id, equation) "
872
                      " VALUES (%s, %s, %s) ")
873
        cursor.execute(add_values, (str(uuid.uuid4()),
874
                                    id_,
875
                                    new_values['data']['expression']['equation'].lower()))
876
        new_expression_id = cursor.lastrowid
877
        cnx.commit()
878
879
        # add variables
880
        for variable in new_values['data']['expression']['variables']:
881
            add_values = (" INSERT INTO tbl_variables (name, expression_id, meter_type, meter_id) "
882
                          " VALUES (%s, %s, %s, %s) ")
883
            cursor.execute(add_values, (variable['name'].lower(),
884
                                        new_expression_id,
885
                                        variable['meter_type'],
886
                                        variable['meter_id'],))
887
            cnx.commit()
888
889
        cursor.close()
890
        cnx.disconnect()
891
892
        resp.status = falcon.HTTP_200
893
894