core.virtualmeter.VirtualMeterExport.on_options()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nop 3
1
import uuid
2
from datetime import datetime, timedelta
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
from core.useractivity import user_logger, admin_control, access_control, api_key_control
7
import config
8
9
10
class VirtualMeterCollection:
11
    def __init__(self):
12
        """"Initializes VirtualMeterCollection"""
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        _ = req
18
        resp.status = falcon.HTTP_200
19
20
    @staticmethod
21
    def on_get(req, resp):
22
        if 'API-KEY' not in req.headers or \
23
                not isinstance(req.headers['API-KEY'], str) or \
24
                len(str.strip(req.headers['API-KEY'])) == 0:
25
            access_control(req)
26
        else:
27
            api_key_control(req)
28
        search_query = req.get_param('q', default=None)
29
        if search_query is not None:
30
            search_query = search_query.strip()
31
        else:
32
            search_query = ''
33
34
        cnx = mysql.connector.connect(**config.myems_system_db)
35
        cursor = cnx.cursor()
36
37
        query = (" SELECT id, name, uuid "
38
                 " FROM tbl_energy_categories ")
39
        cursor.execute(query)
40
        rows_energy_categories = cursor.fetchall()
41
42
        energy_category_dict = dict()
43
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
44
            for row in rows_energy_categories:
45
                energy_category_dict[row[0]] = {"id": row[0],
46
                                                "name": row[1],
47
                                                "uuid": row[2]}
48
49
        query = (" SELECT id, name, uuid "
50
                 " FROM tbl_energy_items ")
51
        cursor.execute(query)
52
        rows_energy_items = cursor.fetchall()
53
54
        energy_item_dict = dict()
55
        if rows_energy_items is not None and len(rows_energy_items) > 0:
56
            for row in rows_energy_items:
57
                energy_item_dict[row[0]] = {"id": row[0],
58
                                            "name": row[1],
59
                                            "uuid": row[2]}
60
61
        query = (" SELECT id, name, uuid "
62
                 " FROM tbl_cost_centers ")
63
        cursor.execute(query)
64
        rows_cost_centers = cursor.fetchall()
65
66
        cost_center_dict = dict()
67
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
68
            for row in rows_cost_centers:
69
                cost_center_dict[row[0]] = {"id": row[0],
70
                                            "name": row[1],
71
                                            "uuid": row[2]}
72
73
        query = (" SELECT id, name, uuid, equation, energy_category_id, is_counted, cost_center_id, "
74
                 "        energy_item_id, description "
75
                 " FROM tbl_virtual_meters " )
76
        params = []
77
        if search_query:
78
            query += " WHERE name LIKE %s OR description LIKE %s "
79
            params = [f'%{search_query}%', f'%{search_query}%']
80
81
        query += " ORDER BY id "
82
        cursor.execute(query,params)
83
        rows_virtual_meters = cursor.fetchall()
84
85
        result = list()
86
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
87
            for row in rows_virtual_meters:
88
                meta_result = {"id": row[0],
89
                               "name": row[1],
90
                               "uuid": row[2],
91
                               "equation": row[3],
92
                               "energy_category": energy_category_dict.get(row[4], None),
93
                               "is_counted": True if row[5] else False,
94
                               "cost_center": cost_center_dict.get(row[6], None),
95
                               "energy_item": energy_item_dict.get(row[7], None),
96
                               "description": row[8],
97
                               "expression": {}}
98
99
                expression = dict()
100
101
                if meta_result["equation"] is not None:
102
                    expression = {'equation': meta_result["equation"], 'variables': []}
103
104
                    query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
105
                                       " FROM tbl_virtual_meters vm, tbl_variables v "
106
                                       " WHERE vm.id = %s AND v.virtual_meter_id = vm.id "
107
                                       " ORDER BY SUBSTRING(v.name, 2, 10) + 0 ")
108
                    cursor.execute(query_variables, (meta_result['id'],))
109
                    rows_variables = cursor.fetchall()
110
                    if rows_variables is not None:
111
                        for row_variable in rows_variables:
112
                            if row_variable[2].lower() == 'meter':
113
                                query_meter = (" SELECT m.name "
114
                                               " FROM tbl_meters m "
115
                                               " WHERE m.id = %s ")
116
                                cursor.execute(query_meter, (row_variable[3],))
117
                                row_meter = cursor.fetchone()
118
                                if row_meter is not None:
119
                                    expression['variables'].append({'id': row_variable[0],
120
                                                                    'name': row_variable[1],
121
                                                                    'meter_type': row_variable[2],
122
                                                                    'meter_id': row_variable[3],
123
                                                                    'meter_name': row_meter[0]})
124
                            elif row_variable[2].lower() == 'offline_meter':
125
                                query_meter = (" SELECT m.name "
126
                                               " FROM tbl_offline_meters m "
127
                                               " WHERE m.id = %s ")
128
                                cursor.execute(query_meter, (row_variable[3],))
129
                                row_meter = cursor.fetchone()
130
                                if row_meter is not None:
131
                                    expression['variables'].append({'id': row_variable[0],
132
                                                                    'name': row_variable[1],
133
                                                                    'meter_type': row_variable[2],
134
                                                                    'meter_id': row_variable[3],
135
                                                                    'meter_name': row_meter[0]})
136
                            elif row_variable[2].lower() == 'virtual_meter':
137
                                query_meter = (" SELECT m.name "
138
                                               " FROM tbl_virtual_meters m "
139
                                               " WHERE m.id = %s ")
140
                                cursor.execute(query_meter, (row_variable[3],))
141
                                row_meter = cursor.fetchone()
142
                                if row_meter is not None:
143
                                    expression['variables'].append({'id': row_variable[0],
144
                                                                    'name': row_variable[1],
145
                                                                    'meter_type': row_variable[2],
146
                                                                    'meter_id': row_variable[3],
147
                                                                    'meter_name': row_meter[0]})
148
149
                meta_result['expression'] = expression
150
                result.append(meta_result)
151
152
        cursor.close()
153
        cnx.close()
154
        resp.text = json.dumps(result)
155
156
    @staticmethod
157
    @user_logger
158
    def on_post(req, resp):
159
        """Handles POST requests"""
160
        admin_control(req)
161
        try:
162
            raw_json = req.stream.read().decode('utf-8')
163
        except Exception as ex:
164
            print(str(ex))
165
            raise falcon.HTTPError(status=falcon.HTTP_400,
166
                                   title='API.BAD_REQUEST',
167
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
168
169
        new_values = json.loads(raw_json)
170
171
        if 'name' not in new_values['data'].keys() or \
172
                not isinstance(new_values['data']['name'], str) or \
173
                len(str.strip(new_values['data']['name'])) == 0:
174
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
175
                                   description='API.INVALID_VIRTUAL_METER_NAME')
176
        name = str.strip(new_values['data']['name'])
177
178
        if 'energy_category_id' not in new_values['data'].keys() or new_values['data']['energy_category_id'] <= 0:
179
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
180
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
181
        energy_category_id = new_values['data']['energy_category_id']
182
183
        if 'is_counted' not in new_values['data'].keys() or not isinstance(new_values['data']['is_counted'], bool):
184
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
185
                                   description='API.INVALID_IS_COUNTED_VALUE')
186
        is_counted = new_values['data']['is_counted']
187
188
        if 'cost_center_id' not in new_values['data'].keys() or \
189
                not isinstance(new_values['data']['cost_center_id'], int) or \
190
                new_values['data']['cost_center_id'] <= 0:
191
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
192
                                   description='API.INVALID_COST_CENTER_ID')
193
194
        cost_center_id = new_values['data']['cost_center_id']
195
196
        if 'energy_item_id' in new_values['data'].keys() and \
197
                new_values['data']['energy_item_id'] is not None:
198
            if not isinstance(new_values['data']['energy_item_id'], int) or \
199
                    new_values['data']['energy_item_id'] <= 0:
200
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
201
                                       description='API.INVALID_ENERGY_ITEM_ID')
202
            energy_item_id = new_values['data']['energy_item_id']
203
        else:
204
            energy_item_id = None
205
206
        if 'description' in new_values['data'].keys() and \
207
                new_values['data']['description'] is not None and \
208
                len(str(new_values['data']['description'])) > 0:
209
            description = str.strip(new_values['data']['description'])
210
        else:
211
            description = None
212
213
        if 'expression' not in new_values['data'].keys():
214
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
215
                                   description='API.INVALID_EXPRESSION_OBJECT')
216
217
        if 'equation' not in new_values['data']['expression'].keys() \
218
                or len(new_values['data']['expression']['equation']) == 0:
219
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
220
                                   description='API.INVALID_EQUATION_IN_EXPRESSION')
221
        # todo: validate equation with more rules
222
223
        if 'variables' not in new_values['data']['expression'].keys() \
224
                or len(new_values['data']['expression']['variables']) == 0:
225
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
226
                                   description='API.EMPTY_VARIABLES_ARRAY')
227
228
        for variable in new_values['data']['expression']['variables']:
229
            if 'name' not in variable.keys() or \
230
                    len(variable['name']) == 0:
231
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
232
                                       description='API.INVALID_VARIABLE_NAME')
233
            if 'meter_type' not in variable.keys() or \
234
                    len(variable['meter_type']) == 0 or \
235
                    variable['meter_type'].lower() not in ['meter', 'offline_meter', 'virtual_meter']:
236
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
237
                                       description='API.INVALID_VARIABLE_METER_TYPE')
238
            if 'meter_id' not in variable.keys() or \
239
                    variable['meter_id'] <= 0:
240
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
241
                                       description='API.INVALID_VARIABLE_METER_ID')
242
243
        cnx = mysql.connector.connect(**config.myems_system_db)
244
        cursor = cnx.cursor()
245
246
        cursor.execute(" SELECT name "
247
                       " FROM tbl_virtual_meters "
248
                       " WHERE name = %s ", (name,))
249
        if cursor.fetchone() is not None:
250
            cursor.close()
251
            cnx.close()
252
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
253
                                   description='API.VIRTUAL_METER_NAME_IS_ALREADY_IN_USE')
254
255
        cursor.execute(" SELECT name "
256
                       " FROM tbl_energy_categories "
257
                       " WHERE id = %s ",
258
                       (energy_category_id,))
259
        if cursor.fetchone() is None:
260
            cursor.close()
261
            cnx.close()
262
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
263
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
264
265
        cursor.execute(" SELECT name "
266
                       " FROM tbl_cost_centers "
267
                       " WHERE id = %s ",
268
                       (new_values['data']['cost_center_id'],))
269
        row = cursor.fetchone()
270
        if row is None:
271
            cursor.close()
272
            cnx.close()
273
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
274
                                   description='API.COST_CENTER_NOT_FOUND')
275
276 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...
277
            cursor.execute(" SELECT name, energy_category_id "
278
                           " FROM tbl_energy_items "
279
                           " WHERE id = %s ",
280
                           (new_values['data']['energy_item_id'],))
281
            row = cursor.fetchone()
282
            if row is None:
283
                cursor.close()
284
                cnx.close()
285
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
286
                                       description='API.ENERGY_ITEM_NOT_FOUND')
287
            else:
288
                if row[1] != energy_category_id:
289
                    cursor.close()
290
                    cnx.close()
291
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
292
                                           description='API.ENERGY_ITEM_IS_NOT_BELONG_TO_ENERGY_CATEGORY')
293
294
        for variable in new_values['data']['expression']['variables']:
295 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...
296
                cursor.execute(" SELECT name "
297
                               " FROM tbl_meters "
298
                               " WHERE id = %s ", (variable['meter_id'],))
299
                if cursor.fetchone() is None:
300
                    cursor.close()
301
                    cnx.close()
302
                    raise falcon.HTTPError(status=falcon.HTTP_404,
303
                                           title='API.NOT_FOUND',
304
                                           description='API.METER_OF_VARIABLE_NOT_FOUND')
305
            elif variable['meter_type'].lower() == 'offline_meter':
306
                cursor.execute(" SELECT name "
307
                               " FROM tbl_offline_meters "
308
                               " WHERE id = %s ", (variable['meter_id'],))
309
                if cursor.fetchone() is None:
310
                    cursor.close()
311
                    cnx.close()
312
                    raise falcon.HTTPError(status=falcon.HTTP_404,
313
                                           title='API.NOT_FOUND',
314
                                           description='API.OFFLINE_METER_OF_VARIABLE_NOT_FOUND')
315
            elif variable['meter_type'].lower() == 'virtual_meter':
316
                cursor.execute(" SELECT name "
317
                               " FROM tbl_virtual_meters "
318
                               " WHERE id = %s ", (variable['meter_id'],))
319
                if cursor.fetchone() is None:
320
                    cursor.close()
321
                    cnx.close()
322
                    raise falcon.HTTPError(status=falcon.HTTP_404,
323
                                           title='API.NOT_FOUND',
324
                                           description='API.VIRTUAL_METER_OF_VARIABLE_NOT_FOUND')
325
326
        add_values = (" INSERT INTO tbl_virtual_meters "
327
                      "     (name, uuid, equation, energy_category_id, is_counted, "
328
                      "      cost_center_id, energy_item_id, description) "
329
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
330
        cursor.execute(add_values, (name,
331
                                    str(uuid.uuid4()),
332
                                    new_values['data']['expression']['equation'].lower(),
333
                                    energy_category_id,
334
                                    is_counted,
335
                                    cost_center_id,
336
                                    energy_item_id,
337
                                    description))
338
        new_id = cursor.lastrowid
339
        cnx.commit()
340
341
        # add variables
342
        for variable in new_values['data']['expression']['variables']:
343
            add_values = (" INSERT INTO tbl_variables (name, virtual_meter_id, meter_type, meter_id) "
344
                          " VALUES (%s, %s, %s, %s) ")
345
            cursor.execute(add_values, (variable['name'].lower(),
346
                                        new_id,
347
                                        variable['meter_type'],
348
                                        variable['meter_id'],))
349
            cnx.commit()
350
351
        cursor.close()
352
        cnx.close()
353
354
        resp.status = falcon.HTTP_201
355
        resp.location = '/virtualmeters/' + str(new_id)
356
357
358
class VirtualMeterItem:
359
    def __init__(self):
360
        """"Initializes VirtualMeterItem"""
361
        pass
362
363
    @staticmethod
364
    def on_options(req, resp, id_):
365
        _ = req
366
        resp.status = falcon.HTTP_200
367
        _ = id_
368
369 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
370
    def on_get(req, resp, id_):
371
        if 'API-KEY' not in req.headers or \
372
                not isinstance(req.headers['API-KEY'], str) or \
373
                len(str.strip(req.headers['API-KEY'])) == 0:
374
            access_control(req)
375
        else:
376
            api_key_control(req)
377
        if not id_.isdigit() or int(id_) <= 0:
378
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
379
                                   description='API.INVALID_VIRTUAL_METER_ID')
380
381
        cnx = mysql.connector.connect(**config.myems_system_db)
382
        cursor = cnx.cursor()
383
384
        query = (" SELECT id, name, uuid "
385
                 " FROM tbl_energy_categories ")
386
        cursor.execute(query)
387
        rows_energy_categories = cursor.fetchall()
388
389
        energy_category_dict = dict()
390
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
391
            for row in rows_energy_categories:
392
                energy_category_dict[row[0]] = {"id": row[0],
393
                                                "name": row[1],
394
                                                "uuid": row[2]}
395
396
        query = (" SELECT id, name, uuid, energy_category_id "
397
                 " FROM tbl_energy_items ")
398
        cursor.execute(query)
399
        rows_energy_items = cursor.fetchall()
400
401
        energy_item_dict = dict()
402
        if rows_energy_items is not None and len(rows_energy_items) > 0:
403
            for row in rows_energy_items:
404
                energy_item_dict[row[0]] = {"id": row[0],
405
                                            "name": row[1],
406
                                            "uuid": row[2]}
407
408
        query = (" SELECT id, name, uuid "
409
                 " FROM tbl_cost_centers ")
410
        cursor.execute(query)
411
        rows_cost_centers = cursor.fetchall()
412
413
        cost_center_dict = dict()
414
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
415
            for row in rows_cost_centers:
416
                cost_center_dict[row[0]] = {"id": row[0],
417
                                            "name": row[1],
418
                                            "uuid": row[2]}
419
420
        query = (" SELECT id, name, uuid, equation, energy_category_id, is_counted, cost_center_id, "
421
                 "        energy_item_id, description "
422
                 " FROM tbl_virtual_meters "
423
                 " WHERE id = %s ")
424
        cursor.execute(query, (id_,))
425
        row = cursor.fetchone()
426
        if row is None:
427
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
428
                                   description='API.VIRTUAL_METER_NOT_FOUND')
429
        else:
430
            meta_result = {"id": row[0],
431
                           "name": row[1],
432
                           "uuid": row[2],
433
                           "equation": row[3],
434
                           "energy_category": energy_category_dict.get(row[4], None),
435
                           "is_counted": True if row[5] else False,
436
                           "cost_center": cost_center_dict.get(row[6], None),
437
                           "energy_item": energy_item_dict.get(row[7], None),
438
                           "description": row[8],
439
                           "expression": {}}
440
441
        expression = dict()
442
443
        if meta_result["equation"] is not None:
444
            expression = {'equation': meta_result["equation"], 'variables': []}
445
446
            query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
447
                               " FROM tbl_virtual_meters  vm, tbl_variables v "
448
                               " WHERE vm.id = %s AND v.virtual_meter_id = vm.id "
449
                               " ORDER BY v.name ")
450
            cursor.execute(query_variables, (meta_result["id"],))
451
            rows_variables = cursor.fetchall()
452
            if rows_variables is not None:
453
                for row_variable in rows_variables:
454
                    if row_variable[2].lower() == 'meter':
455
                        query_meter = (" SELECT m.name "
456
                                       " FROM tbl_meters m "
457
                                       " WHERE m.id = %s ")
458
                        cursor.execute(query_meter, (row_variable[3],))
459
                        row_meter = cursor.fetchone()
460
                        if row_meter is not None:
461
                            expression['variables'].append({'id': row_variable[0],
462
                                                            'name': row_variable[1],
463
                                                            'meter_type': row_variable[2],
464
                                                            'meter_id': row_variable[3],
465
                                                            'meter_name': row_meter[0]})
466
                    elif row_variable[2].lower() == 'offline_meter':
467
                        query_meter = (" SELECT m.name "
468
                                       " FROM tbl_offline_meters m "
469
                                       " WHERE m.id = %s ")
470
                        cursor.execute(query_meter, (row_variable[3],))
471
                        row_meter = cursor.fetchone()
472
                        if row_meter is not None:
473
                            expression['variables'].append({'id': row_variable[0],
474
                                                            'name': row_variable[1],
475
                                                            'meter_type': row_variable[2],
476
                                                            'meter_id': row_variable[3],
477
                                                            'meter_name': row_meter[0]})
478
                    elif row_variable[2].lower() == 'virtual_meter':
479
                        query_meter = (" SELECT m.name "
480
                                       " FROM tbl_virtual_meters m "
481
                                       " WHERE m.id = %s ")
482
                        cursor.execute(query_meter, (row_variable[3],))
483
                        row_meter = cursor.fetchone()
484
                        if row_meter is not None:
485
                            expression['variables'].append({'id': row_variable[0],
486
                                                            'name': row_variable[1],
487
                                                            'meter_type': row_variable[2],
488
                                                            'meter_id': row_variable[3],
489
                                                            'meter_name': row_meter[0]})
490
491
        meta_result['expression'] = expression
492
493
        cursor.close()
494
        cnx.close()
495
        resp.text = json.dumps(meta_result)
496
497
    @staticmethod
498
    @user_logger
499
    def on_delete(req, resp, id_):
500
        admin_control(req)
501
        if not id_.isdigit() or int(id_) <= 0:
502
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
503
                                   description='API.INVALID_VIRTUAL_METER_ID')
504
505
        cnx = mysql.connector.connect(**config.myems_system_db)
506
        cursor = cnx.cursor()
507
508
        cursor.execute(" SELECT uuid "
509
                       " FROM tbl_virtual_meters "
510
                       " WHERE id = %s ", (id_,))
511
        row = cursor.fetchone()
512
        if row is None:
513
            cursor.close()
514
            cnx.close()
515
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
516
                                   description='API.VIRTUAL_METER_NOT_FOUND')
517
        else:
518
            virtual_meter_uuid = row[0]
519
520
        # check relations with other virtual meters
521
        cursor.execute(" SELECT vm.name "
522
                       " FROM tbl_variables va, tbl_virtual_meters vm "
523
                       " WHERE va.meter_id = %s AND va.meter_type = 'virtual_meter' AND va.virtual_meter_id = vm.id ",
524
                       (id_,))
525
        rows_virtual_meters = cursor.fetchall()
526
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
527
            cursor.close()
528
            cnx.close()
529
            raise falcon.HTTPError(status=falcon.HTTP_400,
530
                                   title='API.BAD_REQUEST',
531
                                   description='API.THERE_IS_RELATION_WITH_OTHER_VIRTUAL_METERS')
532
533
        # check relation with spaces
534
        cursor.execute(" SELECT id "
535
                       " FROM tbl_spaces_virtual_meters "
536
                       " WHERE virtual_meter_id = %s ", (id_,))
537
        rows_spaces = cursor.fetchall()
538
        if rows_spaces is not None and len(rows_spaces) > 0:
539
            cursor.close()
540
            cnx.close()
541
            raise falcon.HTTPError(status=falcon.HTTP_400,
542
                                   title='API.BAD_REQUEST',
543
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
544
545
        # check relation with combined equipments
546
        cursor.execute(" SELECT combined_equipment_id "
547
                       " FROM tbl_combined_equipments_virtual_meters "
548
                       " WHERE virtual_meter_id = %s ",
549
                       (id_,))
550
        rows_combined_equipments = cursor.fetchall()
551
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
552
            cursor.close()
553
            cnx.close()
554
            raise falcon.HTTPError(status=falcon.HTTP_400,
555
                                   title='API.BAD_REQUEST',
556
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENTS')
557
558
        # check relation with combined equipment parameters
559
        cursor.execute(" SELECT combined_equipment_id "
560
                       " FROM tbl_combined_equipments_parameters "
561
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s",
562
                       (virtual_meter_uuid, virtual_meter_uuid,))
563
        rows_combined_equipments = cursor.fetchall()
564
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
565
            cursor.close()
566
            cnx.close()
567
            raise falcon.HTTPError(status=falcon.HTTP_400,
568
                                   title='API.BAD_REQUEST',
569
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENT_PARAMETERS')
570
571
        # check relation with equipments
572
        cursor.execute(" SELECT equipment_id "
573
                       " FROM tbl_equipments_virtual_meters "
574
                       " WHERE virtual_meter_id = %s ", (id_,))
575
        rows_equipments = cursor.fetchall()
576
        if rows_equipments is not None and len(rows_equipments) > 0:
577
            cursor.close()
578
            cnx.close()
579
            raise falcon.HTTPError(status=falcon.HTTP_400,
580
                                   title='API.BAD_REQUEST',
581
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENTS')
582
583
        # check relation with equipment parameters
584
        cursor.execute(" SELECT equipment_id "
585
                       " FROM tbl_equipments_parameters "
586
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s",
587
                       (virtual_meter_uuid, virtual_meter_uuid,))
588
        rows_equipments = cursor.fetchall()
589
        if rows_equipments is not None and len(rows_equipments) > 0:
590
            cursor.close()
591
            cnx.close()
592
            raise falcon.HTTPError(status=falcon.HTTP_400,
593
                                   title='API.BAD_REQUEST',
594
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENT_PARAMETERS')
595
596
        # check relations with tenants
597
        cursor.execute(" SELECT tenant_id "
598
                       " FROM tbl_tenants_virtual_meters "
599
                       " WHERE virtual_meter_id = %s ", (id_,))
600
        rows_tenants = cursor.fetchall()
601
        if rows_tenants is not None and len(rows_tenants) > 0:
602
            cursor.close()
603
            cnx.close()
604
            raise falcon.HTTPError(status=falcon.HTTP_400,
605
                                   title='API.BAD_REQUEST',
606
                                   description='API.THERE_IS_RELATION_WITH_TENANTS')
607
608
        # check relations with stores
609
        cursor.execute(" SELECT store_id "
610
                       " FROM tbl_stores_virtual_meters "
611
                       " WHERE virtual_meter_id = %s ", (id_,))
612
        rows_stores = cursor.fetchall()
613
        if rows_stores is not None and len(rows_stores) > 0:
614
            cursor.close()
615
            cnx.close()
616
            raise falcon.HTTPError(status=falcon.HTTP_400,
617
                                   title='API.BAD_REQUEST',
618
                                   description='API.THERE_IS_RELATION_WITH_STORES')
619
620
        # check relations with shopfloors
621
        cursor.execute(" SELECT shopfloor_id "
622
                       " FROM tbl_shopfloors_virtual_meters "
623
                       " WHERE virtual_meter_id = %s ", (id_,))
624
        rows_shopfloors = cursor.fetchall()
625
        if rows_shopfloors is not None and len(rows_shopfloors) > 0:
626
            cursor.close()
627
            cnx.close()
628
            raise falcon.HTTPError(status=falcon.HTTP_400,
629
                                   title='API.BAD_REQUEST',
630
                                   description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
631
632
        # check relation with energy flow diagram links
633
        cursor.execute(" SELECT id "
634
                       " FROM tbl_energy_flow_diagrams_links "
635
                       " WHERE meter_uuid = %s ", (virtual_meter_uuid,))
636
        rows_links = cursor.fetchall()
637
        if rows_links is not None and len(rows_links) > 0:
638
            cursor.close()
639
            cnx.close()
640
            raise falcon.HTTPError(status=falcon.HTTP_400,
641
                                   title='API.BAD_REQUEST',
642
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_FLOW_DIAGRAM_LINKS')
643
644
        cursor.execute(" SELECT id "
645
                       " FROM tbl_variables "
646
                       " WHERE virtual_meter_id = %s ", (id_,))
647
        row_variables = cursor.fetchall()
648
        if row_variables is not None and len(row_variables) > 0:
649
            # delete variables
650
            cursor.execute(" DELETE FROM tbl_variables WHERE virtual_meter_id = %s ", (id_,))
651
            cnx.commit()
652
653
        cursor.execute(" DELETE FROM tbl_virtual_meters WHERE id = %s ", (id_,))
654
        cnx.commit()
655
656
        cursor.close()
657
        cnx.close()
658
659
        resp.status = falcon.HTTP_204
660
661
    @staticmethod
662
    @user_logger
663
    def on_put(req, resp, id_):
664
        """Handles PUT requests"""
665
        admin_control(req)
666
        try:
667
            raw_json = req.stream.read().decode('utf-8')
668
        except Exception as ex:
669
            print(str(ex))
670
            raise falcon.HTTPError(status=falcon.HTTP_400,
671
                                   title='API.BAD_REQUEST',
672
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
673
674
        if not id_.isdigit() or int(id_) <= 0:
675
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
676
                                   description='API.INVALID_VIRTUAL_METER_ID')
677
678
        new_values = json.loads(raw_json)
679
680
        if 'name' not in new_values['data'].keys() or \
681
                not isinstance(new_values['data']['name'], str) or \
682
                len(str.strip(new_values['data']['name'])) == 0:
683
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
684
                                   description='API.INVALID_VIRTUAL_METER_NAME')
685
        name = str.strip(new_values['data']['name'])
686
687
        if 'energy_category_id' not in new_values['data'].keys() or new_values['data']['energy_category_id'] <= 0:
688
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
689
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
690
        energy_category_id = new_values['data']['energy_category_id']
691
692
        if 'is_counted' not in new_values['data'].keys() or not isinstance(new_values['data']['is_counted'], bool):
693
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
694
                                   description='API.INVALID_IS_COUNTED_VALUE')
695
        is_counted = new_values['data']['is_counted']
696
697
        if 'cost_center_id' not in new_values['data'].keys() or \
698
                not isinstance(new_values['data']['cost_center_id'], int) or \
699
                new_values['data']['cost_center_id'] <= 0:
700
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
701
                                   description='API.INVALID_COST_CENTER_ID')
702
703
        cost_center_id = new_values['data']['cost_center_id']
704
705
        if 'energy_item_id' in new_values['data'].keys() and \
706
                new_values['data']['energy_item_id'] is not None:
707
            if not isinstance(new_values['data']['energy_item_id'], int) or \
708
                    new_values['data']['energy_item_id'] <= 0:
709
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
710
                                       description='API.INVALID_ENERGY_ITEM_ID')
711
            energy_item_id = new_values['data']['energy_item_id']
712
        else:
713
            energy_item_id = None
714
715
        if 'description' in new_values['data'].keys() and \
716
                new_values['data']['description'] is not None and \
717
                len(str(new_values['data']['description'])) > 0:
718
            description = str.strip(new_values['data']['description'])
719
        else:
720
            description = None
721
722
        if 'expression' not in new_values['data'].keys():
723
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
724
                                   description='API.INVALID_EXPRESSION_OBJECT')
725
726
        if 'equation' not in new_values['data']['expression'].keys() \
727
                or len(new_values['data']['expression']['equation']) == 0:
728
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
729
                                   description='API.INVALID_EQUATION_IN_EXPRESSION')
730
        # todo: validate equation with more rules
731
732
        if 'variables' not in new_values['data']['expression'].keys() \
733
                or len(new_values['data']['expression']['variables']) == 0:
734
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
735
                                   description='API.EMPTY_VARIABLES_ARRAY')
736
737
        for variable in new_values['data']['expression']['variables']:
738
            if 'name' not in variable.keys() or \
739
                    len(variable['name']) == 0:
740
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
741
                                       description='API.INVALID_VARIABLE_NAME')
742
            if 'meter_type' not in variable.keys() or \
743
                len(variable['meter_type']) == 0 or \
744
                    variable['meter_type'].lower() not in ['meter', 'offline_meter', 'virtual_meter']:
745
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
746
                                       description='API.INVALID_VARIABLE_METER_TYPE')
747
            if 'meter_id' not in variable.keys() or \
748
                    variable['meter_id'] <= 0:
749
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
750
                                       description='API.INVALID_VARIABLE_METER_ID')
751
752
        cnx = mysql.connector.connect(**config.myems_system_db)
753
        cursor = cnx.cursor()
754
755
        cursor.execute(" SELECT name "
756
                       " FROM tbl_virtual_meters "
757
                       " WHERE id = %s ", (id_,))
758
        if cursor.fetchone() is None:
759
            cursor.close()
760
            cnx.close()
761
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
762
                                   description='API.VIRTUAL_METER_NOT_FOUND')
763
764
        cursor.execute(" SELECT name "
765
                       " FROM tbl_virtual_meters "
766
                       " WHERE name = %s AND id != %s ", (name, id_))
767
        if cursor.fetchone() is not None:
768
            cursor.close()
769
            cnx.close()
770
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
771
                                   description='API.VIRTUAL_METER_NAME_IS_ALREADY_IN_USE')
772
773
        cursor.execute(" SELECT name "
774
                       " FROM tbl_energy_categories "
775
                       " WHERE id = %s ",
776
                       (energy_category_id,))
777
        if cursor.fetchone() is None:
778
            cursor.close()
779
            cnx.close()
780
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
781
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
782
783
        cursor.execute(" SELECT name "
784
                       " FROM tbl_cost_centers "
785
                       " WHERE id = %s ",
786
                       (new_values['data']['cost_center_id'],))
787
        row = cursor.fetchone()
788
        if row is None:
789
            cursor.close()
790
            cnx.close()
791
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
792
                                   description='API.COST_CENTER_NOT_FOUND')
793
794
        if energy_item_id is not None:
795
            cursor.execute(" SELECT name, energy_category_id "
796
                           " FROM tbl_energy_items "
797
                           " WHERE id = %s ",
798
                           (new_values['data']['energy_item_id'],))
799
            row = cursor.fetchone()
800
            if row is None:
801
                cursor.close()
802
                cnx.close()
803
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
804
                                       description='API.ENERGY_ITEM_NOT_FOUND')
805
            else:
806
                if row[1] != energy_category_id:
807
                    cursor.close()
808
                    cnx.close()
809
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
810
                                           description='API.ENERGY_ITEM_IS_NOT_BELONG_TO_ENERGY_CATEGORY')
811
812
        for variable in new_values['data']['expression']['variables']:
813 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...
814
                cursor.execute(" SELECT name "
815
                               " FROM tbl_meters "
816
                               " WHERE id = %s ", (variable['meter_id'],))
817
                if cursor.fetchone() is None:
818
                    cursor.close()
819
                    cnx.close()
820
                    raise falcon.HTTPError(status=falcon.HTTP_404,
821
                                           title='API.NOT_FOUND',
822
                                           description='API.METER_OF_VARIABLE_NOT_FOUND')
823
            elif variable['meter_type'].lower() == 'offline_meter':
824
                cursor.execute(" SELECT name "
825
                               " FROM tbl_offline_meters "
826
                               " WHERE id = %s ", (variable['meter_id'],))
827
                if cursor.fetchone() is None:
828
                    cursor.close()
829
                    cnx.close()
830
                    raise falcon.HTTPError(status=falcon.HTTP_404,
831
                                           title='API.NOT_FOUND',
832
                                           description='API.OFFLINE_METER_OF_VARIABLE_NOT_FOUND')
833
            elif variable['meter_type'].lower() == 'virtual_meter':
834
                cursor.execute(" SELECT name "
835
                               " FROM tbl_virtual_meters "
836
                               " WHERE id = %s ", (variable['meter_id'],))
837
                if cursor.fetchone() is None:
838
                    cursor.close()
839
                    cnx.close()
840
                    raise falcon.HTTPError(status=falcon.HTTP_404,
841
                                           title='API.NOT_FOUND',
842
                                           description='API.VIRTUAL_METER_OF_VARIABLE_NOT_FOUND')
843
        try:
844
            update_row = (" UPDATE tbl_virtual_meters "
845
                          " SET name = %s, equation = %s, energy_category_id = %s, is_counted = %s, "
846
                          "     cost_center_id = %s, energy_item_id = %s, description = %s "
847
                          " WHERE id = %s ")
848
            cursor.execute(update_row, (name,
849
                                        new_values['data']['expression']['equation'].lower(),
850
                                        energy_category_id,
851
                                        is_counted,
852
                                        cost_center_id,
853
                                        energy_item_id,
854
                                        description,
855
                                        id_,))
856
            cnx.commit()
857
        except Exception as ex:
858
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR', description=str(ex))
859
860
        try:
861
            cursor.execute(" SELECT id "
862
                           " FROM tbl_variables "
863
                           " WHERE virtual_meter_id = %s ", (id_,))
864
            row_variables = cursor.fetchall()
865
            if row_variables is not None and len(row_variables) > 0:
866
                # delete variables
867
                cursor.execute(" DELETE FROM tbl_variables WHERE virtual_meter_id = %s ", (id_,))
868
                cnx.commit()
869
        except Exception as ex:
870
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR', description=str(ex))
871
872
        # add variables
873
        for variable in new_values['data']['expression']['variables']:
874
            try:
875
                add_values = (" INSERT INTO tbl_variables (name, virtual_meter_id, meter_type, meter_id) "
876
                              " VALUES (%s, %s, %s, %s) ")
877
                cursor.execute(add_values, (variable['name'].lower(),
878
                                            id_,
879
                                            variable['meter_type'],
880
                                            variable['meter_id'],))
881
                cnx.commit()
882
            except Exception as ex:
883
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR', description=str(ex))
884
885
        cursor.close()
886
        cnx.close()
887
888
        resp.status = falcon.HTTP_200
889
890
891
class VirtualMeterExport:
892
    def __init__(self):
893
        """"Initializes VirtualMeterItem"""
894
        pass
895
896
    @staticmethod
897
    def on_options(req, resp, id_):
898
        _ = req
899
        resp.status = falcon.HTTP_200
900
        _ = id_
901
902 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
903
    def on_get(req, resp, id_):
904
        if 'API-KEY' not in req.headers or \
905
                not isinstance(req.headers['API-KEY'], str) or \
906
                len(str.strip(req.headers['API-KEY'])) == 0:
907
            access_control(req)
908
        else:
909
            api_key_control(req)
910
        if not id_.isdigit() or int(id_) <= 0:
911
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
912
                                   description='API.INVALID_VIRTUAL_METER_ID')
913
914
        cnx = mysql.connector.connect(**config.myems_system_db)
915
        cursor = cnx.cursor()
916
917
        query = (" SELECT id, name, uuid "
918
                 " FROM tbl_energy_categories ")
919
        cursor.execute(query)
920
        rows_energy_categories = cursor.fetchall()
921
922
        energy_category_dict = dict()
923
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
924
            for row in rows_energy_categories:
925
                energy_category_dict[row[0]] = {"id": row[0],
926
                                                "name": row[1],
927
                                                "uuid": row[2]}
928
929
        query = (" SELECT id, name, uuid, energy_category_id "
930
                 " FROM tbl_energy_items ")
931
        cursor.execute(query)
932
        rows_energy_items = cursor.fetchall()
933
934
        energy_item_dict = dict()
935
        if rows_energy_items is not None and len(rows_energy_items) > 0:
936
            for row in rows_energy_items:
937
                energy_item_dict[row[0]] = {"id": row[0],
938
                                            "name": row[1],
939
                                            "uuid": row[2]}
940
941
        query = (" SELECT id, name, uuid "
942
                 " FROM tbl_cost_centers ")
943
        cursor.execute(query)
944
        rows_cost_centers = cursor.fetchall()
945
946
        cost_center_dict = dict()
947
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
948
            for row in rows_cost_centers:
949
                cost_center_dict[row[0]] = {"id": row[0],
950
                                            "name": row[1],
951
                                            "uuid": row[2]}
952
953
        query = (" SELECT id, name, uuid, equation, energy_category_id, is_counted, cost_center_id, "
954
                 "        energy_item_id, description "
955
                 " FROM tbl_virtual_meters "
956
                 " WHERE id = %s ")
957
        cursor.execute(query, (id_,))
958
        row = cursor.fetchone()
959
        if row is None:
960
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
961
                                   description='API.VIRTUAL_METER_NOT_FOUND')
962
        else:
963
            meta_result = {"id": row[0],
964
                           "name": row[1],
965
                           "uuid": row[2],
966
                           "equation": row[3],
967
                           "energy_category": energy_category_dict.get(row[4], None),
968
                           "is_counted": True if row[5] else False,
969
                           "cost_center": cost_center_dict.get(row[6], None),
970
                           "energy_item": energy_item_dict.get(row[7], None),
971
                           "description": row[8],
972
                           "expression": {}}
973
974
        expression = dict()
975
976
        if meta_result["equation"] is not None:
977
            expression = {'equation': meta_result["equation"], 'variables': []}
978
979
            query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
980
                               " FROM tbl_virtual_meters  vm, tbl_variables v "
981
                               " WHERE vm.id = %s AND v.virtual_meter_id = vm.id "
982
                               " ORDER BY v.name ")
983
            cursor.execute(query_variables, (meta_result["id"],))
984
            rows_variables = cursor.fetchall()
985
            if rows_variables is not None:
986
                for row_variable in rows_variables:
987
                    if row_variable[2].lower() == 'meter':
988
                        query_meter = (" SELECT m.name "
989
                                       " FROM tbl_meters m "
990
                                       " WHERE m.id = %s ")
991
                        cursor.execute(query_meter, (row_variable[3],))
992
                        row_meter = cursor.fetchone()
993
                        if row_meter is not None:
994
                            expression['variables'].append({'id': row_variable[0],
995
                                                            'name': row_variable[1],
996
                                                            'meter_type': row_variable[2],
997
                                                            'meter_id': row_variable[3],
998
                                                            'meter_name': row_meter[0]})
999
                    elif row_variable[2].lower() == 'offline_meter':
1000
                        query_meter = (" SELECT m.name "
1001
                                       " FROM tbl_offline_meters m "
1002
                                       " WHERE m.id = %s ")
1003
                        cursor.execute(query_meter, (row_variable[3],))
1004
                        row_meter = cursor.fetchone()
1005
                        if row_meter is not None:
1006
                            expression['variables'].append({'id': row_variable[0],
1007
                                                            'name': row_variable[1],
1008
                                                            'meter_type': row_variable[2],
1009
                                                            'meter_id': row_variable[3],
1010
                                                            'meter_name': row_meter[0]})
1011
                    elif row_variable[2].lower() == 'virtual_meter':
1012
                        query_meter = (" SELECT m.name "
1013
                                       " FROM tbl_virtual_meters m "
1014
                                       " WHERE m.id = %s ")
1015
                        cursor.execute(query_meter, (row_variable[3],))
1016
                        row_meter = cursor.fetchone()
1017
                        if row_meter is not None:
1018
                            expression['variables'].append({'id': row_variable[0],
1019
                                                            'name': row_variable[1],
1020
                                                            'meter_type': row_variable[2],
1021
                                                            'meter_id': row_variable[3],
1022
                                                            'meter_name': row_meter[0]})
1023
1024
        meta_result['expression'] = expression
1025
1026
        cursor.close()
1027
        cnx.close()
1028
        resp.text = json.dumps(meta_result)
1029
1030
1031
class VirtualMeterImport:
1032
    def __init__(self):
1033
        """"Initializes VirtualMeterImport"""
1034
        pass
1035
1036
    @staticmethod
1037
    def on_options(req, resp):
1038
        _ = req
1039
        resp.status = falcon.HTTP_200
1040
1041
    @staticmethod
1042
    @user_logger
1043
    def on_post(req, resp):
1044
        """Handles POST requests"""
1045
        admin_control(req)
1046
        try:
1047
            raw_json = req.stream.read().decode('utf-8')
1048
        except Exception as ex:
1049
            print(str(ex))
1050
            raise falcon.HTTPError(status=falcon.HTTP_400,
1051
                                   title='API.BAD_REQUEST',
1052
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1053
1054
        new_values = json.loads(raw_json)
1055
1056
        if 'name' not in new_values.keys() or \
1057
                not isinstance(new_values['name'], str) or \
1058
                len(str.strip(new_values['name'])) == 0:
1059
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1060
                                   description='API.INVALID_VIRTUAL_METER_NAME')
1061
1062
        name = str.strip(new_values['name'])
1063
1064
        if 'energy_category' not in new_values.keys() or \
1065
            'id' not in new_values['energy_category'].keys() or \
1066
            not isinstance(new_values['energy_category']['id'], int) or \
1067
                new_values['energy_category']['id'] <= 0:
1068
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1069
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
1070
        energy_category_id = new_values['energy_category']['id']
1071
1072
        if 'is_counted' not in new_values.keys() or not isinstance(new_values['is_counted'], bool):
1073
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1074
                                   description='API.INVALID_IS_COUNTED_VALUE')
1075
        is_counted = new_values['is_counted']
1076
1077
        if 'cost_center' not in new_values.keys() or \
1078
            new_values['cost_center'] is None or \
1079
            'id' not in new_values['cost_center'].keys() or \
1080
                not isinstance(new_values['cost_center']['id'], int) or \
1081
                new_values['cost_center']['id'] <= 0:
1082
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1083
                                   description='API.INVALID_COST_CENTER_ID')
1084
1085
        cost_center_id = new_values['cost_center']['id']
1086
1087 View Code Duplication
        if 'energy_item' in new_values.keys() and \
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1088
            new_values['energy_item'] is not None and \
1089
                'id' in new_values['energy_item'].keys() and \
1090
                new_values['energy_item']['id'] is not None:
1091
            if not isinstance(new_values['energy_item']['id'], int) or \
1092
                    new_values['energy_item']['id'] <= 0:
1093
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1094
                                       description='API.INVALID_ENERGY_ITEM_ID')
1095
            energy_item_id = new_values['energy_item']['id']
1096
        else:
1097
            energy_item_id = None
1098
1099
        if 'description' in new_values.keys() and \
1100
                new_values['description'] is not None and \
1101
                len(str(new_values['description'])) > 0:
1102
            description = str.strip(new_values['description'])
1103
        else:
1104
            description = None
1105
1106
        if 'expression' not in new_values.keys():
1107
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1108
                                   description='API.INVALID_EXPRESSION_OBJECT')
1109
1110
        if 'equation' not in new_values['expression'].keys() \
1111
                or len(new_values['expression']['equation']) == 0:
1112
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1113
                                   description='API.INVALID_EQUATION_IN_EXPRESSION')
1114
        # todo: validate equation with more rules
1115
1116
        if 'variables' not in new_values['expression'].keys() \
1117
                or len(new_values['expression']['variables']) == 0:
1118
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1119
                                   description='API.EMPTY_VARIABLES_ARRAY')
1120
1121
        for variable in new_values['expression']['variables']:
1122
            if 'name' not in variable.keys() or \
1123
                    len(variable['name']) == 0:
1124
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1125
                                       description='API.INVALID_VARIABLE_NAME')
1126
            if 'meter_type' not in variable.keys() or \
1127
                    len(variable['meter_type']) == 0 or \
1128
                    variable['meter_type'].lower() not in ['meter', 'offline_meter', 'virtual_meter']:
1129
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1130
                                       description='API.INVALID_VARIABLE_METER_TYPE')
1131
            if 'meter_id' not in variable.keys() or \
1132
                    variable['meter_id'] <= 0:
1133
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1134
                                       description='API.INVALID_VARIABLE_METER_ID')
1135
1136
        cnx = mysql.connector.connect(**config.myems_system_db)
1137
        cursor = cnx.cursor()
1138
1139
        cursor.execute(" SELECT name "
1140
                       " FROM tbl_virtual_meters "
1141
                       " WHERE name = %s ", (name,))
1142
        if cursor.fetchone() is not None:
1143
            cursor.close()
1144
            cnx.close()
1145
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1146
                                   description='API.VIRTUAL_METER_NAME_IS_ALREADY_IN_USE')
1147
1148
        cursor.execute(" SELECT name "
1149
                       " FROM tbl_energy_categories "
1150
                       " WHERE id = %s ",
1151
                       (energy_category_id,))
1152
        if cursor.fetchone() is None:
1153
            cursor.close()
1154
            cnx.close()
1155
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1156
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
1157
1158
        cursor.execute(" SELECT name "
1159
                       " FROM tbl_cost_centers "
1160
                       " WHERE id = %s ",
1161
                       (new_values['cost_center']['id'],))
1162
        row = cursor.fetchone()
1163
        if row is None:
1164
            cursor.close()
1165
            cnx.close()
1166
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1167
                                   description='API.COST_CENTER_NOT_FOUND')
1168
1169 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...
1170
            cursor.execute(" SELECT name, energy_category_id "
1171
                           " FROM tbl_energy_items "
1172
                           " WHERE id = %s ",
1173
                           (new_values['energy_item']['id'],))
1174
            row = cursor.fetchone()
1175
            if row is None:
1176
                cursor.close()
1177
                cnx.close()
1178
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1179
                                       description='API.ENERGY_ITEM_NOT_FOUND')
1180
            else:
1181
                if row[1] != energy_category_id:
1182
                    cursor.close()
1183
                    cnx.close()
1184
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
1185
                                           description='API.ENERGY_ITEM_IS_NOT_BELONG_TO_ENERGY_CATEGORY')
1186
1187
        for variable in new_values['expression']['variables']:
1188 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...
1189
                cursor.execute(" SELECT name "
1190
                               " FROM tbl_meters "
1191
                               " WHERE id = %s ", (variable['meter_id'],))
1192
                if cursor.fetchone() is None:
1193
                    cursor.close()
1194
                    cnx.close()
1195
                    raise falcon.HTTPError(status=falcon.HTTP_404,
1196
                                           title='API.NOT_FOUND',
1197
                                           description='API.METER_OF_VARIABLE_NOT_FOUND')
1198
            elif variable['meter_type'].lower() == 'offline_meter':
1199
                cursor.execute(" SELECT name "
1200
                               " FROM tbl_offline_meters "
1201
                               " WHERE id = %s ", (variable['meter_id'],))
1202
                if cursor.fetchone() is None:
1203
                    cursor.close()
1204
                    cnx.close()
1205
                    raise falcon.HTTPError(status=falcon.HTTP_404,
1206
                                           title='API.NOT_FOUND',
1207
                                           description='API.OFFLINE_METER_OF_VARIABLE_NOT_FOUND')
1208
            elif variable['meter_type'].lower() == 'virtual_meter':
1209
                cursor.execute(" SELECT name "
1210
                               " FROM tbl_virtual_meters "
1211
                               " WHERE id = %s ", (variable['meter_id'],))
1212
                if cursor.fetchone() is None:
1213
                    cursor.close()
1214
                    cnx.close()
1215
                    raise falcon.HTTPError(status=falcon.HTTP_404,
1216
                                           title='API.NOT_FOUND',
1217
                                           description='API.VIRTUAL_METER_OF_VARIABLE_NOT_FOUND')
1218
1219
        add_values = (" INSERT INTO tbl_virtual_meters "
1220
                      "     (name, uuid, equation, energy_category_id, is_counted, "
1221
                      "      cost_center_id, energy_item_id, description) "
1222
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
1223
        cursor.execute(add_values, (name,
1224
                                    str(uuid.uuid4()),
1225
                                    new_values['expression']['equation'].lower(),
1226
                                    energy_category_id,
1227
                                    is_counted,
1228
                                    cost_center_id,
1229
                                    energy_item_id,
1230
                                    description))
1231
        new_id = cursor.lastrowid
1232
        cnx.commit()
1233
1234
        # add variables
1235
        for variable in new_values['expression']['variables']:
1236
            add_values = (" INSERT INTO tbl_variables (name, virtual_meter_id, meter_type, meter_id) "
1237
                          " VALUES (%s, %s, %s, %s) ")
1238
            cursor.execute(add_values, (variable['name'].lower(),
1239
                                        new_id,
1240
                                        variable['meter_type'],
1241
                                        variable['meter_id'],))
1242
            cnx.commit()
1243
1244
        cursor.close()
1245
        cnx.close()
1246
1247
        resp.status = falcon.HTTP_201
1248
        resp.location = '/virtualmeters/' + str(new_id)
1249
1250
1251
class VirtualMeterClone:
1252
    def __init__(self):
1253
        """"Initializes VirtualMeterClone"""
1254
        pass
1255
1256
    @staticmethod
1257
    def on_options(req, resp, id_):
1258
        _ = req
1259
        resp.status = falcon.HTTP_200
1260
        _ = id_
1261
1262
    @staticmethod
1263
    @user_logger
1264
    def on_post(req, resp, id_):
1265
        admin_control(req)
1266
        if not id_.isdigit() or int(id_) <= 0:
1267
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1268
                                   description='API.INVALID_VIRTUAL_METER_ID')
1269
1270
        cnx = mysql.connector.connect(**config.myems_system_db)
1271
        cursor = cnx.cursor()
1272
1273
        query = (" SELECT id, name, uuid "
1274
                 " FROM tbl_energy_categories ")
1275
        cursor.execute(query)
1276
        rows_energy_categories = cursor.fetchall()
1277
1278
        energy_category_dict = dict()
1279
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1280
            for row in rows_energy_categories:
1281
                energy_category_dict[row[0]] = {"id": row[0],
1282
                                                "name": row[1],
1283
                                                "uuid": row[2]}
1284
1285
        query = (" SELECT id, name, uuid, energy_category_id "
1286
                 " FROM tbl_energy_items ")
1287
        cursor.execute(query)
1288
        rows_energy_items = cursor.fetchall()
1289
1290
        energy_item_dict = dict()
1291
        if rows_energy_items is not None and len(rows_energy_items) > 0:
1292
            for row in rows_energy_items:
1293
                energy_item_dict[row[0]] = {"id": row[0],
1294
                                            "name": row[1],
1295
                                            "uuid": row[2]}
1296
1297
        query = (" SELECT id, name, uuid "
1298
                 " FROM tbl_cost_centers ")
1299
        cursor.execute(query)
1300
        rows_cost_centers = cursor.fetchall()
1301
1302
        cost_center_dict = dict()
1303
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
1304
            for row in rows_cost_centers:
1305
                cost_center_dict[row[0]] = {"id": row[0],
1306
                                            "name": row[1],
1307
                                            "uuid": row[2]}
1308
        query = (" SELECT id, name, uuid, equation, energy_category_id, is_counted, cost_center_id, "
1309
                 "        energy_item_id, description "
1310
                 " FROM tbl_virtual_meters "
1311
                 " WHERE id = %s ")
1312
        cursor.execute(query, (id_,))
1313
        row = cursor.fetchone()
1314
        if row is None:
1315
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1316
                                   description='API.VIRTUAL_METER_NOT_FOUND')
1317
        else:
1318
            meta_result = {"id": row[0],
1319
                           "name": row[1],
1320
                           "uuid": row[2],
1321
                           "equation": row[3],
1322
                           "energy_category": energy_category_dict.get(row[4], None),
1323
                           "is_counted": True if row[5] else False,
1324
                           "cost_center": cost_center_dict.get(row[6], None),
1325
                           "energy_item": energy_item_dict.get(row[7], None),
1326
                           "description": row[8],
1327
                           "expression": {}}
1328
1329
        expression = dict()
1330
1331
        if meta_result["equation"] is not None:
1332
            expression = {'equation': meta_result["equation"], 'variables': []}
1333
1334
            query_variables = (" SELECT v.id, v.name, v.meter_type, v.meter_id "
1335
                               " FROM tbl_virtual_meters  vm, tbl_variables v "
1336
                               " WHERE vm.id = %s AND v.virtual_meter_id = vm.id "
1337
                               " ORDER BY v.name ")
1338
            cursor.execute(query_variables, (meta_result["id"],))
1339
            rows_variables = cursor.fetchall()
1340
            if rows_variables is not None:
1341
                for row_variable in rows_variables:
1342
                    if row_variable[2].lower() == 'meter':
1343
                        query_meter = (" SELECT m.name "
1344
                                       " FROM tbl_meters m "
1345
                                       " WHERE m.id = %s ")
1346
                        cursor.execute(query_meter, (row_variable[3],))
1347
                        row_meter = cursor.fetchone()
1348
                        if row_meter is not None:
1349
                            expression['variables'].append({'id': row_variable[0],
1350
                                                            'name': row_variable[1],
1351
                                                            'meter_type': row_variable[2],
1352
                                                            'meter_id': row_variable[3],
1353
                                                            'meter_name': row_meter[0]})
1354
                    elif row_variable[2].lower() == 'offline_meter':
1355
                        query_meter = (" SELECT m.name "
1356
                                       " FROM tbl_offline_meters m "
1357
                                       " WHERE m.id = %s ")
1358
                        cursor.execute(query_meter, (row_variable[3],))
1359
                        row_meter = cursor.fetchone()
1360
                        if row_meter is not None:
1361
                            expression['variables'].append({'id': row_variable[0],
1362
                                                            'name': row_variable[1],
1363
                                                            'meter_type': row_variable[2],
1364
                                                            'meter_id': row_variable[3],
1365
                                                            'meter_name': row_meter[0]})
1366
                    elif row_variable[2].lower() == 'virtual_meter':
1367
                        query_meter = (" SELECT m.name "
1368
                                       " FROM tbl_virtual_meters m "
1369
                                       " WHERE m.id = %s ")
1370
                        cursor.execute(query_meter, (row_variable[3],))
1371
                        row_meter = cursor.fetchone()
1372
                        if row_meter is not None:
1373
                            expression['variables'].append({'id': row_variable[0],
1374
                                                            'name': row_variable[1],
1375
                                                            'meter_type': row_variable[2],
1376
                                                            'meter_id': row_variable[3],
1377
                                                            'meter_name': row_meter[0]})
1378
1379
        meta_result['expression'] = expression
1380
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
1381
        if config.utc_offset[0] == '-':
1382
            timezone_offset = -timezone_offset
1383
        new_name = (str.strip(meta_result['name']) +
1384
                    (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
1385
        energy_item_id = meta_result['energy_item']['id'] if meta_result['energy_item'] is not None else None
1386
        add_values = (" INSERT INTO tbl_virtual_meters "
1387
                      "     (name, uuid, equation, energy_category_id, is_counted, "
1388
                      "      cost_center_id, energy_item_id, description) "
1389
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
1390
        cursor.execute(add_values, (new_name,
1391
                                    str(uuid.uuid4()),
1392
                                    meta_result['expression']['equation'].lower(),
1393
                                    meta_result['energy_category']['id'],
1394
                                    meta_result['is_counted'],
1395
                                    meta_result['cost_center']['id'],
1396
                                    energy_item_id,
1397
                                    meta_result['description']))
1398
        new_id = cursor.lastrowid
1399
        cnx.commit()
1400
1401
        # add variables
1402
        for variable in meta_result['expression']['variables']:
1403
            add_values = (" INSERT INTO tbl_variables (name, virtual_meter_id, meter_type, meter_id) "
1404
                          " VALUES (%s, %s, %s, %s) ")
1405
            cursor.execute(add_values, (variable['name'].lower(),
1406
                                        new_id,
1407
                                        variable['meter_type'],
1408
                                        variable['meter_id'],))
1409
            cnx.commit()
1410
1411
        cursor.close()
1412
        cnx.close()
1413
1414
        resp.status = falcon.HTTP_201
1415
        resp.location = '/virtualmeters/' + str(new_id)
1416
1417