core.meter.MeterCollection.on_get()   F
last analyzed

Complexity

Conditions 22

Size

Total Lines 99
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 99
rs 0
c 0
b 0
f 0
cc 22
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like core.meter.MeterCollection.on_get() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import 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 MeterCollection:
11
    """
12
    Meter Collection Resource
13
14
    This class handles CRUD operations for meter collection.
15
    It provides endpoints for listing all meters and creating new meters.
16
    Meters are used for measuring energy consumption and production.
17
    """
18
    def __init__(self):
19
        """Initialize MeterCollection"""
20
        pass
21
22
    @staticmethod
23
    def on_options(req, resp):
24
        """Handle OPTIONS requests for CORS preflight"""
25
        _ = req
26
        resp.status = falcon.HTTP_200
27
28
    @staticmethod
29
    def on_get(req, resp):
30
        if 'API-KEY' not in req.headers or \
31
                not isinstance(req.headers['API-KEY'], str) or \
32
                len(str.strip(req.headers['API-KEY'])) == 0:
33
            access_control(req)
34
        else:
35
            api_key_control(req)
36
37
        search_query = req.get_param('q', default=None)
38
        if search_query is not None:
39
            search_query = search_query.strip()
40
        else:
41
            search_query = ''
42
43
        cnx = mysql.connector.connect(**config.myems_system_db)
44
        cursor = cnx.cursor()
45
46
        query = (" SELECT id, name, uuid "
47
                 " FROM tbl_energy_categories ")
48
        cursor.execute(query)
49
        rows_energy_categories = cursor.fetchall()
50
51
        energy_category_dict = dict()
52
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
53
            for row in rows_energy_categories:
54
                energy_category_dict[row[0]] = {"id": row[0],
55
                                                "name": row[1],
56
                                                "uuid": row[2]}
57
58
        query = (" SELECT id, name, uuid "
59
                 " FROM tbl_cost_centers ")
60
        cursor.execute(query)
61
        rows_cost_centers = cursor.fetchall()
62
63
        cost_center_dict = dict()
64
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
65
            for row in rows_cost_centers:
66
                cost_center_dict[row[0]] = {"id": row[0],
67
                                            "name": row[1],
68
                                            "uuid": row[2]}
69
70
        query = (" SELECT id, name, uuid "
71
                 " FROM tbl_energy_items ")
72
        cursor.execute(query)
73
        rows_energy_items = cursor.fetchall()
74
75
        energy_item_dict = dict()
76
        if rows_energy_items is not None and len(rows_energy_items) > 0:
77
            for row in rows_energy_items:
78
                energy_item_dict[row[0]] = {"id": row[0],
79
                                            "name": row[1],
80
                                            "uuid": row[2]}
81
82
        query = (" SELECT id, name, uuid "
83
                 " FROM tbl_meters ")
84
        cursor.execute(query)
85
        rows_master_meters = cursor.fetchall()
86
87
        master_meter_dict = dict()
88
        if rows_master_meters is not None and len(rows_master_meters) > 0:
89
            for row in rows_master_meters:
90
                master_meter_dict[row[0]] = {"id": row[0],
91
                                             "name": row[1],
92
                                             "uuid": row[2]}
93
94
        query_base = (" SELECT id, name, uuid, energy_category_id, "
95
                      "        is_counted, hourly_low_limit, hourly_high_limit, "
96
                      "        cost_center_id, energy_item_id, master_meter_id, description "
97
                      " FROM tbl_meters ")
98
        params = []
99
        if search_query:
100
            query_base += " WHERE name LIKE %s OR description LIKE %s "
101
            params = [f'%{search_query}%', f'%{search_query}%']
102
103
        query_base += " ORDER BY id "
104
        cursor.execute(query_base, params)
105
        rows_meters = cursor.fetchall()
106
107
        result = list()
108
        if rows_meters is not None and len(rows_meters) > 0:
109
            for row in rows_meters:
110
                meta_result = {"id": row[0],
111
                               "name": row[1],
112
                               "uuid": row[2],
113
                               "energy_category": energy_category_dict.get(row[3], None),
114
                               "is_counted": True if row[4] else False,
115
                               "hourly_low_limit": row[5],
116
                               "hourly_high_limit": row[6],
117
                               "cost_center": cost_center_dict.get(row[7], None),
118
                               "energy_item": energy_item_dict.get(row[8], None),
119
                               "master_meter": master_meter_dict.get(row[9], None),
120
                               "description": row[10],
121
                               "qrcode": "meter:" + row[2]}
122
                result.append(meta_result)
123
124
        cursor.close()
125
        cnx.close()
126
        resp.text = json.dumps(result)
127
128
    @staticmethod
129
    @user_logger
130
    def on_post(req, resp):
131
        """Handles POST requests"""
132
        admin_control(req)
133
        try:
134
            raw_json = req.stream.read().decode('utf-8')
135
        except Exception as ex:
136
            print(ex)
137
            raise falcon.HTTPError(status=falcon.HTTP_400,
138
                                   title='API.BAD_REQUEST',
139
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
140
141
        new_values = json.loads(raw_json)
142
143
        if 'name' not in new_values['data'].keys() or \
144
                not isinstance(new_values['data']['name'], str) or \
145
                len(str.strip(new_values['data']['name'])) == 0:
146
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
147
                                   description='API.INVALID_METER_NAME')
148
        name = str.strip(new_values['data']['name'])
149
150
        if 'energy_category_id' not in new_values['data'].keys() or \
151
                not isinstance(new_values['data']['energy_category_id'], int) or \
152
                new_values['data']['energy_category_id'] <= 0:
153
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
154
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
155
        energy_category_id = new_values['data']['energy_category_id']
156
157
        if 'is_counted' not in new_values['data'].keys() or \
158
                not isinstance(new_values['data']['is_counted'], bool):
159
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
160
                                   description='API.INVALID_IS_COUNTED_VALUE')
161
        is_counted = new_values['data']['is_counted']
162
163
        if 'hourly_low_limit' not in new_values['data'].keys() or \
164
                not (isinstance(new_values['data']['hourly_low_limit'], float) or
165
                     isinstance(new_values['data']['hourly_low_limit'], int)):
166
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
167
                                   description='API.INVALID_HOURLY_LOW_LIMIT_VALUE')
168
        hourly_low_limit = new_values['data']['hourly_low_limit']
169
170
        if 'hourly_high_limit' not in new_values['data'].keys() or \
171
                not (isinstance(new_values['data']['hourly_high_limit'], float) or
172
                     isinstance(new_values['data']['hourly_high_limit'], int)):
173
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
174
                                   description='API.INVALID_HOURLY_HIGH_LIMIT_VALUE')
175
        hourly_high_limit = new_values['data']['hourly_high_limit']
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
        cost_center_id = new_values['data']['cost_center_id']
183
184
        if 'energy_item_id' in new_values['data'].keys() and \
185
                new_values['data']['energy_item_id'] is not None:
186
            if not isinstance(new_values['data']['energy_item_id'], int) or \
187
                    new_values['data']['energy_item_id'] <= 0:
188
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
189
                                       description='API.INVALID_ENERGY_ITEM_ID')
190
            energy_item_id = new_values['data']['energy_item_id']
191
        else:
192
            energy_item_id = None
193
194
        if 'master_meter_id' in new_values['data'].keys():
195
            if not isinstance(new_values['data']['master_meter_id'], int) or \
196
                    new_values['data']['master_meter_id'] <= 0:
197
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
198
                                       description='API.INVALID_MASTER_METER_ID')
199
            master_meter_id = new_values['data']['master_meter_id']
200
        else:
201
            master_meter_id = None
202
203
        if 'description' in new_values['data'].keys() and \
204
                new_values['data']['description'] is not None and \
205
                len(str(new_values['data']['description'])) > 0:
206
            description = str.strip(new_values['data']['description'])
207
        else:
208
            description = None
209
210
        cnx = mysql.connector.connect(**config.myems_system_db)
211
        cursor = cnx.cursor()
212
213
        cursor.execute(" SELECT name "
214
                       " FROM tbl_meters "
215
                       " WHERE name = %s ", (name,))
216
        if cursor.fetchone() is not None:
217
            cursor.close()
218
            cnx.close()
219
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
220
                                   description='API.METER_NAME_IS_ALREADY_IN_USE')
221
222
        cursor.execute(" SELECT name "
223
                       " FROM tbl_energy_categories "
224
                       " WHERE id = %s ",
225
                       (new_values['data']['energy_category_id'],))
226
        if cursor.fetchone() is None:
227
            cursor.close()
228
            cnx.close()
229
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
230
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
231
232
        cursor.execute(" SELECT name "
233
                       " FROM tbl_cost_centers "
234
                       " WHERE id = %s ",
235
                       (new_values['data']['cost_center_id'],))
236
        row = cursor.fetchone()
237
        if row is None:
238
            cursor.close()
239
            cnx.close()
240
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
241
                                   description='API.COST_CENTER_NOT_FOUND')
242
243 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...
244
            cursor.execute(" SELECT name, energy_category_id "
245
                           " FROM tbl_energy_items "
246
                           " WHERE id = %s ",
247
                           (new_values['data']['energy_item_id'],))
248
            row = cursor.fetchone()
249
            if row is None:
250
                cursor.close()
251
                cnx.close()
252
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
253
                                       description='API.ENERGY_ITEM_NOT_FOUND')
254
            else:
255
                if row[1] != energy_category_id:
256
                    cursor.close()
257
                    cnx.close()
258
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
259
                                           description='API.ENERGY_ITEM_DOES_NOT_BELONG_TO_ENERGY_CATEGORY')
260
261 View Code Duplication
        if master_meter_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
262
            cursor.execute(" SELECT name, energy_category_id "
263
                           " FROM tbl_meters "
264
                           " WHERE id = %s ",
265
                           (new_values['data']['master_meter_id'],))
266
            row = cursor.fetchone()
267
            if row is None:
268
                cursor.close()
269
                cnx.close()
270
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
271
                                       description='API.MASTER_METER_NOT_FOUND')
272
            else:
273
                if row[1] != energy_category_id:
274
                    cursor.close()
275
                    cnx.close()
276
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
277
                                           description='API.MASTER_METER_DOES_NOT_BELONG_TO_SAME_ENERGY_CATEGORY')
278
279
        add_values = (" INSERT INTO tbl_meters "
280
                      "    (name, uuid, energy_category_id, is_counted, hourly_low_limit, hourly_high_limit,"
281
                      "     cost_center_id, energy_item_id, master_meter_id, description) "
282
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
283
        cursor.execute(add_values, (name,
284
                                    str(uuid.uuid4()),
285
                                    energy_category_id,
286
                                    is_counted,
287
                                    hourly_low_limit,
288
                                    hourly_high_limit,
289
                                    cost_center_id,
290
                                    energy_item_id,
291
                                    master_meter_id,
292
                                    description))
293
        new_id = cursor.lastrowid
294
        cnx.commit()
295
        cursor.close()
296
        cnx.close()
297
298
        resp.status = falcon.HTTP_201
299
        resp.location = '/meters/' + str(new_id)
300
301
302
class MeterItem:
303
    def __init__(self):
304
        pass
305
306
    @staticmethod
307
    def on_options(req, resp, id_):
308
        _ = req
309
        _ = id_
310
        resp.status = falcon.HTTP_200
311
312
    @staticmethod
313
    def on_get(req, resp, id_):
314
        if 'API-KEY' not in req.headers or \
315
                not isinstance(req.headers['API-KEY'], str) or \
316
                len(str.strip(req.headers['API-KEY'])) == 0:
317
            access_control(req)
318
        else:
319
            api_key_control(req)
320
        if not id_.isdigit() or int(id_) <= 0:
321
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
322
                                   description='API.INVALID_METER_ID')
323
324
        cnx = mysql.connector.connect(**config.myems_system_db)
325
        cursor = cnx.cursor()
326
327
        query = (" SELECT id, name, uuid "
328
                 " FROM tbl_energy_categories ")
329
        cursor.execute(query)
330
        rows_energy_categories = cursor.fetchall()
331
332
        energy_category_dict = dict()
333
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
334
            for row in rows_energy_categories:
335
                energy_category_dict[row[0]] = {"id": row[0],
336
                                                "name": row[1],
337
                                                "uuid": row[2]}
338
339
        query = (" SELECT id, name, uuid "
340
                 " FROM tbl_cost_centers ")
341
        cursor.execute(query)
342
        rows_cost_centers = cursor.fetchall()
343
344
        cost_center_dict = dict()
345
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
346
            for row in rows_cost_centers:
347
                cost_center_dict[row[0]] = {"id": row[0],
348
                                            "name": row[1],
349
                                            "uuid": row[2]}
350
351
        query = (" SELECT id, name, uuid "
352
                 " FROM tbl_energy_items ")
353
        cursor.execute(query)
354
        rows_energy_items = cursor.fetchall()
355
356
        energy_item_dict = dict()
357
        if rows_energy_items is not None and len(rows_energy_items) > 0:
358
            for row in rows_energy_items:
359
                energy_item_dict[row[0]] = {"id": row[0],
360
                                            "name": row[1],
361
                                            "uuid": row[2]}
362
363
        query = (" SELECT id, name, uuid "
364
                 " FROM tbl_meters ")
365
        cursor.execute(query)
366
        rows_master_meters = cursor.fetchall()
367
368
        master_meter_dict = dict()
369
        if rows_master_meters is not None and len(rows_master_meters) > 0:
370
            for row in rows_master_meters:
371
                master_meter_dict[row[0]] = {"id": row[0],
372
                                             "name": row[1],
373
                                             "uuid": row[2]}
374
375
        query = (" SELECT id, name, uuid, energy_category_id, "
376
                 "        is_counted, hourly_low_limit, hourly_high_limit, "
377
                 "        cost_center_id, energy_item_id, master_meter_id, description "
378
                 " FROM tbl_meters "
379
                 " WHERE id = %s ")
380
        cursor.execute(query, (id_,))
381
        row = cursor.fetchone()
382
        cursor.close()
383
        cnx.close()
384
385
        if row is None:
386
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
387
                                   description='API.METER_NOT_FOUND')
388
        else:
389
            meta_result = {"id": row[0],
390
                           "name": row[1],
391
                           "uuid": row[2],
392
                           "energy_category": energy_category_dict.get(row[3], None),
393
                           "is_counted": True if row[4] else False,
394
                           "hourly_low_limit": row[5],
395
                           "hourly_high_limit": row[6],
396
                           "cost_center": cost_center_dict.get(row[7], None),
397
                           "energy_item": energy_item_dict.get(row[8], None),
398
                           "master_meter": master_meter_dict.get(row[9], None),
399
                           "description": row[10],
400
                           "qrcode": "meter:"+row[2]}
401
402
        resp.text = json.dumps(meta_result)
403
404
    @staticmethod
405
    @user_logger
406
    def on_delete(req, resp, id_):
407
        admin_control(req)
408
        if not id_.isdigit() or int(id_) <= 0:
409
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
410
                                   description='API.INVALID_METER_ID')
411
412
        cnx = mysql.connector.connect(**config.myems_system_db)
413
        cursor = cnx.cursor()
414
415
        cursor.execute(" SELECT uuid "
416
                       " FROM tbl_meters "
417
                       " WHERE id = %s ", (id_,))
418
        row = cursor.fetchone()
419
        if row is None:
420
            cursor.close()
421
            cnx.close()
422
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
423
                                   description='API.METER_NOT_FOUND')
424
        else:
425
            meter_uuid = row[0]
426
427
        # check relation with tbl_energy_storage_containers_batteries
428
        cursor.execute("SELECT name "
429
                       "FROM tbl_energy_storage_containers_batteries "
430
                       "WHERE charge_meter_id = %s "
431
                       "   OR discharge_meter_id = %s "
432
                       "LIMIT 1",
433
                       (id_, id_))
434
        if cursor.fetchone() is not None:
435
            cursor.close()
436
            cnx.close()
437
            raise falcon.HTTPError(status=falcon.HTTP_400,
438
                                   title='API.BAD_REQUEST',
439
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_STORAGE_CONTAINERS_BATTERIES')
440
441
        # check relation with tbl_energy_storage_containers_grids
442
        cursor.execute("SELECT name "
443
                       "FROM tbl_energy_storage_containers_grids "
444
                       "WHERE buy_meter_id = %s "
445
                       "   OR sell_meter_id = %s "
446
                       "LIMIT 1",
447
                       (id_, id_))
448
        if cursor.fetchone() is not None:
449
            cursor.close()
450
            cnx.close()
451
            raise falcon.HTTPError(status=falcon.HTTP_400,
452
                                   title='API.BAD_REQUEST',
453
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_STORAGE_CONTAINERS_GRIDS')
454
455
        # check relation with tbl_energy_storage_containers_loads
456
        cursor.execute("SELECT name "
457
                       "FROM tbl_energy_storage_containers_loads "
458
                       "WHERE meter_id = %s "
459
                       "LIMIT 1",
460
                       (id_,))
461
        if cursor.fetchone() is not None:
462
            cursor.close()
463
            cnx.close()
464
            raise falcon.HTTPError(status=falcon.HTTP_400,
465
                                   title='API.BAD_REQUEST',
466
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_STORAGE_CONTAINERS_LOADS')
467
468
        # check relation with tbl_meters
469
        cursor.execute("SELECT name "
470
                       "FROM tbl_meters "
471
                       "WHERE master_meter_id = %s "
472
                       "LIMIT 1",
473
                       (id_,))
474
        if cursor.fetchone() is not None:
475
            cursor.close()
476
            cnx.close()
477
            raise falcon.HTTPError(status=falcon.HTTP_400,
478
                                   title='API.BAD_REQUEST',
479
                                   description='API.THERE_IS_RELATION_WITH_METERS')
480
481
        # check relation with tbl_photovoltaic_power_stations_grids
482
        cursor.execute("SELECT name "
483
                       "FROM tbl_photovoltaic_power_stations_grids "
484
                       "WHERE buy_meter_id = %s "
485
                       "   OR sell_meter_id = %s "
486
                       "LIMIT 1",
487
                       (id_, id_))
488
        if cursor.fetchone() is not None:
489
            cursor.close()
490
            cnx.close()
491
            raise falcon.HTTPError(status=falcon.HTTP_400,
492
                                   title='API.BAD_REQUEST',
493
                                   description='API.THERE_IS_RELATION_WITH_PHOTOVOLTAIC_POWER_STATIONS_GRIDS')
494
495
        # check relation with tbl_photovoltaic_power_stations_invertors
496
        cursor.execute("SELECT name "
497
                       "FROM tbl_photovoltaic_power_stations_invertors "
498
                       "WHERE generation_meter_id = %s "
499
                       "LIMIT 1",
500
                       (id_,))
501
        if cursor.fetchone() is not None:
502
            cursor.close()
503
            cnx.close()
504
            raise falcon.HTTPError(status=falcon.HTTP_400,
505
                                   title='API.BAD_REQUEST',
506
                                   description='API.THERE_IS_RELATION_WITH_PHOTOVOLTAIC_POWER_STATIONS_INVERTORS')
507
508
        # check relation with tbl_photovoltaic_power_stations_loads
509
        cursor.execute("SELECT name "
510
                       "FROM tbl_photovoltaic_power_stations_loads "
511
                       "WHERE meter_id = %s "
512
                       "LIMIT 1",
513
                       (id_,))
514
        if cursor.fetchone() is not None:
515
            cursor.close()
516
            cnx.close()
517
            raise falcon.HTTPError(status=falcon.HTTP_400,
518
                                   title='API.BAD_REQUEST',
519
                                   description='API.THERE_IS_RELATION_WITH_PHOTOVOLTAIC_POWER_STATIONS_LOADS')
520
521
        # check if this meter is being used by virtual meters
522
        cursor.execute(" SELECT vm.name "
523
                       " FROM tbl_variables va, tbl_virtual_meters vm "
524
                       " WHERE va.meter_id = %s AND va.meter_type = 'meter' AND va.virtual_meter_id = vm.id ",
525
                       (id_,))
526
        rows_virtual_meters = cursor.fetchall()
527
        if rows_virtual_meters is not None and len(rows_virtual_meters)>0:
528
            cursor.close()
529
            cnx.close()
530
            raise falcon.HTTPError(status=falcon.HTTP_400,
531
                                   title='API.BAD_REQUEST',
532
                                   description='API.THIS_METER_IS_BEING_USED_BY_A_VIRTUAL_METER')
533
534
        # check relation with child meters
535
        cursor.execute(" SELECT id "
536
                       " FROM tbl_meters "
537
                       " WHERE master_meter_id = %s ", (id_,))
538
        rows_child_meters = cursor.fetchall()
539
        if rows_child_meters is not None and len(rows_child_meters) > 0:
540
            cursor.close()
541
            cnx.close()
542
            raise falcon.HTTPError(status=falcon.HTTP_400,
543
                                   title='API.BAD_REQUEST',
544
                                   description='API.THERE_IS_RELATION_WITH_CHILD_METERS')
545
546
        # check relation with spaces
547
        cursor.execute(" SELECT id "
548
                       " FROM tbl_spaces_meters "
549
                       " WHERE meter_id = %s ", (id_,))
550
        rows_spaces = cursor.fetchall()
551
        if rows_spaces is not None and len(rows_spaces) > 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_SPACES')
557
558
        # check relation with tenants
559
        cursor.execute(" SELECT tenant_id "
560
                       " FROM tbl_tenants_meters "
561
                       " WHERE meter_id = %s ", (id_,))
562
        rows_tenants = cursor.fetchall()
563
        if rows_tenants is not None and len(rows_tenants) > 0:
564
            cursor.close()
565
            cnx.close()
566
            raise falcon.HTTPError(status=falcon.HTTP_400,
567
                                   title='API.BAD_REQUEST',
568
                                   description='API.THERE_IS_RELATION_WITH_TENANTS')
569
570
        # check relation with stores
571
        cursor.execute(" SELECT store_id "
572
                       " FROM tbl_stores_meters "
573
                       " WHERE meter_id = %s ", (id_,))
574
        rows_stores = cursor.fetchall()
575
        if rows_stores is not None and len(rows_stores) > 0:
576
            cursor.close()
577
            cnx.close()
578
            raise falcon.HTTPError(status=falcon.HTTP_400,
579
                                   title='API.BAD_REQUEST',
580
                                   description='API.THERE_IS_RELATION_WITH_STORES')
581
582
        # check relation with shopfloors
583
        cursor.execute(" SELECT shopfloor_id "
584
                       " FROM tbl_shopfloors_meters "
585
                       " WHERE meter_id = %s ", (id_,))
586
        rows_shopfloors = cursor.fetchall()
587
        if rows_shopfloors is not None and len(rows_shopfloors) > 0:
588
            cursor.close()
589
            cnx.close()
590
            raise falcon.HTTPError(status=falcon.HTTP_400,
591
                                   title='API.BAD_REQUEST',
592
                                   description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
593
594
        # check relation with combined equipments
595
        cursor.execute(" SELECT combined_equipment_id "
596
                       " FROM tbl_combined_equipments_meters "
597
                       " WHERE meter_id = %s ",
598
                       (id_,))
599
        rows_combined_equipments = cursor.fetchall()
600
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
601
            cursor.close()
602
            cnx.close()
603
            raise falcon.HTTPError(status=falcon.HTTP_400,
604
                                   title='API.BAD_REQUEST',
605
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENTS')
606
607
        # check relation with combined equipment parameters
608
        cursor.execute(" SELECT combined_equipment_id "
609
                       " FROM tbl_combined_equipments_parameters "
610
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s", (meter_uuid, meter_uuid,))
611
        rows_combined_equipments = cursor.fetchall()
612
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
613
            cursor.close()
614
            cnx.close()
615
            raise falcon.HTTPError(status=falcon.HTTP_400,
616
                                   title='API.BAD_REQUEST',
617
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENT_PARAMETERS')
618
619
        # check relation with equipments
620
        cursor.execute(" SELECT equipment_id "
621
                       " FROM tbl_equipments_meters "
622
                       " WHERE meter_id = %s ", (id_,))
623
        rows_equipments = cursor.fetchall()
624
        if rows_equipments is not None and len(rows_equipments) > 0:
625
            cursor.close()
626
            cnx.close()
627
            raise falcon.HTTPError(status=falcon.HTTP_400,
628
                                   title='API.BAD_REQUEST',
629
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENTS')
630
631
        # check relation with equipment parameters
632
        cursor.execute(" SELECT equipment_id "
633
                       " FROM tbl_equipments_parameters "
634
                       " WHERE numerator_meter_uuid = %s OR denominator_meter_uuid = %s", (meter_uuid, meter_uuid, ))
635
        rows_equipments = cursor.fetchall()
636
        if rows_equipments is not None and len(rows_equipments) > 0:
637
            cursor.close()
638
            cnx.close()
639
            raise falcon.HTTPError(status=falcon.HTTP_400,
640
                                   title='API.BAD_REQUEST',
641
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENT_PARAMETERS')
642
643
        # check relation with energy flow diagram links
644
        cursor.execute(" SELECT id "
645
                       " FROM tbl_energy_flow_diagrams_links "
646
                       " WHERE meter_uuid = %s ", (meter_uuid,))
647
        rows_links = cursor.fetchall()
648
        if rows_links is not None and len(rows_links) > 0:
649
            cursor.close()
650
            cnx.close()
651
            raise falcon.HTTPError(status=falcon.HTTP_400,
652
                                   title='API.BAD_REQUEST',
653
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_FLOW_DIAGRAM_LINKS')
654
655
        # check relation with microgrids batteries
656
        cursor.execute("SELECT name "
657
                       "FROM tbl_microgrids_batteries "
658
                       "WHERE charge_meter_id = %s "
659
                       "   OR discharge_meter_id = %s "
660
                       "LIMIT 1",
661
                       (id_, id_))
662
        if cursor.fetchone() is not None:
663
            cursor.close()
664
            cnx.close()
665
            raise falcon.HTTPError(status=falcon.HTTP_400,
666
                                   title='API.BAD_REQUEST',
667
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_BATTERIES')
668
669
        # check relation with microgrids evchargers
670
        cursor.execute("SELECT name "
671
                       "FROM tbl_microgrids_evchargers "
672
                       "WHERE meter_id = %s "
673
                       "LIMIT 1",
674
                       (id_,))
675
        if cursor.fetchone() is not None:
676
            cursor.close()
677
            cnx.close()
678
            raise falcon.HTTPError(status=falcon.HTTP_400,
679
                                   title='API.BAD_REQUEST',
680
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_EVCHARGERS')
681
682
        # check relation with microgrids generators
683
        cursor.execute("SELECT name "
684
                       "FROM tbl_microgrids_generators "
685
                       "WHERE meter_id = %s "
686
                       "LIMIT 1",
687
                       (id_,))
688
        if cursor.fetchone() is not None:
689
            cursor.close()
690
            cnx.close()
691
            raise falcon.HTTPError(status=falcon.HTTP_400,
692
                                   title='API.BAD_REQUEST',
693
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_GENERATORS')
694
695
        # check relation with microgrids grids
696
        cursor.execute("SELECT name "
697
                       "FROM tbl_microgrids_grids "
698
                       "WHERE buy_meter_id = %s "
699
                       "   OR sell_meter_id = %s "
700
                       "LIMIT 1",
701
                       (id_, id_))
702
        if cursor.fetchone() is not None:
703
            cursor.close()
704
            cnx.close()
705
            raise falcon.HTTPError(status=falcon.HTTP_400,
706
                                   title='API.BAD_REQUEST',
707
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_GRIDS')
708
709
        # check relation with microgrids heatpumps
710
        cursor.execute("SELECT name "
711
                       "FROM tbl_microgrids_heatpumps "
712
                       "WHERE electricity_meter_id = %s "
713
                       "   OR heat_meter_id = %s "
714
                       "   OR cooling_meter_id = %s "
715
                       "LIMIT 1",
716
                       (id_, id_, id_))
717
        if cursor.fetchone() is not None:
718
            cursor.close()
719
            cnx.close()
720
            raise falcon.HTTPError(status=falcon.HTTP_400,
721
                                   title='API.BAD_REQUEST',
722
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_HEATPUMPS')
723
724
        # check relation with microgrids loads
725
        cursor.execute("SELECT name "
726
                       "FROM tbl_microgrids_loads "
727
                       "WHERE meter_id = %s "
728
                       "LIMIT 1",
729
                       (id_,))
730
        if cursor.fetchone() is not None:
731
            cursor.close()
732
            cnx.close()
733
            raise falcon.HTTPError(status=falcon.HTTP_400,
734
                                   title='API.BAD_REQUEST',
735
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_LOADS')
736
737
        # check relation with microgrids photovoltaics
738
        cursor.execute("SELECT name "
739
                       "FROM tbl_microgrids_photovoltaics "
740
                       "WHERE meter_id = %s "
741
                       "LIMIT 1",
742
                       (id_,))
743
        if cursor.fetchone() is not None:
744
            cursor.close()
745
            cnx.close()
746
            raise falcon.HTTPError(status=falcon.HTTP_400,
747
                                   title='API.BAD_REQUEST',
748
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS_PHOTOVOLTAICS')
749
750
        # delete relation with commands
751
        cursor.execute(" DELETE FROM tbl_meters_commands WHERE meter_id = %s ", (id_,))
752
753
        # delete relation with points
754
        cursor.execute(" DELETE FROM tbl_meters_points WHERE meter_id = %s ", (id_,))
755
756
        cursor.execute(" DELETE FROM tbl_meters WHERE id = %s ", (id_,))
757
        cnx.commit()
758
759
        cursor.close()
760
        cnx.close()
761
762
        resp.status = falcon.HTTP_204
763
764
    @staticmethod
765
    @user_logger
766
    def on_put(req, resp, id_):
767
        """Handles PUT requests"""
768
        admin_control(req)
769
        try:
770
            raw_json = req.stream.read().decode('utf-8')
771
        except Exception as ex:
772
            print(ex)
773
            raise falcon.HTTPError(status=falcon.HTTP_400,
774
                                   title='API.BAD_REQUEST',
775
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
776
777
        if not id_.isdigit() or int(id_) <= 0:
778
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
779
                                   description='API.INVALID_METER_ID')
780
781
        new_values = json.loads(raw_json)
782
783
        if 'name' not in new_values['data'].keys() or \
784
                not isinstance(new_values['data']['name'], str) or \
785
                len(str.strip(new_values['data']['name'])) == 0:
786
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
787
                                   description='API.INVALID_METER_NAME')
788
        name = str.strip(new_values['data']['name'])
789
790
        if 'energy_category_id' not in new_values['data'].keys() or \
791
                not isinstance(new_values['data']['energy_category_id'], int) or \
792
                new_values['data']['energy_category_id'] <= 0:
793
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
794
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
795
        energy_category_id = new_values['data']['energy_category_id']
796
797
        if 'is_counted' not in new_values['data'].keys() or \
798
                not isinstance(new_values['data']['is_counted'], bool):
799
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
800
                                   description='API.INVALID_IS_COUNTED_VALUE')
801
        is_counted = new_values['data']['is_counted']
802
803
        if 'hourly_low_limit' not in new_values['data'].keys() or \
804
                not (isinstance(new_values['data']['hourly_low_limit'], float) or
805
                     isinstance(new_values['data']['hourly_low_limit'], int)):
806
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
807
                                   description='API.INVALID_HOURLY_LOW_LIMIT_VALUE')
808
        hourly_low_limit = new_values['data']['hourly_low_limit']
809
810
        if 'hourly_high_limit' not in new_values['data'].keys() or \
811
                not (isinstance(new_values['data']['hourly_high_limit'], float) or
812
                     isinstance(new_values['data']['hourly_high_limit'], int)):
813
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
814
                                   description='API.INVALID_HOURLY_HIGH_LIMIT_VALUE')
815
        hourly_high_limit = new_values['data']['hourly_high_limit']
816
817
        if 'cost_center_id' not in new_values['data'].keys() or \
818
                not isinstance(new_values['data']['cost_center_id'], int) or \
819
                new_values['data']['cost_center_id'] <= 0:
820
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
821
                                   description='API.INVALID_COST_CENTER_ID')
822
823
        cost_center_id = new_values['data']['cost_center_id']
824
825
        if 'energy_item_id' in new_values['data'].keys() and \
826
                new_values['data']['energy_item_id'] is not None:
827
            if not isinstance(new_values['data']['energy_item_id'], int) or \
828
                    new_values['data']['energy_item_id'] <= 0:
829
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
830
                                       description='API.INVALID_ENERGY_ITEM_ID')
831
            energy_item_id = new_values['data']['energy_item_id']
832
        else:
833
            energy_item_id = None
834
835
        if 'master_meter_id' in new_values['data'].keys():
836
            if not isinstance(new_values['data']['master_meter_id'], int) or \
837
                    new_values['data']['master_meter_id'] <= 0 or \
838
                    new_values['data']['master_meter_id'] == int(id_):
839
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
840
                                       description='API.INVALID_MASTER_METER_ID')
841
            master_meter_id = new_values['data']['master_meter_id']
842
        else:
843
            master_meter_id = None
844
845
        if 'description' in new_values['data'].keys() and \
846
                new_values['data']['description'] is not None and \
847
                len(str(new_values['data']['description'])) > 0:
848
            description = str.strip(new_values['data']['description'])
849
        else:
850
            description = None
851
852
        cnx = mysql.connector.connect(**config.myems_system_db)
853
        cursor = cnx.cursor()
854
855
        cursor.execute(" SELECT name "
856
                       " FROM tbl_meters "
857
                       " WHERE id = %s ", (id_,))
858
        if cursor.fetchone() is None:
859
            cursor.close()
860
            cnx.close()
861
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
862
                                   description='API.METER_NOT_FOUND')
863
864
        cursor.execute(" SELECT name "
865
                       " FROM tbl_meters "
866
                       " WHERE name = %s AND id != %s ", (name, id_))
867
        if cursor.fetchone() is not None:
868
            cursor.close()
869
            cnx.close()
870
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
871
                                   description='API.METER_NAME_IS_ALREADY_IN_USE')
872
873
        cursor.execute(" SELECT name "
874
                       " FROM tbl_energy_categories "
875
                       " WHERE id = %s ",
876
                       (new_values['data']['energy_category_id'],))
877
        if cursor.fetchone() is None:
878
            cursor.close()
879
            cnx.close()
880
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
881
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
882
883
        cursor.execute(" SELECT name "
884
                       " FROM tbl_cost_centers "
885
                       " WHERE id = %s ",
886
                       (new_values['data']['cost_center_id'],))
887
        row = cursor.fetchone()
888
        if row is None:
889
            cursor.close()
890
            cnx.close()
891
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
892
                                   description='API.COST_CENTER_NOT_FOUND')
893
894 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...
895
            cursor.execute(" SELECT name, energy_category_id "
896
                           " FROM tbl_energy_items "
897
                           " WHERE id = %s ",
898
                           (new_values['data']['energy_item_id'],))
899
            row = cursor.fetchone()
900
            if row is None:
901
                cursor.close()
902
                cnx.close()
903
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
904
                                       description='API.ENERGY_ITEM_NOT_FOUND')
905
            else:
906
                if row[1] != energy_category_id:
907
                    cursor.close()
908
                    cnx.close()
909
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
910
                                           description='API.ENERGY_ITEM_DOES_NOT_BELONG_TO_ENERGY_CATEGORY')
911
912 View Code Duplication
        if master_meter_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
913
            cursor.execute(" SELECT name, energy_category_id "
914
                           " FROM tbl_meters "
915
                           " WHERE id = %s ",
916
                           (new_values['data']['master_meter_id'],))
917
            row = cursor.fetchone()
918
            if row is None:
919
                cursor.close()
920
                cnx.close()
921
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
922
                                       description='API.MASTER_METER_NOT_FOUND')
923
            else:
924
                if row[1] != energy_category_id:
925
                    cursor.close()
926
                    cnx.close()
927
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
928
                                           description='API.MASTER_METER_DOES_NOT_BELONG_TO_SAME_ENERGY_CATEGORY')
929
930
        # todo: check all descendants against new_values['data']['master_meter_id']
931
        if master_meter_id is not None:
932
            cursor.execute(" SELECT name "
933
                           " FROM tbl_meters "
934
                           " WHERE id = %s AND master_meter_id = %s ",
935
                           (new_values['data']['master_meter_id'], id_))
936
            row = cursor.fetchone()
937
            if row is not None:
938
                cursor.close()
939
                cnx.close()
940
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
941
                                       description='API.CANNOT_SET_EXISTING_SUBMETER_AS_MASTER_METER')
942
943
        update_row = (" UPDATE tbl_meters "
944
                      " SET name = %s, energy_category_id = %s, is_counted = %s, "
945
                      "     hourly_low_limit = %s, hourly_high_limit = %s, "
946
                      "     cost_center_id = %s, energy_item_id = %s, master_meter_id = %s, description = %s "
947
                      " WHERE id = %s ")
948
        cursor.execute(update_row, (name,
949
                                    energy_category_id,
950
                                    is_counted,
951
                                    hourly_low_limit,
952
                                    hourly_high_limit,
953
                                    cost_center_id,
954
                                    energy_item_id,
955
                                    master_meter_id,
956
                                    description,
957
                                    id_,))
958
        cnx.commit()
959
960
        cursor.close()
961
        cnx.close()
962
963
        resp.status = falcon.HTTP_200
964
965
966
class MeterSubmeterCollection:
967
    def __init__(self):
968
        pass
969
970
    @staticmethod
971
    def on_options(req, resp, id_):
972
        _ = req
973
        _ = id_
974
        resp.status = falcon.HTTP_200
975
976
    @staticmethod
977
    def on_get(req, resp, id_):
978
        if 'API-KEY' not in req.headers or \
979
                not isinstance(req.headers['API-KEY'], str) or \
980
                len(str.strip(req.headers['API-KEY'])) == 0:
981
            access_control(req)
982
        else:
983
            api_key_control(req)
984
        if not id_.isdigit() or int(id_) <= 0:
985
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
986
                                   description='API.INVALID_METER_ID')
987
988
        cnx = mysql.connector.connect(**config.myems_system_db)
989
        cursor = cnx.cursor()
990
991
        cursor.execute(" SELECT name, uuid "
992
                       " FROM tbl_meters "
993
                       " WHERE id = %s ", (id_,))
994
        row = cursor.fetchone()
995
        if row is None:
996
            cursor.close()
997
            cnx.close()
998
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
999
                                   description='API.METER_NOT_FOUND')
1000
        else:
1001
            master_meter = {"id": id_,
1002
                            "name": row[0],
1003
                            "uuid": row[1]}
1004
1005
        query = (" SELECT id, name, uuid "
1006
                 " FROM tbl_energy_categories ")
1007
        cursor.execute(query)
1008
        rows_energy_categories = cursor.fetchall()
1009
1010
        energy_category_dict = dict()
1011
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1012
            for row in rows_energy_categories:
1013
                energy_category_dict[row[0]] = {"id": row[0],
1014
                                                "name": row[1],
1015
                                                "uuid": row[2]}
1016
1017
        query = (" SELECT id, name, uuid "
1018
                 " FROM tbl_cost_centers ")
1019
        cursor.execute(query)
1020
        rows_cost_centers = cursor.fetchall()
1021
1022
        cost_center_dict = dict()
1023
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
1024
            for row in rows_cost_centers:
1025
                cost_center_dict[row[0]] = {"id": row[0],
1026
                                            "name": row[1],
1027
                                            "uuid": row[2]}
1028
1029
        query = (" SELECT id, name, uuid "
1030
                 " FROM tbl_energy_items ")
1031
        cursor.execute(query)
1032
        rows_energy_items = cursor.fetchall()
1033
1034
        energy_item_dict = dict()
1035
        if rows_energy_items is not None and len(rows_energy_items) > 0:
1036
            for row in rows_energy_items:
1037
                energy_item_dict[row[0]] = {"id": row[0],
1038
                                            "name": row[1],
1039
                                            "uuid": row[2]}
1040
1041
        query = (" SELECT id, name, uuid, energy_category_id, "
1042
                 "        is_counted, hourly_low_limit, hourly_high_limit, "
1043
                 "        cost_center_id, energy_item_id, master_meter_id, description "
1044
                 " FROM tbl_meters "
1045
                 " WHERE master_meter_id = %s "
1046
                 " ORDER BY id ")
1047
        cursor.execute(query, (id_, ))
1048
        rows_meters = cursor.fetchall()
1049
1050
        result = list()
1051 View Code Duplication
        if rows_meters is not None and len(rows_meters) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1052
            for row in rows_meters:
1053
                meta_result = {"id": row[0],
1054
                               "name": row[1],
1055
                               "uuid": row[2],
1056
                               "energy_category": energy_category_dict.get(row[3], None),
1057
                               "is_counted": True if row[4] else False,
1058
                               "hourly_low_limit": row[5],
1059
                               "hourly_high_limit": row[6],
1060
                               "cost_center": cost_center_dict.get(row[7], None),
1061
                               "energy_item": energy_item_dict.get(row[8], None),
1062
                               "master_meter": master_meter,
1063
                               "description": row[10]}
1064
                result.append(meta_result)
1065
1066
        cursor.close()
1067
        cnx.close()
1068
        resp.text = json.dumps(result)
1069
1070
1071
class MeterPointCollection:
1072
    def __init__(self):
1073
        pass
1074
1075
    @staticmethod
1076
    def on_options(req, resp, id_):
1077
        _ = req
1078
        _ = id_
1079
        resp.status = falcon.HTTP_200
1080
1081 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1082
    def on_get(req, resp, id_):
1083
        if 'API-KEY' not in req.headers or \
1084
                not isinstance(req.headers['API-KEY'], str) or \
1085
                len(str.strip(req.headers['API-KEY'])) == 0:
1086
            access_control(req)
1087
        else:
1088
            api_key_control(req)
1089
        if not id_.isdigit() or int(id_) <= 0:
1090
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1091
                                   description='API.INVALID_METER_ID')
1092
1093
        cnx = mysql.connector.connect(**config.myems_system_db)
1094
        cursor = cnx.cursor()
1095
1096
        cursor.execute(" SELECT name "
1097
                       " FROM tbl_meters "
1098
                       " WHERE id = %s ", (id_,))
1099
        if cursor.fetchone() is None:
1100
            cursor.close()
1101
            cnx.close()
1102
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1103
                                   description='API.METER_NOT_FOUND')
1104
1105
        query = (" SELECT p.id, p.name, "
1106
                 "        ds.id, ds.name, ds.uuid, "
1107
                 "        p.address "
1108
                 " FROM tbl_points p, tbl_meters_points mp, tbl_data_sources ds "
1109
                 " WHERE mp.meter_id = %s AND p.id = mp.point_id AND p.data_source_id = ds.id "
1110
                 " ORDER BY p.name ")
1111
        cursor.execute(query, (id_,))
1112
        rows = cursor.fetchall()
1113
1114
        result = list()
1115
        if rows is not None and len(rows) > 0:
1116
            for row in rows:
1117
                meta_result = {"id": row[0], "name": row[1],
1118
                               "data_source": {"id": row[2], "name": row[3], "uuid": row[4]},
1119
                               "address": row[5]}
1120
                result.append(meta_result)
1121
1122
        resp.text = json.dumps(result)
1123
1124
    @staticmethod
1125
    @user_logger
1126
    def on_post(req, resp, id_):
1127
        """Handles POST requests"""
1128
        admin_control(req)
1129
        try:
1130
            raw_json = req.stream.read().decode('utf-8')
1131
        except Exception as ex:
1132
            print(ex)
1133
            raise falcon.HTTPError(status=falcon.HTTP_400,
1134
                                   title='API.BAD_REQUEST',
1135
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1136
1137
        if not id_.isdigit() or int(id_) <= 0:
1138
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1139
                                   description='API.INVALID_METER_ID')
1140
1141
        new_values = json.loads(raw_json)
1142
        cnx = mysql.connector.connect(**config.myems_system_db)
1143
        cursor = cnx.cursor()
1144
1145
        cursor.execute(" SELECT name "
1146
                       " from tbl_meters "
1147
                       " WHERE id = %s ", (id_,))
1148
        if cursor.fetchone() is None:
1149
            cursor.close()
1150
            cnx.close()
1151
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1152
                                   description='API.METER_NOT_FOUND')
1153
        cursor.execute(" SELECT name, object_type "
1154
                       " FROM tbl_points "
1155
                       " WHERE id = %s ", (new_values['data']['point_id'],))
1156
        row = cursor.fetchone()
1157 View Code Duplication
        if row is None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1158
            cursor.close()
1159
            cnx.close()
1160
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1161
                                   description='API.POINT_NOT_FOUND')
1162
        elif row[1] == 'ENERGY_VALUE':
1163
            query = (" SELECT p.id "
1164
                     " FROM tbl_meters_points mp, tbl_points p "
1165
                     " WHERE mp.meter_id = %s AND mp.point_id = p.id AND p.object_type = 'ENERGY_VALUE' ")
1166
            cursor.execute(query, (id_,))
1167
            rows_points = cursor.fetchall()
1168
            if rows_points is not None and len(rows_points) > 0:
1169
                cursor.close()
1170
                cnx.close()
1171
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1172
                                       description='API.METER_CANNOT_HAVE_MORE_THAN_ONE_ENERGY_VALUE_POINTS')
1173
1174
        query = (" SELECT id "
1175
                 " FROM tbl_meters_points "
1176
                 " WHERE meter_id = %s AND point_id = %s")
1177
        cursor.execute(query, (id_, new_values['data']['point_id'],))
1178
        if cursor.fetchone() is not None:
1179
            cursor.close()
1180
            cnx.close()
1181
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1182
                                   description='API.METER_POINT_RELATION_EXISTS')
1183
1184
        add_row = (" INSERT INTO tbl_meters_points (meter_id, point_id) "
1185
                   " VALUES (%s, %s) ")
1186
        cursor.execute(add_row, (id_, new_values['data']['point_id'],))
1187
        cnx.commit()
1188
        cursor.close()
1189
        cnx.close()
1190
1191
        resp.status = falcon.HTTP_201
1192
        resp.location = '/meters/' + str(id_) + '/points/' + str(new_values['data']['point_id'])
1193
1194
1195
class MeterPointItem:
1196
    def __init__(self):
1197
        pass
1198
1199
    @staticmethod
1200
    def on_options(req, resp, id_, pid):
1201
        _ = req
1202
        _ = id_
1203
        _ = pid
1204
        resp.status = falcon.HTTP_200
1205
1206
    @staticmethod
1207
    @user_logger
1208
    def on_delete(req, resp, id_, pid):
1209
        """Handles DELETE requests"""
1210
        admin_control(req)
1211
        if not id_.isdigit() or int(id_) <= 0:
1212
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1213
                                   description='API.INVALID_METER_ID')
1214
1215
        if not pid.isdigit() or int(pid) <= 0:
1216
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1217
                                   description='API.INVALID_POINT_ID')
1218
1219
        cnx = mysql.connector.connect(**config.myems_system_db)
1220
        cursor = cnx.cursor()
1221
1222
        cursor.execute(" SELECT name "
1223
                       " FROM tbl_meters "
1224
                       " WHERE id = %s ", (id_,))
1225
        if cursor.fetchone() is None:
1226
            cursor.close()
1227
            cnx.close()
1228
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1229
                                   description='API.METER_NOT_FOUND')
1230
1231
        cursor.execute(" SELECT name "
1232
                       " FROM tbl_points "
1233
                       " WHERE id = %s ", (pid,))
1234
        if cursor.fetchone() is None:
1235
            cursor.close()
1236
            cnx.close()
1237
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1238
                                   description='API.POINT_NOT_FOUND')
1239
1240
        cursor.execute(" SELECT id "
1241
                       " FROM tbl_meters_points "
1242
                       " WHERE meter_id = %s AND point_id = %s ", (id_, pid))
1243
        if cursor.fetchone() is None:
1244
            cursor.close()
1245
            cnx.close()
1246
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1247
                                   description='API.METER_POINT_RELATION_NOT_FOUND')
1248
1249
        cursor.execute(" DELETE FROM tbl_meters_points WHERE meter_id = %s AND point_id = %s ", (id_, pid))
1250
        cnx.commit()
1251
1252
        cursor.close()
1253
        cnx.close()
1254
1255
        resp.status = falcon.HTTP_204
1256
1257
1258 View Code Duplication
class MeterCommandCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1259
    def __init__(self):
1260
        pass
1261
1262
    @staticmethod
1263
    def on_options(req, resp, id_):
1264
        _ = req
1265
        _ = id_
1266
        resp.status = falcon.HTTP_200
1267
1268
    @staticmethod
1269
    def on_get(req, resp, id_):
1270
        if 'API-KEY' not in req.headers or \
1271
                not isinstance(req.headers['API-KEY'], str) or \
1272
                len(str.strip(req.headers['API-KEY'])) == 0:
1273
            access_control(req)
1274
        else:
1275
            api_key_control(req)
1276
        if not id_.isdigit() or int(id_) <= 0:
1277
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1278
                                   description='API.INVALID_METER_ID')
1279
1280
        cnx = mysql.connector.connect(**config.myems_system_db)
1281
        cursor = cnx.cursor()
1282
1283
        cursor.execute(" SELECT name "
1284
                       " FROM tbl_meters "
1285
                       " WHERE id = %s ", (id_,))
1286
        if cursor.fetchone() is None:
1287
            cursor.close()
1288
            cnx.close()
1289
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1290
                                   description='API.METER_NOT_FOUND')
1291
1292
        query = (" SELECT c.id, c.name, c.uuid "
1293
                 " FROM tbl_meters m, tbl_meters_commands mc, tbl_commands c "
1294
                 " WHERE mc.meter_id = m.id AND c.id = mc.command_id AND m.id = %s "
1295
                 " ORDER BY c.id ")
1296
        cursor.execute(query, (id_,))
1297
        rows = cursor.fetchall()
1298
1299
        result = list()
1300
        if rows is not None and len(rows) > 0:
1301
            for row in rows:
1302
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
1303
                result.append(meta_result)
1304
1305
        resp.text = json.dumps(result)
1306
1307
    @staticmethod
1308
    @user_logger
1309
    def on_post(req, resp, id_):
1310
        """Handles POST requests"""
1311
        admin_control(req)
1312
        try:
1313
            raw_json = req.stream.read().decode('utf-8')
1314
        except Exception as ex:
1315
            print(ex)
1316
            raise falcon.HTTPError(status=falcon.HTTP_400,
1317
                                   title='API.BAD_REQUEST',
1318
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1319
1320
        if not id_.isdigit() or int(id_) <= 0:
1321
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1322
                                   description='API.INVALID_METER_ID')
1323
1324
        new_values = json.loads(raw_json)
1325
1326
        if 'command_id' not in new_values['data'].keys() or \
1327
                not isinstance(new_values['data']['command_id'], int) or \
1328
                new_values['data']['command_id'] <= 0:
1329
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1330
                                   description='API.INVALID_COMMAND_ID')
1331
        command_id = new_values['data']['command_id']
1332
1333
        cnx = mysql.connector.connect(**config.myems_system_db)
1334
        cursor = cnx.cursor()
1335
1336
        cursor.execute(" SELECT name "
1337
                       " from tbl_meters "
1338
                       " WHERE id = %s ", (id_,))
1339
        if cursor.fetchone() is None:
1340
            cursor.close()
1341
            cnx.close()
1342
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1343
                                   description='API.METER_NOT_FOUND')
1344
1345
        cursor.execute(" SELECT name "
1346
                       " FROM tbl_commands "
1347
                       " WHERE id = %s ", (command_id,))
1348
        if cursor.fetchone() is None:
1349
            cursor.close()
1350
            cnx.close()
1351
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1352
                                   description='API.COMMAND_NOT_FOUND')
1353
1354
        query = (" SELECT id "
1355
                 " FROM tbl_meters_commands "
1356
                 " WHERE meter_id = %s AND command_id = %s")
1357
        cursor.execute(query, (id_, command_id,))
1358
        if cursor.fetchone() is not None:
1359
            cursor.close()
1360
            cnx.close()
1361
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1362
                                   description='API.METER_COMMAND_RELATION_EXISTS')
1363
1364
        add_row = (" INSERT INTO tbl_meters_commands (meter_id, command_id) "
1365
                   " VALUES (%s, %s) ")
1366
        cursor.execute(add_row, (id_, command_id,))
1367
        cnx.commit()
1368
        cursor.close()
1369
        cnx.close()
1370
1371
        resp.status = falcon.HTTP_201
1372
        resp.location = '/meters/' + str(id_) + '/commands/' + str(command_id)
1373
1374
1375
class MeterCommandItem:
1376
    def __init__(self):
1377
        pass
1378
1379
    @staticmethod
1380
    def on_options(req, resp, id_, cid):
1381
        _ = req
1382
        _ = id_
1383
        _ = cid
1384
        resp.status = falcon.HTTP_200
1385
1386
    @staticmethod
1387
    @user_logger
1388
    def on_delete(req, resp, id_, cid):
1389
        admin_control(req)
1390
        if not id_.isdigit() or int(id_) <= 0:
1391
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1392
                                   description='API.INVALID_METER_ID')
1393
1394
        if not cid.isdigit() or int(cid) <= 0:
1395
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1396
                                   description='API.INVALID_COMMAND_ID')
1397
1398
        cnx = mysql.connector.connect(**config.myems_system_db)
1399
        cursor = cnx.cursor()
1400
1401
        cursor.execute(" SELECT name "
1402
                       " FROM tbl_meters "
1403
                       " WHERE id = %s ", (id_,))
1404
        if cursor.fetchone() is None:
1405
            cursor.close()
1406
            cnx.close()
1407
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1408
                                   description='API.METER_NOT_FOUND')
1409
1410
        cursor.execute(" SELECT name "
1411
                       " FROM tbl_commands "
1412
                       " WHERE id = %s ", (cid,))
1413
        if cursor.fetchone() is None:
1414
            cursor.close()
1415
            cnx.close()
1416
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1417
                                   description='API.COMMAND_NOT_FOUND')
1418
1419
        cursor.execute(" SELECT id "
1420
                       " FROM tbl_meters_commands "
1421
                       " WHERE meter_id = %s AND command_id = %s ", (id_, cid))
1422
        if cursor.fetchone() is None:
1423
            cursor.close()
1424
            cnx.close()
1425
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1426
                                   description='API.METER_COMMAND_RELATION_NOT_FOUND')
1427
1428
        cursor.execute(" DELETE FROM tbl_meters_commands WHERE meter_id = %s AND command_id = %s ", (id_, cid))
1429
        cnx.commit()
1430
1431
        cursor.close()
1432
        cnx.close()
1433
1434
        resp.status = falcon.HTTP_204
1435
1436
1437
class MeterExport:
1438
    def __init__(self):
1439
        pass
1440
1441
    @staticmethod
1442
    def on_options(req, resp, id_):
1443
        _ = req
1444
        _ = id_
1445
        resp.status = falcon.HTTP_200
1446
1447
    @staticmethod
1448
    def on_get(req, resp, id_):
1449
        if 'API-KEY' not in req.headers or \
1450
                not isinstance(req.headers['API-KEY'], str) or \
1451
                len(str.strip(req.headers['API-KEY'])) == 0:
1452
            access_control(req)
1453
        else:
1454
            api_key_control(req)
1455
        if not id_.isdigit() or int(id_) <= 0:
1456
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1457
                                   description='API.INVALID_METER_ID')
1458
1459
        cnx = mysql.connector.connect(**config.myems_system_db)
1460
        cursor = cnx.cursor()
1461
1462
        query = (" SELECT id, name, uuid "
1463
                 " FROM tbl_energy_categories ")
1464
        cursor.execute(query)
1465
        rows_energy_categories = cursor.fetchall()
1466
1467
        energy_category_dict = dict()
1468
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1469
            for row in rows_energy_categories:
1470
                energy_category_dict[row[0]] = {"id": row[0],
1471
                                                "name": row[1],
1472
                                                "uuid": row[2]}
1473
1474
        query = (" SELECT id, name, uuid "
1475
                 " FROM tbl_cost_centers ")
1476
        cursor.execute(query)
1477
        rows_cost_centers = cursor.fetchall()
1478
1479
        cost_center_dict = dict()
1480
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
1481
            for row in rows_cost_centers:
1482
                cost_center_dict[row[0]] = {"id": row[0],
1483
                                            "name": row[1],
1484
                                            "uuid": row[2]}
1485
1486
        query = (" SELECT id, name, uuid "
1487
                 " FROM tbl_energy_items ")
1488
        cursor.execute(query)
1489
        rows_energy_items = cursor.fetchall()
1490
1491
        energy_item_dict = dict()
1492
        if rows_energy_items is not None and len(rows_energy_items) > 0:
1493
            for row in rows_energy_items:
1494
                energy_item_dict[row[0]] = {"id": row[0],
1495
                                            "name": row[1],
1496
                                            "uuid": row[2]}
1497
1498
        query = (" SELECT id, name, uuid "
1499
                 " FROM tbl_meters ")
1500
        cursor.execute(query)
1501
        rows_master_meters = cursor.fetchall()
1502
1503
        master_meter_dict = dict()
1504
        if rows_master_meters is not None and len(rows_master_meters) > 0:
1505
            for row in rows_master_meters:
1506
                master_meter_dict[row[0]] = {"id": row[0],
1507
                                             "name": row[1],
1508
                                             "uuid": row[2]}
1509
1510
        query = (" SELECT id, name, uuid, energy_category_id, "
1511
                 "        is_counted, hourly_low_limit, hourly_high_limit, "
1512
                 "        cost_center_id, energy_item_id, master_meter_id, description "
1513
                 " FROM tbl_meters "
1514
                 " WHERE id = %s ")
1515
        cursor.execute(query, (id_,))
1516
        row = cursor.fetchone()
1517
1518
        if row is None:
1519
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1520
                                   description='API.METER_NOT_FOUND')
1521
        else:
1522
            meta_result = {"name": row[1],
1523
                           "uuid": row[2],
1524
                           "energy_category": energy_category_dict.get(row[3], None),
1525
                           "is_counted": True if row[4] else False,
1526
                           "hourly_low_limit": row[5],
1527
                           "hourly_high_limit": row[6],
1528
                           "cost_center": cost_center_dict.get(row[7], None),
1529
                           "energy_item": energy_item_dict.get(row[8], None),
1530
                           "master_meter": master_meter_dict.get(row[9], None),
1531
                           "description": row[10],
1532
                           "points": None}
1533
            query = (" SELECT p.id, p.name, "
1534
                     "        ds.id, ds.name, ds.uuid, "
1535
                     "        p.address "
1536
                     " FROM tbl_points p, tbl_meters_points mp, tbl_data_sources ds "
1537
                     " WHERE mp.meter_id = %s AND p.id = mp.point_id AND p.data_source_id = ds.id "
1538
                     " ORDER BY p.name ")
1539
            cursor.execute(query, (id_,))
1540
            rows = cursor.fetchall()
1541
1542
            result = list()
1543
            if rows is not None and len(rows) > 0:
1544
                for row in rows:
1545
                    point_result = {"id": row[0], "name": row[1]}
1546
                    result.append(point_result)
1547
                meta_result['points'] = result
1548
            cursor.close()
1549
            cnx.close()
1550
1551
        resp.text = json.dumps(meta_result)
1552
1553
1554
class MeterImport:
1555
    def __init__(self):
1556
        pass
1557
1558
    @staticmethod
1559
    def on_options(req, resp):
1560
        _ = req
1561
        resp.status = falcon.HTTP_200
1562
1563
    @staticmethod
1564
    @user_logger
1565
    def on_post(req, resp):
1566
        """Handles POST requests"""
1567
        admin_control(req)
1568
        try:
1569
            raw_json = req.stream.read().decode('utf-8')
1570
        except Exception as ex:
1571
            print(ex)
1572
            raise falcon.HTTPError(status=falcon.HTTP_400,
1573
                                   title='API.BAD_REQUEST',
1574
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1575
1576
        new_values = json.loads(raw_json)
1577
1578
        if 'name' not in new_values.keys() or \
1579
                not isinstance(new_values['name'], str) or \
1580
                len(str.strip(new_values['name'])) == 0:
1581
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1582
                                   description='API.INVALID_METER_NAME')
1583
        name = str.strip(new_values['name'])
1584
1585
        if 'energy_category' not in new_values.keys() or \
1586
            'id' not in new_values['energy_category'].keys() or \
1587
            not isinstance(new_values['energy_category']['id'], int) or \
1588
                new_values['energy_category']['id'] <= 0:
1589
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1590
                                   description='API.INVALID_ENERGY_CATEGORY_ID')
1591
        energy_category_id = new_values['energy_category']['id']
1592
1593
        if 'is_counted' not in new_values.keys() or \
1594
                not isinstance(new_values['is_counted'], bool):
1595
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1596
                                   description='API.INVALID_IS_COUNTED_VALUE')
1597
        is_counted = new_values['is_counted']
1598
1599
        if 'hourly_low_limit' not in new_values.keys() or \
1600
                not (isinstance(new_values['hourly_low_limit'], float) or
1601
                     isinstance(new_values['hourly_low_limit'], int)):
1602
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1603
                                   description='API.INVALID_HOURLY_LOW_LIMIT_VALUE')
1604
        hourly_low_limit = new_values['hourly_low_limit']
1605
1606
        if 'hourly_high_limit' not in new_values.keys() or \
1607
                not (isinstance(new_values['hourly_high_limit'], float) or
1608
                     isinstance(new_values['hourly_high_limit'], int)):
1609
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1610
                                   description='API.INVALID_HOURLY_HIGH_LIMIT_VALUE')
1611
        hourly_high_limit = new_values['hourly_high_limit']
1612
1613
        if 'cost_center' not in new_values.keys() or \
1614
            new_values['cost_center'] is None or \
1615
            'id' not in new_values['cost_center'].keys() or \
1616
                not isinstance(new_values['cost_center']['id'], int) or \
1617
                new_values['cost_center']['id'] <= 0:
1618
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1619
                                   description='API.INVALID_COST_CENTER_ID')
1620
        cost_center_id = new_values['cost_center']['id']
1621
1622 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...
1623
            new_values['energy_item'] is not None and \
1624
                'id' in new_values['energy_item'].keys() and \
1625
                new_values['energy_item']['id'] is not None:
1626
            if not isinstance(new_values['energy_item']['id'], int) or \
1627
                    new_values['energy_item']['id'] <= 0:
1628
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1629
                                       description='API.INVALID_ENERGY_ITEM_ID')
1630
            energy_item_id = new_values['energy_item']['id']
1631
        else:
1632
            energy_item_id = None
1633
1634
        if 'master_meter' in new_values.keys() and \
1635
            new_values['master_meter'] is not None and \
1636
                'id' in new_values['master_meter'].keys():
1637
            if not isinstance(new_values['master_meter']['id'], int) or \
1638
                    new_values['master_meter']['id'] <= 0:
1639
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1640
                                       description='API.INVALID_MASTER_METER_ID')
1641
            master_meter_id = new_values['master_meter']['id']
1642
        else:
1643
            master_meter_id = None
1644
1645
        if 'description' in new_values.keys() and \
1646
                new_values['description'] is not None and \
1647
                len(str(new_values['description'])) > 0:
1648
            description = str.strip(new_values['description'])
1649
        else:
1650
            description = None
1651
1652
        cnx = mysql.connector.connect(**config.myems_system_db)
1653
        cursor = cnx.cursor()
1654
1655
        cursor.execute(" SELECT name "
1656
                       " FROM tbl_meters "
1657
                       " WHERE name = %s ", (name,))
1658
        if cursor.fetchone() is not None:
1659
            cursor.close()
1660
            cnx.close()
1661
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1662
                                   description='API.METER_NAME_IS_ALREADY_IN_USE')
1663
1664
        cursor.execute(" SELECT name "
1665
                       " FROM tbl_energy_categories "
1666
                       " WHERE id = %s ",
1667
                       (energy_category_id,))
1668
        if cursor.fetchone() is None:
1669
            cursor.close()
1670
            cnx.close()
1671
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1672
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
1673
1674
        cursor.execute(" SELECT name "
1675
                       " FROM tbl_cost_centers "
1676
                       " WHERE id = %s ",
1677
                       (new_values['cost_center']['id'],))
1678
        row = cursor.fetchone()
1679
        if row is None:
1680
            cursor.close()
1681
            cnx.close()
1682
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1683
                                   description='API.COST_CENTER_NOT_FOUND')
1684
1685
        if energy_item_id is not None:
1686
            cursor.execute(" SELECT name, energy_category_id "
1687
                           " FROM tbl_energy_items "
1688
                           " WHERE id = %s ",
1689
                           (energy_item_id,))
1690
            row = cursor.fetchone()
1691
            if row is None:
1692
                cursor.close()
1693
                cnx.close()
1694
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1695
                                       description='API.ENERGY_ITEM_NOT_FOUND')
1696
            else:
1697
                if row[1] != energy_category_id:
1698
                    cursor.close()
1699
                    cnx.close()
1700
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
1701
                                           description='API.ENERGY_ITEM_DOES_NOT_BELONG_TO_ENERGY_CATEGORY')
1702
1703 View Code Duplication
        if master_meter_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1704
            cursor.execute(" SELECT name, energy_category_id "
1705
                           " FROM tbl_meters "
1706
                           " WHERE id = %s ",
1707
                           (master_meter_id,))
1708
            row = cursor.fetchone()
1709
            if row is None:
1710
                cursor.close()
1711
                cnx.close()
1712
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1713
                                       description='API.MASTER_METER_NOT_FOUND')
1714
            else:
1715
                if row[1] != energy_category_id:
1716
                    cursor.close()
1717
                    cnx.close()
1718
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.BAD_REQUEST',
1719
                                           description='API.MASTER_METER_DOES_NOT_BELONG_TO_SAME_ENERGY_CATEGORY')
1720
1721
        add_values = (" INSERT INTO tbl_meters "
1722
                      "    (name, uuid, energy_category_id, is_counted, hourly_low_limit, hourly_high_limit,"
1723
                      "     cost_center_id, energy_item_id, master_meter_id, description) "
1724
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
1725
        cursor.execute(add_values, (name,
1726
                                    str(uuid.uuid4()),
1727
                                    energy_category_id,
1728
                                    is_counted,
1729
                                    hourly_low_limit,
1730
                                    hourly_high_limit,
1731
                                    cost_center_id,
1732
                                    energy_item_id,
1733
                                    master_meter_id,
1734
                                    description))
1735
        new_id = cursor.lastrowid
1736
        if 'points' in new_values.keys() and \
1737
                new_values['points'] is not None and \
1738
                len(new_values['points']) > 0:
1739
            for point in new_values['points']:
1740
                if 'id' in point and isinstance(point['id'], int):
1741
                    cursor.execute(" SELECT name, object_type "
1742
                                   " FROM tbl_points "
1743
                                   " WHERE id = %s ", (point['id'],))
1744
                    row = cursor.fetchone()
1745 View Code Duplication
                    if row is None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1746
                        cursor.close()
1747
                        cnx.close()
1748
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1749
                                               description='API.POINT_NOT_FOUND')
1750
                    elif row[1] == 'ENERGY_VALUE':
1751
                        query = (" SELECT p.id "
1752
                                 " FROM tbl_meters_points mp, tbl_points p "
1753
                                 " WHERE mp.meter_id = %s AND mp.point_id = p.id AND p.object_type = 'ENERGY_VALUE' ")
1754
                        cursor.execute(query, (new_id,))
1755
                        rows_points = cursor.fetchall()
1756
                        if rows_points is not None and len(rows_points) > 0:
1757
                            cursor.close()
1758
                            cnx.close()
1759
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1760
                                                   description=
1761
                                                   'API.METER_CANNOT_HAVE_MORE_THAN_ONE_ENERGY_VALUE_POINTS')
1762
1763
                    query = (" SELECT id "
1764
                             " FROM tbl_meters_points "
1765
                             " WHERE meter_id = %s AND point_id = %s")
1766
                    cursor.execute(query, (new_id, point['id'],))
1767
                    if cursor.fetchone() is not None:
1768
                        cursor.close()
1769
                        cnx.close()
1770
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1771
                                               description='API.METER_POINT_RELATION_EXISTS')
1772
1773
                    add_row = (" INSERT INTO tbl_meters_points (meter_id, point_id) "
1774
                               " VALUES (%s, %s) ")
1775
                    cursor.execute(add_row, (new_id, point['id'],))
1776
                else:
1777
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1778
                                           description='API.INVALID_POINT_ID')
1779
        cnx.commit()
1780
        cursor.close()
1781
        cnx.close()
1782
1783
        resp.status = falcon.HTTP_201
1784
        resp.location = '/meters/' + str(new_id)
1785
1786
1787
class MeterClone:
1788
    def __init__(self):
1789
        pass
1790
1791
    @staticmethod
1792
    def on_options(req, resp, id_):
1793
        _ = req
1794
        _ = id_
1795
        resp.status = falcon.HTTP_200
1796
1797
    @staticmethod
1798
    @user_logger
1799
    def on_post(req, resp, id_):
1800
        """Handles POST requests"""
1801
        admin_control(req)
1802
        if not id_.isdigit() or int(id_) <= 0:
1803
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1804
                                   description='API.INVALID_METER_ID')
1805
1806
        cnx = mysql.connector.connect(**config.myems_system_db)
1807
        cursor = cnx.cursor()
1808
1809
        query = (" SELECT id, name, uuid "
1810
                 " FROM tbl_meters ")
1811
        cursor.execute(query)
1812
        rows_master_meters = cursor.fetchall()
1813
1814
        master_meter_dict = dict()
1815
        if rows_master_meters is not None and len(rows_master_meters) > 0:
1816
            for row in rows_master_meters:
1817
                master_meter_dict[row[0]] = {"id": row[0],
1818
                                             "name": row[1],
1819
                                             "uuid": row[2]}
1820
1821
        query = (" SELECT id, name, uuid, energy_category_id, "
1822
                 "        is_counted, hourly_low_limit, hourly_high_limit, "
1823
                 "        cost_center_id, energy_item_id, master_meter_id, description "
1824
                 " FROM tbl_meters "
1825
                 " WHERE id = %s ")
1826
        cursor.execute(query, (id_,))
1827
        row = cursor.fetchone()
1828
1829
        if row is None:
1830
            cursor.close()
1831
            cnx.close()
1832
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1833
                                   description='API.METER_NOT_FOUND')
1834
        else:
1835
            meta_result = {"id": row[0],
1836
                           "name": row[1],
1837
                           "uuid": row[2],
1838
                           "energy_category_id": row[3],
1839
                           "is_counted": row[4],
1840
                           "hourly_low_limit": row[5],
1841
                           "hourly_high_limit": row[6],
1842
                           "cost_center_id": row[7],
1843
                           "energy_item_id": row[8],
1844
                           "master_meter_id": row[9],
1845
                           "description": row[10],
1846
                           "points": None}
1847
            query = (" SELECT p.id, p.name, "
1848
                     "        ds.id, ds.name, ds.uuid, "
1849
                     "        p.address "
1850
                     " FROM tbl_points p, tbl_meters_points mp, tbl_data_sources ds "
1851
                     " WHERE mp.meter_id = %s AND p.id = mp.point_id AND p.data_source_id = ds.id "
1852
                     " ORDER BY p.name ")
1853
            cursor.execute(query, (id_,))
1854
            rows = cursor.fetchall()
1855
1856
            result = list()
1857
            if rows is not None and len(rows) > 0:
1858
                for row in rows:
1859
                    point_result = {"id": row[0], "name": row[1]}
1860
                    result.append(point_result)
1861
                meta_result['points'] = result
1862
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
1863
        if config.utc_offset[0] == '-':
1864
            timezone_offset = -timezone_offset
1865
        new_name = str.strip(meta_result['name']) + \
1866
            (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds')
1867
1868
        add_values = (" INSERT INTO tbl_meters "
1869
                      "    (name, uuid, energy_category_id, is_counted, hourly_low_limit, hourly_high_limit,"
1870
                      "     cost_center_id, energy_item_id, master_meter_id, description) "
1871
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
1872
        cursor.execute(add_values, (new_name,
1873
                                    str(uuid.uuid4()),
1874
                                    meta_result['energy_category_id'],
1875
                                    meta_result['is_counted'],
1876
                                    meta_result['hourly_low_limit'],
1877
                                    meta_result['hourly_high_limit'],
1878
                                    meta_result['cost_center_id'],
1879
                                    meta_result['energy_item_id'],
1880
                                    meta_result['master_meter_id'],
1881
                                    meta_result['description']))
1882
        new_id = cursor.lastrowid
1883
        if 'points' in meta_result.keys() and \
1884
                meta_result['points'] is not None and \
1885
                len(meta_result['points']) > 0:
1886
            for point in meta_result['points']:
1887
                if 'id' in point and isinstance(point['id'], int):
1888
                    cursor.execute(" SELECT name, object_type "
1889
                                   " FROM tbl_points "
1890
                                   " WHERE id = %s ", (point['id'],))
1891
                    row = cursor.fetchone()
1892 View Code Duplication
                    if row is None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1893
                        cursor.close()
1894
                        cnx.close()
1895
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1896
                                               description='API.POINT_NOT_FOUND')
1897
                    elif row[1] == 'ENERGY_VALUE':
1898
                        query = (" SELECT p.id "
1899
                                 " FROM tbl_meters_points mp, tbl_points p "
1900
                                 " WHERE mp.meter_id = %s AND mp.point_id = p.id AND p.object_type = 'ENERGY_VALUE' ")
1901
                        cursor.execute(query, (new_id,))
1902
                        rows_points = cursor.fetchall()
1903
                        if rows_points is not None and len(rows_points) > 0:
1904
                            cursor.close()
1905
                            cnx.close()
1906
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1907
                                                   description=
1908
                                                   'API.METER_CANNOT_HAVE_MORE_THAN_ONE_ENERGY_VALUE_POINTS')
1909
1910
                    query = (" SELECT id "
1911
                             " FROM tbl_meters_points "
1912
                             " WHERE meter_id = %s AND point_id = %s")
1913
                    cursor.execute(query, (new_id, point['id'],))
1914
                    if cursor.fetchone() is not None:
1915
                        cursor.close()
1916
                        cnx.close()
1917
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1918
                                               description='API.METER_POINT_RELATION_EXISTS')
1919
1920
                    add_row = (" INSERT INTO tbl_meters_points (meter_id, point_id) "
1921
                               " VALUES (%s, %s) ")
1922
                    cursor.execute(add_row, (new_id, point['id'],))
1923
        cnx.commit()
1924
        cursor.close()
1925
        cnx.close()
1926
1927
        resp.status = falcon.HTTP_201
1928
        resp.location = '/meters/' + str(new_id)
1929