core.meter.MeterClone.on_post()   F
last analyzed

Complexity

Conditions 22

Size

Total Lines 132
Code Lines 101

Duplication

Lines 16
Ratio 12.12 %

Importance

Changes 0
Metric Value
eloc 101
dl 16
loc 132
rs 0
c 0
b 0
f 0
cc 22
nop 3

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