core.virtualmeter.VirtualMeterClone.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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