Passed
Push — master ( f8b1cd...9ee003 )
by
unknown
10:23 queued 16s
created

core.space.clear_space_cache()   C

Complexity

Conditions 9

Size

Total Lines 75
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 52
dl 0
loc 75
rs 6.2375
c 0
b 0
f 0
cc 9
nop 2

How to fix   Long Method   

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:

1
import uuid
2
from datetime import datetime, timedelta
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
import redis
7
from anytree import AnyNode, LevelOrderIter
8
from anytree.exporter import JsonExporter
9
from core.useractivity import user_logger, admin_control, access_control, api_key_control
10
import config
11
12
13
def clear_space_cache(space_id=None, parent_space_id=None):
14
    """
15
    Clear space-related cache after data modification
16
17
    Args:
18
        space_id: Space ID (optional, for specific space cache)
19
        parent_space_id: Parent space ID (optional, for parent space cache)
20
    """
21
    # Check if Redis is enabled
22
    if not config.redis.get('is_enabled', False):
23
        return
24
25
    redis_client = None
26
    try:
27
        redis_client = redis.Redis(
28
            host=config.redis['host'],
29
            port=config.redis['port'],
30
            password=config.redis['password'] if config.redis['password'] else None,
31
            db=config.redis['db'],
32
            decode_responses=True,
33
            socket_connect_timeout=2,
34
            socket_timeout=2
35
        )
36
        redis_client.ping()
37
38
        # Clear space list cache
39
        list_cache_key = 'space:list'
40
        redis_client.delete(list_cache_key)
41
42
        # Clear specific space item cache if space_id is provided
43
        if space_id:
44
            item_cache_key = f'space:item:{space_id}'
45
            redis_client.delete(item_cache_key)
46
            children_cache_key = f'space:children:{space_id}'
47
            redis_client.delete(children_cache_key)
48
49
        # Clear parent space children cache if parent_space_id is provided
50
        if parent_space_id:
51
            parent_children_cache_key = f'space:children:{parent_space_id}'
52
            redis_client.delete(parent_children_cache_key)
53
54
        # Clear all space tree caches
55
        pattern = 'space:tree:*'
56
        keys = redis_client.keys(pattern)
57
        if keys:
58
            redis_client.delete(*keys)
59
60
        # Clear space-related collection caches (meters, equipments, etc.)
61
        if space_id:
62
            patterns = [
63
                f'space:combinedequipments:{space_id}',
64
                f'space:equipments:{space_id}',
65
                f'space:meters:{space_id}',
66
                f'space:offlinemeters:{space_id}',
67
                f'space:points:{space_id}',
68
                f'space:sensors:{space_id}',
69
                f'space:shopfloors:{space_id}',
70
                f'space:stores:{space_id}',
71
                f'space:tenants:{space_id}',
72
                f'space:virtualmeters:{space_id}',
73
                f'space:workingcalendars:{space_id}',
74
                f'space:commands:{space_id}',
75
                f'space:microgrids:{space_id}',
76
                f'space:photovoltaicpowerstations:{space_id}',
77
                f'space:energystoragepowerstations:{space_id}',
78
                f'space:energyflowdiagrams:{space_id}',
79
                f'space:distributionsystems:{space_id}',
80
                f'space:export:{space_id}',
81
            ]
82
            for pattern_key in patterns:
83
                redis_client.delete(pattern_key)
84
85
    except Exception:
86
        # If cache clear fails, ignore and continue
87
        pass
88
89
90
class SpaceCollection:
91
    """
92
    Space Collection Resource
93
94
    This class handles CRUD operations for space collection.
95
    It provides endpoints for listing all spaces and creating new spaces.
96
    Spaces represent physical locations or areas in the energy management system.
97
    """
98
    def __init__(self):
99
        pass
100
101
    @staticmethod
102
    def on_options(req, resp):
103
        _ = req
104
        resp.status = falcon.HTTP_200
105
106
    @staticmethod
107
    def on_get(req, resp):
108
        if 'API-KEY' not in req.headers or \
109
                not isinstance(req.headers['API-KEY'], str) or \
110
                len(str.strip(req.headers['API-KEY'])) == 0:
111
            access_control(req)
112
        else:
113
            api_key_control(req)
114
115
        # Redis cache key
116
        cache_key = 'space:list'
117
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
118
119
        # Try to get from Redis cache (only if Redis is enabled)
120
        redis_client = None
121
        if config.redis.get('is_enabled', False):
122
            try:
123
                redis_client = redis.Redis(
124
                    host=config.redis['host'],
125
                    port=config.redis['port'],
126
                    password=config.redis['password'] if config.redis['password'] else None,
127
                    db=config.redis['db'],
128
                    decode_responses=True,
129
                    socket_connect_timeout=2,
130
                    socket_timeout=2
131
                )
132
                redis_client.ping()
133
                cached_result = redis_client.get(cache_key)
134
                if cached_result:
135
                    resp.text = cached_result
136
                    return
137
            except Exception:
138
                # If Redis connection fails, continue to database query
139
                pass
140
141
        # Cache miss or Redis error - query database
142
        cnx = mysql.connector.connect(**config.myems_system_db)
143
        cursor = cnx.cursor()
144
145
        query = (" SELECT id, name, uuid "
146
                 " FROM tbl_spaces ")
147
        cursor.execute(query)
148
        rows_spaces = cursor.fetchall()
149
150
        space_dict = dict()
151
        if rows_spaces is not None and len(rows_spaces) > 0:
152
            for row in rows_spaces:
153
                space_dict[row[0]] = {"id": row[0],
154
                                      "name": row[1],
155
                                      "uuid": row[2]}
156
157
        query = (" SELECT id, name, utc_offset "
158
                 " FROM tbl_timezones ")
159
        cursor.execute(query)
160
        rows_timezones = cursor.fetchall()
161
162
        timezone_dict = dict()
163
        if rows_timezones is not None and len(rows_timezones) > 0:
164
            for row in rows_timezones:
165
                timezone_dict[row[0]] = {"id": row[0],
166
                                         "name": row[1],
167
                                         "utc_offset": row[2]}
168
169
        query = (" SELECT id, name, uuid "
170
                 " FROM tbl_contacts ")
171
        cursor.execute(query)
172
        rows_contacts = cursor.fetchall()
173
174
        contact_dict = dict()
175
        if rows_contacts is not None and len(rows_contacts) > 0:
176
            for row in rows_contacts:
177
                contact_dict[row[0]] = {"id": row[0],
178
                                        "name": row[1],
179
                                        "uuid": row[2]}
180
181
        query = (" SELECT id, name, uuid "
182
                 " FROM tbl_cost_centers ")
183
        cursor.execute(query)
184
        rows_cost_centers = cursor.fetchall()
185
186
        cost_center_dict = dict()
187
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
188
            for row in rows_cost_centers:
189
                cost_center_dict[row[0]] = {"id": row[0],
190
                                            "name": row[1],
191
                                            "uuid": row[2]}
192
193
        query = (" SELECT id, name, uuid, "
194
                 "      parent_space_id, area, number_of_occupants, timezone_id, is_input_counted, is_output_counted, "
195
                 "      contact_id, cost_center_id, latitude, longitude, description "
196
                 " FROM tbl_spaces "
197
                 " ORDER BY id ")
198
        cursor.execute(query)
199
        rows_spaces = cursor.fetchall()
200
201
        result = list()
202 View Code Duplication
        if rows_spaces is not None and len(rows_spaces) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
203
            for row in rows_spaces:
204
                meta_result = {"id": row[0],
205
                               "name": row[1],
206
                               "uuid": row[2],
207
                               "parent_space": space_dict.get(row[3], None),
208
                               "area": row[4],
209
                               "number_of_occupants": row[5],
210
                               "timezone": timezone_dict.get(row[6], None),
211
                               "is_input_counted": bool(row[7]),
212
                               "is_output_counted": bool(row[8]),
213
                               "contact": contact_dict.get(row[9], None),
214
                               "cost_center": cost_center_dict.get(row[10], None),
215
                               "latitude": row[11],
216
                               "longitude": row[12],
217
                               "description": row[13],
218
                               "qrcode": "space:" + row[2]}
219
                result.append(meta_result)
220
221
        cursor.close()
222
        cnx.close()
223
224
        # Store result in Redis cache
225
        result_json = json.dumps(result)
226
        if redis_client:
227
            try:
228
                redis_client.setex(cache_key, cache_expire, result_json)
229
            except Exception:
230
                pass
231
232
        resp.text = result_json
233
234
    @staticmethod
235
    @user_logger
236
    def on_post(req, resp):
237
        """Handles POST requests"""
238
        admin_control(req)
239
        try:
240
            raw_json = req.stream.read().decode('utf-8')
241
            new_values = json.loads(raw_json)
242
        except UnicodeDecodeError as ex:
243
            print("Failed to decode request")
244
            raise falcon.HTTPError(status=falcon.HTTP_400,
245
                                   title='API.BAD_REQUEST',
246
                                   description='API.INVALID_ENCODING')
247
        except json.JSONDecodeError as ex:
248
            print("Failed to parse JSON")
249
            raise falcon.HTTPError(status=falcon.HTTP_400,
250
                                   title='API.BAD_REQUEST',
251
                                   description='API.INVALID_JSON_FORMAT')
252
        except Exception as ex:
253
            print("Unexpected error reading request stream")
254
            raise falcon.HTTPError(status=falcon.HTTP_400,
255
                                   title='API.BAD_REQUEST',
256
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
257
258
        if 'name' not in new_values['data'].keys() or \
259
                not isinstance(new_values['data']['name'], str) or \
260
                len(str.strip(new_values['data']['name'])) == 0:
261
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
262
                                   description='API.INVALID_SPACE_NAME')
263
        name = str.strip(new_values['data']['name'])
264
265
        if 'parent_space_id' in new_values['data'].keys():
266
            if new_values['data']['parent_space_id'] <= 0:
267
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
268
                                       description='API.INVALID_PARENT_SPACE_ID')
269
            parent_space_id = new_values['data']['parent_space_id']
270
        else:
271
            parent_space_id = None
272
273
        if 'area' not in new_values['data'].keys() or \
274
                not (isinstance(new_values['data']['area'], float) or
275
                     isinstance(new_values['data']['area'], int)) or \
276
                new_values['data']['area'] <= 0.0:
277
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
278
                                   description='API.INVALID_AREA_VALUE')
279
        area = new_values['data']['area']
280
281
        if 'number_of_occupants' not in new_values['data'].keys() or \
282
                not (isinstance(new_values['data']['number_of_occupants'], float) or
283
                     isinstance(new_values['data']['number_of_occupants'], int)) or \
284
                new_values['data']['number_of_occupants'] <= 0:
285
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
286
                                   description='API.INVALID_NUMBER_OF_OCCUPANTS')
287
        number_of_occupants = new_values['data']['number_of_occupants']
288
289
        if 'timezone_id' not in new_values['data'].keys() or \
290
                not isinstance(new_values['data']['timezone_id'], int) or \
291
                new_values['data']['timezone_id'] <= 0:
292
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
293
                                   description='API.INVALID_TIMEZONE_ID')
294
        timezone_id = new_values['data']['timezone_id']
295
296
        if 'is_input_counted' not in new_values['data'].keys() or \
297
                not isinstance(new_values['data']['is_input_counted'], bool):
298
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
299
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
300
        is_input_counted = new_values['data']['is_input_counted']
301
302
        if 'is_output_counted' not in new_values['data'].keys() or \
303
                not isinstance(new_values['data']['is_output_counted'], bool):
304
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
305
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
306
        is_output_counted = new_values['data']['is_output_counted']
307
308
        if 'contact_id' in new_values['data'].keys():
309
            if new_values['data']['contact_id'] <= 0:
310
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
311
                                       description='API.INVALID_CONTACT_ID')
312
            contact_id = new_values['data']['contact_id']
313
        else:
314
            contact_id = None
315
316
        if 'cost_center_id' in new_values['data'].keys():
317
            if new_values['data']['cost_center_id'] <= 0:
318
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
319
                                       description='API.INVALID_COST_CENTER_ID')
320
            cost_center_id = new_values['data']['cost_center_id']
321
        else:
322
            cost_center_id = None
323
324 View Code Duplication
        if 'latitude' in new_values['data'].keys() and new_values['data']['latitude'] is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
325
            if not (isinstance(new_values['data']['latitude'], float) or
326
                    isinstance(new_values['data']['latitude'], int)) or \
327
                    new_values['data']['latitude'] < -90.0 or \
328
                    new_values['data']['latitude'] > 90.0:
329
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
330
                                       description='API.INVALID_LATITUDE_VALUE')
331
            latitude = new_values['data']['latitude']
332
        else:
333
            latitude = None
334
335 View Code Duplication
        if 'longitude' in new_values['data'].keys() and new_values['data']['longitude'] is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
336
            if not (isinstance(new_values['data']['longitude'], float) or
337
                    isinstance(new_values['data']['longitude'], int)) or \
338
                    new_values['data']['longitude'] < -180.0 or \
339
                    new_values['data']['longitude'] > 180.0:
340
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
341
                                       description='API.INVALID_LONGITUDE_VALUE')
342
            longitude = new_values['data']['longitude']
343
        else:
344
            longitude = None
345
346
        if 'description' in new_values['data'].keys() and \
347
                new_values['data']['description'] is not None and \
348
                len(str(new_values['data']['description'])) > 0:
349
            description = str.strip(new_values['data']['description'])
350
        else:
351
            description = None
352
353
        cnx = mysql.connector.connect(**config.myems_system_db)
354
        cursor = cnx.cursor()
355
356
        cursor.execute(" SELECT name "
357
                       " FROM tbl_spaces "
358
                       " WHERE name = %s AND parent_space_id = %s", (name, parent_space_id))
359
        if cursor.fetchone() is not None:
360
            cursor.close()
361
            cnx.close()
362
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
363
                                   description='API.SPACE_NAME_IS_ALREADY_IN_USE')
364
365 View Code Duplication
        if parent_space_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
366
            cursor.execute(" SELECT name "
367
                           " FROM tbl_spaces "
368
                           " WHERE id = %s ",
369
                           (new_values['data']['parent_space_id'],))
370
            row = cursor.fetchone()
371
            if row is None:
372
                cursor.close()
373
                cnx.close()
374
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
375
                                       description='API.PARENT_SPACE_NOT_FOUND')
376
377
        cursor.execute(" SELECT name "
378
                       " FROM tbl_timezones "
379
                       " WHERE id = %s ",
380
                       (new_values['data']['timezone_id'],))
381
        if cursor.fetchone() is None:
382
            cursor.close()
383
            cnx.close()
384
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
385
                                   description='API.TIMEZONE_NOT_FOUND')
386 View Code Duplication
        if contact_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
387
            cursor.execute(" SELECT name "
388
                           " FROM tbl_contacts "
389
                           " WHERE id = %s ",
390
                           (new_values['data']['contact_id'],))
391
            row = cursor.fetchone()
392
            if row is None:
393
                cursor.close()
394
                cnx.close()
395
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
396
                                       description='API.CONTACT_NOT_FOUND')
397
398
        if cost_center_id is not None:
399
            cursor.execute(" SELECT name "
400
                           " FROM tbl_cost_centers "
401
                           " WHERE id = %s ",
402
                           (new_values['data']['cost_center_id'],))
403
            row = cursor.fetchone()
404
            if row is None:
405
                cursor.close()
406
                cnx.close()
407
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
408
                                       description='API.COST_CENTER_NOT_FOUND')
409
410
        add_values = (" INSERT INTO tbl_spaces "
411
                      "    (name, uuid, parent_space_id, area, number_of_occupants, timezone_id, is_input_counted, "
412
                      "     is_output_counted, contact_id, cost_center_id, latitude, longitude, description) "
413
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
414
        cursor.execute(add_values, (name,
415
                                    str(uuid.uuid4()),
416
                                    parent_space_id,
417
                                    area,
418
                                    number_of_occupants,
419
                                    timezone_id,
420
                                    is_input_counted,
421
                                    is_output_counted,
422
                                    contact_id,
423
                                    cost_center_id,
424
                                    latitude,
425
                                    longitude,
426
                                    description))
427
        new_id = cursor.lastrowid
428
        cnx.commit()
429
        cursor.close()
430
        cnx.close()
431
432
        # Clear cache after POST
433
        clear_space_cache(space_id=new_id, parent_space_id=parent_space_id)
434
435
        resp.status = falcon.HTTP_201
436
        resp.location = '/spaces/' + str(new_id)
437
438
439
class SpaceItem:
440
    def __init__(self):
441
        pass
442
443
    @staticmethod
444
    def on_options(req, resp, id_):
445
        _ = req
446
        resp.status = falcon.HTTP_200
447
        _ = id_
448
449
    @staticmethod
450
    def on_get(req, resp, id_):
451
        if 'API-KEY' not in req.headers or \
452
                not isinstance(req.headers['API-KEY'], str) or \
453
                len(str.strip(req.headers['API-KEY'])) == 0:
454
            access_control(req)
455
        else:
456
            api_key_control(req)
457
        if not id_.isdigit() or int(id_) <= 0:
458
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
459
                                   description='API.INVALID_METER_ID')
460
461
        # Redis cache key
462
        cache_key = f'space:item:{id_}'
463
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
464
465
        # Try to get from Redis cache (only if Redis is enabled)
466
        redis_client = None
467
        if config.redis.get('is_enabled', False):
468
            try:
469
                redis_client = redis.Redis(
470
                    host=config.redis['host'],
471
                    port=config.redis['port'],
472
                    password=config.redis['password'] if config.redis['password'] else None,
473
                    db=config.redis['db'],
474
                    decode_responses=True,
475
                    socket_connect_timeout=2,
476
                    socket_timeout=2
477
                )
478
                redis_client.ping()
479
                cached_result = redis_client.get(cache_key)
480
                if cached_result:
481
                    resp.text = cached_result
482
                    return
483
            except Exception:
484
                # If Redis connection fails, continue to database query
485
                pass
486
487
        # Cache miss or Redis error - query database
488
        cnx = mysql.connector.connect(**config.myems_system_db)
489
        cursor = cnx.cursor()
490
491
        query = (" SELECT id, name, uuid "
492
                 " FROM tbl_spaces ")
493
        cursor.execute(query)
494
        rows_spaces = cursor.fetchall()
495
496
        space_dict = dict()
497
        if rows_spaces is not None and len(rows_spaces) > 0:
498
            for row in rows_spaces:
499
                space_dict[row[0]] = {"id": row[0],
500
                                      "name": row[1],
501
                                      "uuid": row[2]}
502
503
        query = (" SELECT id, name, utc_offset "
504
                 " FROM tbl_timezones ")
505
        cursor.execute(query)
506
        rows_timezones = cursor.fetchall()
507
508
        timezone_dict = dict()
509
        if rows_timezones is not None and len(rows_timezones) > 0:
510
            for row in rows_timezones:
511
                timezone_dict[row[0]] = {"id": row[0],
512
                                         "name": row[1],
513
                                         "utc_offset": row[2]}
514
515
        query = (" SELECT id, name, uuid "
516
                 " FROM tbl_contacts ")
517
        cursor.execute(query)
518
        rows_contacts = cursor.fetchall()
519
520
        contact_dict = dict()
521
        if rows_contacts is not None and len(rows_contacts) > 0:
522
            for row in rows_contacts:
523
                contact_dict[row[0]] = {"id": row[0],
524
                                        "name": row[1],
525
                                        "uuid": row[2]}
526
527
        query = (" SELECT id, name, uuid "
528
                 " FROM tbl_cost_centers ")
529
        cursor.execute(query)
530
        rows_cost_centers = cursor.fetchall()
531
532
        cost_center_dict = dict()
533
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
534
            for row in rows_cost_centers:
535
                cost_center_dict[row[0]] = {"id": row[0],
536
                                            "name": row[1],
537
                                            "uuid": row[2]}
538
539
        query = (" SELECT id, name, uuid, "
540
                 "       parent_space_id, area, number_of_occupants, timezone_id, is_input_counted, is_output_counted, "
541
                 "       contact_id, cost_center_id, latitude, longitude, description "
542
                 " FROM tbl_spaces "
543
                 " WHERE id = %s ")
544
        cursor.execute(query, (id_,))
545
        row = cursor.fetchone()
546
        cursor.close()
547
        cnx.close()
548
549
        if row is None:
550
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
551
                                   description='API.SPACE_NOT_FOUND')
552
        else:
553
            meta_result = {"id": row[0],
554
                           "name": row[1],
555
                           "uuid": row[2],
556
                           "parent_space_id": space_dict.get(row[3], None),
557
                           "area": row[4],
558
                           "number_of_occupants": row[5],
559
                           "timezone": timezone_dict.get(row[6], None),
560
                           "is_input_counted": bool(row[7]),
561
                           "is_output_counted": bool(row[8]),
562
                           "contact": contact_dict.get(row[9], None),
563
                           "cost_center": cost_center_dict.get(row[10], None),
564
                           "latitude": row[11],
565
                           "longitude": row[12],
566
                           "description": row[13],
567
                           "qrcode": "space:" + row[2]}
568
569
        # Store result in Redis cache
570
        result_json = json.dumps(meta_result)
571
        if redis_client:
572
            try:
573
                redis_client.setex(cache_key, cache_expire, result_json)
574
            except Exception:
575
                pass
576
577
        resp.text = result_json
578
579
    @staticmethod
580
    @user_logger
581
    def on_delete(req, resp, id_):
582
        admin_control(req)
583
        if not id_.isdigit() or int(id_) <= 0:
584
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
585
                                   description='API.INVALID_SPACE_ID')
586
        if int(id_) == 1:
587
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
588
                                   description='API.THIS_SPACE_CANNOT_BE_DELETED')
589
590
        cnx = mysql.connector.connect(**config.myems_system_db)
591
        cursor = cnx.cursor()
592
593
        cursor.execute(" SELECT name, parent_space_id "
594
                       " FROM tbl_spaces "
595
                       " WHERE id = %s ", (id_,))
596
        row = cursor.fetchone()
597
        if row is None:
598
            cursor.close()
599
            cnx.close()
600
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
601
                                   description='API.SPACE_NOT_FOUND')
602
        parent_space_id = row[1]
603
604
        # checkout relation with children spaces
605
        cursor.execute(" SELECT id "
606
                       " FROM tbl_spaces "
607
                       " WHERE parent_space_id = %s ",
608
                       (id_,))
609
        rows_spaces = cursor.fetchall()
610
        if rows_spaces is not None and len(rows_spaces) > 0:
611
            cursor.close()
612
            cnx.close()
613
            raise falcon.HTTPError(status=falcon.HTTP_400,
614
                                   title='API.BAD_REQUEST',
615
                                   description='API.THERE_IS_RELATION_WITH_CHILDREN_SPACES')
616
617
        # delete relation with combined equipment
618
        cursor.execute(" DELETE FROM tbl_spaces_combined_equipments WHERE space_id = %s ", (id_,))
619
620
        # delete relation with commands
621
        cursor.execute(" DELETE FROM tbl_spaces_commands WHERE space_id = %s ", (id_,))
622
623
        # delete relation with equipments
624
        cursor.execute(" DELETE FROM tbl_spaces_equipments WHERE space_id = %s ", (id_,))
625
626
        # delete relation with meters
627
        cursor.execute(" DELETE FROM tbl_spaces_meters WHERE space_id = %s ", (id_,))
628
629
        # delete relation with offline meters
630
        cursor.execute(" DELETE FROM tbl_spaces_offline_meters WHERE space_id = %s ", (id_,))
631
632
        # delete relation with points
633
        cursor.execute(" DELETE FROM tbl_spaces_points WHERE space_id = %s ", (id_,))
634
635
        # delete relation with sensors
636
        cursor.execute(" DELETE FROM tbl_spaces_sensors WHERE space_id = %s ", (id_,))
637
638
        # delete relation with shopfloors
639
        cursor.execute(" DELETE FROM tbl_spaces_shopfloors WHERE space_id = %s ", (id_,))
640
641
        # delete relation with stores
642
        cursor.execute(" DELETE FROM tbl_spaces_stores WHERE space_id = %s ", (id_,))
643
644
        # delete relation with tenants
645
        cursor.execute(" DELETE FROM tbl_spaces_tenants WHERE space_id = %s ", (id_,))
646
647
        # delete relation with virtual meters
648
        cursor.execute(" DELETE FROM tbl_spaces_virtual_meters WHERE space_id = %s ", (id_,))
649
650
        # delete relation with working calendars
651
        cursor.execute(" DELETE FROM tbl_spaces_working_calendars WHERE space_id = %s ", (id_,))
652
653
        cursor.execute(" DELETE FROM tbl_spaces WHERE id = %s ", (id_,))
654
        cnx.commit()
655
656
        cursor.close()
657
        cnx.close()
658
659
        # Clear cache after DELETE
660
        clear_space_cache(space_id=int(id_), parent_space_id=parent_space_id)
661
662
        resp.status = falcon.HTTP_204
663
664
    @staticmethod
665
    @user_logger
666
    def on_put(req, resp, id_):
667
        """Handles PUT requests"""
668
        admin_control(req)
669
        try:
670
            raw_json = req.stream.read().decode('utf-8')
671
        except UnicodeDecodeError as ex:
672
            print("Failed to decode request")
673
            raise falcon.HTTPError(status=falcon.HTTP_400,
674
                                   title='API.BAD_REQUEST',
675
                                   description='API.INVALID_ENCODING')
676
        except Exception as ex:
677
            print("Unexpected error reading request stream")
678
            raise falcon.HTTPError(status=falcon.HTTP_400,
679
                                   title='API.BAD_REQUEST',
680
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
681
682
        if not id_.isdigit() or int(id_) <= 0:
683
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
684
                                   description='API.INVALID_SPACE_ID')
685
686
        new_values = json.loads(raw_json)
687
688
        if 'name' not in new_values['data'].keys() or \
689
                not isinstance(new_values['data']['name'], str) or \
690
                len(str.strip(new_values['data']['name'])) == 0:
691
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
692
                                   description='API.INVALID_SPACE_NAME')
693
        name = str.strip(new_values['data']['name'])
694
695
        if int(id_) == 1:
696
            parent_space_id = None
697
        else:
698
            if 'parent_space_id' not in new_values['data'].keys() or \
699
                    new_values['data']['parent_space_id'] is None or \
700
                    not isinstance(new_values['data']['parent_space_id'], int) or \
701
                    int(new_values['data']['parent_space_id']) <= 0:
702
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
703
                                       description='API.INVALID_PARENT_SPACE_ID')
704
            parent_space_id = int(new_values['data']['parent_space_id'])
705
706
        if 'area' not in new_values['data'].keys() or \
707
                not (isinstance(new_values['data']['area'], float) or
708
                     isinstance(new_values['data']['area'], int)) or \
709
                new_values['data']['area'] <= 0.0:
710
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
711
                                   description='API.INVALID_AREA_VALUE')
712
        area = new_values['data']['area']
713
714
        if 'number_of_occupants' not in new_values['data'].keys() or \
715
                not (isinstance(new_values['data']['number_of_occupants'], float) or
716
                     isinstance(new_values['data']['number_of_occupants'], int)) or \
717
                new_values['data']['number_of_occupants'] <= 0:
718
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
719
                                   description='API.INVALID_NUMBER_OF_OCCUPANTS')
720
        number_of_occupants = new_values['data']['number_of_occupants']
721
722
        if 'timezone_id' not in new_values['data'].keys() or \
723
                not isinstance(new_values['data']['timezone_id'], int) or \
724
                new_values['data']['timezone_id'] <= 0:
725
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
726
                                   description='API.INVALID_TIMEZONE_ID')
727
        timezone_id = new_values['data']['timezone_id']
728
729
        if 'is_input_counted' not in new_values['data'].keys() or \
730
                not isinstance(new_values['data']['is_input_counted'], bool):
731
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
732
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
733
        is_input_counted = new_values['data']['is_input_counted']
734
735
        if 'is_output_counted' not in new_values['data'].keys() or \
736
                not isinstance(new_values['data']['is_output_counted'], bool):
737
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
738
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
739
        is_output_counted = new_values['data']['is_output_counted']
740
741
        if 'contact_id' in new_values['data'].keys() and new_values['data']['contact_id'] is not None:
742
            if new_values['data']['contact_id'] <= 0:
743
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
744
                                       description='API.INVALID_CONTACT_ID')
745
            contact_id = new_values['data']['contact_id']
746
        else:
747
            contact_id = None
748
749
        if 'cost_center_id' in new_values['data'].keys():
750
            if new_values['data']['cost_center_id'] <= 0:
751
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
752
                                       description='API.INVALID_COST_CENTER_ID')
753
            cost_center_id = new_values['data']['cost_center_id']
754
        else:
755
            cost_center_id = None
756
757 View Code Duplication
        if 'latitude' in new_values['data'].keys():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
758
            if new_values['data']['latitude'] is not None:
759
                if not (isinstance(new_values['data']['latitude'], float) or
760
                        isinstance(new_values['data']['latitude'], int)) or \
761
                        new_values['data']['latitude'] < -90.0 or \
762
                        new_values['data']['latitude'] > 90.0:
763
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
764
                                           description='API.INVALID_LATITUDE_VALUE')
765
                latitude = new_values['data']['latitude']
766
            else:
767
                latitude = None
768
        else:
769
            latitude = None
770
771 View Code Duplication
        if 'longitude' in new_values['data'].keys():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
772
            if new_values['data']['latitude'] is not None:
773
                if not (isinstance(new_values['data']['longitude'], float) or
774
                        isinstance(new_values['data']['longitude'], int)) or \
775
                        new_values['data']['longitude'] < -180.0 or \
776
                        new_values['data']['longitude'] > 180.0:
777
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
778
                                           description='API.INVALID_LONGITUDE_VALUE')
779
                longitude = new_values['data']['longitude']
780
            else:
781
                longitude = None
782
        else:
783
            longitude = None
784
785
        if 'description' in new_values['data'].keys() and \
786
                new_values['data']['description'] is not None and \
787
                len(str(new_values['data']['description'])) > 0:
788
            description = str.strip(new_values['data']['description'])
789
        else:
790
            description = None
791
792
        cnx = mysql.connector.connect(**config.myems_system_db)
793
        cursor = cnx.cursor()
794
795
        cursor.execute(" SELECT name, parent_space_id "
796
                       " FROM tbl_spaces "
797
                       " WHERE id = %s ", (id_,))
798
        row = cursor.fetchone()
799
        if row is None:
800
            cursor.close()
801
            cnx.close()
802
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
803
                                   description='API.SPACE_NOT_FOUND')
804
        old_parent_space_id = row[1]
805
806
        cursor.execute(" SELECT name "
807
                       " FROM tbl_spaces "
808
                       " WHERE name = %s AND id != %s AND parent_space_id = %s", (name, id_, parent_space_id))
809
        if cursor.fetchone() is not None:
810
            cursor.close()
811
            cnx.close()
812
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
813
                                   description='API.SPACE_NAME_IS_ALREADY_IN_USE')
814
815 View Code Duplication
        if parent_space_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
816
            cursor.execute(" SELECT name "
817
                           " FROM tbl_spaces "
818
                           " WHERE id = %s ",
819
                           (new_values['data']['parent_space_id'],))
820
            row = cursor.fetchone()
821
            if row is None:
822
                cursor.close()
823
                cnx.close()
824
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
825
                                       description='API.PARENT_SPACE_NOT_FOUND')
826
827
        cursor.execute(" SELECT name "
828
                       " FROM tbl_timezones "
829
                       " WHERE id = %s ",
830
                       (new_values['data']['timezone_id'],))
831
        if cursor.fetchone() is None:
832
            cursor.close()
833
            cnx.close()
834
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
835
                                   description='API.TIMEZONE_NOT_FOUND')
836 View Code Duplication
        if contact_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
837
            cursor.execute(" SELECT name "
838
                           " FROM tbl_contacts "
839
                           " WHERE id = %s ",
840
                           (new_values['data']['contact_id'],))
841
            row = cursor.fetchone()
842
            if row is None:
843
                cursor.close()
844
                cnx.close()
845
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
846
                                       description='API.CONTACT_NOT_FOUND')
847
848
        if cost_center_id is not None:
849
            cursor.execute(" SELECT name "
850
                           " FROM tbl_cost_centers "
851
                           " WHERE id = %s ",
852
                           (new_values['data']['cost_center_id'],))
853
            row = cursor.fetchone()
854
            if row is None:
855
                cursor.close()
856
                cnx.close()
857
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
858
                                       description='API.COST_CENTER_NOT_FOUND')
859
860
        update_row = (" UPDATE tbl_spaces "
861
                      " SET name = %s, parent_space_id = %s, area = %s, number_of_occupants = %s, timezone_id = %s, "
862
                      "     is_input_counted = %s, is_output_counted = %s, contact_id = %s, cost_center_id = %s, "
863
                      "     latitude = %s, longitude = %s, description = %s "
864
                      " WHERE id = %s ")
865
        cursor.execute(update_row, (name,
866
                                    parent_space_id,
867
                                    area,
868
                                    number_of_occupants,
869
                                    timezone_id,
870
                                    is_input_counted,
871
                                    is_output_counted,
872
                                    contact_id,
873
                                    cost_center_id,
874
                                    latitude,
875
                                    longitude,
876
                                    description,
877
                                    id_))
878
        cnx.commit()
879
880
        cursor.close()
881
        cnx.close()
882
883
        # Clear cache after PUT
884
        clear_space_cache(space_id=int(id_), parent_space_id=parent_space_id)
885
        # Also clear old parent space cache if parent_space_id changed
886
        if old_parent_space_id != parent_space_id:
887
            clear_space_cache(parent_space_id=old_parent_space_id)
888
889
        resp.status = falcon.HTTP_200
890
891
892
class SpaceChildrenCollection:
893
    def __init__(self):
894
        pass
895
896
    @staticmethod
897
    def on_options(req, resp, id_):
898
        _ = req
899
        resp.status = falcon.HTTP_200
900
        _ = id_
901
902
    @staticmethod
903
    def on_get(req, resp, id_):
904
        if 'API-KEY' not in req.headers or \
905
                not isinstance(req.headers['API-KEY'], str) or \
906
                len(str.strip(req.headers['API-KEY'])) == 0:
907
            access_control(req)
908
        else:
909
            api_key_control(req)
910
        if not id_.isdigit() or int(id_) <= 0:
911
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
912
                                   description='API.INVALID_SPACE_ID')
913
914
        # Redis cache key
915
        cache_key = f'space:children:{id_}'
916
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
917
918
        # Try to get from Redis cache (only if Redis is enabled)
919
        redis_client = None
920
        if config.redis.get('is_enabled', False):
921
            try:
922
                redis_client = redis.Redis(
923
                    host=config.redis['host'],
924
                    port=config.redis['port'],
925
                    password=config.redis['password'] if config.redis['password'] else None,
926
                    db=config.redis['db'],
927
                    decode_responses=True,
928
                    socket_connect_timeout=2,
929
                    socket_timeout=2
930
                )
931
                redis_client.ping()
932
                cached_result = redis_client.get(cache_key)
933
                if cached_result:
934
                    resp.text = cached_result
935
                    return
936
            except Exception:
937
                # If Redis connection fails, continue to database query
938
                pass
939
940
        # Cache miss or Redis error - query database
941
        cnx = mysql.connector.connect(**config.myems_system_db)
942
        cursor = cnx.cursor()
943
944
        query = (" SELECT id, name, uuid, "
945
                 "  parent_space_id, area, number_of_occupants, timezone_id, is_input_counted, is_output_counted, "
946
                 "  contact_id, cost_center_id, latitude, longitude, description "
947
                 " FROM tbl_spaces "
948
                 " WHERE id = %s ")
949
        cursor.execute(query, (id_,))
950
        row_current_space = cursor.fetchone()
951
        if row_current_space is None:
952
            cursor.close()
953
            cnx.close()
954
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
955
                                   description='API.SPACE_NOT_FOUND')
956
        # note: row_current_space will be used at the end
957
958
        query = (" SELECT id, name, uuid "
959
                 " FROM tbl_spaces ")
960
        cursor.execute(query)
961
        rows_spaces = cursor.fetchall()
962
963
        space_dict = dict()
964
        if rows_spaces is not None and len(rows_spaces) > 0:
965
            for row in rows_spaces:
966
                space_dict[row[0]] = {"id": row[0],
967
                                      "name": row[1],
968
                                      "uuid": row[2]}
969
970
        query = (" SELECT id, name, utc_offset "
971
                 " FROM tbl_timezones ")
972
        cursor.execute(query)
973
        rows_timezones = cursor.fetchall()
974
975
        timezone_dict = dict()
976
        if rows_timezones is not None and len(rows_timezones) > 0:
977
            for row in rows_timezones:
978
                timezone_dict[row[0]] = {"id": row[0],
979
                                         "name": row[1],
980
                                         "utc_offset": row[2]}
981
982
        query = (" SELECT id, name, uuid "
983
                 " FROM tbl_contacts ")
984
        cursor.execute(query)
985
        rows_contacts = cursor.fetchall()
986
987
        contact_dict = dict()
988
        if rows_contacts is not None and len(rows_contacts) > 0:
989
            for row in rows_contacts:
990
                contact_dict[row[0]] = {"id": row[0],
991
                                        "name": row[1],
992
                                        "uuid": row[2]}
993
994
        query = (" SELECT id, name, uuid "
995
                 " FROM tbl_cost_centers ")
996
        cursor.execute(query)
997
        rows_cost_centers = cursor.fetchall()
998
999
        cost_center_dict = dict()
1000
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
1001
            for row in rows_cost_centers:
1002
                cost_center_dict[row[0]] = {"id": row[0],
1003
                                            "name": row[1],
1004
                                            "uuid": row[2]}
1005
        result = dict()
1006
        result['current'] = dict()
1007
        result['current']['id'] = row_current_space[0]
1008
        result['current']['name'] = row_current_space[1]
1009
        result['current']['uuid'] = row_current_space[2]
1010
        result['current']['parent_space'] = space_dict.get(row_current_space[3], None)
1011
        result['current']['area'] = row_current_space[4]
1012
        result['current']['number_of_occupants'] = row_current_space[5]
1013
        result['current']['timezone'] = timezone_dict.get(row_current_space[6], None)
1014
        result['current']['is_input_counted'] = bool(row_current_space[7])
1015
        result['current']['is_output_counted'] = bool(row_current_space[8])
1016
        result['current']['contact'] = contact_dict.get(row_current_space[9], None)
1017
        result['current']['cost_center'] = cost_center_dict.get(row_current_space[10], None)
1018
        result['current']['latitude'] = row_current_space[11]
1019
        result['current']['longitude'] = row_current_space[12]
1020
        result['current']['description'] = row_current_space[13]
1021
        result['current']['qrcode'] = 'space:' + row_current_space[2]
1022
1023
        result['children'] = list()
1024
1025
        query = (" SELECT id, name, uuid, "
1026
                 "       parent_space_id, area, number_of_occupants, timezone_id, is_input_counted, is_output_counted, "
1027
                 "        contact_id, cost_center_id, latitude, longitude, description "
1028
                 " FROM tbl_spaces "
1029
                 " WHERE parent_space_id = %s "
1030
                 " ORDER BY id ")
1031
        cursor.execute(query, (id_, ))
1032
        rows_spaces = cursor.fetchall()
1033
1034 View Code Duplication
        if rows_spaces is not None and len(rows_spaces) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1035
            for row in rows_spaces:
1036
                meta_result = {"id": row[0],
1037
                               "name": row[1],
1038
                               "uuid": row[2],
1039
                               "parent_space": space_dict.get(row[3], None),
1040
                               "area": row[4],
1041
                               "number_of_occupants": row[5],
1042
                               "timezone": timezone_dict.get(row[6], None),
1043
                               "is_input_counted": bool(row[7]),
1044
                               "is_output_counted": bool(row[8]),
1045
                               "contact": contact_dict.get(row[9], None),
1046
                               "cost_center": cost_center_dict.get(row[10], None),
1047
                               "latitude": row[11],
1048
                               "longitude": row[12],
1049
                               "description": row[13],
1050
                               "qrcode": 'space:' + row[2]}
1051
                result['children'].append(meta_result)
1052
1053
        cursor.close()
1054
        cnx.close()
1055
1056
        # Store result in Redis cache
1057
        result_json = json.dumps(result)
1058
        if redis_client:
1059
            try:
1060
                redis_client.setex(cache_key, cache_expire, result_json)
1061
            except Exception:
1062
                pass
1063
1064
        resp.text = result_json
1065
1066
1067 View Code Duplication
class SpaceCombinedEquipmentCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1068
    def __init__(self):
1069
        pass
1070
1071
    @staticmethod
1072
    def on_options(req, resp, id_):
1073
        _ = req
1074
        resp.status = falcon.HTTP_200
1075
        _ = id_
1076
1077
    @staticmethod
1078
    def on_get(req, resp, id_):
1079
        if 'API-KEY' not in req.headers or \
1080
                not isinstance(req.headers['API-KEY'], str) or \
1081
                len(str.strip(req.headers['API-KEY'])) == 0:
1082
            access_control(req)
1083
        else:
1084
            api_key_control(req)
1085
        if not id_.isdigit() or int(id_) <= 0:
1086
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1087
                                   description='API.INVALID_SPACE_ID')
1088
1089
        cnx = mysql.connector.connect(**config.myems_system_db)
1090
        cursor = cnx.cursor()
1091
1092
        cursor.execute(" SELECT name "
1093
                       " FROM tbl_spaces "
1094
                       " WHERE id = %s ", (id_,))
1095
        if cursor.fetchone() is None:
1096
            cursor.close()
1097
            cnx.close()
1098
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1099
                                   description='API.SPACE_NOT_FOUND')
1100
1101
        query = (" SELECT e.id, e.name, e.uuid "
1102
                 " FROM tbl_spaces s, tbl_spaces_combined_equipments se, tbl_combined_equipments e "
1103
                 " WHERE se.space_id = s.id AND e.id = se.combined_equipment_id AND s.id = %s "
1104
                 " ORDER BY e.id ")
1105
        cursor.execute(query, (id_,))
1106
        rows = cursor.fetchall()
1107
1108
        result = list()
1109
        if rows is not None and len(rows) > 0:
1110
            for row in rows:
1111
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
1112
                result.append(meta_result)
1113
1114
        resp.text = json.dumps(result)
1115
1116
    @staticmethod
1117
    @user_logger
1118
    def on_post(req, resp, id_):
1119
        """Handles POST requests"""
1120
        admin_control(req)
1121
        try:
1122
            raw_json = req.stream.read().decode('utf-8')
1123
        except UnicodeDecodeError as ex:
1124
            print("Failed to decode request")
1125
            raise falcon.HTTPError(status=falcon.HTTP_400,
1126
                                   title='API.BAD_REQUEST',
1127
                                   description='API.INVALID_ENCODING')
1128
        except Exception as ex:
1129
            print("Unexpected error reading request stream")
1130
            raise falcon.HTTPError(status=falcon.HTTP_400,
1131
                                   title='API.BAD_REQUEST',
1132
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1133
1134
        if not id_.isdigit() or int(id_) <= 0:
1135
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1136
                                   description='API.INVALID_SPACE_ID')
1137
1138
        new_values = json.loads(raw_json)
1139
1140
        if 'combined_equipment_id' not in new_values['data'].keys() or \
1141
                not isinstance(new_values['data']['combined_equipment_id'], int) or \
1142
                new_values['data']['combined_equipment_id'] <= 0:
1143
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1144
                                   description='API.INVALID_COMBINED_EQUIPMENT_ID')
1145
        combined_equipment_id = new_values['data']['combined_equipment_id']
1146
1147
        cnx = mysql.connector.connect(**config.myems_system_db)
1148
        cursor = cnx.cursor()
1149
1150
        cursor.execute(" SELECT name "
1151
                       " from tbl_spaces "
1152
                       " WHERE id = %s ", (id_,))
1153
        if cursor.fetchone() is None:
1154
            cursor.close()
1155
            cnx.close()
1156
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1157
                                   description='API.SPACE_NOT_FOUND')
1158
1159
        cursor.execute(" SELECT name "
1160
                       " FROM tbl_combined_equipments "
1161
                       " WHERE id = %s ", (combined_equipment_id,))
1162
        if cursor.fetchone() is None:
1163
            cursor.close()
1164
            cnx.close()
1165
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1166
                                   description='API.COMBINED_EQUIPMENT_NOT_FOUND')
1167
1168
        query = (" SELECT id "
1169
                 " FROM tbl_spaces_combined_equipments "
1170
                 " WHERE space_id = %s AND combined_equipment_id = %s")
1171
        cursor.execute(query, (id_, combined_equipment_id,))
1172
        if cursor.fetchone() is not None:
1173
            cursor.close()
1174
            cnx.close()
1175
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1176
                                   description='API.SPACE_COMBINED_EQUIPMENT_RELATION_EXISTS')
1177
1178
        add_row = (" INSERT INTO tbl_spaces_combined_equipments (space_id, combined_equipment_id) "
1179
                   " VALUES (%s, %s) ")
1180
        cursor.execute(add_row, (id_, combined_equipment_id,))
1181
        cnx.commit()
1182
        cursor.close()
1183
        cnx.close()
1184
1185
        resp.status = falcon.HTTP_201
1186
        resp.location = '/spaces/' + str(id_) + '/combinedequipments/' + str(combined_equipment_id)
1187
1188
1189
class SpaceCombinedEquipmentItem:
1190
    def __init__(self):
1191
        pass
1192
1193
    @staticmethod
1194
    def on_options(req, resp, id_, eid):
1195
        _ = req
1196
        resp.status = falcon.HTTP_200
1197
        _ = id_
1198
1199
    @staticmethod
1200
    @user_logger
1201
    def on_delete(req, resp, id_, eid):
1202
        admin_control(req)
1203
        if not id_.isdigit() or int(id_) <= 0:
1204
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1205
                                   description='API.INVALID_SPACE_ID')
1206
1207
        if not eid.isdigit() or int(eid) <= 0:
1208
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1209
                                   description='API.INVALID_COMBINED_EQUIPMENT_ID')
1210
1211
        cnx = mysql.connector.connect(**config.myems_system_db)
1212
        cursor = cnx.cursor()
1213
1214
        cursor.execute(" SELECT name "
1215
                       " FROM tbl_spaces "
1216
                       " WHERE id = %s ", (id_,))
1217
        if cursor.fetchone() is None:
1218
            cursor.close()
1219
            cnx.close()
1220
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1221
                                   description='API.SPACE_NOT_FOUND')
1222
1223
        cursor.execute(" SELECT name "
1224
                       " FROM tbl_combined_equipments "
1225
                       " WHERE id = %s ", (eid,))
1226
        if cursor.fetchone() is None:
1227
            cursor.close()
1228
            cnx.close()
1229
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1230
                                   description='API.COMBINED_EQUIPMENT_NOT_FOUND')
1231
1232
        cursor.execute(" SELECT id "
1233
                       " FROM tbl_spaces_combined_equipments "
1234
                       " WHERE space_id = %s AND combined_equipment_id = %s ", (id_, eid))
1235
        if cursor.fetchone() is None:
1236
            cursor.close()
1237
            cnx.close()
1238
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1239
                                   description='API.SPACE_COMBINED_EQUIPMENT_RELATION_NOT_FOUND')
1240
1241
        cursor.execute(" DELETE FROM tbl_spaces_combined_equipments "
1242
                       " WHERE space_id = %s AND combined_equipment_id = %s ", (id_, eid))
1243
        cnx.commit()
1244
1245
        cursor.close()
1246
        cnx.close()
1247
1248
        resp.status = falcon.HTTP_204
1249
1250
1251
class SpaceEnergyStoragePowerStationCollection:
1252
    def __init__(self):
1253
        pass
1254
1255
    @staticmethod
1256
    def on_options(req, resp, id_):
1257
        _ = req
1258
        resp.status = falcon.HTTP_200
1259
        _ = id_
1260
1261
    @staticmethod
1262
    def on_get(req, resp, id_):
1263
        # NOTE: DO NOT allow to be called by api_key
1264
        access_control(req)
1265
1266
        if not id_.isdigit() or int(id_) <= 0:
1267
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1268
                                   description='API.INVALID_SPACE_ID')
1269
1270
        if 'USER-UUID' not in req.headers or \
1271
                not isinstance(req.headers['USER-UUID'], str) or \
1272
                len(str.strip(req.headers['USER-UUID'])) == 0:
1273
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1274
                                   description='API.INVALID_USER_UUID')
1275
        user_uuid = str.strip(req.headers['USER-UUID'])
1276
1277
        cnx_user = mysql.connector.connect(**config.myems_user_db)
1278
        cursor_user = cnx_user.cursor()
1279
        cursor_user.execute(" SELECT id FROM tbl_users WHERE uuid = %s ", (user_uuid,))
1280
        row_user = cursor_user.fetchone()
1281
        if row_user is None or len(row_user) != 1:
1282
            cursor_user.close()
1283
            cnx_user.close()
1284
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1285
                                   description='API.USER_NOT_FOUND')
1286
        else:
1287
            user_id = row_user[0]
1288
1289
        # get privilege
1290
        query = (" SELECT is_admin "
1291
                 " FROM tbl_users "
1292
                 " WHERE uuid = %s ")
1293
        cursor_user.execute(query, (user_uuid,))
1294
        row = cursor_user.fetchone()
1295
        if row is None:
1296
            cursor_user.close()
1297
            cnx_user.close()
1298
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', description='API.USER_NOT_FOUND')
1299
        else:
1300
            is_admin = bool(row[0])
1301
1302
        cnx = mysql.connector.connect(**config.myems_system_db)
1303
        cursor = cnx.cursor()
1304
1305
        cursor.execute(" SELECT name "
1306
                       " FROM tbl_spaces "
1307
                       " WHERE id = %s ", (id_,))
1308
        if cursor.fetchone() is None:
1309
            cursor.close()
1310
            cnx.close()
1311
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1312
                                   description='API.SPACE_NOT_FOUND')
1313
1314
        if is_admin:
1315
            query = (" SELECT e.id, e.name, e.uuid, e.phase_of_lifecycle "
1316
                     " FROM tbl_spaces s, tbl_spaces_energy_storage_power_stations se, "
1317
                     "      tbl_energy_storage_power_stations e "
1318
                     " WHERE se.space_id = s.id AND e.id = se.energy_storage_power_station_id AND s.id = %s "
1319
                     " ORDER BY e.phase_of_lifecycle, e.id ")
1320
            cursor.execute(query, (id_,))
1321
        else:
1322
            query = (" SELECT e.id, e.name, e.uuid, e.phase_of_lifecycle "
1323
                     " FROM tbl_spaces s, tbl_spaces_energy_storage_power_stations se, "
1324
                     "      tbl_energy_storage_power_stations e, tbl_energy_storage_power_stations_users su "
1325
                     " WHERE se.space_id = s.id AND e.id = se.energy_storage_power_station_id AND "
1326
                     "       e.id = su.energy_storage_power_station_id AND s.id = %s AND su.user_id = %s "
1327
                     " ORDER BY e.phase_of_lifecycle, e.id ")
1328
            cursor.execute(query, (id_, user_id))
1329
        rows = cursor.fetchall()
1330
1331
        result = list()
1332
        if rows is not None and len(rows) > 0:
1333
            for row in rows:
1334
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
1335
                result.append(meta_result)
1336
1337
        resp.text = json.dumps(result)
1338
1339
    @staticmethod
1340
    @user_logger
1341
    def on_post(req, resp, id_):
1342
        """Handles POST requests"""
1343
        admin_control(req)
1344
        try:
1345
            raw_json = req.stream.read().decode('utf-8')
1346
        except UnicodeDecodeError as ex:
1347
            print("Failed to decode request")
1348
            raise falcon.HTTPError(status=falcon.HTTP_400,
1349
                                   title='API.BAD_REQUEST',
1350
                                   description='API.INVALID_ENCODING')
1351
        except Exception as ex:
1352
            print("Unexpected error reading request stream")
1353
            raise falcon.HTTPError(status=falcon.HTTP_400,
1354
                                   title='API.BAD_REQUEST',
1355
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1356
1357
        if not id_.isdigit() or int(id_) <= 0:
1358
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1359
                                   description='API.INVALID_SPACE_ID')
1360
1361
        new_values = json.loads(raw_json)
1362
1363
        if 'energy_storage_power_station_id' not in new_values['data'].keys() or \
1364
                not isinstance(new_values['data']['energy_storage_power_station_id'], int) or \
1365
                new_values['data']['energy_storage_power_station_id'] <= 0:
1366
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1367
                                   description='API.INVALID_ENERGY_STORAGE_POWER_STATION_ID')
1368
        energy_storage_power_station_id = new_values['data']['energy_storage_power_station_id']
1369
1370
        cnx = mysql.connector.connect(**config.myems_system_db)
1371
        cursor = cnx.cursor()
1372
1373
        cursor.execute(" SELECT name "
1374
                       " from tbl_spaces "
1375
                       " WHERE id = %s ", (id_,))
1376
        if cursor.fetchone() is None:
1377
            cursor.close()
1378
            cnx.close()
1379
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1380
                                   description='API.SPACE_NOT_FOUND')
1381
1382
        cursor.execute(" SELECT name "
1383
                       " FROM tbl_energy_storage_power_stations "
1384
                       " WHERE id = %s ", (energy_storage_power_station_id,))
1385
        if cursor.fetchone() is None:
1386
            cursor.close()
1387
            cnx.close()
1388
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1389
                                   description='API.ENERGY_STORAGE_POWER_STATION_NOT_FOUND')
1390
1391
        query = (" SELECT id "
1392
                 " FROM tbl_spaces_energy_storage_power_stations "
1393
                 " WHERE space_id = %s AND energy_storage_power_station_id = %s")
1394
        cursor.execute(query, (id_, energy_storage_power_station_id,))
1395
        if cursor.fetchone() is not None:
1396
            cursor.close()
1397
            cnx.close()
1398
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1399
                                   description='API.SPACE_ENERGY_STORAGE_POWER_STATION_RELATION_EXISTS')
1400
1401
        add_row = (" INSERT INTO tbl_spaces_energy_storage_power_stations (space_id, energy_storage_power_station_id) "
1402
                   " VALUES (%s, %s) ")
1403
        cursor.execute(add_row, (id_, energy_storage_power_station_id,))
1404
        cnx.commit()
1405
        cursor.close()
1406
        cnx.close()
1407
1408
        resp.status = falcon.HTTP_201
1409
        resp.location = '/spaces/' + str(id_) + '/energystoragepowerstations/' + str(energy_storage_power_station_id)
1410
1411
1412
class SpaceEnergyStoragePowerStationItem:
1413
    def __init__(self):
1414
        pass
1415
1416
    @staticmethod
1417
    def on_options(req, resp, id_, eid):
1418
        _ = req
1419
        resp.status = falcon.HTTP_200
1420
        _ = id_
1421
1422
    @staticmethod
1423
    @user_logger
1424
    def on_delete(req, resp, id_, eid):
1425
        admin_control(req)
1426
        if not id_.isdigit() or int(id_) <= 0:
1427
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1428
                                   description='API.INVALID_SPACE_ID')
1429
1430
        if not eid.isdigit() or int(eid) <= 0:
1431
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1432
                                   description='API.INVALID_ENERGY_STORAGE_POWER_STATION_ID')
1433
1434
        cnx = mysql.connector.connect(**config.myems_system_db)
1435
        cursor = cnx.cursor()
1436
1437
        cursor.execute(" SELECT name "
1438
                       " FROM tbl_spaces "
1439
                       " WHERE id = %s ", (id_,))
1440
        if cursor.fetchone() is None:
1441
            cursor.close()
1442
            cnx.close()
1443
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1444
                                   description='API.SPACE_NOT_FOUND')
1445
1446
        cursor.execute(" SELECT name "
1447
                       " FROM tbl_energy_storage_power_stations "
1448
                       " WHERE id = %s ", (eid,))
1449
        if cursor.fetchone() is None:
1450
            cursor.close()
1451
            cnx.close()
1452
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1453
                                   description='API.ENERGY_STORAGE_POWER_STATION_NOT_FOUND')
1454
1455
        cursor.execute(" SELECT id "
1456
                       " FROM tbl_spaces_energy_storage_power_stations "
1457
                       " WHERE space_id = %s AND energy_storage_power_station_id = %s ", (id_, eid))
1458
        if cursor.fetchone() is None:
1459
            cursor.close()
1460
            cnx.close()
1461
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1462
                                   description='API.SPACE_ENERGY_STORAGE_POWER_STATION_RELATION_NOT_FOUND')
1463
1464
        cursor.execute(" DELETE FROM tbl_spaces_energy_storage_power_stations "
1465
                       " WHERE space_id = %s AND energy_storage_power_station_id = %s ", (id_, eid))
1466
        cnx.commit()
1467
1468
        cursor.close()
1469
        cnx.close()
1470
1471
        resp.status = falcon.HTTP_204
1472
1473
1474 View Code Duplication
class SpaceEquipmentCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1475
    def __init__(self):
1476
        pass
1477
1478
    @staticmethod
1479
    def on_options(req, resp, id_):
1480
        _ = req
1481
        resp.status = falcon.HTTP_200
1482
        _ = id_
1483
1484
    @staticmethod
1485
    def on_get(req, resp, id_):
1486
        if 'API-KEY' not in req.headers or \
1487
                not isinstance(req.headers['API-KEY'], str) or \
1488
                len(str.strip(req.headers['API-KEY'])) == 0:
1489
            access_control(req)
1490
        else:
1491
            api_key_control(req)
1492
        if not id_.isdigit() or int(id_) <= 0:
1493
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1494
                                   description='API.INVALID_SPACE_ID')
1495
1496
        cnx = mysql.connector.connect(**config.myems_system_db)
1497
        cursor = cnx.cursor()
1498
1499
        cursor.execute(" SELECT name "
1500
                       " FROM tbl_spaces "
1501
                       " WHERE id = %s ", (id_,))
1502
        if cursor.fetchone() is None:
1503
            cursor.close()
1504
            cnx.close()
1505
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1506
                                   description='API.SPACE_NOT_FOUND')
1507
1508
        query = (" SELECT e.id, e.name, e.uuid "
1509
                 " FROM tbl_spaces s, tbl_spaces_equipments se, tbl_equipments e "
1510
                 " WHERE se.space_id = s.id AND e.id = se.equipment_id AND s.id = %s "
1511
                 " ORDER BY e.id ")
1512
        cursor.execute(query, (id_,))
1513
        rows = cursor.fetchall()
1514
1515
        result = list()
1516
        if rows is not None and len(rows) > 0:
1517
            for row in rows:
1518
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
1519
                result.append(meta_result)
1520
1521
        resp.text = json.dumps(result)
1522
1523
    @staticmethod
1524
    @user_logger
1525
    def on_post(req, resp, id_):
1526
        """Handles POST requests"""
1527
        admin_control(req)
1528
        try:
1529
            raw_json = req.stream.read().decode('utf-8')
1530
        except UnicodeDecodeError as ex:
1531
            print("Failed to decode request")
1532
            raise falcon.HTTPError(status=falcon.HTTP_400,
1533
                                   title='API.BAD_REQUEST',
1534
                                   description='API.INVALID_ENCODING')
1535
        except Exception as ex:
1536
            print("Unexpected error reading request stream")
1537
            raise falcon.HTTPError(status=falcon.HTTP_400,
1538
                                   title='API.BAD_REQUEST',
1539
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1540
1541
        if not id_.isdigit() or int(id_) <= 0:
1542
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1543
                                   description='API.INVALID_SPACE_ID')
1544
1545
        new_values = json.loads(raw_json)
1546
1547
        if 'equipment_id' not in new_values['data'].keys() or \
1548
                not isinstance(new_values['data']['equipment_id'], int) or \
1549
                new_values['data']['equipment_id'] <= 0:
1550
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1551
                                   description='API.INVALID_EQUIPMENT_ID')
1552
        equipment_id = new_values['data']['equipment_id']
1553
1554
        cnx = mysql.connector.connect(**config.myems_system_db)
1555
        cursor = cnx.cursor()
1556
1557
        cursor.execute(" SELECT name "
1558
                       " from tbl_spaces "
1559
                       " WHERE id = %s ", (id_,))
1560
        if cursor.fetchone() is None:
1561
            cursor.close()
1562
            cnx.close()
1563
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1564
                                   description='API.SPACE_NOT_FOUND')
1565
1566
        cursor.execute(" SELECT name "
1567
                       " FROM tbl_equipments "
1568
                       " WHERE id = %s ", (equipment_id,))
1569
        if cursor.fetchone() is None:
1570
            cursor.close()
1571
            cnx.close()
1572
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1573
                                   description='API.EQUIPMENT_NOT_FOUND')
1574
1575
        query = (" SELECT id "
1576
                 " FROM tbl_spaces_equipments "
1577
                 " WHERE space_id = %s AND equipment_id = %s")
1578
        cursor.execute(query, (id_, equipment_id,))
1579
        if cursor.fetchone() is not None:
1580
            cursor.close()
1581
            cnx.close()
1582
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1583
                                   description='API.SPACE_EQUIPMENT_RELATION_EXISTS')
1584
1585
        add_row = (" INSERT INTO tbl_spaces_equipments (space_id, equipment_id) "
1586
                   " VALUES (%s, %s) ")
1587
        cursor.execute(add_row, (id_, equipment_id,))
1588
        cnx.commit()
1589
        cursor.close()
1590
        cnx.close()
1591
1592
        resp.status = falcon.HTTP_201
1593
        resp.location = '/spaces/' + str(id_) + '/equipments/' + str(equipment_id)
1594
1595
1596
class SpaceEquipmentItem:
1597
    def __init__(self):
1598
        pass
1599
1600
    @staticmethod
1601
    def on_options(req, resp, id_, eid):
1602
        _ = req
1603
        resp.status = falcon.HTTP_200
1604
        _ = id_
1605
1606
    @staticmethod
1607
    @user_logger
1608
    def on_delete(req, resp, id_, eid):
1609
        admin_control(req)
1610
        if not id_.isdigit() or int(id_) <= 0:
1611
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1612
                                   description='API.INVALID_SPACE_ID')
1613
1614
        if not eid.isdigit() or int(eid) <= 0:
1615
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1616
                                   description='API.INVALID_EQUIPMENT_ID')
1617
1618
        cnx = mysql.connector.connect(**config.myems_system_db)
1619
        cursor = cnx.cursor()
1620
1621
        cursor.execute(" SELECT name "
1622
                       " FROM tbl_spaces "
1623
                       " WHERE id = %s ", (id_,))
1624
        if cursor.fetchone() is None:
1625
            cursor.close()
1626
            cnx.close()
1627
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1628
                                   description='API.SPACE_NOT_FOUND')
1629
1630
        cursor.execute(" SELECT name "
1631
                       " FROM tbl_equipments "
1632
                       " WHERE id = %s ", (eid,))
1633
        if cursor.fetchone() is None:
1634
            cursor.close()
1635
            cnx.close()
1636
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1637
                                   description='API.EQUIPMENT_NOT_FOUND')
1638
1639
        cursor.execute(" SELECT id "
1640
                       " FROM tbl_spaces_equipments "
1641
                       " WHERE space_id = %s AND equipment_id = %s ", (id_, eid))
1642
        if cursor.fetchone() is None:
1643
            cursor.close()
1644
            cnx.close()
1645
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1646
                                   description='API.SPACE_EQUIPMENT_RELATION_NOT_FOUND')
1647
1648
        cursor.execute(" DELETE FROM tbl_spaces_equipments WHERE space_id = %s AND equipment_id = %s ", (id_, eid))
1649
        cnx.commit()
1650
1651
        cursor.close()
1652
        cnx.close()
1653
1654
        resp.status = falcon.HTTP_204
1655
1656
1657 View Code Duplication
class SpaceMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1658
    def __init__(self):
1659
        pass
1660
1661
    @staticmethod
1662
    def on_options(req, resp, id_):
1663
        _ = req
1664
        resp.status = falcon.HTTP_200
1665
        _ = id_
1666
1667
    @staticmethod
1668
    def on_get(req, resp, id_):
1669
        if 'API-KEY' not in req.headers or \
1670
                not isinstance(req.headers['API-KEY'], str) or \
1671
                len(str.strip(req.headers['API-KEY'])) == 0:
1672
            access_control(req)
1673
        else:
1674
            api_key_control(req)
1675
        if not id_.isdigit() or int(id_) <= 0:
1676
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1677
                                   description='API.INVALID_SPACE_ID')
1678
1679
        cnx = mysql.connector.connect(**config.myems_system_db)
1680
        cursor = cnx.cursor()
1681
1682
        cursor.execute(" SELECT name "
1683
                       " FROM tbl_spaces "
1684
                       " WHERE id = %s ", (id_,))
1685
        if cursor.fetchone() is None:
1686
            cursor.close()
1687
            cnx.close()
1688
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1689
                                   description='API.SPACE_NOT_FOUND')
1690
1691
        query = (" SELECT id, name, uuid "
1692
                 " FROM tbl_energy_categories ")
1693
        cursor.execute(query)
1694
        rows_energy_categories = cursor.fetchall()
1695
1696
        energy_category_dict = dict()
1697
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1698
            for row in rows_energy_categories:
1699
                energy_category_dict[row[0]] = {"id": row[0],
1700
                                                "name": row[1],
1701
                                                "uuid": row[2]}
1702
1703
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
1704
                 " FROM tbl_spaces s, tbl_spaces_meters sm, tbl_meters m "
1705
                 " WHERE sm.space_id = s.id AND m.id = sm.meter_id AND s.id = %s "
1706
                 " ORDER BY m.id ")
1707
        cursor.execute(query, (id_,))
1708
        rows = cursor.fetchall()
1709
1710
        result = list()
1711
        if rows is not None and len(rows) > 0:
1712
            for row in rows:
1713
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2],
1714
                               "energy_category": energy_category_dict.get(row[3], None)}
1715
                result.append(meta_result)
1716
1717
        resp.text = json.dumps(result)
1718
1719
    @staticmethod
1720
    @user_logger
1721
    def on_post(req, resp, id_):
1722
        """Handles POST requests"""
1723
        admin_control(req)
1724
        try:
1725
            raw_json = req.stream.read().decode('utf-8')
1726
        except UnicodeDecodeError as ex:
1727
            print("Failed to decode request")
1728
            raise falcon.HTTPError(status=falcon.HTTP_400,
1729
                                   title='API.BAD_REQUEST',
1730
                                   description='API.INVALID_ENCODING')
1731
        except Exception as ex:
1732
            print("Unexpected error reading request stream")
1733
            raise falcon.HTTPError(status=falcon.HTTP_400,
1734
                                   title='API.BAD_REQUEST',
1735
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1736
1737
        if not id_.isdigit() or int(id_) <= 0:
1738
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1739
                                   description='API.INVALID_SPACE_ID')
1740
1741
        new_values = json.loads(raw_json)
1742
1743
        if 'meter_id' not in new_values['data'].keys() or \
1744
                not isinstance(new_values['data']['meter_id'], int) or \
1745
                new_values['data']['meter_id'] <= 0:
1746
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1747
                                   description='API.INVALID_METER_ID')
1748
        meter_id = new_values['data']['meter_id']
1749
1750
        cnx = mysql.connector.connect(**config.myems_system_db)
1751
        cursor = cnx.cursor()
1752
1753
        cursor.execute(" SELECT name "
1754
                       " from tbl_spaces "
1755
                       " WHERE id = %s ", (id_,))
1756
        if cursor.fetchone() is None:
1757
            cursor.close()
1758
            cnx.close()
1759
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1760
                                   description='API.SPACE_NOT_FOUND')
1761
1762
        cursor.execute(" SELECT name "
1763
                       " FROM tbl_meters "
1764
                       " WHERE id = %s ", (meter_id,))
1765
        if cursor.fetchone() is None:
1766
            cursor.close()
1767
            cnx.close()
1768
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1769
                                   description='API.METER_NOT_FOUND')
1770
1771
        query = (" SELECT id "
1772
                 " FROM tbl_spaces_meters "
1773
                 " WHERE space_id = %s AND meter_id = %s")
1774
        cursor.execute(query, (id_, meter_id,))
1775
        if cursor.fetchone() is not None:
1776
            cursor.close()
1777
            cnx.close()
1778
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1779
                                   description='API.SPACE_METER_RELATION_EXISTS')
1780
1781
        add_row = (" INSERT INTO tbl_spaces_meters (space_id, meter_id) "
1782
                   " VALUES (%s, %s) ")
1783
        cursor.execute(add_row, (id_, meter_id,))
1784
        cnx.commit()
1785
        cursor.close()
1786
        cnx.close()
1787
1788
        resp.status = falcon.HTTP_201
1789
        resp.location = '/spaces/' + str(id_) + '/meters/' + str(meter_id)
1790
1791
1792 View Code Duplication
class SpaceMeterItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1793
    def __init__(self):
1794
        pass
1795
1796
    @staticmethod
1797
    def on_options(req, resp, id_, mid):
1798
        _ = req
1799
        resp.status = falcon.HTTP_200
1800
        _ = id_
1801
1802
    @staticmethod
1803
    @user_logger
1804
    def on_delete(req, resp, id_, mid):
1805
        admin_control(req)
1806
        if not id_.isdigit() or int(id_) <= 0:
1807
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1808
                                   description='API.INVALID_SPACE_ID')
1809
1810
        if not mid.isdigit() or int(mid) <= 0:
1811
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1812
                                   description='API.INVALID_METER_ID')
1813
1814
        cnx = mysql.connector.connect(**config.myems_system_db)
1815
        cursor = cnx.cursor()
1816
1817
        cursor.execute(" SELECT name "
1818
                       " FROM tbl_spaces "
1819
                       " WHERE id = %s ", (id_,))
1820
        if cursor.fetchone() is None:
1821
            cursor.close()
1822
            cnx.close()
1823
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1824
                                   description='API.SPACE_NOT_FOUND')
1825
1826
        cursor.execute(" SELECT name "
1827
                       " FROM tbl_meters "
1828
                       " WHERE id = %s ", (mid,))
1829
        if cursor.fetchone() 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
1835
        cursor.execute(" SELECT id "
1836
                       " FROM tbl_spaces_meters "
1837
                       " WHERE space_id = %s AND meter_id = %s ", (id_, mid))
1838
        # use fetchall to avoid 'Unread result found' error in case there are duplicate rows
1839
        rows = cursor.fetchall()
1840
        if rows is None or len(rows) == 0:
1841
            cursor.close()
1842
            cnx.close()
1843
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1844
                                   description='API.SPACE_METER_RELATION_NOT_FOUND')
1845
1846
        cursor.execute(" DELETE FROM tbl_spaces_meters WHERE space_id = %s AND meter_id = %s ", (id_, mid))
1847
        cnx.commit()
1848
1849
        cursor.close()
1850
        cnx.close()
1851
1852
        resp.status = falcon.HTTP_204
1853
1854
1855 View Code Duplication
class SpaceMicrogridCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1856
    def __init__(self):
1857
        pass
1858
1859
    @staticmethod
1860
    def on_options(req, resp, id_):
1861
        _ = req
1862
        resp.status = falcon.HTTP_200
1863
        _ = id_
1864
1865
    @staticmethod
1866
    def on_get(req, resp, id_):
1867
        if 'API-KEY' not in req.headers or \
1868
                not isinstance(req.headers['API-KEY'], str) or \
1869
                len(str.strip(req.headers['API-KEY'])) == 0:
1870
            access_control(req)
1871
        else:
1872
            api_key_control(req)
1873
        if not id_.isdigit() or int(id_) <= 0:
1874
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1875
                                   description='API.INVALID_SPACE_ID')
1876
1877
        cnx = mysql.connector.connect(**config.myems_system_db)
1878
        cursor = cnx.cursor()
1879
1880
        cursor.execute(" SELECT name "
1881
                       " FROM tbl_spaces "
1882
                       " WHERE id = %s ", (id_,))
1883
        if cursor.fetchone() is None:
1884
            cursor.close()
1885
            cnx.close()
1886
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1887
                                   description='API.SPACE_NOT_FOUND')
1888
1889
        query = (" SELECT e.id, e.name, e.uuid, e.phase_of_lifecycle "
1890
                 " FROM tbl_spaces s, tbl_spaces_microgrids se, tbl_microgrids e "
1891
                 " WHERE se.space_id = s.id AND e.id = se.microgrid_id AND s.id = %s "
1892
                 " ORDER BY e.phase_of_lifecycle, e.id ")
1893
        cursor.execute(query, (id_,))
1894
        rows = cursor.fetchall()
1895
1896
        result = list()
1897
        if rows is not None and len(rows) > 0:
1898
            for row in rows:
1899
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
1900
                result.append(meta_result)
1901
1902
        resp.text = json.dumps(result)
1903
1904
    @staticmethod
1905
    @user_logger
1906
    def on_post(req, resp, id_):
1907
        """Handles POST requests"""
1908
        admin_control(req)
1909
        try:
1910
            raw_json = req.stream.read().decode('utf-8')
1911
        except UnicodeDecodeError as ex:
1912
            print("Failed to decode request")
1913
            raise falcon.HTTPError(status=falcon.HTTP_400,
1914
                                   title='API.BAD_REQUEST',
1915
                                   description='API.INVALID_ENCODING')
1916
        except Exception as ex:
1917
            print("Unexpected error reading request stream")
1918
            raise falcon.HTTPError(status=falcon.HTTP_400,
1919
                                   title='API.BAD_REQUEST',
1920
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1921
1922
        if not id_.isdigit() or int(id_) <= 0:
1923
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1924
                                   description='API.INVALID_SPACE_ID')
1925
1926
        new_values = json.loads(raw_json)
1927
1928
        if 'microgrid_id' not in new_values['data'].keys() or \
1929
                not isinstance(new_values['data']['microgrid_id'], int) or \
1930
                new_values['data']['microgrid_id'] <= 0:
1931
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1932
                                   description='API.INVALID_MICROGRID_ID')
1933
        microgrid_id = new_values['data']['microgrid_id']
1934
1935
        cnx = mysql.connector.connect(**config.myems_system_db)
1936
        cursor = cnx.cursor()
1937
1938
        cursor.execute(" SELECT name "
1939
                       " from tbl_spaces "
1940
                       " WHERE id = %s ", (id_,))
1941
        if cursor.fetchone() is None:
1942
            cursor.close()
1943
            cnx.close()
1944
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1945
                                   description='API.SPACE_NOT_FOUND')
1946
1947
        cursor.execute(" SELECT name "
1948
                       " FROM tbl_microgrids "
1949
                       " WHERE id = %s ", (microgrid_id,))
1950
        if cursor.fetchone() is None:
1951
            cursor.close()
1952
            cnx.close()
1953
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1954
                                   description='API.MICROGRID_NOT_FOUND')
1955
1956
        query = (" SELECT id "
1957
                 " FROM tbl_spaces_microgrids "
1958
                 " WHERE space_id = %s AND microgrid_id = %s")
1959
        cursor.execute(query, (id_, microgrid_id,))
1960
        if cursor.fetchone() is not None:
1961
            cursor.close()
1962
            cnx.close()
1963
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1964
                                   description='API.SPACE_MICROGRID_RELATION_EXISTS')
1965
1966
        add_row = (" INSERT INTO tbl_spaces_microgrids (space_id, microgrid_id) "
1967
                   " VALUES (%s, %s) ")
1968
        cursor.execute(add_row, (id_, microgrid_id,))
1969
        cnx.commit()
1970
        cursor.close()
1971
        cnx.close()
1972
1973
        resp.status = falcon.HTTP_201
1974
        resp.location = '/spaces/' + str(id_) + '/microgrids/' + str(microgrid_id)
1975
1976
1977
class SpaceMicrogridItem:
1978
    def __init__(self):
1979
        pass
1980
1981
    @staticmethod
1982
    def on_options(req, resp, id_, mid):
1983
        _ = req
1984
        resp.status = falcon.HTTP_200
1985
        _ = id_
1986
1987
    @staticmethod
1988
    @user_logger
1989
    def on_delete(req, resp, id_, mid):
1990
        admin_control(req)
1991
        if not id_.isdigit() or int(id_) <= 0:
1992
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1993
                                   description='API.INVALID_SPACE_ID')
1994
1995
        if not mid.isdigit() or int(mid) <= 0:
1996
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1997
                                   description='API.INVALID_MICROGRID_ID')
1998
1999
        cnx = mysql.connector.connect(**config.myems_system_db)
2000
        cursor = cnx.cursor()
2001
2002
        cursor.execute(" SELECT name "
2003
                       " FROM tbl_spaces "
2004
                       " WHERE id = %s ", (id_,))
2005
        if cursor.fetchone() is None:
2006
            cursor.close()
2007
            cnx.close()
2008
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2009
                                   description='API.SPACE_NOT_FOUND')
2010
2011
        cursor.execute(" SELECT name "
2012
                       " FROM tbl_microgrids "
2013
                       " WHERE id = %s ", (mid,))
2014
        if cursor.fetchone() is None:
2015
            cursor.close()
2016
            cnx.close()
2017
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2018
                                   description='API.MICROGRID_NOT_FOUND')
2019
2020
        cursor.execute(" SELECT id "
2021
                       " FROM tbl_spaces_microgrids "
2022
                       " WHERE space_id = %s AND microgrid_id = %s ", (id_, mid))
2023
        if cursor.fetchone() is None:
2024
            cursor.close()
2025
            cnx.close()
2026
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2027
                                   description='API.SPACE_MICROGRID_RELATION_NOT_FOUND')
2028
2029
        cursor.execute(" DELETE FROM tbl_spaces_microgrids "
2030
                       " WHERE space_id = %s AND microgrid_id = %s ", (id_, mid))
2031
        cnx.commit()
2032
2033
        cursor.close()
2034
        cnx.close()
2035
2036
        resp.status = falcon.HTTP_204
2037
2038
2039 View Code Duplication
class SpaceOfflineMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2040
    def __init__(self):
2041
        pass
2042
2043
    @staticmethod
2044
    def on_options(req, resp, id_):
2045
        _ = req
2046
        resp.status = falcon.HTTP_200
2047
        _ = id_
2048
2049
    @staticmethod
2050
    def on_get(req, resp, id_):
2051
        if 'API-KEY' not in req.headers or \
2052
                not isinstance(req.headers['API-KEY'], str) or \
2053
                len(str.strip(req.headers['API-KEY'])) == 0:
2054
            access_control(req)
2055
        else:
2056
            api_key_control(req)
2057
        if not id_.isdigit() or int(id_) <= 0:
2058
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2059
                                   description='API.INVALID_SPACE_ID')
2060
2061
        cnx = mysql.connector.connect(**config.myems_system_db)
2062
        cursor = cnx.cursor()
2063
2064
        cursor.execute(" SELECT name "
2065
                       " FROM tbl_spaces "
2066
                       " WHERE id = %s ", (id_,))
2067
        if cursor.fetchone() is None:
2068
            cursor.close()
2069
            cnx.close()
2070
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2071
                                   description='API.SPACE_NOT_FOUND')
2072
2073
        query = (" SELECT id, name, uuid "
2074
                 " FROM tbl_energy_categories ")
2075
        cursor.execute(query)
2076
        rows_energy_categories = cursor.fetchall()
2077
2078
        energy_category_dict = dict()
2079
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2080
            for row in rows_energy_categories:
2081
                energy_category_dict[row[0]] = {"id": row[0],
2082
                                                "name": row[1],
2083
                                                "uuid": row[2]}
2084
2085
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2086
                 " FROM tbl_spaces s, tbl_spaces_offline_meters sm, tbl_offline_meters m "
2087
                 " WHERE sm.space_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
2088
                 " ORDER BY m.id ")
2089
        cursor.execute(query, (id_,))
2090
        rows = cursor.fetchall()
2091
2092
        result = list()
2093
        if rows is not None and len(rows) > 0:
2094
            for row in rows:
2095
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2],
2096
                               "energy_category": energy_category_dict.get(row[3], None)}
2097
                result.append(meta_result)
2098
2099
        resp.text = json.dumps(result)
2100
2101
    @staticmethod
2102
    @user_logger
2103
    def on_post(req, resp, id_):
2104
        """Handles POST requests"""
2105
        admin_control(req)
2106
        try:
2107
            raw_json = req.stream.read().decode('utf-8')
2108
        except UnicodeDecodeError as ex:
2109
            print("Failed to decode request")
2110
            raise falcon.HTTPError(status=falcon.HTTP_400,
2111
                                   title='API.BAD_REQUEST',
2112
                                   description='API.INVALID_ENCODING')
2113
        except Exception as ex:
2114
            print("Unexpected error reading request stream")
2115
            raise falcon.HTTPError(status=falcon.HTTP_400,
2116
                                   title='API.BAD_REQUEST',
2117
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2118
2119
        if not id_.isdigit() or int(id_) <= 0:
2120
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2121
                                   description='API.INVALID_SPACE_ID')
2122
2123
        new_values = json.loads(raw_json)
2124
2125
        if 'offline_meter_id' not in new_values['data'].keys() or \
2126
                not isinstance(new_values['data']['offline_meter_id'], int) or \
2127
                new_values['data']['offline_meter_id'] <= 0:
2128
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2129
                                   description='API.INVALID_OFFLINE_METER_ID')
2130
        offline_meter_id = new_values['data']['offline_meter_id']
2131
2132
        cnx = mysql.connector.connect(**config.myems_system_db)
2133
        cursor = cnx.cursor()
2134
2135
        cursor.execute(" SELECT name "
2136
                       " from tbl_spaces "
2137
                       " WHERE id = %s ", (id_,))
2138
        if cursor.fetchone() is None:
2139
            cursor.close()
2140
            cnx.close()
2141
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2142
                                   description='API.SPACE_NOT_FOUND')
2143
2144
        cursor.execute(" SELECT name "
2145
                       " FROM tbl_offline_meters "
2146
                       " WHERE id = %s ", (offline_meter_id,))
2147
        if cursor.fetchone() is None:
2148
            cursor.close()
2149
            cnx.close()
2150
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2151
                                   description='API.OFFLINE_METER_NOT_FOUND')
2152
2153
        query = (" SELECT id "
2154
                 " FROM tbl_spaces_offline_meters "
2155
                 " WHERE space_id = %s AND offline_meter_id = %s")
2156
        cursor.execute(query, (id_, offline_meter_id,))
2157
        if cursor.fetchone() is not None:
2158
            cursor.close()
2159
            cnx.close()
2160
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2161
                                   description='API.SPACE_OFFLINE_METER_RELATION_EXISTS')
2162
2163
        add_row = (" INSERT INTO tbl_spaces_offline_meters (space_id, offline_meter_id) "
2164
                   " VALUES (%s, %s) ")
2165
        cursor.execute(add_row, (id_, offline_meter_id,))
2166
        cnx.commit()
2167
        cursor.close()
2168
        cnx.close()
2169
2170
        resp.status = falcon.HTTP_201
2171
        resp.location = '/spaces/' + str(id_) + '/offlinemeters/' + str(offline_meter_id)
2172
2173
2174
class SpaceOfflineMeterItem:
2175
    def __init__(self):
2176
        pass
2177
2178
    @staticmethod
2179
    def on_options(req, resp, id_, mid):
2180
        _ = req
2181
        resp.status = falcon.HTTP_200
2182
        _ = id_
2183
2184
    @staticmethod
2185
    @user_logger
2186
    def on_delete(req, resp, id_, mid):
2187
        admin_control(req)
2188
        if not id_.isdigit() or int(id_) <= 0:
2189
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2190
                                   description='API.INVALID_SPACE_ID')
2191
2192
        if not mid.isdigit() or int(mid) <= 0:
2193
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2194
                                   description='API.INVALID_OFFLINE_METER_ID')
2195
2196
        cnx = mysql.connector.connect(**config.myems_system_db)
2197
        cursor = cnx.cursor()
2198
2199
        cursor.execute(" SELECT name "
2200
                       " FROM tbl_spaces "
2201
                       " WHERE id = %s ", (id_,))
2202
        if cursor.fetchone() is None:
2203
            cursor.close()
2204
            cnx.close()
2205
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2206
                                   description='API.SPACE_NOT_FOUND')
2207
2208
        cursor.execute(" SELECT name "
2209
                       " FROM tbl_offline_meters "
2210
                       " WHERE id = %s ", (mid,))
2211
        if cursor.fetchone() is None:
2212
            cursor.close()
2213
            cnx.close()
2214
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2215
                                   description='API.OFFLINE_METER_NOT_FOUND')
2216
2217
        cursor.execute(" SELECT id "
2218
                       " FROM tbl_spaces_offline_meters "
2219
                       " WHERE space_id = %s AND offline_meter_id = %s ", (id_, mid))
2220
        if cursor.fetchone() is None:
2221
            cursor.close()
2222
            cnx.close()
2223
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2224
                                   description='API.SPACE_OFFLINE_METER_RELATION_NOT_FOUND')
2225
2226
        cursor.execute(" DELETE FROM tbl_spaces_offline_meters "
2227
                       " WHERE space_id = %s AND offline_meter_id = %s ", (id_, mid))
2228
        cnx.commit()
2229
2230
        cursor.close()
2231
        cnx.close()
2232
2233
        resp.status = falcon.HTTP_204
2234
2235
2236 View Code Duplication
class SpacePhotovoltaicPowerStationCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2237
    def __init__(self):
2238
        pass
2239
2240
    @staticmethod
2241
    def on_options(req, resp, id_):
2242
        _ = req
2243
        resp.status = falcon.HTTP_200
2244
        _ = id_
2245
2246
    @staticmethod
2247
    def on_get(req, resp, id_):
2248
        if 'API-KEY' not in req.headers or \
2249
                not isinstance(req.headers['API-KEY'], str) or \
2250
                len(str.strip(req.headers['API-KEY'])) == 0:
2251
            access_control(req)
2252
        else:
2253
            api_key_control(req)
2254
        if not id_.isdigit() or int(id_) <= 0:
2255
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2256
                                   description='API.INVALID_SPACE_ID')
2257
2258
        cnx = mysql.connector.connect(**config.myems_system_db)
2259
        cursor = cnx.cursor()
2260
2261
        cursor.execute(" SELECT name "
2262
                       " FROM tbl_spaces "
2263
                       " WHERE id = %s ", (id_,))
2264
        if cursor.fetchone() is None:
2265
            cursor.close()
2266
            cnx.close()
2267
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2268
                                   description='API.SPACE_NOT_FOUND')
2269
2270
        query = (" SELECT e.id, e.name, e.uuid, e.phase_of_lifecycle "
2271
                 " FROM tbl_spaces s, tbl_spaces_photovoltaic_power_stations se, tbl_photovoltaic_power_stations e "
2272
                 " WHERE se.space_id = s.id AND e.id = se.photovoltaic_power_station_id AND s.id = %s "
2273
                 " ORDER BY e.phase_of_lifecycle, e.id ")
2274
        cursor.execute(query, (id_,))
2275
        rows = cursor.fetchall()
2276
2277
        result = list()
2278
        if rows is not None and len(rows) > 0:
2279
            for row in rows:
2280
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
2281
                result.append(meta_result)
2282
2283
        resp.text = json.dumps(result)
2284
2285
    @staticmethod
2286
    @user_logger
2287
    def on_post(req, resp, id_):
2288
        """Handles POST requests"""
2289
        admin_control(req)
2290
        try:
2291
            raw_json = req.stream.read().decode('utf-8')
2292
        except UnicodeDecodeError as ex:
2293
            print("Failed to decode request")
2294
            raise falcon.HTTPError(status=falcon.HTTP_400,
2295
                                   title='API.BAD_REQUEST',
2296
                                   description='API.INVALID_ENCODING')
2297
        except Exception as ex:
2298
            print("Unexpected error reading request stream")
2299
            raise falcon.HTTPError(status=falcon.HTTP_400,
2300
                                   title='API.BAD_REQUEST',
2301
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2302
2303
        if not id_.isdigit() or int(id_) <= 0:
2304
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2305
                                   description='API.INVALID_SPACE_ID')
2306
2307
        new_values = json.loads(raw_json)
2308
2309
        if 'photovoltaic_power_station_id' not in new_values['data'].keys() or \
2310
                not isinstance(new_values['data']['photovoltaic_power_station_id'], int) or \
2311
                new_values['data']['photovoltaic_power_station_id'] <= 0:
2312
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2313
                                   description='API.INVALID_PHOTOVOLTAIC_POWER_STATION_ID')
2314
        photovoltaic_power_station_id = new_values['data']['photovoltaic_power_station_id']
2315
2316
        cnx = mysql.connector.connect(**config.myems_system_db)
2317
        cursor = cnx.cursor()
2318
2319
        cursor.execute(" SELECT name "
2320
                       " from tbl_spaces "
2321
                       " WHERE id = %s ", (id_,))
2322
        if cursor.fetchone() is None:
2323
            cursor.close()
2324
            cnx.close()
2325
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2326
                                   description='API.SPACE_NOT_FOUND')
2327
2328
        cursor.execute(" SELECT name "
2329
                       " FROM tbl_photovoltaic_power_stations "
2330
                       " WHERE id = %s ", (photovoltaic_power_station_id,))
2331
        if cursor.fetchone() is None:
2332
            cursor.close()
2333
            cnx.close()
2334
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2335
                                   description='API.PHOTOVOLTAIC_POWER_STATION_NOT_FOUND')
2336
2337
        query = (" SELECT id "
2338
                 " FROM tbl_spaces_photovoltaic_power_stations "
2339
                 " WHERE space_id = %s AND photovoltaic_power_station_id = %s")
2340
        cursor.execute(query, (id_, photovoltaic_power_station_id,))
2341
        if cursor.fetchone() is not None:
2342
            cursor.close()
2343
            cnx.close()
2344
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2345
                                   description='API.SPACE_PHOTOVOLTAIC_POWER_STATION_RELATION_EXISTS')
2346
2347
        add_row = (" INSERT INTO tbl_spaces_photovoltaic_power_stations (space_id, photovoltaic_power_station_id) "
2348
                   " VALUES (%s, %s) ")
2349
        cursor.execute(add_row, (id_, photovoltaic_power_station_id,))
2350
        cnx.commit()
2351
        cursor.close()
2352
        cnx.close()
2353
2354
        resp.status = falcon.HTTP_201
2355
        resp.location = '/spaces/' + str(id_) + '/photovoltaicpowerstations/' + str(photovoltaic_power_station_id)
2356
2357
2358
class SpacePhotovoltaicPowerStationItem:
2359
    def __init__(self):
2360
        pass
2361
2362
    @staticmethod
2363
    def on_options(req, resp, id_, eid):
2364
        _ = req
2365
        resp.status = falcon.HTTP_200
2366
        _ = id_
2367
2368
    @staticmethod
2369
    @user_logger
2370
    def on_delete(req, resp, id_, eid):
2371
        admin_control(req)
2372
        if not id_.isdigit() or int(id_) <= 0:
2373
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2374
                                   description='API.INVALID_SPACE_ID')
2375
2376
        if not eid.isdigit() or int(eid) <= 0:
2377
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2378
                                   description='API.INVALID_PHOTOVOLTAIC_POWER_STATION_ID')
2379
2380
        cnx = mysql.connector.connect(**config.myems_system_db)
2381
        cursor = cnx.cursor()
2382
2383
        cursor.execute(" SELECT name "
2384
                       " FROM tbl_spaces "
2385
                       " WHERE id = %s ", (id_,))
2386
        if cursor.fetchone() is None:
2387
            cursor.close()
2388
            cnx.close()
2389
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2390
                                   description='API.SPACE_NOT_FOUND')
2391
2392
        cursor.execute(" SELECT name "
2393
                       " FROM tbl_photovoltaic_power_stations "
2394
                       " WHERE id = %s ", (eid,))
2395
        if cursor.fetchone() is None:
2396
            cursor.close()
2397
            cnx.close()
2398
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2399
                                   description='API.PHOTOVOLTAIC_POWER_STATION_NOT_FOUND')
2400
2401
        cursor.execute(" SELECT id "
2402
                       " FROM tbl_spaces_photovoltaic_power_stations "
2403
                       " WHERE space_id = %s AND photovoltaic_power_station_id = %s ", (id_, eid))
2404
        if cursor.fetchone() is None:
2405
            cursor.close()
2406
            cnx.close()
2407
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2408
                                   description='API.SPACE_PHOTOVOLTAIC_POWER_STATION_RELATION_NOT_FOUND')
2409
2410
        cursor.execute(" DELETE FROM tbl_spaces_photovoltaic_power_stations "
2411
                       " WHERE space_id = %s AND photovoltaic_power_station_id = %s ", (id_, eid))
2412
        cnx.commit()
2413
2414
        cursor.close()
2415
        cnx.close()
2416
2417
        resp.status = falcon.HTTP_204
2418
2419
2420 View Code Duplication
class SpacePointCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2421
    def __init__(self):
2422
        pass
2423
2424
    @staticmethod
2425
    def on_options(req, resp, id_):
2426
        _ = req
2427
        resp.status = falcon.HTTP_200
2428
        _ = id_
2429
2430
    @staticmethod
2431
    def on_get(req, resp, id_):
2432
        if 'API-KEY' not in req.headers or \
2433
                not isinstance(req.headers['API-KEY'], str) or \
2434
                len(str.strip(req.headers['API-KEY'])) == 0:
2435
            access_control(req)
2436
        else:
2437
            api_key_control(req)
2438
        if not id_.isdigit() or int(id_) <= 0:
2439
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2440
                                   description='API.INVALID_SPACE_ID')
2441
2442
        cnx = mysql.connector.connect(**config.myems_system_db)
2443
        cursor = cnx.cursor()
2444
2445
        cursor.execute(" SELECT name "
2446
                       " FROM tbl_spaces "
2447
                       " WHERE id = %s ", (id_,))
2448
        if cursor.fetchone() is None:
2449
            cursor.close()
2450
            cnx.close()
2451
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2452
                                   description='API.SPACE_NOT_FOUND')
2453
2454
        query = (" SELECT id, name, uuid "
2455
                 " FROM tbl_data_sources ")
2456
        cursor.execute(query)
2457
        rows_data_sources = cursor.fetchall()
2458
2459
        data_source_dict = dict()
2460
        if rows_data_sources is not None and len(rows_data_sources) > 0:
2461
            for row in rows_data_sources:
2462
                data_source_dict[row[0]] = {"id": row[0],
2463
                                            "name": row[1],
2464
                                            "uuid": row[2]}
2465
2466
        query = (" SELECT p.id, p.name, p.data_source_id "
2467
                 " FROM tbl_spaces s, tbl_spaces_points sp, tbl_points p "
2468
                 " WHERE sp.space_id = s.id AND p.id = sp.point_id AND s.id = %s "
2469
                 " ORDER BY p.id ")
2470
        cursor.execute(query, (id_,))
2471
        rows = cursor.fetchall()
2472
2473
        result = list()
2474
        if rows is not None and len(rows) > 0:
2475
            for row in rows:
2476
                meta_result = {"id": row[0], "name": row[1], "data_source": data_source_dict.get(row[2], None)}
2477
                result.append(meta_result)
2478
2479
        resp.text = json.dumps(result)
2480
2481
    @staticmethod
2482
    @user_logger
2483
    def on_post(req, resp, id_):
2484
        """Handles POST requests"""
2485
        admin_control(req)
2486
        try:
2487
            raw_json = req.stream.read().decode('utf-8')
2488
        except UnicodeDecodeError as ex:
2489
            print("Failed to decode request")
2490
            raise falcon.HTTPError(status=falcon.HTTP_400,
2491
                                   title='API.BAD_REQUEST',
2492
                                   description='API.INVALID_ENCODING')
2493
        except Exception as ex:
2494
            print("Unexpected error reading request stream")
2495
            raise falcon.HTTPError(status=falcon.HTTP_400,
2496
                                   title='API.BAD_REQUEST',
2497
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2498
2499
        if not id_.isdigit() or int(id_) <= 0:
2500
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2501
                                   description='API.INVALID_SPACE_ID')
2502
2503
        new_values = json.loads(raw_json)
2504
2505
        if 'point_id' not in new_values['data'].keys() or \
2506
                not isinstance(new_values['data']['point_id'], int) or \
2507
                new_values['data']['point_id'] <= 0:
2508
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2509
                                   description='API.INVALID_POINT_ID')
2510
        point_id = new_values['data']['point_id']
2511
2512
        cnx = mysql.connector.connect(**config.myems_system_db)
2513
        cursor = cnx.cursor()
2514
2515
        cursor.execute(" SELECT name "
2516
                       " from tbl_spaces "
2517
                       " WHERE id = %s ", (id_,))
2518
        if cursor.fetchone() is None:
2519
            cursor.close()
2520
            cnx.close()
2521
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2522
                                   description='API.SPACE_NOT_FOUND')
2523
2524
        cursor.execute(" SELECT name "
2525
                       " FROM tbl_points "
2526
                       " WHERE id = %s ", (point_id,))
2527
        if cursor.fetchone() is None:
2528
            cursor.close()
2529
            cnx.close()
2530
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2531
                                   description='API.POINT_NOT_FOUND')
2532
2533
        query = (" SELECT id "
2534
                 " FROM tbl_spaces_points "
2535
                 " WHERE space_id = %s AND point_id = %s")
2536
        cursor.execute(query, (id_, point_id,))
2537
        if cursor.fetchone() is not None:
2538
            cursor.close()
2539
            cnx.close()
2540
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2541
                                   description='API.SPACE_POINT_RELATION_EXISTS')
2542
2543
        add_row = (" INSERT INTO tbl_spaces_points (space_id, point_id) "
2544
                   " VALUES (%s, %s) ")
2545
        cursor.execute(add_row, (id_, point_id,))
2546
        cnx.commit()
2547
        cursor.close()
2548
        cnx.close()
2549
2550
        resp.status = falcon.HTTP_201
2551
        resp.location = '/spaces/' + str(id_) + '/points/' + str(point_id)
2552
2553
2554
class SpacePointItem:
2555
    def __init__(self):
2556
        pass
2557
2558
    @staticmethod
2559
    def on_options(req, resp, id_, pid):
2560
        _ = req
2561
        resp.status = falcon.HTTP_200
2562
        _ = id_
2563
2564
    @staticmethod
2565
    @user_logger
2566
    def on_delete(req, resp, id_, pid):
2567
        admin_control(req)
2568
        if not id_.isdigit() or int(id_) <= 0:
2569
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2570
                                   description='API.INVALID_SPACE_ID')
2571
2572
        if not pid.isdigit() or int(pid) <= 0:
2573
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2574
                                   description='API.INVALID_POINT_ID')
2575
2576
        cnx = mysql.connector.connect(**config.myems_system_db)
2577
        cursor = cnx.cursor()
2578
2579
        cursor.execute(" SELECT name "
2580
                       " FROM tbl_spaces "
2581
                       " WHERE id = %s ", (id_,))
2582
        if cursor.fetchone() is None:
2583
            cursor.close()
2584
            cnx.close()
2585
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2586
                                   description='API.SPACE_NOT_FOUND')
2587
2588
        cursor.execute(" SELECT name "
2589
                       " FROM tbl_points "
2590
                       " WHERE id = %s ", (pid,))
2591
        if cursor.fetchone() is None:
2592
            cursor.close()
2593
            cnx.close()
2594
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2595
                                   description='API.POINT_NOT_FOUND')
2596
2597
        cursor.execute(" SELECT id "
2598
                       " FROM tbl_spaces_points "
2599
                       " WHERE space_id = %s AND point_id = %s ", (id_, pid))
2600
        if cursor.fetchone() is None:
2601
            cursor.close()
2602
            cnx.close()
2603
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2604
                                   description='API.SPACE_POINT_RELATION_NOT_FOUND')
2605
2606
        cursor.execute(" DELETE FROM tbl_spaces_points "
2607
                       " WHERE space_id = %s AND point_id = %s ", (id_, pid))
2608
        cnx.commit()
2609
2610
        cursor.close()
2611
        cnx.close()
2612
2613
        resp.status = falcon.HTTP_204
2614
2615
2616 View Code Duplication
class SpaceSensorCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2617
    def __init__(self):
2618
        pass
2619
2620
    @staticmethod
2621
    def on_options(req, resp, id_):
2622
        _ = req
2623
        resp.status = falcon.HTTP_200
2624
        _ = id_
2625
2626
    @staticmethod
2627
    def on_get(req, resp, id_):
2628
        if 'API-KEY' not in req.headers or \
2629
                not isinstance(req.headers['API-KEY'], str) or \
2630
                len(str.strip(req.headers['API-KEY'])) == 0:
2631
            access_control(req)
2632
        else:
2633
            api_key_control(req)
2634
        if not id_.isdigit() or int(id_) <= 0:
2635
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2636
                                   description='API.INVALID_SPACE_ID')
2637
2638
        cnx = mysql.connector.connect(**config.myems_system_db)
2639
        cursor = cnx.cursor()
2640
2641
        cursor.execute(" SELECT name "
2642
                       " FROM tbl_spaces "
2643
                       " WHERE id = %s ", (id_,))
2644
        if cursor.fetchone() is None:
2645
            cursor.close()
2646
            cnx.close()
2647
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2648
                                   description='API.SPACE_NOT_FOUND')
2649
2650
        query = (" SELECT se.id, se.name, se.uuid "
2651
                 " FROM tbl_spaces sp, tbl_spaces_sensors ss, tbl_sensors se "
2652
                 " WHERE ss.space_id = sp.id AND se.id = ss.sensor_id AND sp.id = %s "
2653
                 " ORDER BY se.id ")
2654
        cursor.execute(query, (id_,))
2655
        rows = cursor.fetchall()
2656
2657
        result = list()
2658
        if rows is not None and len(rows) > 0:
2659
            for row in rows:
2660
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
2661
                result.append(meta_result)
2662
2663
        resp.text = json.dumps(result)
2664
2665
    @staticmethod
2666
    @user_logger
2667
    def on_post(req, resp, id_):
2668
        """Handles POST requests"""
2669
        admin_control(req)
2670
        try:
2671
            raw_json = req.stream.read().decode('utf-8')
2672
        except UnicodeDecodeError as ex:
2673
            print("Failed to decode request")
2674
            raise falcon.HTTPError(status=falcon.HTTP_400,
2675
                                   title='API.BAD_REQUEST',
2676
                                   description='API.INVALID_ENCODING')
2677
        except Exception as ex:
2678
            print("Unexpected error reading request stream")
2679
            raise falcon.HTTPError(status=falcon.HTTP_400,
2680
                                   title='API.BAD_REQUEST',
2681
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2682
2683
        if not id_.isdigit() or int(id_) <= 0:
2684
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2685
                                   description='API.INVALID_SPACE_ID')
2686
2687
        new_values = json.loads(raw_json)
2688
2689
        if 'sensor_id' not in new_values['data'].keys() or \
2690
                not isinstance(new_values['data']['sensor_id'], int) or \
2691
                new_values['data']['sensor_id'] <= 0:
2692
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2693
                                   description='API.INVALID_SENSOR_ID')
2694
        sensor_id = new_values['data']['sensor_id']
2695
2696
        cnx = mysql.connector.connect(**config.myems_system_db)
2697
        cursor = cnx.cursor()
2698
2699
        cursor.execute(" SELECT name "
2700
                       " from tbl_spaces "
2701
                       " WHERE id = %s ", (id_,))
2702
        if cursor.fetchone() is None:
2703
            cursor.close()
2704
            cnx.close()
2705
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2706
                                   description='API.SPACE_NOT_FOUND')
2707
2708
        cursor.execute(" SELECT name "
2709
                       " FROM tbl_sensors "
2710
                       " WHERE id = %s ", (sensor_id,))
2711
        if cursor.fetchone() is None:
2712
            cursor.close()
2713
            cnx.close()
2714
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2715
                                   description='API.SENSOR_NOT_FOUND')
2716
2717
        query = (" SELECT id "
2718
                 " FROM tbl_spaces_sensors "
2719
                 " WHERE space_id = %s AND sensor_id = %s")
2720
        cursor.execute(query, (id_, sensor_id,))
2721
        if cursor.fetchone() is not None:
2722
            cursor.close()
2723
            cnx.close()
2724
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2725
                                   description='API.SPACE_SENSOR_RELATION_EXISTS')
2726
2727
        add_row = (" INSERT INTO tbl_spaces_sensors (space_id, sensor_id) "
2728
                   " VALUES (%s, %s) ")
2729
        cursor.execute(add_row, (id_, sensor_id,))
2730
        cnx.commit()
2731
        cursor.close()
2732
        cnx.close()
2733
2734
        resp.status = falcon.HTTP_201
2735
        resp.location = '/spaces/' + str(id_) + '/sensors/' + str(sensor_id)
2736
2737
2738
class SpaceSensorItem:
2739
    def __init__(self):
2740
        pass
2741
2742
    @staticmethod
2743
    def on_options(req, resp, id_, sid):
2744
        _ = req
2745
        resp.status = falcon.HTTP_200
2746
        _ = id_
2747
2748
    @staticmethod
2749
    @user_logger
2750
    def on_delete(req, resp, id_, sid):
2751
        admin_control(req)
2752
        if not id_.isdigit() or int(id_) <= 0:
2753
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2754
                                   description='API.INVALID_SPACE_ID')
2755
2756
        if not sid.isdigit() or int(sid) <= 0:
2757
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2758
                                   description='API.INVALID_SENSOR_ID')
2759
2760
        cnx = mysql.connector.connect(**config.myems_system_db)
2761
        cursor = cnx.cursor()
2762
2763
        cursor.execute(" SELECT name "
2764
                       " FROM tbl_spaces "
2765
                       " WHERE id = %s ", (id_,))
2766
        if cursor.fetchone() is None:
2767
            cursor.close()
2768
            cnx.close()
2769
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2770
                                   description='API.SPACE_NOT_FOUND')
2771
2772
        cursor.execute(" SELECT name "
2773
                       " FROM tbl_sensors "
2774
                       " WHERE id = %s ", (sid,))
2775
        if cursor.fetchone() is None:
2776
            cursor.close()
2777
            cnx.close()
2778
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2779
                                   description='API.SENSOR_NOT_FOUND')
2780
2781
        cursor.execute(" SELECT id "
2782
                       " FROM tbl_spaces_sensors "
2783
                       " WHERE space_id = %s AND sensor_id = %s ", (id_, sid))
2784
        if cursor.fetchone() is None:
2785
            cursor.close()
2786
            cnx.close()
2787
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2788
                                   description='API.SPACE_SENSOR_RELATION_NOT_FOUND')
2789
2790
        cursor.execute(" DELETE FROM tbl_spaces_sensors WHERE space_id = %s AND sensor_id = %s ", (id_, sid))
2791
        cnx.commit()
2792
2793
        cursor.close()
2794
        cnx.close()
2795
2796
        resp.status = falcon.HTTP_204
2797
2798
2799 View Code Duplication
class SpaceShopfloorCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2800
    def __init__(self):
2801
        pass
2802
2803
    @staticmethod
2804
    def on_options(req, resp, id_):
2805
        _ = req
2806
        resp.status = falcon.HTTP_200
2807
        _ = id_
2808
2809
    @staticmethod
2810
    def on_get(req, resp, id_):
2811
        if 'API-KEY' not in req.headers or \
2812
                not isinstance(req.headers['API-KEY'], str) or \
2813
                len(str.strip(req.headers['API-KEY'])) == 0:
2814
            access_control(req)
2815
        else:
2816
            api_key_control(req)
2817
        if not id_.isdigit() or int(id_) <= 0:
2818
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2819
                                   description='API.INVALID_SPACE_ID')
2820
2821
        cnx = mysql.connector.connect(**config.myems_system_db)
2822
        cursor = cnx.cursor()
2823
2824
        cursor.execute(" SELECT name "
2825
                       " FROM tbl_spaces "
2826
                       " WHERE id = %s ", (id_,))
2827
        if cursor.fetchone() is None:
2828
            cursor.close()
2829
            cnx.close()
2830
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2831
                                   description='API.SPACE_NOT_FOUND')
2832
2833
        query = (" SELECT sf.id, sf.name, sf.uuid "
2834
                 " FROM tbl_spaces sp, tbl_spaces_shopfloors ss, tbl_shopfloors sf "
2835
                 " WHERE ss.space_id = sp.id AND sf.id = ss.shopfloor_id AND sp.id = %s "
2836
                 " ORDER BY sf.id ")
2837
        cursor.execute(query, (id_,))
2838
        rows = cursor.fetchall()
2839
2840
        result = list()
2841
        if rows is not None and len(rows) > 0:
2842
            for row in rows:
2843
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
2844
                result.append(meta_result)
2845
2846
        resp.text = json.dumps(result)
2847
2848
    @staticmethod
2849
    @user_logger
2850
    def on_post(req, resp, id_):
2851
        """Handles POST requests"""
2852
        admin_control(req)
2853
        try:
2854
            raw_json = req.stream.read().decode('utf-8')
2855
        except UnicodeDecodeError as ex:
2856
            print("Failed to decode request")
2857
            raise falcon.HTTPError(status=falcon.HTTP_400,
2858
                                   title='API.BAD_REQUEST',
2859
                                   description='API.INVALID_ENCODING')
2860
        except Exception as ex:
2861
            print("Unexpected error reading request stream")
2862
            raise falcon.HTTPError(status=falcon.HTTP_400,
2863
                                   title='API.BAD_REQUEST',
2864
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2865
2866
        if not id_.isdigit() or int(id_) <= 0:
2867
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2868
                                   description='API.INVALID_SPACE_ID')
2869
2870
        new_values = json.loads(raw_json)
2871
2872
        if 'shopfloor_id' not in new_values['data'].keys() or \
2873
                not isinstance(new_values['data']['shopfloor_id'], int) or \
2874
                new_values['data']['shopfloor_id'] <= 0:
2875
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2876
                                   description='API.INVALID_SHOPFLOOR_ID')
2877
        shopfloor_id = new_values['data']['shopfloor_id']
2878
2879
        cnx = mysql.connector.connect(**config.myems_system_db)
2880
        cursor = cnx.cursor()
2881
2882
        cursor.execute(" SELECT name "
2883
                       " from tbl_spaces "
2884
                       " WHERE id = %s ", (id_,))
2885
        if cursor.fetchone() is None:
2886
            cursor.close()
2887
            cnx.close()
2888
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2889
                                   description='API.SPACE_NOT_FOUND')
2890
2891
        cursor.execute(" SELECT name "
2892
                       " FROM tbl_shopfloors "
2893
                       " WHERE id = %s ", (shopfloor_id,))
2894
        if cursor.fetchone() is None:
2895
            cursor.close()
2896
            cnx.close()
2897
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2898
                                   description='API.SHOPFLOOR_NOT_FOUND')
2899
2900
        query = (" SELECT id "
2901
                 " FROM tbl_spaces_shopfloors "
2902
                 " WHERE space_id = %s AND shopfloor_id = %s")
2903
        cursor.execute(query, (id_, shopfloor_id,))
2904
        if cursor.fetchone() is not None:
2905
            cursor.close()
2906
            cnx.close()
2907
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2908
                                   description='API.SPACE_SHOPFLOOR_RELATION_EXISTS')
2909
2910
        add_row = (" INSERT INTO tbl_spaces_shopfloors (space_id, shopfloor_id) "
2911
                   " VALUES (%s, %s) ")
2912
        cursor.execute(add_row, (id_, shopfloor_id,))
2913
        cnx.commit()
2914
        cursor.close()
2915
        cnx.close()
2916
2917
        resp.status = falcon.HTTP_201
2918
        resp.location = '/spaces/' + str(id_) + '/shopfloors/' + str(shopfloor_id)
2919
2920
2921
class SpaceShopfloorItem:
2922
    def __init__(self):
2923
        pass
2924
2925
    @staticmethod
2926
    def on_options(req, resp, id_, sid):
2927
        _ = req
2928
        resp.status = falcon.HTTP_200
2929
        _ = id_
2930
2931
    @staticmethod
2932
    @user_logger
2933
    def on_delete(req, resp, id_, sid):
2934
        admin_control(req)
2935
        if not id_.isdigit() or int(id_) <= 0:
2936
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2937
                                   description='API.INVALID_SPACE_ID')
2938
2939
        if not sid.isdigit() or int(sid) <= 0:
2940
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2941
                                   description='API.INVALID_SHOPFLOOR_ID')
2942
2943
        cnx = mysql.connector.connect(**config.myems_system_db)
2944
        cursor = cnx.cursor()
2945
2946
        cursor.execute(" SELECT name "
2947
                       " FROM tbl_spaces "
2948
                       " WHERE id = %s ", (id_,))
2949
        if cursor.fetchone() is None:
2950
            cursor.close()
2951
            cnx.close()
2952
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2953
                                   description='API.SPACE_NOT_FOUND')
2954
2955
        cursor.execute(" SELECT name "
2956
                       " FROM tbl_shopfloors "
2957
                       " WHERE id = %s ", (sid,))
2958
        if cursor.fetchone() is None:
2959
            cursor.close()
2960
            cnx.close()
2961
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2962
                                   description='API.SHOPFLOOR_NOT_FOUND')
2963
2964
        cursor.execute(" SELECT id "
2965
                       " FROM tbl_spaces_shopfloors "
2966
                       " WHERE space_id = %s AND shopfloor_id = %s ", (id_, sid))
2967
        if cursor.fetchone() is None:
2968
            cursor.close()
2969
            cnx.close()
2970
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2971
                                   description='API.SPACE_SHOPFLOOR_RELATION_NOT_FOUND')
2972
2973
        cursor.execute(" DELETE FROM tbl_spaces_shopfloors WHERE space_id = %s AND shopfloor_id = %s ", (id_, sid))
2974
        cnx.commit()
2975
2976
        cursor.close()
2977
        cnx.close()
2978
2979
        resp.status = falcon.HTTP_204
2980
2981
2982 View Code Duplication
class SpaceStoreCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2983
    def __init__(self):
2984
        pass
2985
2986
    @staticmethod
2987
    def on_options(req, resp, id_):
2988
        _ = req
2989
        resp.status = falcon.HTTP_200
2990
        _ = id_
2991
2992
    @staticmethod
2993
    def on_get(req, resp, id_):
2994
        if 'API-KEY' not in req.headers or \
2995
                not isinstance(req.headers['API-KEY'], str) or \
2996
                len(str.strip(req.headers['API-KEY'])) == 0:
2997
            access_control(req)
2998
        else:
2999
            api_key_control(req)
3000
        if not id_.isdigit() or int(id_) <= 0:
3001
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3002
                                   description='API.INVALID_SPACE_ID')
3003
3004
        cnx = mysql.connector.connect(**config.myems_system_db)
3005
        cursor = cnx.cursor()
3006
3007
        cursor.execute(" SELECT name "
3008
                       " FROM tbl_spaces "
3009
                       " WHERE id = %s ", (id_,))
3010
        if cursor.fetchone() is None:
3011
            cursor.close()
3012
            cnx.close()
3013
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3014
                                   description='API.SPACE_NOT_FOUND')
3015
3016
        query = (" SELECT t.id, t.name, t.uuid "
3017
                 " FROM tbl_spaces s, tbl_spaces_stores st, tbl_stores t "
3018
                 " WHERE st.space_id = s.id AND t.id = st.store_id AND s.id = %s "
3019
                 " ORDER BY t.id ")
3020
        cursor.execute(query, (id_,))
3021
        rows = cursor.fetchall()
3022
3023
        result = list()
3024
        if rows is not None and len(rows) > 0:
3025
            for row in rows:
3026
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
3027
                result.append(meta_result)
3028
3029
        resp.text = json.dumps(result)
3030
3031
    @staticmethod
3032
    @user_logger
3033
    def on_post(req, resp, id_):
3034
        """Handles POST requests"""
3035
        admin_control(req)
3036
        try:
3037
            raw_json = req.stream.read().decode('utf-8')
3038
        except UnicodeDecodeError as ex:
3039
            print("Failed to decode request")
3040
            raise falcon.HTTPError(status=falcon.HTTP_400,
3041
                                   title='API.BAD_REQUEST',
3042
                                   description='API.INVALID_ENCODING')
3043
        except Exception as ex:
3044
            print("Unexpected error reading request stream")
3045
            raise falcon.HTTPError(status=falcon.HTTP_400,
3046
                                   title='API.BAD_REQUEST',
3047
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3048
3049
        if not id_.isdigit() or int(id_) <= 0:
3050
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3051
                                   description='API.INVALID_SPACE_ID')
3052
3053
        new_values = json.loads(raw_json)
3054
3055
        if 'store_id' not in new_values['data'].keys() or \
3056
                not isinstance(new_values['data']['store_id'], int) or \
3057
                new_values['data']['store_id'] <= 0:
3058
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3059
                                   description='API.INVALID_STORE_ID')
3060
        store_id = new_values['data']['store_id']
3061
3062
        cnx = mysql.connector.connect(**config.myems_system_db)
3063
        cursor = cnx.cursor()
3064
3065
        cursor.execute(" SELECT name "
3066
                       " from tbl_spaces "
3067
                       " WHERE id = %s ", (id_,))
3068
        if cursor.fetchone() is None:
3069
            cursor.close()
3070
            cnx.close()
3071
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3072
                                   description='API.SPACE_NOT_FOUND')
3073
3074
        cursor.execute(" SELECT name "
3075
                       " FROM tbl_stores "
3076
                       " WHERE id = %s ", (store_id,))
3077
        if cursor.fetchone() is None:
3078
            cursor.close()
3079
            cnx.close()
3080
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3081
                                   description='API.STORE_NOT_FOUND')
3082
3083
        query = (" SELECT id "
3084
                 " FROM tbl_spaces_stores "
3085
                 " WHERE space_id = %s AND store_id = %s")
3086
        cursor.execute(query, (id_, store_id,))
3087
        if cursor.fetchone() is not None:
3088
            cursor.close()
3089
            cnx.close()
3090
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3091
                                   description='API.SPACE_STORE_RELATION_EXISTS')
3092
3093
        add_row = (" INSERT INTO tbl_spaces_stores (space_id, store_id) "
3094
                   " VALUES (%s, %s) ")
3095
        cursor.execute(add_row, (id_, store_id,))
3096
        cnx.commit()
3097
        cursor.close()
3098
        cnx.close()
3099
3100
        resp.status = falcon.HTTP_201
3101
        resp.location = '/spaces/' + str(id_) + '/stores/' + str(store_id)
3102
3103
3104
class SpaceStoreItem:
3105
    def __init__(self):
3106
        pass
3107
3108
    @staticmethod
3109
    def on_options(req, resp, id_, tid):
3110
        _ = req
3111
        resp.status = falcon.HTTP_200
3112
        _ = id_
3113
3114
    @staticmethod
3115
    @user_logger
3116
    def on_delete(req, resp, id_, tid):
3117
        admin_control(req)
3118
        if not id_.isdigit() or int(id_) <= 0:
3119
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3120
                                   description='API.INVALID_SPACE_ID')
3121
3122
        if not tid.isdigit() or int(tid) <= 0:
3123
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3124
                                   description='API.INVALID_STORE_ID')
3125
3126
        cnx = mysql.connector.connect(**config.myems_system_db)
3127
        cursor = cnx.cursor()
3128
3129
        cursor.execute(" SELECT name "
3130
                       " FROM tbl_spaces "
3131
                       " WHERE id = %s ", (id_,))
3132
        if cursor.fetchone() is None:
3133
            cursor.close()
3134
            cnx.close()
3135
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3136
                                   description='API.SPACE_NOT_FOUND')
3137
3138
        cursor.execute(" SELECT name "
3139
                       " FROM tbl_stores "
3140
                       " WHERE id = %s ", (tid,))
3141
        if cursor.fetchone() is None:
3142
            cursor.close()
3143
            cnx.close()
3144
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3145
                                   description='API.STORE_NOT_FOUND')
3146
3147
        cursor.execute(" SELECT id "
3148
                       " FROM tbl_spaces_stores "
3149
                       " WHERE space_id = %s AND store_id = %s ", (id_, tid))
3150
        if cursor.fetchone() is None:
3151
            cursor.close()
3152
            cnx.close()
3153
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3154
                                   description='API.SPACE_STORE_RELATION_NOT_FOUND')
3155
3156
        cursor.execute(" DELETE FROM tbl_spaces_stores WHERE space_id = %s AND store_id = %s ", (id_, tid))
3157
        cnx.commit()
3158
3159
        cursor.close()
3160
        cnx.close()
3161
3162
        resp.status = falcon.HTTP_204
3163
3164
3165 View Code Duplication
class SpaceTenantCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3166
    def __init__(self):
3167
        pass
3168
3169
    @staticmethod
3170
    def on_options(req, resp, id_):
3171
        _ = req
3172
        resp.status = falcon.HTTP_200
3173
        _ = id_
3174
3175
    @staticmethod
3176
    def on_get(req, resp, id_):
3177
        if 'API-KEY' not in req.headers or \
3178
                not isinstance(req.headers['API-KEY'], str) or \
3179
                len(str.strip(req.headers['API-KEY'])) == 0:
3180
            access_control(req)
3181
        else:
3182
            api_key_control(req)
3183
        if not id_.isdigit() or int(id_) <= 0:
3184
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3185
                                   description='API.INVALID_SPACE_ID')
3186
3187
        cnx = mysql.connector.connect(**config.myems_system_db)
3188
        cursor = cnx.cursor()
3189
3190
        cursor.execute(" SELECT name "
3191
                       " FROM tbl_spaces "
3192
                       " WHERE id = %s ", (id_,))
3193
        if cursor.fetchone() is None:
3194
            cursor.close()
3195
            cnx.close()
3196
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3197
                                   description='API.SPACE_NOT_FOUND')
3198
3199
        query = (" SELECT t.id, t.name, t.uuid "
3200
                 " FROM tbl_spaces s, tbl_spaces_tenants st, tbl_tenants t "
3201
                 " WHERE st.space_id = s.id AND t.id = st.tenant_id AND s.id = %s "
3202
                 " ORDER BY t.id ")
3203
        cursor.execute(query, (id_,))
3204
        rows = cursor.fetchall()
3205
3206
        result = list()
3207
        if rows is not None and len(rows) > 0:
3208
            for row in rows:
3209
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
3210
                result.append(meta_result)
3211
3212
        resp.text = json.dumps(result)
3213
3214
    @staticmethod
3215
    @user_logger
3216
    def on_post(req, resp, id_):
3217
        """Handles POST requests"""
3218
        admin_control(req)
3219
        try:
3220
            raw_json = req.stream.read().decode('utf-8')
3221
        except UnicodeDecodeError as ex:
3222
            print("Failed to decode request")
3223
            raise falcon.HTTPError(status=falcon.HTTP_400,
3224
                                   title='API.BAD_REQUEST',
3225
                                   description='API.INVALID_ENCODING')
3226
        except Exception as ex:
3227
            print("Unexpected error reading request stream")
3228
            raise falcon.HTTPError(status=falcon.HTTP_400,
3229
                                   title='API.BAD_REQUEST',
3230
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3231
3232
        if not id_.isdigit() or int(id_) <= 0:
3233
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3234
                                   description='API.INVALID_SPACE_ID')
3235
3236
        new_values = json.loads(raw_json)
3237
3238
        if 'tenant_id' not in new_values['data'].keys() or \
3239
                not isinstance(new_values['data']['tenant_id'], int) or \
3240
                new_values['data']['tenant_id'] <= 0:
3241
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3242
                                   description='API.INVALID_TENANT_ID')
3243
        tenant_id = new_values['data']['tenant_id']
3244
3245
        cnx = mysql.connector.connect(**config.myems_system_db)
3246
        cursor = cnx.cursor()
3247
3248
        cursor.execute(" SELECT name "
3249
                       " from tbl_spaces "
3250
                       " WHERE id = %s ", (id_,))
3251
        if cursor.fetchone() is None:
3252
            cursor.close()
3253
            cnx.close()
3254
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3255
                                   description='API.SPACE_NOT_FOUND')
3256
3257
        cursor.execute(" SELECT name "
3258
                       " FROM tbl_tenants "
3259
                       " WHERE id = %s ", (tenant_id,))
3260
        if cursor.fetchone() is None:
3261
            cursor.close()
3262
            cnx.close()
3263
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3264
                                   description='API.TENANT_NOT_FOUND')
3265
3266
        query = (" SELECT id "
3267
                 " FROM tbl_spaces_tenants "
3268
                 " WHERE space_id = %s AND tenant_id = %s")
3269
        cursor.execute(query, (id_, tenant_id,))
3270
        if cursor.fetchone() is not None:
3271
            cursor.close()
3272
            cnx.close()
3273
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3274
                                   description='API.SPACE_TENANT_RELATION_EXISTS')
3275
3276
        add_row = (" INSERT INTO tbl_spaces_tenants (space_id, tenant_id) "
3277
                   " VALUES (%s, %s) ")
3278
        cursor.execute(add_row, (id_, tenant_id,))
3279
        cnx.commit()
3280
        cursor.close()
3281
        cnx.close()
3282
3283
        resp.status = falcon.HTTP_201
3284
        resp.location = '/spaces/' + str(id_) + '/tenants/' + str(tenant_id)
3285
3286
3287
class SpaceTenantItem:
3288
    def __init__(self):
3289
        pass
3290
3291
    @staticmethod
3292
    def on_options(req, resp, id_, tid):
3293
        _ = req
3294
        resp.status = falcon.HTTP_200
3295
        _ = id_
3296
3297
    @staticmethod
3298
    @user_logger
3299
    def on_delete(req, resp, id_, tid):
3300
        admin_control(req)
3301
        if not id_.isdigit() or int(id_) <= 0:
3302
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3303
                                   description='API.INVALID_SPACE_ID')
3304
3305
        if not tid.isdigit() or int(tid) <= 0:
3306
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3307
                                   description='API.INVALID_TENANT_ID')
3308
3309
        cnx = mysql.connector.connect(**config.myems_system_db)
3310
        cursor = cnx.cursor()
3311
3312
        cursor.execute(" SELECT name "
3313
                       " FROM tbl_spaces "
3314
                       " WHERE id = %s ", (id_,))
3315
        if cursor.fetchone() is None:
3316
            cursor.close()
3317
            cnx.close()
3318
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3319
                                   description='API.SPACE_NOT_FOUND')
3320
3321
        cursor.execute(" SELECT name "
3322
                       " FROM tbl_tenants "
3323
                       " WHERE id = %s ", (tid,))
3324
        if cursor.fetchone() is None:
3325
            cursor.close()
3326
            cnx.close()
3327
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3328
                                   description='API.TENANT_NOT_FOUND')
3329
3330
        cursor.execute(" SELECT id "
3331
                       " FROM tbl_spaces_tenants "
3332
                       " WHERE space_id = %s AND tenant_id = %s ", (id_, tid))
3333
        if cursor.fetchone() is None:
3334
            cursor.close()
3335
            cnx.close()
3336
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3337
                                   description='API.SPACE_TENANT_RELATION_NOT_FOUND')
3338
3339
        cursor.execute(" DELETE FROM tbl_spaces_tenants WHERE space_id = %s AND tenant_id = %s ", (id_, tid))
3340
        cnx.commit()
3341
3342
        cursor.close()
3343
        cnx.close()
3344
3345
        resp.status = falcon.HTTP_204
3346
3347
3348 View Code Duplication
class SpaceVirtualMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3349
    def __init__(self):
3350
        pass
3351
3352
    @staticmethod
3353
    def on_options(req, resp, id_):
3354
        _ = req
3355
        resp.status = falcon.HTTP_200
3356
        _ = id_
3357
3358
    @staticmethod
3359
    def on_get(req, resp, id_):
3360
        if 'API-KEY' not in req.headers or \
3361
                not isinstance(req.headers['API-KEY'], str) or \
3362
                len(str.strip(req.headers['API-KEY'])) == 0:
3363
            access_control(req)
3364
        else:
3365
            api_key_control(req)
3366
        if not id_.isdigit() or int(id_) <= 0:
3367
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3368
                                   description='API.INVALID_SPACE_ID')
3369
3370
        cnx = mysql.connector.connect(**config.myems_system_db)
3371
        cursor = cnx.cursor()
3372
3373
        cursor.execute(" SELECT name "
3374
                       " FROM tbl_spaces "
3375
                       " WHERE id = %s ", (id_,))
3376
        if cursor.fetchone() is None:
3377
            cursor.close()
3378
            cnx.close()
3379
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3380
                                   description='API.SPACE_NOT_FOUND')
3381
3382
        query = (" SELECT id, name, uuid "
3383
                 " FROM tbl_energy_categories ")
3384
        cursor.execute(query)
3385
        rows_energy_categories = cursor.fetchall()
3386
3387
        energy_category_dict = dict()
3388
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
3389
            for row in rows_energy_categories:
3390
                energy_category_dict[row[0]] = {"id": row[0],
3391
                                                "name": row[1],
3392
                                                "uuid": row[2]}
3393
3394
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
3395
                 " FROM tbl_spaces s, tbl_spaces_virtual_meters sm, tbl_virtual_meters m "
3396
                 " WHERE sm.space_id = s.id AND m.id = sm.virtual_meter_id AND s.id = %s "
3397
                 " ORDER BY m.id ")
3398
        cursor.execute(query, (id_,))
3399
        rows = cursor.fetchall()
3400
3401
        result = list()
3402
        if rows is not None and len(rows) > 0:
3403
            for row in rows:
3404
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2],
3405
                               "energy_category": energy_category_dict.get(row[3], None)}
3406
                result.append(meta_result)
3407
3408
        resp.text = json.dumps(result)
3409
3410
    @staticmethod
3411
    @user_logger
3412
    def on_post(req, resp, id_):
3413
        """Handles POST requests"""
3414
        admin_control(req)
3415
        try:
3416
            raw_json = req.stream.read().decode('utf-8')
3417
        except UnicodeDecodeError as ex:
3418
            print("Failed to decode request")
3419
            raise falcon.HTTPError(status=falcon.HTTP_400,
3420
                                   title='API.BAD_REQUEST',
3421
                                   description='API.INVALID_ENCODING')
3422
        except Exception as ex:
3423
            print("Unexpected error reading request stream")
3424
            raise falcon.HTTPError(status=falcon.HTTP_400,
3425
                                   title='API.BAD_REQUEST',
3426
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3427
3428
        if not id_.isdigit() or int(id_) <= 0:
3429
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3430
                                   description='API.INVALID_SPACE_ID')
3431
3432
        new_values = json.loads(raw_json)
3433
3434
        if 'virtual_meter_id' not in new_values['data'].keys() or \
3435
                not isinstance(new_values['data']['virtual_meter_id'], int) or \
3436
                new_values['data']['virtual_meter_id'] <= 0:
3437
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3438
                                   description='API.INVALID_VIRTUAL_METER_ID')
3439
        virtual_meter_id = new_values['data']['virtual_meter_id']
3440
3441
        cnx = mysql.connector.connect(**config.myems_system_db)
3442
        cursor = cnx.cursor()
3443
3444
        cursor.execute(" SELECT name "
3445
                       " from tbl_spaces "
3446
                       " WHERE id = %s ", (id_,))
3447
        if cursor.fetchone() is None:
3448
            cursor.close()
3449
            cnx.close()
3450
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3451
                                   description='API.SPACE_NOT_FOUND')
3452
3453
        cursor.execute(" SELECT name "
3454
                       " FROM tbl_virtual_meters "
3455
                       " WHERE id = %s ", (virtual_meter_id,))
3456
        if cursor.fetchone() is None:
3457
            cursor.close()
3458
            cnx.close()
3459
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3460
                                   description='API.VIRTUAL_METER_NOT_FOUND')
3461
3462
        query = (" SELECT id "
3463
                 " FROM tbl_spaces_virtual_meters "
3464
                 " WHERE space_id = %s AND virtual_meter_id = %s")
3465
        cursor.execute(query, (id_, virtual_meter_id,))
3466
        if cursor.fetchone() is not None:
3467
            cursor.close()
3468
            cnx.close()
3469
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3470
                                   description='API.SPACE_VIRTUAL_METER_RELATION_EXISTS')
3471
3472
        add_row = (" INSERT INTO tbl_spaces_virtual_meters (space_id, virtual_meter_id) "
3473
                   " VALUES (%s, %s) ")
3474
        cursor.execute(add_row, (id_, virtual_meter_id,))
3475
        cnx.commit()
3476
        cursor.close()
3477
        cnx.close()
3478
3479
        resp.status = falcon.HTTP_201
3480
        resp.location = '/spaces/' + str(id_) + '/virtualmeters/' + str(virtual_meter_id)
3481
3482
3483
class SpaceVirtualMeterItem:
3484
    def __init__(self):
3485
        pass
3486
3487
    @staticmethod
3488
    def on_options(req, resp, id_, mid):
3489
        _ = req
3490
        resp.status = falcon.HTTP_200
3491
        _ = id_
3492
3493
    @staticmethod
3494
    @user_logger
3495
    def on_delete(req, resp, id_, mid):
3496
        admin_control(req)
3497
        if not id_.isdigit() or int(id_) <= 0:
3498
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3499
                                   description='API.INVALID_SPACE_ID')
3500
3501
        if not mid.isdigit() or int(mid) <= 0:
3502
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3503
                                   description='API.INVALID_VIRTUAL_METER_ID')
3504
3505
        cnx = mysql.connector.connect(**config.myems_system_db)
3506
        cursor = cnx.cursor()
3507
3508
        cursor.execute(" SELECT name "
3509
                       " FROM tbl_spaces "
3510
                       " WHERE id = %s ", (id_,))
3511
        if cursor.fetchone() is None:
3512
            cursor.close()
3513
            cnx.close()
3514
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3515
                                   description='API.SPACE_NOT_FOUND')
3516
3517
        cursor.execute(" SELECT name "
3518
                       " FROM tbl_virtual_meters "
3519
                       " WHERE id = %s ", (mid,))
3520
        if cursor.fetchone() is None:
3521
            cursor.close()
3522
            cnx.close()
3523
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3524
                                   description='API.VIRTUAL_METER_NOT_FOUND')
3525
3526
        cursor.execute(" SELECT id "
3527
                       " FROM tbl_spaces_virtual_meters "
3528
                       " WHERE space_id = %s AND virtual_meter_id = %s ", (id_, mid))
3529
        if cursor.fetchone() is None:
3530
            cursor.close()
3531
            cnx.close()
3532
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3533
                                   description='API.SPACE_VIRTUAL_METER_RELATION_NOT_FOUND')
3534
3535
        cursor.execute(" DELETE FROM tbl_spaces_virtual_meters "
3536
                       " WHERE space_id = %s AND virtual_meter_id = %s ", (id_, mid))
3537
        cnx.commit()
3538
3539
        cursor.close()
3540
        cnx.close()
3541
3542
        resp.status = falcon.HTTP_204
3543
3544
3545
class SpaceTreeCollection:
3546
    def __init__(self):
3547
        pass
3548
3549
    @staticmethod
3550
    def on_options(req, resp):
3551
        _ = req
3552
        resp.status = falcon.HTTP_200
3553
3554
    @staticmethod
3555
    def on_get(req, resp):
3556
        access_control(req)
3557
        if 'USER-UUID' not in req.headers or \
3558
                not isinstance(req.headers['USER-UUID'], str) or \
3559
                len(str.strip(req.headers['USER-UUID'])) == 0:
3560
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3561
                                   description='API.INVALID_USER_UUID')
3562
        user_uuid = str.strip(req.headers['USER-UUID'])
3563
3564
        if 'TOKEN' not in req.headers or \
3565
                not isinstance(req.headers['TOKEN'], str) or \
3566
                len(str.strip(req.headers['TOKEN'])) == 0:
3567
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3568
                                   description='API.INVALID_TOKEN')
3569
        token = str.strip(req.headers['TOKEN'])
3570
3571
        # Optimized: Use a single JOIN query to get session, user, and privilege data
3572
        cnx = mysql.connector.connect(**config.myems_user_db)
3573
        cursor = cnx.cursor()
3574
        try:
3575
            # Combined query to get session expiry, user admin status, privilege_id, and privilege data in one go
3576
            query = (" SELECT s.utc_expires, u.is_admin, u.privilege_id, p.data "
3577
                     " FROM tbl_sessions s "
3578
                     " INNER JOIN tbl_users u ON s.user_uuid = u.uuid "
3579
                     " LEFT JOIN tbl_privileges p ON u.privilege_id = p.id "
3580
                     " WHERE s.user_uuid = %s AND s.token = %s")
3581
            cursor.execute(query, (user_uuid, token,))
3582
            row = cursor.fetchone()
3583
3584
            if row is None:
3585
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3586
                                       description='API.USER_SESSION_NOT_FOUND')
3587
3588
            utc_expires = row[0]
3589
            if datetime.utcnow() > utc_expires:
3590
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3591
                                       description='API.USER_SESSION_TIMEOUT')
3592
3593
            is_admin = bool(row[1])
3594
            privilege_id = row[2]
3595
            privilege_data = row[3]
3596
3597
            # get space_id in privilege
3598
            if is_admin:
3599
                space_id = 1
3600
            elif privilege_id is None:
3601
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3602
                                       description='API.PRIVILEGE_NOT_FOUND')
3603
            else:
3604
                if privilege_data is None:
3605
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3606
                                           description='API.PRIVILEGE_NOT_FOUND')
3607
                try:
3608
                    data = json.loads(privilege_data)
3609
                except json.JSONDecodeError as ex:
3610
                    print("Failed to parse JSON")
3611
                    raise falcon.HTTPError(status=falcon.HTTP_400,
3612
                                           title='API.BAD_REQUEST',
3613
                                           description='API.INVALID_JSON_FORMAT')
3614
                except Exception as ex:
3615
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR', description=str(ex))
3616
3617
                if 'spaces' not in data or len(data['spaces']) == 0:
3618
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3619
                                           description='API.SPACE_NOT_FOUND_IN_PRIVILEGE')
3620
3621
                space_id = data['spaces'][0]
3622
                if space_id is None:
3623
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3624
                                           description='API.PRIVILEGE_NOT_FOUND')
3625
        finally:
3626
            cursor.close()
3627
            cnx.close()
3628
3629
        # get all spaces
3630
        cnx = mysql.connector.connect(**config.myems_system_db)
3631
        cursor = cnx.cursor()
3632
        try:
3633
            query = (" SELECT id, name, parent_space_id "
3634
                     " FROM tbl_spaces "
3635
                     " ORDER BY id ")
3636
            cursor.execute(query)
3637
            rows_spaces = cursor.fetchall()
3638
            node_dict = dict()
3639
            if rows_spaces is not None and len(rows_spaces) > 0:
3640
                for row in rows_spaces:
3641
                    parent_node = node_dict[row[2]] if row[2] is not None else None
3642
                    node_dict[row[0]] = AnyNode(id=row[0], parent=parent_node, name=row[1])
3643
3644
            resp.text = JsonExporter(sort_keys=True).export(node_dict[space_id], )
0 ignored issues
show
introduced by
The variable space_id does not seem to be defined for all execution paths.
Loading history...
3645
        finally:
3646
            cursor.close()
3647
            cnx.close()
3648
3649
3650
# Get energy categories of all meters in the space tree
3651
class SpaceTreeMetersEnergyCategoryCollection:
3652
    def __init__(self):
3653
        pass
3654
3655
    @staticmethod
3656
    def on_options(req, resp, id_):
3657
        _ = req
3658
        resp.status = falcon.HTTP_200
3659
        _ = id_
3660
3661
    @staticmethod
3662
    def on_get(req, resp, id_):
3663
        if 'API-KEY' not in req.headers or \
3664
                not isinstance(req.headers['API-KEY'], str) or \
3665
                len(str.strip(req.headers['API-KEY'])) == 0:
3666
            access_control(req)
3667
        else:
3668
            api_key_control(req)
3669
        ################################################################################################################
3670
        # Step 1: valid parameters
3671
        ################################################################################################################
3672
        if not id_.isdigit() or int(id_) <= 0:
3673
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3674
                                   description='API.INVALID_SPACE_ID')
3675
3676
        cnx = mysql.connector.connect(**config.myems_system_db)
3677
        cursor = cnx.cursor()
3678
3679
        cursor.execute(" SELECT name "
3680
                       " FROM tbl_spaces "
3681
                       " WHERE id = %s ", (id_,))
3682
        if cursor.fetchone() is None:
3683
            cursor.close()
3684
            cnx.close()
3685
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3686
                                   description='API.SPACE_NOT_FOUND')
3687
3688
        ################################################################################################################
3689
        # Step 2: build a space tree
3690
        ################################################################################################################
3691
        query = (" SELECT id, name, parent_space_id "
3692
                 " FROM tbl_spaces "
3693
                 " ORDER BY id ")
3694
        cursor.execute(query)
3695
        rows_spaces = cursor.fetchall()
3696
        node_dict = dict()
3697
        if rows_spaces is not None and len(rows_spaces) > 0:
3698
            for row in rows_spaces:
3699
                parent_node = node_dict[row[2]] if row[2] is not None else None
3700
                node_dict[row[0]] = AnyNode(id=row[0], parent=parent_node, name=row[1])
3701
        ################################################################################################################
3702
        # Step 3: query energy categories of all meters in the space tree
3703
        ################################################################################################################
3704
        space_dict = dict()
3705
3706
        for node in LevelOrderIter(node_dict[int(id_)]):
3707
            space_dict[node.id] = node.name
3708
3709
        cursor.execute(" SELECT distinct(m.energy_category_id), ec.name AS energy_category_name, ec.uuid "
3710
                       " FROM tbl_spaces s, tbl_spaces_meters sm, tbl_meters m, tbl_energy_categories ec  "
3711
                       " WHERE s.id IN ( " + ', '.join(map(str, space_dict.keys())) + ") "
3712
                       "       AND sm.space_id = s.id AND sm.meter_id = m.id  AND m.energy_category_id = ec.id ", )
3713
        rows_energy_categories = cursor.fetchall()
3714
3715
        result = list()
3716
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
3717
            for row in rows_energy_categories:
3718
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
3719
                result.append(meta_result)
3720
3721
        resp.text = json.dumps(result)
3722
3723
3724 View Code Duplication
class SpaceWorkingCalendarCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3725
    def __init__(self):
3726
        pass
3727
3728
    @staticmethod
3729
    def on_options(req, resp, id_):
3730
        _ = req
3731
        resp.status = falcon.HTTP_200
3732
        _ = id_
3733
3734
    @staticmethod
3735
    def on_get(req, resp, id_):
3736
        if 'API-KEY' not in req.headers or \
3737
                not isinstance(req.headers['API-KEY'], str) or \
3738
                len(str.strip(req.headers['API-KEY'])) == 0:
3739
            access_control(req)
3740
        else:
3741
            api_key_control(req)
3742
        if not id_.isdigit() or int(id_) <= 0:
3743
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3744
                                   description='API.INVALID_SPACE_ID')
3745
3746
        cnx = mysql.connector.connect(**config.myems_system_db)
3747
        cursor = cnx.cursor()
3748
3749
        cursor.execute(" SELECT name "
3750
                       " FROM tbl_spaces "
3751
                       " WHERE id = %s ", (id_,))
3752
        if cursor.fetchone() is None:
3753
            cursor.close()
3754
            cnx.close()
3755
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3756
                                   description='API.SPACE_NOT_FOUND')
3757
3758
        query = (" SELECT wc.id, wc.name, wc.description "
3759
                 " FROM tbl_spaces s, tbl_spaces_working_calendars swc, tbl_working_calendars wc "
3760
                 " WHERE swc.space_id = s.id AND wc.id = swc.working_calendar_id AND s.id = %s "
3761
                 " ORDER BY wc.id ")
3762
        cursor.execute(query, (id_,))
3763
        rows = cursor.fetchall()
3764
3765
        result = list()
3766
        if rows is not None and len(rows) > 0:
3767
            for row in rows:
3768
                meta_result = {"id": row[0], "name": row[1], "description": row[2]}
3769
                result.append(meta_result)
3770
3771
        resp.text = json.dumps(result)
3772
3773
    @staticmethod
3774
    @user_logger
3775
    def on_post(req, resp, id_):
3776
        """Handles POST requests"""
3777
        admin_control(req)
3778
        try:
3779
            raw_json = req.stream.read().decode('utf-8')
3780
        except UnicodeDecodeError as ex:
3781
            print("Failed to decode request")
3782
            raise falcon.HTTPError(status=falcon.HTTP_400,
3783
                                   title='API.BAD_REQUEST',
3784
                                   description='API.INVALID_ENCODING')
3785
        except Exception as ex:
3786
            print("Unexpected error reading request stream")
3787
            raise falcon.HTTPError(status=falcon.HTTP_400,
3788
                                   title='API.BAD_REQUEST',
3789
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3790
3791
        if not id_.isdigit() or int(id_) <= 0:
3792
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3793
                                   description='API.INVALID_SPACE_ID')
3794
3795
        new_values = json.loads(raw_json)
3796
3797
        if 'working_calendar_id' not in new_values['data'].keys() or \
3798
                not isinstance(new_values['data']['working_calendar_id'], int) or \
3799
                new_values['data']['working_calendar_id'] <= 0:
3800
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3801
                                   description='API.INVALID_WORKING_CALENDAR_ID')
3802
        working_calendar_id = new_values['data']['working_calendar_id']
3803
3804
        cnx = mysql.connector.connect(**config.myems_system_db)
3805
        cursor = cnx.cursor()
3806
3807
        cursor.execute(" SELECT name "
3808
                       " from tbl_spaces "
3809
                       " WHERE id = %s ", (id_,))
3810
        if cursor.fetchone() is None:
3811
            cursor.close()
3812
            cnx.close()
3813
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3814
                                   description='API.SPACE_NOT_FOUND')
3815
3816
        cursor.execute(" SELECT name "
3817
                       " FROM tbl_working_calendars "
3818
                       " WHERE id = %s ", (working_calendar_id,))
3819
        if cursor.fetchone() is None:
3820
            cursor.close()
3821
            cnx.close()
3822
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3823
                                   description='API.WORKING_CALENDAR_NOT_FOUND')
3824
3825
        query = (" SELECT id "
3826
                 " FROM tbl_spaces_working_calendars "
3827
                 " WHERE space_id = %s AND working_calendar_id = %s")
3828
        cursor.execute(query, (id_, working_calendar_id,))
3829
        if cursor.fetchone() is not None:
3830
            cursor.close()
3831
            cnx.close()
3832
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3833
                                   description='API.SPACE_WORKING_CALENDAR_RELATION_EXISTS')
3834
3835
        add_row = (" INSERT INTO tbl_spaces_working_calendars (space_id, working_calendar_id) "
3836
                   " VALUES (%s, %s) ")
3837
        cursor.execute(add_row, (id_, working_calendar_id,))
3838
        cnx.commit()
3839
        cursor.close()
3840
        cnx.close()
3841
3842
        resp.status = falcon.HTTP_201
3843
        resp.location = '/spaces/' + str(id_) + '/workingcalendars/' + str(working_calendar_id)
3844
3845
3846
class SpaceWorkingCalendarItem:
3847
    def __init__(self):
3848
        pass
3849
3850
    @staticmethod
3851
    def on_options(req, resp, id_, wcid):
3852
        _ = req
3853
        resp.status = falcon.HTTP_200
3854
        _ = id_
3855
3856
    @staticmethod
3857
    @user_logger
3858
    def on_delete(req, resp, id_, wcid):
3859
        admin_control(req)
3860
        if not id_.isdigit() or int(id_) <= 0:
3861
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3862
                                   description='API.INVALID_SPACE_ID')
3863
3864
        if not wcid.isdigit() or int(wcid) <= 0:
3865
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3866
                                   description='API.INVALID_WORKING_CALENDAR_ID')
3867
3868
        cnx = mysql.connector.connect(**config.myems_system_db)
3869
        cursor = cnx.cursor()
3870
3871
        cursor.execute(" SELECT name "
3872
                       " FROM tbl_spaces "
3873
                       " WHERE id = %s ", (id_,))
3874
        if cursor.fetchone() is None:
3875
            cursor.close()
3876
            cnx.close()
3877
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3878
                                   description='API.SPACE_NOT_FOUND')
3879
3880
        cursor.execute(" SELECT name "
3881
                       " FROM tbl_working_calendars "
3882
                       " WHERE id = %s ", (wcid,))
3883
        if cursor.fetchone() is None:
3884
            cursor.close()
3885
            cnx.close()
3886
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3887
                                   description='API.WORKING_CALENDAR_NOT_FOUND')
3888
3889
        cursor.execute(" SELECT id "
3890
                       " FROM tbl_spaces_working_calendars "
3891
                       " WHERE space_id = %s AND working_calendar_id = %s ", (id_, wcid))
3892
        if cursor.fetchone() is None:
3893
            cursor.close()
3894
            cnx.close()
3895
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3896
                                   description='API.SPACE_WORKING_CALENDAR_RELATION_NOT_FOUND')
3897
3898
        cursor.execute(" DELETE FROM tbl_spaces_working_calendars "
3899
                       " WHERE space_id = %s AND working_calendar_id = %s ", (id_, wcid))
3900
        cnx.commit()
3901
3902
        cursor.close()
3903
        cnx.close()
3904
3905
        resp.status = falcon.HTTP_204
3906
3907
3908 View Code Duplication
class SpaceCommandCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3909
    def __init__(self):
3910
        pass
3911
3912
    @staticmethod
3913
    def on_options(req, resp, id_):
3914
        _ = req
3915
        resp.status = falcon.HTTP_200
3916
        _ = id_
3917
3918
    @staticmethod
3919
    def on_get(req, resp, id_):
3920
        if 'API-KEY' not in req.headers or \
3921
                not isinstance(req.headers['API-KEY'], str) or \
3922
                len(str.strip(req.headers['API-KEY'])) == 0:
3923
            access_control(req)
3924
        else:
3925
            api_key_control(req)
3926
        if not id_.isdigit() or int(id_) <= 0:
3927
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3928
                                   description='API.INVALID_SPACE_ID')
3929
3930
        cnx = mysql.connector.connect(**config.myems_system_db)
3931
        cursor = cnx.cursor()
3932
3933
        cursor.execute(" SELECT name "
3934
                       " FROM tbl_spaces "
3935
                       " WHERE id = %s ", (id_,))
3936
        if cursor.fetchone() is None:
3937
            cursor.close()
3938
            cnx.close()
3939
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3940
                                   description='API.SPACE_NOT_FOUND')
3941
3942
        query = (" SELECT c.id, c.name, c.uuid "
3943
                 " FROM tbl_spaces s, tbl_spaces_commands sc, tbl_commands c "
3944
                 " WHERE sc.space_id = s.id AND c.id = sc.command_id AND s.id = %s "
3945
                 " ORDER BY c.id ")
3946
        cursor.execute(query, (id_,))
3947
        rows = cursor.fetchall()
3948
3949
        result = list()
3950
        if rows is not None and len(rows) > 0:
3951
            for row in rows:
3952
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
3953
                result.append(meta_result)
3954
3955
        resp.text = json.dumps(result)
3956
3957
    @staticmethod
3958
    @user_logger
3959
    def on_post(req, resp, id_):
3960
        """Handles POST requests"""
3961
        admin_control(req)
3962
        try:
3963
            raw_json = req.stream.read().decode('utf-8')
3964
        except UnicodeDecodeError as ex:
3965
            print("Failed to decode request")
3966
            raise falcon.HTTPError(status=falcon.HTTP_400,
3967
                                   title='API.BAD_REQUEST',
3968
                                   description='API.INVALID_ENCODING')
3969
        except Exception as ex:
3970
            print("Unexpected error reading request stream")
3971
            raise falcon.HTTPError(status=falcon.HTTP_400,
3972
                                   title='API.BAD_REQUEST',
3973
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3974
3975
        if not id_.isdigit() or int(id_) <= 0:
3976
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3977
                                   description='API.INVALID_SPACE_ID')
3978
3979
        new_values = json.loads(raw_json)
3980
3981
        if 'command_id' not in new_values['data'].keys() or \
3982
                not isinstance(new_values['data']['command_id'], int) or \
3983
                new_values['data']['command_id'] <= 0:
3984
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3985
                                   description='API.INVALID_COMMAND_ID')
3986
        command_id = new_values['data']['command_id']
3987
3988
        cnx = mysql.connector.connect(**config.myems_system_db)
3989
        cursor = cnx.cursor()
3990
3991
        cursor.execute(" SELECT name "
3992
                       " from tbl_spaces "
3993
                       " WHERE id = %s ", (id_,))
3994
        if cursor.fetchone() is None:
3995
            cursor.close()
3996
            cnx.close()
3997
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3998
                                   description='API.SPACE_NOT_FOUND')
3999
4000
        cursor.execute(" SELECT name "
4001
                       " FROM tbl_commands "
4002
                       " WHERE id = %s ", (command_id,))
4003
        if cursor.fetchone() is None:
4004
            cursor.close()
4005
            cnx.close()
4006
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4007
                                   description='API.COMMAND_NOT_FOUND')
4008
4009
        query = (" SELECT id "
4010
                 " FROM tbl_spaces_commands "
4011
                 " WHERE space_id = %s AND command_id = %s")
4012
        cursor.execute(query, (id_, command_id,))
4013
        if cursor.fetchone() is not None:
4014
            cursor.close()
4015
            cnx.close()
4016
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4017
                                   description='API.SPACE_COMMAND_RELATION_EXISTS')
4018
4019
        add_row = (" INSERT INTO tbl_spaces_commands (space_id, command_id) "
4020
                   " VALUES (%s, %s) ")
4021
        cursor.execute(add_row, (id_, command_id,))
4022
        cnx.commit()
4023
        cursor.close()
4024
        cnx.close()
4025
4026
        resp.status = falcon.HTTP_201
4027
        resp.location = '/spaces/' + str(id_) + '/commands/' + str(command_id)
4028
4029
4030
class SpaceCommandItem:
4031
    def __init__(self):
4032
        pass
4033
4034
    @staticmethod
4035
    def on_options(req, resp, id_, cid):
4036
        _ = req
4037
        resp.status = falcon.HTTP_200
4038
        _ = id_
4039
4040
    @staticmethod
4041
    @user_logger
4042
    def on_delete(req, resp, id_, cid):
4043
        admin_control(req)
4044
        if not id_.isdigit() or int(id_) <= 0:
4045
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4046
                                   description='API.INVALID_SPACE_ID')
4047
4048
        if not cid.isdigit() or int(cid) <= 0:
4049
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4050
                                   description='API.INVALID_COMMAND_ID')
4051
4052
        cnx = mysql.connector.connect(**config.myems_system_db)
4053
        cursor = cnx.cursor()
4054
4055
        cursor.execute(" SELECT name "
4056
                       " FROM tbl_spaces "
4057
                       " WHERE id = %s ", (id_,))
4058
        if cursor.fetchone() is None:
4059
            cursor.close()
4060
            cnx.close()
4061
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4062
                                   description='API.SPACE_NOT_FOUND')
4063
4064
        cursor.execute(" SELECT name "
4065
                       " FROM tbl_commands "
4066
                       " WHERE id = %s ", (cid,))
4067
        if cursor.fetchone() is None:
4068
            cursor.close()
4069
            cnx.close()
4070
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4071
                                   description='API.COMMAND_NOT_FOUND')
4072
4073
        cursor.execute(" SELECT id "
4074
                       " FROM tbl_spaces_commands "
4075
                       " WHERE space_id = %s AND command_id = %s ", (id_, cid))
4076
        if cursor.fetchone() is None:
4077
            cursor.close()
4078
            cnx.close()
4079
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4080
                                   description='API.SPACE_COMMAND_RELATION_NOT_FOUND')
4081
4082
        cursor.execute(" DELETE FROM tbl_spaces_commands WHERE space_id = %s AND command_id = %s ", (id_, cid))
4083
        cnx.commit()
4084
4085
        cursor.close()
4086
        cnx.close()
4087
4088
        resp.status = falcon.HTTP_204
4089
4090
4091
class SpaceExport:
4092
    def __init__(self):
4093
        pass
4094
4095
    @staticmethod
4096
    def on_options(req, resp, id_):
4097
        _ = req
4098
        resp.status = falcon.HTTP_200
4099
        _ = id_
4100
4101
    @staticmethod
4102
    def on_get(req, resp, id_):
4103
        if 'API-KEY' not in req.headers or \
4104
                not isinstance(req.headers['API-KEY'], str) or \
4105
                len(str.strip(req.headers['API-KEY'])) == 0:
4106
            access_control(req)
4107
        else:
4108
            api_key_control(req)
4109
        if not id_.isdigit() or int(id_) <= 0:
4110
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4111
                                   description='API.INVALID_METER_ID')
4112
4113
        cnx = mysql.connector.connect(**config.myems_system_db)
4114
        cursor = cnx.cursor()
4115
4116
        query = (" SELECT id, name, uuid "
4117
                 " FROM tbl_spaces ")
4118
        cursor.execute(query)
4119
        rows_spaces = cursor.fetchall()
4120
4121
        space_dict = dict()
4122
        if rows_spaces is not None and len(rows_spaces) > 0:
4123
            for row in rows_spaces:
4124
                space_dict[row[0]] = {"id": row[0],
4125
                                      "name": row[1],
4126
                                      "uuid": row[2]}
4127
4128
        query = (" SELECT id, name, utc_offset "
4129
                 " FROM tbl_timezones ")
4130
        cursor.execute(query)
4131
        rows_timezones = cursor.fetchall()
4132
4133
        timezone_dict = dict()
4134
        if rows_timezones is not None and len(rows_timezones) > 0:
4135
            for row in rows_timezones:
4136
                timezone_dict[row[0]] = {"id": row[0],
4137
                                         "name": row[1],
4138
                                         "utc_offset": row[2]}
4139
4140
        query = (" SELECT id, name, uuid "
4141
                 " FROM tbl_contacts ")
4142
        cursor.execute(query)
4143
        rows_contacts = cursor.fetchall()
4144
4145
        contact_dict = dict()
4146
        if rows_contacts is not None and len(rows_contacts) > 0:
4147
            for row in rows_contacts:
4148
                contact_dict[row[0]] = {"id": row[0],
4149
                                        "name": row[1],
4150
                                        "uuid": row[2]}
4151
4152
        query = (" SELECT id, name, uuid "
4153
                 " FROM tbl_cost_centers ")
4154
        cursor.execute(query)
4155
        rows_cost_centers = cursor.fetchall()
4156
4157
        cost_center_dict = dict()
4158
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
4159
            for row in rows_cost_centers:
4160
                cost_center_dict[row[0]] = {"id": row[0],
4161
                                            "name": row[1],
4162
                                            "uuid": row[2]}
4163
4164
        query = (" SELECT id, name, uuid, "
4165
                 "        parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
4166
                 "        contact_id, cost_center_id, latitude, longitude, description "
4167
                 " FROM tbl_spaces "
4168
                 " WHERE id = %s ")
4169
        cursor.execute(query, (id_,))
4170
        row = cursor.fetchone()
4171
4172
        if row is None:
4173
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4174
                                   description='API.SPACE_NOT_FOUND')
4175
        else:
4176
            meta_result = {"id": row[0],
4177
                           "name": row[1],
4178
                           "uuid": row[2],
4179
                           "parent_space_id": space_dict.get(row[3], None),
4180
                           "area": row[4],
4181
                           "timezone": timezone_dict.get(row[5], None),
4182
                           "is_input_counted": bool(row[6]),
4183
                           "is_output_counted": bool(row[7]),
4184
                           "contact": contact_dict.get(row[8], None),
4185
                           "cost_center": cost_center_dict.get(row[9], None),
4186
                           "latitude": row[10],
4187
                           "longitude": row[11],
4188
                           "description": row[12],
4189
                           "children": None,
4190
                           "commands": None,
4191
                           "meters": None,
4192
                           "offline_meters": None,
4193
                           "virtual_meters": None,
4194
                           "shopfloors": None,
4195
                           "combined_equipments": None,
4196
                           "equipments": None,
4197
                           "points": None,
4198
                           "sensors": None,
4199
                           "tenants": None,
4200
                           "stores": None,
4201
                           "working_calendars": None
4202
                           }
4203
            query = (" SELECT id, name, uuid, "
4204
                     "        parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
4205
                     "        contact_id, cost_center_id, latitude, longitude, description "
4206
                     " FROM tbl_spaces "
4207
                     " WHERE id = %s ")
4208
            cursor.execute(query, (id_,))
4209
            row_current_space = cursor.fetchone()
4210
            if row_current_space is None:
4211
                cursor.close()
4212
                cnx.close()
4213
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4214
                                       description='API.SPACE_NOT_FOUND')
4215
            # note: row_current_space will be used at the end
4216
4217
            query = (" SELECT id, name, uuid "
4218
                     " FROM tbl_spaces ")
4219
            cursor.execute(query)
4220
            rows_spaces = cursor.fetchall()
4221
4222
            space_dict = dict()
4223
            if rows_spaces is not None and len(rows_spaces) > 0:
4224
                for row in rows_spaces:
4225
                    space_dict[row[0]] = {"id": row[0],
4226
                                          "name": row[1],
4227
                                          "uuid": row[2]}
4228
4229
            query = (" SELECT id, name, utc_offset "
4230
                     " FROM tbl_timezones ")
4231
            cursor.execute(query)
4232
            rows_timezones = cursor.fetchall()
4233
4234
            timezone_dict = dict()
4235
            if rows_timezones is not None and len(rows_timezones) > 0:
4236
                for row in rows_timezones:
4237
                    timezone_dict[row[0]] = {"id": row[0],
4238
                                             "name": row[1],
4239
                                             "utc_offset": row[2]}
4240
4241
            query = (" SELECT id, name, uuid "
4242
                     " FROM tbl_contacts ")
4243
            cursor.execute(query)
4244
            rows_contacts = cursor.fetchall()
4245
4246
            contact_dict = dict()
4247
            if rows_contacts is not None and len(rows_contacts) > 0:
4248
                for row in rows_contacts:
4249
                    contact_dict[row[0]] = {"id": row[0],
4250
                                            "name": row[1],
4251
                                            "uuid": row[2]}
4252
4253
            query = (" SELECT id, name, uuid "
4254
                     " FROM tbl_cost_centers ")
4255
            cursor.execute(query)
4256
            rows_cost_centers = cursor.fetchall()
4257
4258
            cost_center_dict = dict()
4259
            if rows_cost_centers is not None and len(rows_cost_centers) > 0:
4260
                for row in rows_cost_centers:
4261
                    cost_center_dict[row[0]] = {"id": row[0],
4262
                                                "name": row[1],
4263
                                                "uuid": row[2]}
4264
            result = dict()
4265
            result['current'] = dict()
4266
            result['current']['id'] = row_current_space[0]
4267
            result['current']['name'] = row_current_space[1]
4268
            result['current']['uuid'] = row_current_space[2]
4269
            result['current']['parent_space'] = space_dict.get(row_current_space[3], None)
4270
            result['current']['area'] = row_current_space[4]
4271
            result['current']['timezone'] = timezone_dict.get(row_current_space[5], None)
4272
            result['current']['is_input_counted'] = bool(row_current_space[6])
4273
            result['current']['is_output_counted'] = bool(row_current_space[7])
4274
            result['current']['contact'] = contact_dict.get(row_current_space[8], None)
4275
            result['current']['cost_center'] = cost_center_dict.get(row_current_space[9], None)
4276
            result['current']['latitude'] = row_current_space[10]
4277
            result['current']['longitude'] = row_current_space[11]
4278
            result['current']['description'] = row_current_space[12]
4279
            result['current']['qrcode'] = 'space:' + row_current_space[2]
4280
4281
            result['children'] = list()
4282
4283
            query = (" SELECT id, name, uuid, "
4284
                     "        parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
4285
                     "        contact_id, cost_center_id, latitude, longitude, description "
4286
                     " FROM tbl_spaces "
4287
                     " WHERE parent_space_id = %s "
4288
                     " ORDER BY id ")
4289
            cursor.execute(query, (id_,))
4290
            rows_spaces = cursor.fetchall()
4291
4292 View Code Duplication
            if rows_spaces is not None and len(rows_spaces) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4293
                for row in rows_spaces:
4294
                    children_result = {"id": row[0],
4295
                                       "name": row[1],
4296
                                       "uuid": row[2],
4297
                                       "parent_space": space_dict.get(row[3], None),
4298
                                       "area": row[4],
4299
                                       "timezone": timezone_dict.get(row[5], None),
4300
                                       "is_input_counted": bool(row[6]),
4301
                                       "is_output_counted": bool(row[7]),
4302
                                       "contact": contact_dict.get(row[8], None),
4303
                                       "cost_center": cost_center_dict.get(row[9], None),
4304
                                       "latitude": row[10],
4305
                                       "longitude": row[11],
4306
                                       "description": row[12]}
4307
                    result['children'].append(children_result)
4308
                meta_result['children'] = result['children']
4309
            query = (" SELECT c.id, c.name, c.uuid "
4310
                     " FROM tbl_spaces s, tbl_spaces_commands sc, tbl_commands c "
4311
                     " WHERE sc.space_id = s.id AND c.id = sc.command_id AND s.id = %s "
4312
                     " ORDER BY c.id ")
4313
            cursor.execute(query, (id_,))
4314
            rows = cursor.fetchall()
4315
4316
            command_result = list()
4317
            if rows is not None and len(rows) > 0:
4318
                for row in rows:
4319
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4320
                    command_result.append(result)
4321
                meta_result['commands'] = command_result
4322
            query = (" SELECT id, name, uuid "
4323
                     " FROM tbl_energy_categories ")
4324
            cursor.execute(query)
4325
            rows_energy_categories = cursor.fetchall()
4326
4327
            energy_category_dict = dict()
4328
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
4329
                for row in rows_energy_categories:
4330
                    energy_category_dict[row[0]] = {"id": row[0],
4331
                                                    "name": row[1],
4332
                                                    "uuid": row[2]}
4333
4334
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
4335
                     " FROM tbl_spaces s, tbl_spaces_meters sm, tbl_meters m "
4336
                     " WHERE sm.space_id = s.id AND m.id = sm.meter_id AND s.id = %s "
4337
                     " ORDER BY m.id ")
4338
            cursor.execute(query, (id_,))
4339
            rows = cursor.fetchall()
4340
4341
            meter_result = list()
4342
            if rows is not None and len(rows) > 0:
4343
                for row in rows:
4344
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
4345
                              "energy_category": energy_category_dict.get(row[3], None)}
4346
                    meter_result.append(result)
4347
                meta_result['meters'] = meter_result
4348
            query = (" SELECT id, name, uuid "
4349
                     " FROM tbl_energy_categories ")
4350
            cursor.execute(query)
4351
            rows_energy_categories = cursor.fetchall()
4352
4353
            energy_category_dict = dict()
4354
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
4355
                for row in rows_energy_categories:
4356
                    energy_category_dict[row[0]] = {"id": row[0],
4357
                                                    "name": row[1],
4358
                                                    "uuid": row[2]}
4359
4360
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
4361
                     " FROM tbl_spaces s, tbl_spaces_offline_meters sm, tbl_offline_meters m "
4362
                     " WHERE sm.space_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
4363
                     " ORDER BY m.id ")
4364
            cursor.execute(query, (id_,))
4365
            rows = cursor.fetchall()
4366
4367
            offlinemeter_result = list()
4368
            if rows is not None and len(rows) > 0:
4369
                for row in rows:
4370
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
4371
                              "energy_category": energy_category_dict.get(row[3], None)}
4372
                    offlinemeter_result.append(result)
4373
                meta_result['offline_meters'] = offlinemeter_result
4374
            query = (" SELECT id, name, uuid "
4375
                     " FROM tbl_energy_categories ")
4376
            cursor.execute(query)
4377
            rows_energy_categories = cursor.fetchall()
4378
4379
            energy_category_dict = dict()
4380
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
4381
                for row in rows_energy_categories:
4382
                    energy_category_dict[row[0]] = {"id": row[0],
4383
                                                    "name": row[1],
4384
                                                    "uuid": row[2]}
4385
4386
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
4387
                     " FROM tbl_spaces s, tbl_spaces_virtual_meters sm, tbl_virtual_meters m "
4388
                     " WHERE sm.space_id = s.id AND m.id = sm.virtual_meter_id AND s.id = %s "
4389
                     " ORDER BY m.id ")
4390
            cursor.execute(query, (id_,))
4391
            rows = cursor.fetchall()
4392
4393
            virtualmeter_result = list()
4394
            if rows is not None and len(rows) > 0:
4395
                for row in rows:
4396
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
4397
                              "energy_category": energy_category_dict.get(row[3], None)}
4398
                    virtualmeter_result.append(result)
4399
                meta_result['virtual_meters'] = virtualmeter_result
4400
            query = (" SELECT sf.id, sf.name, sf.uuid "
4401
                     " FROM tbl_spaces sp, tbl_spaces_shopfloors ss, tbl_shopfloors sf "
4402
                     " WHERE ss.space_id = sp.id AND sf.id = ss.shopfloor_id AND sp.id = %s "
4403
                     " ORDER BY sf.id ")
4404
            cursor.execute(query, (id_,))
4405
            rows = cursor.fetchall()
4406
4407
            shopfloor_result = list()
4408
            if rows is not None and len(rows) > 0:
4409
                for row in rows:
4410
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4411
                    shopfloor_result.append(result)
4412
                meta_result['shopfloors'] = shopfloor_result
4413
            query = (" SELECT e.id, e.name, e.uuid "
4414
                     " FROM tbl_spaces s, tbl_spaces_combined_equipments se, tbl_combined_equipments e "
4415
                     " WHERE se.space_id = s.id AND e.id = se.combined_equipment_id AND s.id = %s "
4416
                     " ORDER BY e.id ")
4417
            cursor.execute(query, (id_,))
4418
            rows = cursor.fetchall()
4419
4420
            combinedequipment_result = list()
4421
            if rows is not None and len(rows) > 0:
4422
                for row in rows:
4423
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4424
                    combinedequipment_result.append(result)
4425
                meta_result['combined_equipments'] = combinedequipment_result
4426
            query = (" SELECT e.id, e.name, e.uuid "
4427
                     " FROM tbl_spaces s, tbl_spaces_equipments se, tbl_equipments e "
4428
                     " WHERE se.space_id = s.id AND e.id = se.equipment_id AND s.id = %s "
4429
                     " ORDER BY e.id ")
4430
            cursor.execute(query, (id_,))
4431
            rows = cursor.fetchall()
4432
4433
            equipment_result = list()
4434
            if rows is not None and len(rows) > 0:
4435
                for row in rows:
4436
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4437
                    equipment_result.append(result)
4438
                meta_result['equipments'] = equipment_result
4439
            query = (" SELECT id, name, uuid "
4440
                     " FROM tbl_data_sources ")
4441
            cursor.execute(query)
4442
            rows_data_sources = cursor.fetchall()
4443
4444
            data_source_dict = dict()
4445
            if rows_data_sources is not None and len(rows_data_sources) > 0:
4446
                for row in rows_data_sources:
4447
                    data_source_dict[row[0]] = {"id": row[0],
4448
                                                "name": row[1],
4449
                                                "uuid": row[2]}
4450
4451
            query = (" SELECT p.id, p.name, p.data_source_id "
4452
                     " FROM tbl_spaces s, tbl_spaces_points sp, tbl_points p "
4453
                     " WHERE sp.space_id = s.id AND p.id = sp.point_id AND s.id = %s "
4454
                     " ORDER BY p.id ")
4455
            cursor.execute(query, (id_,))
4456
            rows = cursor.fetchall()
4457
4458
            point_result = list()
4459
            if rows is not None and len(rows) > 0:
4460
                for row in rows:
4461
                    result = {"id": row[0], "name": row[1], "data_source": data_source_dict.get(row[2], None)}
4462
                    point_result.append(result)
4463
                meta_result['points'] = point_result
4464
            query = (" SELECT se.id, se.name, se.uuid "
4465
                     " FROM tbl_spaces sp, tbl_spaces_sensors ss, tbl_sensors se "
4466
                     " WHERE ss.space_id = sp.id AND se.id = ss.sensor_id AND sp.id = %s "
4467
                     " ORDER BY se.id ")
4468
            cursor.execute(query, (id_,))
4469
            rows = cursor.fetchall()
4470
4471
            sensor_result = list()
4472
            if rows is not None and len(rows) > 0:
4473
                for row in rows:
4474
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4475
                    sensor_result.append(result)
4476
                meta_result['sensors'] = sensor_result
4477
            query = (" SELECT t.id, t.name, t.uuid "
4478
                     " FROM tbl_spaces s, tbl_spaces_tenants st, tbl_tenants t "
4479
                     " WHERE st.space_id = s.id AND t.id = st.tenant_id AND s.id = %s "
4480
                     " ORDER BY t.id ")
4481
            cursor.execute(query, (id_,))
4482
            rows = cursor.fetchall()
4483
4484
            tenant_result = list()
4485
            if rows is not None and len(rows) > 0:
4486
                for row in rows:
4487
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4488
                    tenant_result.append(result)
4489
                meta_result['tenants'] = tenant_result
4490
            query = (" SELECT t.id, t.name, t.uuid "
4491
                     " FROM tbl_spaces s, tbl_spaces_stores st, tbl_stores t "
4492
                     " WHERE st.space_id = s.id AND t.id = st.store_id AND s.id = %s "
4493
                     " ORDER BY t.id ")
4494
            cursor.execute(query, (id_,))
4495
            rows = cursor.fetchall()
4496
4497
            store_result = list()
4498
            if rows is not None and len(rows) > 0:
4499
                for row in rows:
4500
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
4501
                    store_result.append(result)
4502
                meta_result['stores'] = store_result
4503
            query = (" SELECT wc.id, wc.name, wc.description "
4504
                     " FROM tbl_spaces s, tbl_spaces_working_calendars swc, tbl_working_calendars wc "
4505
                     " WHERE swc.space_id = s.id AND wc.id = swc.working_calendar_id AND s.id = %s "
4506
                     " ORDER BY wc.id ")
4507
            cursor.execute(query, (id_,))
4508
            rows = cursor.fetchall()
4509
4510
            workingcalendar_result = list()
4511
            if rows is not None and len(rows) > 0:
4512
                for row in rows:
4513
                    result = {"id": row[0], "name": row[1], "description": row[2]}
4514
                    workingcalendar_result.append(result)
4515
                meta_result['working_calendars'] = workingcalendar_result
4516
        cursor.close()
4517
        cnx.close()
4518
        resp.text = json.dumps(meta_result)
4519
4520
4521
class SpaceImport:
4522
    def __init__(self):
4523
        pass
4524
4525
    @staticmethod
4526
    def on_options(req, resp):
4527
        _ = req
4528
        resp.status = falcon.HTTP_200
4529
4530
    @staticmethod
4531
    @user_logger
4532
    def on_post(req, resp):
4533
        """Handles POST requests"""
4534
        admin_control(req)
4535
        try:
4536
            raw_json = req.stream.read().decode('utf-8')
4537
            new_values = json.loads(raw_json)
4538
        except UnicodeDecodeError as ex:
4539
            print("Failed to decode request")
4540
            raise falcon.HTTPError(status=falcon.HTTP_400,
4541
                                   title='API.BAD_REQUEST',
4542
                                   description='API.INVALID_ENCODING')
4543
        except json.JSONDecodeError as ex:
4544
            print("Failed to parse JSON")
4545
            raise falcon.HTTPError(status=falcon.HTTP_400,
4546
                                   title='API.BAD_REQUEST',
4547
                                   description='API.INVALID_JSON_FORMAT')
4548
        except Exception as ex:
4549
            print("Unexpected error reading request stream")
4550
            raise falcon.HTTPError(status=falcon.HTTP_400,
4551
                                   title='API.BAD_REQUEST',
4552
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
4553
4554
        if 'name' not in new_values.keys() or \
4555
                not isinstance(new_values['name'], str) or \
4556
                len(str.strip(new_values['name'])) == 0:
4557
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4558
                                   description='API.INVALID_SPACE_NAME')
4559
        name = str.strip(new_values['name'])
4560
4561
        if 'id' in new_values['parent_space_id'].keys():
4562
            if new_values['parent_space_id']['id'] <= 0:
4563
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4564
                                       description='API.INVALID_PARENT_SPACE_ID')
4565
            parent_space_id = new_values['parent_space_id']['id']
4566
        else:
4567
            parent_space_id = None
4568
4569
        if 'area' not in new_values.keys() or \
4570
                not (isinstance(new_values['area'], float) or
4571
                     isinstance(new_values['area'], int)) or \
4572
                new_values['area'] <= 0.0:
4573
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4574
                                   description='API.INVALID_AREA_VALUE')
4575
        area = new_values['area']
4576
4577
        if 'id' not in new_values['timezone'].keys() or \
4578
                not isinstance(new_values['timezone']['id'], int) or \
4579
                new_values['timezone']['id'] <= 0:
4580
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4581
                                   description='API.INVALID_TIMEZONE_ID')
4582
        timezone_id = new_values['timezone']['id']
4583
4584
        if 'is_input_counted' not in new_values.keys() or \
4585
                not isinstance(new_values['is_input_counted'], bool):
4586
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4587
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
4588
        is_input_counted = new_values['is_input_counted']
4589
4590
        if 'is_output_counted' not in new_values.keys() or \
4591
                not isinstance(new_values['is_output_counted'], bool):
4592
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4593
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
4594
        is_output_counted = new_values['is_output_counted']
4595
4596 View Code Duplication
        if 'contact' in new_values.keys() and \
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4597
            new_values['contact'] is not None and \
4598
                'id' in new_values['contact'].keys() and \
4599
                new_values['contact']['id'] is not None:
4600
            if not isinstance(new_values['contact']['id'], int) or \
4601
                    new_values['contact']['id'] <= 0:
4602
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4603
                                       description='API.INVALID_CONTACT_ID')
4604
            contact_id = new_values['contact']['id']
4605
        else:
4606
            contact_id = None
4607
4608
        if 'id' in new_values['cost_center'].keys():
4609
            if new_values['cost_center']['id'] <= 0:
4610
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4611
                                       description='API.INVALID_COST_CENTER_ID')
4612
            cost_center_id = new_values['cost_center']['id']
4613
        else:
4614
            cost_center_id = None
4615
4616 View Code Duplication
        if 'latitude' in new_values.keys() and new_values['latitude'] is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4617
            if not (isinstance(new_values['latitude'], float) or
4618
                    isinstance(new_values['latitude'], int)) or \
4619
                    new_values['latitude'] < -90.0 or \
4620
                    new_values['latitude'] > 90.0:
4621
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4622
                                       description='API.INVALID_LATITUDE_VALUE')
4623
            latitude = new_values['latitude']
4624
        else:
4625
            latitude = None
4626
4627 View Code Duplication
        if 'longitude' in new_values.keys() and new_values['longitude'] is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4628
            if not (isinstance(new_values['longitude'], float) or
4629
                    isinstance(new_values['longitude'], int)) or \
4630
                    new_values['longitude'] < -180.0 or \
4631
                    new_values['longitude'] > 180.0:
4632
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4633
                                       description='API.INVALID_LONGITUDE_VALUE')
4634
            longitude = new_values['longitude']
4635
        else:
4636
            longitude = None
4637
4638
        if 'description' in new_values.keys() and \
4639
                new_values['description'] is not None and \
4640
                len(str(new_values['description'])) > 0:
4641
            description = str.strip(new_values['description'])
4642
        else:
4643
            description = None
4644
4645
        cnx = mysql.connector.connect(**config.myems_system_db)
4646
        cursor = cnx.cursor()
4647
4648
        cursor.execute(" SELECT name "
4649
                       " FROM tbl_spaces "
4650
                       " WHERE name = %s ", (name,))
4651
        if cursor.fetchone() is not None:
4652
            cursor.close()
4653
            cnx.close()
4654
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
4655
                                   description='API.SPACE_NAME_IS_ALREADY_IN_USE')
4656
4657 View Code Duplication
        if parent_space_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4658
            cursor.execute(" SELECT name "
4659
                           " FROM tbl_spaces "
4660
                           " WHERE id = %s ",
4661
                           (new_values['parent_space_id']['id'],))
4662
            row = cursor.fetchone()
4663
            if row is None:
4664
                cursor.close()
4665
                cnx.close()
4666
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4667
                                       description='API.PARENT_SPACE_NOT_FOUND')
4668
4669
        cursor.execute(" SELECT name "
4670
                       " FROM tbl_timezones "
4671
                       " WHERE id = %s ",
4672
                       (new_values['timezone']['id'],))
4673
        if cursor.fetchone() is None:
4674
            cursor.close()
4675
            cnx.close()
4676
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4677
                                   description='API.TIMEZONE_NOT_FOUND')
4678 View Code Duplication
        if contact_id is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4679
            cursor.execute(" SELECT name "
4680
                           " FROM tbl_contacts "
4681
                           " WHERE id = %s ",
4682
                           (new_values['contact']['id'],))
4683
            row = cursor.fetchone()
4684
            if row is None:
4685
                cursor.close()
4686
                cnx.close()
4687
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4688
                                       description='API.CONTACT_NOT_FOUND')
4689
4690
        if cost_center_id is not None:
4691
            cursor.execute(" SELECT name "
4692
                           " FROM tbl_cost_centers "
4693
                           " WHERE id = %s ",
4694
                           (new_values['cost_center']['id'],))
4695
            row = cursor.fetchone()
4696
            if row is None:
4697
                cursor.close()
4698
                cnx.close()
4699
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4700
                                       description='API.COST_CENTER_NOT_FOUND')
4701
4702
        add_values = (" INSERT INTO tbl_spaces "
4703
                      "    (name, uuid, parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
4704
                      "     contact_id, cost_center_id, latitude, longitude, description) "
4705
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
4706
        cursor.execute(add_values, (name,
4707
                                    str(uuid.uuid4()),
4708
                                    parent_space_id,
4709
                                    area,
4710
                                    timezone_id,
4711
                                    is_input_counted,
4712
                                    is_output_counted,
4713
                                    contact_id,
4714
                                    cost_center_id,
4715
                                    latitude,
4716
                                    longitude,
4717
                                    description))
4718
        new_id = cursor.lastrowid
4719
        if new_values['commands'] is not None and len(new_values['commands']) > 0:
4720
            for command in new_values['commands']:
4721
                cursor.execute(" SELECT name "
4722
                               " FROM tbl_commands "
4723
                               " WHERE id = %s ", (command['id'],))
4724
                if cursor.fetchone() is None:
4725
                    cursor.close()
4726
                    cnx.close()
4727
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4728
                                           description='API.COMMAND_NOT_FOUND')
4729
4730
                query = (" SELECT id "
4731
                         " FROM tbl_spaces_commands "
4732
                         " WHERE space_id = %s AND command_id = %s")
4733
                cursor.execute(query, (new_id, command['id'],))
4734
                if cursor.fetchone() is not None:
4735
                    cursor.close()
4736
                    cnx.close()
4737
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4738
                                           description='API.SPACE_COMMAND_RELATION_EXISTS')
4739
4740
                add_row = (" INSERT INTO tbl_spaces_commands (space_id, command_id) "
4741
                           " VALUES (%s, %s) ")
4742
                cursor.execute(add_row, (new_id, command['id'],))
4743
        if new_values['meters'] is not None and len(new_values['meters']) > 0:
4744
            for meter in new_values['meters']:
4745
                cursor.execute(" SELECT name "
4746
                               " FROM tbl_meters "
4747
                               " WHERE id = %s ", (meter['id'],))
4748
                if cursor.fetchone() is None:
4749
                    cursor.close()
4750
                    cnx.close()
4751
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4752
                                           description='API.METER_NOT_FOUND')
4753
4754
                query = (" SELECT id "
4755
                         " FROM tbl_spaces_meters "
4756
                         " WHERE space_id = %s AND meter_id = %s")
4757
                cursor.execute(query, (new_id, meter['id'],))
4758
                if cursor.fetchone() is not None:
4759
                    cursor.close()
4760
                    cnx.close()
4761
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4762
                                           description='API.SPACE_METER_RELATION_EXISTS')
4763
4764
                add_row = (" INSERT INTO tbl_spaces_meters (space_id, meter_id) "
4765
                           " VALUES (%s, %s) ")
4766
                cursor.execute(add_row, (new_id, meter['id'],))
4767
        if new_values['offline_meters'] is not None and len(new_values['offline_meters']) > 0:
4768
            for offline_meter in new_values['offline_meters']:
4769
                cursor.execute(" SELECT name "
4770
                               " FROM tbl_offline_meters "
4771
                               " WHERE id = %s ", (offline_meter['id'],))
4772
                if cursor.fetchone() is None:
4773
                    cursor.close()
4774
                    cnx.close()
4775
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4776
                                           description='API.OFFLINE_METER_NOT_FOUND')
4777
4778
                query = (" SELECT id "
4779
                         " FROM tbl_spaces_offline_meters "
4780
                         " WHERE space_id = %s AND offline_meter_id = %s")
4781
                cursor.execute(query, (new_id, offline_meter['id'],))
4782
                if cursor.fetchone() is not None:
4783
                    cursor.close()
4784
                    cnx.close()
4785
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4786
                                           description='API.SPACE_OFFLINE_METER_RELATION_EXISTS')
4787
4788
                add_row = (" INSERT INTO tbl_spaces_offline_meters (space_id, offline_meter_id) "
4789
                           " VALUES (%s, %s) ")
4790
                cursor.execute(add_row, (new_id, offline_meter['id'],))
4791
        if new_values['virtual_meters'] is not None and len(new_values['virtual_meters']) > 0:
4792
            for virtual_meter in new_values['virtual_meters']:
4793
                cursor.execute(" SELECT name "
4794
                               " FROM tbl_virtual_meters "
4795
                               " WHERE id = %s ", (virtual_meter['id'],))
4796
                if cursor.fetchone() is None:
4797
                    cursor.close()
4798
                    cnx.close()
4799
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4800
                                           description='API.VIRTUAL_METER_NOT_FOUND')
4801
4802
                query = (" SELECT id "
4803
                         " FROM tbl_spaces_virtual_meters "
4804
                         " WHERE space_id = %s AND virtual_meter_id = %s")
4805
                cursor.execute(query, (new_id, virtual_meter['id'],))
4806
                if cursor.fetchone() is not None:
4807
                    cursor.close()
4808
                    cnx.close()
4809
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4810
                                           description='API.SPACE_VIRTUAL_METER_RELATION_EXISTS')
4811
4812
                add_row = (" INSERT INTO tbl_spaces_virtual_meters (space_id, virtual_meter_id) "
4813
                           " VALUES (%s, %s) ")
4814
                cursor.execute(add_row, (new_id, virtual_meter['id'],))
4815
        if new_values['shopfloors'] is not None and len(new_values['shopfloors']) > 0:
4816
            for shopfloor in new_values['shopfloors']:
4817
                cursor.execute(" SELECT name "
4818
                               " FROM tbl_shopfloors "
4819
                               " WHERE id = %s ", (shopfloor['id'],))
4820
                if cursor.fetchone() is None:
4821
                    cursor.close()
4822
                    cnx.close()
4823
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4824
                                           description='API.SHOPFLOOR_NOT_FOUND')
4825
4826
                query = (" SELECT id "
4827
                         " FROM tbl_spaces_shopfloors "
4828
                         " WHERE space_id = %s AND shopfloor_id = %s")
4829
                cursor.execute(query, (new_id, shopfloor['id'],))
4830
                if cursor.fetchone() is not None:
4831
                    cursor.close()
4832
                    cnx.close()
4833
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4834
                                           description='API.SPACE_SHOPFLOOR_RELATION_EXISTS')
4835
4836
                add_row = (" INSERT INTO tbl_spaces_shopfloors (space_id, shopfloor_id) "
4837
                           " VALUES (%s, %s) ")
4838
                cursor.execute(add_row, (new_id, shopfloor['id'],))
4839
        if new_values['combined_equipments'] is not None and len(new_values['combined_equipments']) > 0:
4840
            for combined_equipment in new_values['combined_equipments']:
4841
                cursor.execute(" SELECT name "
4842
                               " FROM tbl_combined_equipments "
4843
                               " WHERE id = %s ", (combined_equipment['id'],))
4844
                if cursor.fetchone() is None:
4845
                    cursor.close()
4846
                    cnx.close()
4847
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4848
                                           description='API.COMBINED_EQUIPMENT_NOT_FOUND')
4849
4850
                query = (" SELECT id "
4851
                         " FROM tbl_spaces_combined_equipments "
4852
                         " WHERE space_id = %s AND combined_equipment_id = %s")
4853
                cursor.execute(query, (new_id, combined_equipment['id'],))
4854
                if cursor.fetchone() is not None:
4855
                    cursor.close()
4856
                    cnx.close()
4857
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4858
                                           description='API.SPACE_COMBINED_EQUIPMENT_RELATION_EXISTS')
4859
4860
                add_row = (" INSERT INTO tbl_spaces_combined_equipments (space_id, combined_equipment_id) "
4861
                           " VALUES (%s, %s) ")
4862
                cursor.execute(add_row, (new_id, combined_equipment['id'],))
4863
        if new_values['equipments'] is not None and len(new_values['equipments']) > 0:
4864
            for equipment in new_values['equipments']:
4865
                cursor.execute(" SELECT name "
4866
                               " FROM tbl_equipments "
4867
                               " WHERE id = %s ", (equipment['id'],))
4868
                if cursor.fetchone() is None:
4869
                    cursor.close()
4870
                    cnx.close()
4871
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4872
                                           description='API.EQUIPMENT_NOT_FOUND')
4873
4874
                query = (" SELECT id "
4875
                         " FROM tbl_spaces_equipments "
4876
                         " WHERE space_id = %s AND equipment_id = %s")
4877
                cursor.execute(query, (new_id, equipment['id'],))
4878
                if cursor.fetchone() is not None:
4879
                    cursor.close()
4880
                    cnx.close()
4881
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4882
                                           description='API.SPACE_EQUIPMENT_RELATION_EXISTS')
4883
4884
                add_row = (" INSERT INTO tbl_spaces_equipments (space_id, equipment_id) "
4885
                           " VALUES (%s, %s) ")
4886
                cursor.execute(add_row, (new_id, equipment['id'],))
4887
        if new_values['points'] is not None and len(new_values['points']) > 0:
4888
            for point in new_values['points']:
4889
                cursor.execute(" SELECT name "
4890
                               " FROM tbl_points "
4891
                               " WHERE id = %s ", (point['id'],))
4892
                if cursor.fetchone() is None:
4893
                    cursor.close()
4894
                    cnx.close()
4895
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4896
                                           description='API.POINT_NOT_FOUND')
4897
4898
                query = (" SELECT id "
4899
                         " FROM tbl_spaces_points "
4900
                         " WHERE space_id = %s AND point_id = %s")
4901
                cursor.execute(query, (new_id, point['id'],))
4902
                if cursor.fetchone() is not None:
4903
                    cursor.close()
4904
                    cnx.close()
4905
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4906
                                           description='API.SPACE_POINT_RELATION_EXISTS')
4907
4908
                add_row = (" INSERT INTO tbl_spaces_points (space_id, point_id) "
4909
                           " VALUES (%s, %s) ")
4910
                cursor.execute(add_row, (new_id, point['id'],))
4911
        if new_values['sensors'] is not None and len(new_values['sensors']) > 0:
4912
            for sensor in new_values['sensors']:
4913
                cursor.execute(" SELECT name "
4914
                               " FROM tbl_sensors "
4915
                               " WHERE id = %s ", (sensor['id'],))
4916
                if cursor.fetchone() is None:
4917
                    cursor.close()
4918
                    cnx.close()
4919
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4920
                                           description='API.SENSOR_NOT_FOUND')
4921
4922
                query = (" SELECT id "
4923
                         " FROM tbl_spaces_sensors "
4924
                         " WHERE space_id = %s AND sensor_id = %s")
4925
                cursor.execute(query, (new_id, sensor['id'],))
4926
                if cursor.fetchone() is not None:
4927
                    cursor.close()
4928
                    cnx.close()
4929
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4930
                                           description='API.SPACE_SENSOR_RELATION_EXISTS')
4931
4932
                add_row = (" INSERT INTO tbl_spaces_sensors (space_id, sensor_id) "
4933
                           " VALUES (%s, %s) ")
4934
                cursor.execute(add_row, (new_id, sensor['id'],))
4935
        if new_values['tenants'] is not None and len(new_values['tenants']) > 0:
4936
            for tenant in new_values['tenants']:
4937
                cursor.execute(" SELECT name "
4938
                               " FROM tbl_tenants "
4939
                               " WHERE id = %s ", (tenant['id'],))
4940
                if cursor.fetchone() is None:
4941
                    cursor.close()
4942
                    cnx.close()
4943
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4944
                                           description='API.TENANT_NOT_FOUND')
4945
4946
                query = (" SELECT id "
4947
                         " FROM tbl_spaces_tenants "
4948
                         " WHERE space_id = %s AND tenant_id = %s")
4949
                cursor.execute(query, (new_id, tenant['id'],))
4950
                if cursor.fetchone() is not None:
4951
                    cursor.close()
4952
                    cnx.close()
4953
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4954
                                           description='API.SPACE_TENANT_RELATION_EXISTS')
4955
4956
                add_row = (" INSERT INTO tbl_spaces_tenants (space_id, tenant_id) "
4957
                           " VALUES (%s, %s) ")
4958
                cursor.execute(add_row, (new_id, tenant['id'],))
4959
        if new_values['stores'] is not None and len(new_values['stores']) > 0:
4960
            for store in new_values['stores']:
4961
                cursor.execute(" SELECT name "
4962
                               " FROM tbl_stores "
4963
                               " WHERE id = %s ", (store['id'],))
4964
                if cursor.fetchone() is None:
4965
                    cursor.close()
4966
                    cnx.close()
4967
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4968
                                           description='API.STORE_NOT_FOUND')
4969
4970
                query = (" SELECT id "
4971
                         " FROM tbl_spaces_stores "
4972
                         " WHERE space_id = %s AND store_id = %s")
4973
                cursor.execute(query, (new_id, store['id'],))
4974
                if cursor.fetchone() is not None:
4975
                    cursor.close()
4976
                    cnx.close()
4977
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
4978
                                           description='API.SPACE_STORE_RELATION_EXISTS')
4979
4980
                add_row = (" INSERT INTO tbl_spaces_stores (space_id, store_id) "
4981
                           " VALUES (%s, %s) ")
4982
                cursor.execute(add_row, (new_id, store['id'],))
4983
            if new_values['working_calendars'] is not None and len(new_values['working_calendars']) > 0:
4984
                for working_calendar in new_values['working_calendars']:
4985
                    cursor.execute(" SELECT name "
4986
                                   " FROM tbl_working_calendars "
4987
                                   " WHERE id = %s ", (working_calendar['id'],))
4988
                    if cursor.fetchone() is None:
4989
                        cursor.close()
4990
                        cnx.close()
4991
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
4992
                                               description='API.WORKING_CALENDAR_NOT_FOUND')
4993
4994
                    query = (" SELECT id "
4995
                             " FROM tbl_spaces_working_calendars "
4996
                             " WHERE space_id = %s AND working_calendar_id = %s")
4997
                    cursor.execute(query, (new_id, working_calendar['id'],))
4998
                    if cursor.fetchone() is not None:
4999
                        cursor.close()
5000
                        cnx.close()
5001
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5002
                                               description='API.SPACE_WORKING_CALENDAR_RELATION_EXISTS')
5003
5004
                    add_row = (" INSERT INTO tbl_spaces_working_calendars (space_id, working_calendar_id) "
5005
                               " VALUES (%s, %s) ")
5006
                    cursor.execute(add_row, (new_id, working_calendar['id'],))
5007
        cnx.commit()
5008
        cursor.close()
5009
        cnx.close()
5010
5011
        resp.status = falcon.HTTP_201
5012
        resp.location = '/spaces/' + str(new_id)
5013
5014
5015
class SpaceClone:
5016
    def __init__(self):
5017
        pass
5018
5019
    @staticmethod
5020
    def on_options(req, resp, id_):
5021
        _ = req
5022
        resp.status = falcon.HTTP_200
5023
        _ = id_
5024
5025
    @staticmethod
5026
    @user_logger
5027
    def on_post(req, resp, id_):
5028
        # check parameters
5029
        admin_control(req)
5030
        if not id_.isdigit() or int(id_) <= 0:
5031
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5032
                                   description='API.INVALID_SPACE_ID')
5033
        if int(id_) == 1:
5034
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5035
                                   description='API.THIS_SPACE_CANNOT_BE_CLONED')
5036
        # connect the database
5037
        cnx = mysql.connector.connect(**config.myems_system_db)
5038
        cursor = cnx.cursor()
5039
        # query all spaces
5040
        query = (" SELECT id, name, uuid "
5041
                 " FROM tbl_spaces ")
5042
        cursor.execute(query)
5043
        rows_spaces = cursor.fetchall()
5044
5045
        space_dict = dict()
5046
        if rows_spaces is not None and len(rows_spaces) > 0:
5047
            for row in rows_spaces:
5048
                space_dict[row[0]] = {"id": row[0],
5049
                                      "name": row[1],
5050
                                      "uuid": row[2]}
5051
        # query all timezones
5052
        query = (" SELECT id, name, utc_offset "
5053
                 " FROM tbl_timezones ")
5054
        cursor.execute(query)
5055
        rows_timezones = cursor.fetchall()
5056
5057
        timezone_dict = dict()
5058
        if rows_timezones is not None and len(rows_timezones) > 0:
5059
            for row in rows_timezones:
5060
                timezone_dict[row[0]] = {"id": row[0],
5061
                                         "name": row[1],
5062
                                         "utc_offset": row[2]}
5063
        # query all contacts
5064
        query = (" SELECT id, name, uuid "
5065
                 " FROM tbl_contacts ")
5066
        cursor.execute(query)
5067
        rows_contacts = cursor.fetchall()
5068
5069
        contact_dict = dict()
5070
        if rows_contacts is not None and len(rows_contacts) > 0:
5071
            for row in rows_contacts:
5072
                contact_dict[row[0]] = {"id": row[0],
5073
                                        "name": row[1],
5074
                                        "uuid": row[2]}
5075
        # query all cost centers
5076
        query = (" SELECT id, name, uuid "
5077
                 " FROM tbl_cost_centers ")
5078
        cursor.execute(query)
5079
        rows_cost_centers = cursor.fetchall()
5080
5081
        cost_center_dict = dict()
5082
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
5083
            for row in rows_cost_centers:
5084
                cost_center_dict[row[0]] = {"id": row[0],
5085
                                            "name": row[1],
5086
                                            "uuid": row[2]}
5087
5088
        # query the source space
5089
        query = (" SELECT id, name, uuid, "
5090
                 "        parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
5091
                 "        contact_id, cost_center_id, latitude, longitude, description "
5092
                 " FROM tbl_spaces "
5093
                 " WHERE id = %s ")
5094
        cursor.execute(query, (id_,))
5095
        row = cursor.fetchone()
5096
5097
        if row is None:
5098
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5099
                                   description='API.SPACE_NOT_FOUND')
5100
        else:
5101
            # save the source space properties to meta_result
5102
            meta_result = {"id": row[0],
5103
                           "name": row[1],
5104
                           "uuid": row[2],
5105
                           "parent_space_id": row[3],
5106
                           "area": row[4],
5107
                           "timezone_id": row[5],
5108
                           "is_input_counted": bool(row[6]),
5109
                           "is_output_counted": bool(row[7]),
5110
                           "contact_id": row[8],
5111
                           "cost_center_id": row[9],
5112
                           "latitude": row[10],
5113
                           "longitude": row[11],
5114
                           "description": row[12],
5115
                           "commands": None,
5116
                           "meters": None,
5117
                           "offline_meters": None,
5118
                           "virtual_meters": None,
5119
                           "shopfloors": None,
5120
                           "combined_equipments": None,
5121
                           "equipments": None,
5122
                           "points": None,
5123
                           "sensors": None,
5124
                           "tenants": None,
5125
                           "stores": None,
5126
                           "working_calendars": None
5127
                           }
5128
5129
            # query associated commands
5130
            query = (" SELECT c.id, c.name "
5131
                     " FROM tbl_spaces s, tbl_spaces_commands sc, tbl_commands c "
5132
                     " WHERE sc.space_id = s.id AND c.id = sc.command_id AND s.id = %s "
5133
                     " ORDER BY c.id ")
5134
            cursor.execute(query, (id_,))
5135
            rows = cursor.fetchall()
5136
5137
            command_list = list()
5138
            if rows is not None and len(rows) > 0:
5139
                for row in rows:
5140
                    result = {"id": row[0], "name": row[1]}
5141
                    command_list.append(result)
5142
                meta_result['commands'] = command_list
5143
5144
            # query associated meters
5145
            query = (" SELECT m.id, m.name "
5146
                     " FROM tbl_spaces s, tbl_spaces_meters sm, tbl_meters m "
5147
                     " WHERE sm.space_id = s.id AND m.id = sm.meter_id AND s.id = %s "
5148
                     " ORDER BY m.id ")
5149
            cursor.execute(query, (id_,))
5150
            rows = cursor.fetchall()
5151
5152
            meter_list = list()
5153
            if rows is not None and len(rows) > 0:
5154
                for row in rows:
5155
                    result = {"id": row[0], "name": row[1]}
5156
                    meter_list.append(result)
5157
                meta_result['meters'] = meter_list
5158
5159
            # query associated offline meters
5160
            query = (" SELECT m.id, m.name "
5161
                     " FROM tbl_spaces s, tbl_spaces_offline_meters sm, tbl_offline_meters m "
5162
                     " WHERE sm.space_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
5163
                     " ORDER BY m.id ")
5164
            cursor.execute(query, (id_,))
5165
            rows = cursor.fetchall()
5166
5167
            offline_meter_list = list()
5168
            if rows is not None and len(rows) > 0:
5169
                for row in rows:
5170
                    result = {"id": row[0], "name": row[1]}
5171
                    offline_meter_list.append(result)
5172
                meta_result['offline_meters'] = offline_meter_list
5173
5174
            # query associated virtual meters
5175
            query = (" SELECT m.id, m.name "
5176
                     " FROM tbl_spaces s, tbl_spaces_virtual_meters sm, tbl_virtual_meters m "
5177
                     " WHERE sm.space_id = s.id AND m.id = sm.virtual_meter_id AND s.id = %s "
5178
                     " ORDER BY m.id ")
5179
            cursor.execute(query, (id_,))
5180
            rows = cursor.fetchall()
5181
5182
            virtual_meter_list = list()
5183
            if rows is not None and len(rows) > 0:
5184
                for row in rows:
5185
                    result = {"id": row[0], "name": row[1]}
5186
                    virtual_meter_list.append(result)
5187
                meta_result['virtual_meters'] = virtual_meter_list
5188
5189
            # query associated shopfloors
5190
            query = (" SELECT sf.id, sf.name "
5191
                     " FROM tbl_spaces sp, tbl_spaces_shopfloors ss, tbl_shopfloors sf "
5192
                     " WHERE ss.space_id = sp.id AND sf.id = ss.shopfloor_id AND sp.id = %s "
5193
                     " ORDER BY sf.id ")
5194
            cursor.execute(query, (id_,))
5195
            rows = cursor.fetchall()
5196
5197
            shopfloor_list = list()
5198
            if rows is not None and len(rows) > 0:
5199
                for row in rows:
5200
                    result = {"id": row[0], "name": row[1]}
5201
                    shopfloor_list.append(result)
5202
                meta_result['shopfloors'] = shopfloor_list
5203
5204
            # query associated combined equipments
5205
            query = (" SELECT e.id, e.name "
5206
                     " FROM tbl_spaces s, tbl_spaces_combined_equipments se, tbl_combined_equipments e "
5207
                     " WHERE se.space_id = s.id AND e.id = se.combined_equipment_id AND s.id = %s "
5208
                     " ORDER BY e.id ")
5209
            cursor.execute(query, (id_,))
5210
            rows = cursor.fetchall()
5211
5212
            combined_equipment_list = list()
5213
            if rows is not None and len(rows) > 0:
5214
                for row in rows:
5215
                    result = {"id": row[0], "name": row[1]}
5216
                    combined_equipment_list.append(result)
5217
                meta_result['combined_equipments'] = combined_equipment_list
5218
5219
            # query associated equipments
5220
            query = (" SELECT e.id, e.name "
5221
                     " FROM tbl_spaces s, tbl_spaces_equipments se, tbl_equipments e "
5222
                     " WHERE se.space_id = s.id AND e.id = se.equipment_id AND s.id = %s "
5223
                     " ORDER BY e.id ")
5224
            cursor.execute(query, (id_,))
5225
            rows = cursor.fetchall()
5226
5227
            equipment_list = list()
5228
            if rows is not None and len(rows) > 0:
5229
                for row in rows:
5230
                    result = {"id": row[0], "name": row[1]}
5231
                    equipment_list.append(result)
5232
                meta_result['equipments'] = equipment_list
5233
5234
            # query associated points
5235
            query = (" SELECT p.id, p.name "
5236
                     " FROM tbl_spaces s, tbl_spaces_points sp, tbl_points p "
5237
                     " WHERE sp.space_id = s.id AND p.id = sp.point_id AND s.id = %s "
5238
                     " ORDER BY p.id ")
5239
            cursor.execute(query, (id_,))
5240
            rows = cursor.fetchall()
5241
5242
            point_result = list()
5243
            if rows is not None and len(rows) > 0:
5244
                for row in rows:
5245
                    result = {"id": row[0], "name": row[1]}
5246
                    point_result.append(result)
5247
                meta_result['points'] = point_result
5248
5249
            # query associated sensors
5250
            query = (" SELECT se.id, se.name "
5251
                     " FROM tbl_spaces sp, tbl_spaces_sensors ss, tbl_sensors se "
5252
                     " WHERE ss.space_id = sp.id AND se.id = ss.sensor_id AND sp.id = %s "
5253
                     " ORDER BY se.id ")
5254
            cursor.execute(query, (id_,))
5255
            rows = cursor.fetchall()
5256
5257
            sensor_list = list()
5258
            if rows is not None and len(rows) > 0:
5259
                for row in rows:
5260
                    result = {"id": row[0], "name": row[1]}
5261
                    sensor_list.append(result)
5262
                meta_result['sensors'] = sensor_list
5263
5264
            # query associated tenants
5265
            query = (" SELECT t.id, t.name "
5266
                     " FROM tbl_spaces s, tbl_spaces_tenants st, tbl_tenants t "
5267
                     " WHERE st.space_id = s.id AND t.id = st.tenant_id AND s.id = %s "
5268
                     " ORDER BY t.id ")
5269
            cursor.execute(query, (id_,))
5270
            rows = cursor.fetchall()
5271
5272
            tenant_list = list()
5273
            if rows is not None and len(rows) > 0:
5274
                for row in rows:
5275
                    result = {"id": row[0], "name": row[1]}
5276
                    tenant_list.append(result)
5277
                meta_result['tenants'] = tenant_list
5278
5279
            # query associated stores
5280
            query = (" SELECT t.id, t.name "
5281
                     " FROM tbl_spaces s, tbl_spaces_stores st, tbl_stores t "
5282
                     " WHERE st.space_id = s.id AND t.id = st.store_id AND s.id = %s "
5283
                     " ORDER BY t.id ")
5284
            cursor.execute(query, (id_,))
5285
            rows = cursor.fetchall()
5286
5287
            store_list = list()
5288
            if rows is not None and len(rows) > 0:
5289
                for row in rows:
5290
                    result = {"id": row[0], "name": row[1]}
5291
                    store_list.append(result)
5292
                meta_result['stores'] = store_list
5293
5294
            # query associated working calendars
5295
            query = (" SELECT wc.id, wc.name "
5296
                     " FROM tbl_spaces s, tbl_spaces_working_calendars swc, tbl_working_calendars wc "
5297
                     " WHERE swc.space_id = s.id AND wc.id = swc.working_calendar_id AND s.id = %s "
5298
                     " ORDER BY wc.id ")
5299
            cursor.execute(query, (id_,))
5300
            rows = cursor.fetchall()
5301
5302
            working_calendar_list = list()
5303
            if rows is not None and len(rows) > 0:
5304
                for row in rows:
5305
                    result = {"id": row[0], "name": row[1]}
5306
                    working_calendar_list.append(result)
5307
                meta_result['working_calendars'] = working_calendar_list
5308
5309
            # generate name for new space
5310
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
5311
            if config.utc_offset[0] == '-':
5312
                timezone_offset = -timezone_offset
5313
            new_name = (str.strip(meta_result['name']) +
5314
                        (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
5315
5316
            # save new space to database
5317
            add_values = (" INSERT INTO tbl_spaces "
5318
                          "    (name, uuid, parent_space_id, area, timezone_id, is_input_counted, is_output_counted, "
5319
                          "     contact_id, cost_center_id, latitude, longitude, description) "
5320
                          " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
5321
            cursor.execute(add_values, (new_name,
5322
                                        str(uuid.uuid4()),
5323
                                        meta_result['parent_space_id'],
5324
                                        meta_result['area'],
5325
                                        meta_result['timezone_id'],
5326
                                        meta_result['is_input_counted'],
5327
                                        meta_result['is_output_counted'],
5328
                                        meta_result['contact_id'],
5329
                                        meta_result['cost_center_id'],
5330
                                        meta_result['latitude'],
5331
                                        meta_result['longitude'],
5332
                                        meta_result['description']))
5333
            new_id = cursor.lastrowid
5334
5335
            # associate commands with new space
5336
            if meta_result['commands'] is not None and len(meta_result['commands']) > 0:
5337
                for command in meta_result['commands']:
5338
                    cursor.execute(" SELECT name "
5339
                                   " FROM tbl_commands "
5340
                                   " WHERE id = %s ", (command['id'],))
5341
                    if cursor.fetchone() is None:
5342
                        cursor.close()
5343
                        cnx.close()
5344
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5345
                                               description='API.COMMAND_NOT_FOUND')
5346
5347
                    query = (" SELECT id "
5348
                             " FROM tbl_spaces_commands "
5349
                             " WHERE space_id = %s AND command_id = %s")
5350
                    cursor.execute(query, (new_id, command['id'],))
5351
                    if cursor.fetchone() is not None:
5352
                        cursor.close()
5353
                        cnx.close()
5354
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5355
                                               description='API.SPACE_COMMAND_RELATION_EXISTS')
5356
5357
                    add_row = (" INSERT INTO tbl_spaces_commands (space_id, command_id) "
5358
                               " VALUES (%s, %s) ")
5359
                    cursor.execute(add_row, (new_id, command['id'],))
5360
5361
            # associate meters with new space
5362
            if meta_result['meters'] is not None and len(meta_result['meters']) > 0:
5363
                for meter in meta_result['meters']:
5364
                    cursor.execute(" SELECT name "
5365
                                   " FROM tbl_meters "
5366
                                   " WHERE id = %s ", (meter['id'],))
5367
                    if cursor.fetchone() is None:
5368
                        cursor.close()
5369
                        cnx.close()
5370
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5371
                                               description='API.METER_NOT_FOUND')
5372
5373
                    query = (" SELECT id "
5374
                             " FROM tbl_spaces_meters "
5375
                             " WHERE space_id = %s AND meter_id = %s")
5376
                    cursor.execute(query, (new_id, meter['id'],))
5377
                    if cursor.fetchone() is not None:
5378
                        cursor.close()
5379
                        cnx.close()
5380
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5381
                                               description='API.SPACE_METER_RELATION_EXISTS')
5382
5383
                    add_row = (" INSERT INTO tbl_spaces_meters (space_id, meter_id) "
5384
                               " VALUES (%s, %s) ")
5385
                    cursor.execute(add_row, (new_id, meter['id'],))
5386
5387
            # associate offline meters with new space
5388
            if meta_result['offline_meters'] is not None and len(meta_result['offline_meters']) > 0:
5389
                for offline_meter in meta_result['offline_meters']:
5390
                    cursor.execute(" SELECT name "
5391
                                   " FROM tbl_offline_meters "
5392
                                   " WHERE id = %s ", (offline_meter['id'],))
5393
                    if cursor.fetchone() is None:
5394
                        cursor.close()
5395
                        cnx.close()
5396
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5397
                                               description='API.OFFLINE_METER_NOT_FOUND')
5398
5399
                    query = (" SELECT id "
5400
                             " FROM tbl_spaces_offline_meters "
5401
                             " WHERE space_id = %s AND offline_meter_id = %s")
5402
                    cursor.execute(query, (new_id, offline_meter['id'],))
5403
                    if cursor.fetchone() is not None:
5404
                        cursor.close()
5405
                        cnx.close()
5406
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5407
                                               description='API.SPACE_OFFLINE_METER_RELATION_EXISTS')
5408
5409
                    add_row = (" INSERT INTO tbl_spaces_offline_meters (space_id, offline_meter_id) "
5410
                               " VALUES (%s, %s) ")
5411
                    cursor.execute(add_row, (new_id, offline_meter['id'],))
5412
5413
            # associate virtual meters with new space
5414
            if meta_result['virtual_meters'] is not None and len(meta_result['virtual_meters']) > 0:
5415
                for virtual_meter in meta_result['virtual_meters']:
5416
                    cursor.execute(" SELECT name "
5417
                                   " FROM tbl_virtual_meters "
5418
                                   " WHERE id = %s ", (virtual_meter['id'],))
5419
                    if cursor.fetchone() is None:
5420
                        cursor.close()
5421
                        cnx.close()
5422
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5423
                                               description='API.VIRTUAL_METER_NOT_FOUND')
5424
5425
                    query = (" SELECT id "
5426
                             " FROM tbl_spaces_virtual_meters "
5427
                             " WHERE space_id = %s AND virtual_meter_id = %s")
5428
                    cursor.execute(query, (new_id, virtual_meter['id'],))
5429
                    if cursor.fetchone() is not None:
5430
                        cursor.close()
5431
                        cnx.close()
5432
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5433
                                               description='API.SPACE_VIRTUAL_METER_RELATION_EXISTS')
5434
5435
                    add_row = (" INSERT INTO tbl_spaces_virtual_meters (space_id, virtual_meter_id) "
5436
                               " VALUES (%s, %s) ")
5437
                    cursor.execute(add_row, (new_id, virtual_meter['id'],))
5438
5439
            # associate shopfloors with new space
5440
            if meta_result['shopfloors'] is not None and len(meta_result['shopfloors']) > 0:
5441
                for shopfloor in meta_result['shopfloors']:
5442
                    cursor.execute(" SELECT name "
5443
                                   " FROM tbl_shopfloors "
5444
                                   " WHERE id = %s ", (shopfloor['id'],))
5445
                    if cursor.fetchone() is None:
5446
                        cursor.close()
5447
                        cnx.close()
5448
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5449
                                               description='API.SHOPFLOOR_NOT_FOUND')
5450
5451
                    query = (" SELECT id "
5452
                             " FROM tbl_spaces_shopfloors "
5453
                             " WHERE space_id = %s AND shopfloor_id = %s")
5454
                    cursor.execute(query, (new_id, shopfloor['id'],))
5455
                    if cursor.fetchone() is not None:
5456
                        cursor.close()
5457
                        cnx.close()
5458
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5459
                                               description='API.SPACE_SHOPFLOOR_RELATION_EXISTS')
5460
5461
                    add_row = (" INSERT INTO tbl_spaces_shopfloors (space_id, shopfloor_id) "
5462
                               " VALUES (%s, %s) ")
5463
                    cursor.execute(add_row, (new_id, shopfloor['id'],))
5464
5465
            # associate combined equipments with new space
5466
            if meta_result['combined_equipments'] is not None and len(meta_result['combined_equipments']) > 0:
5467
                for combined_equipment in meta_result['combined_equipments']:
5468
                    cursor.execute(" SELECT name "
5469
                                   " FROM tbl_combined_equipments "
5470
                                   " WHERE id = %s ", (combined_equipment['id'],))
5471
                    if cursor.fetchone() is None:
5472
                        cursor.close()
5473
                        cnx.close()
5474
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5475
                                               description='API.COMBINED_EQUIPMENT_NOT_FOUND')
5476
5477
                    query = (" SELECT id "
5478
                             " FROM tbl_spaces_combined_equipments "
5479
                             " WHERE space_id = %s AND combined_equipment_id = %s")
5480
                    cursor.execute(query, (new_id, combined_equipment['id'],))
5481
                    if cursor.fetchone() is not None:
5482
                        cursor.close()
5483
                        cnx.close()
5484
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5485
                                               description='API.SPACE_COMBINED_EQUIPMENT_RELATION_EXISTS')
5486
5487
                    add_row = (" INSERT INTO tbl_spaces_combined_equipments (space_id, combined_equipment_id) "
5488
                               " VALUES (%s, %s) ")
5489
                    cursor.execute(add_row, (new_id, combined_equipment['id'],))
5490
5491
            # associate equipments with new space
5492
            if meta_result['equipments'] is not None and len(meta_result['equipments']) > 0:
5493
                for equipment in meta_result['equipments']:
5494
                    cursor.execute(" SELECT name "
5495
                                   " FROM tbl_equipments "
5496
                                   " WHERE id = %s ", (equipment['id'],))
5497
                    if cursor.fetchone() is None:
5498
                        cursor.close()
5499
                        cnx.close()
5500
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5501
                                               description='API.EQUIPMENT_NOT_FOUND')
5502
5503
                    query = (" SELECT id "
5504
                             " FROM tbl_spaces_equipments "
5505
                             " WHERE space_id = %s AND equipment_id = %s")
5506
                    cursor.execute(query, (new_id, equipment['id'],))
5507
                    if cursor.fetchone() is not None:
5508
                        cursor.close()
5509
                        cnx.close()
5510
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5511
                                               description='API.SPACE_EQUIPMENT_RELATION_EXISTS')
5512
5513
                    add_row = (" INSERT INTO tbl_spaces_equipments (space_id, equipment_id) "
5514
                               " VALUES (%s, %s) ")
5515
                    cursor.execute(add_row, (new_id, equipment['id'],))
5516
5517
            # associate points with new space
5518
            if meta_result['points'] is not None and len(meta_result['points']) > 0:
5519
                for point in meta_result['points']:
5520
                    cursor.execute(" SELECT name "
5521
                                   " FROM tbl_points "
5522
                                   " WHERE id = %s ", (point['id'],))
5523
                    if cursor.fetchone() is None:
5524
                        cursor.close()
5525
                        cnx.close()
5526
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5527
                                               description='API.POINT_NOT_FOUND')
5528
5529
                    query = (" SELECT id "
5530
                             " FROM tbl_spaces_points "
5531
                             " WHERE space_id = %s AND point_id = %s")
5532
                    cursor.execute(query, (new_id, point['id'],))
5533
                    if cursor.fetchone() is not None:
5534
                        cursor.close()
5535
                        cnx.close()
5536
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5537
                                               description='API.SPACE_POINT_RELATION_EXISTS')
5538
5539
                    add_row = (" INSERT INTO tbl_spaces_points (space_id, point_id) "
5540
                               " VALUES (%s, %s) ")
5541
                    cursor.execute(add_row, (new_id, point['id'],))
5542
5543
            # associate sensors with new space
5544
            if meta_result['sensors'] is not None and len(meta_result['sensors']) > 0:
5545
                for sensor in meta_result['sensors']:
5546
                    cursor.execute(" SELECT name "
5547
                                   " FROM tbl_sensors "
5548
                                   " WHERE id = %s ", (sensor['id'],))
5549
                    if cursor.fetchone() is None:
5550
                        cursor.close()
5551
                        cnx.close()
5552
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5553
                                               description='API.SENSOR_NOT_FOUND')
5554
5555
                    query = (" SELECT id "
5556
                             " FROM tbl_spaces_sensors "
5557
                             " WHERE space_id = %s AND sensor_id = %s")
5558
                    cursor.execute(query, (new_id, sensor['id'],))
5559
                    if cursor.fetchone() is not None:
5560
                        cursor.close()
5561
                        cnx.close()
5562
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5563
                                               description='API.SPACE_SENSOR_RELATION_EXISTS')
5564
5565
                    add_row = (" INSERT INTO tbl_spaces_sensors (space_id, sensor_id) "
5566
                               " VALUES (%s, %s) ")
5567
                    cursor.execute(add_row, (new_id, sensor['id'],))
5568
5569
            # associate tenants with new space
5570
            if meta_result['tenants'] is not None and len(meta_result['tenants']) > 0:
5571
                for tenant in meta_result['tenants']:
5572
                    cursor.execute(" SELECT name "
5573
                                   " FROM tbl_tenants "
5574
                                   " WHERE id = %s ", (tenant['id'],))
5575
                    if cursor.fetchone() is None:
5576
                        cursor.close()
5577
                        cnx.close()
5578
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5579
                                               description='API.TENANT_NOT_FOUND')
5580
5581
                    query = (" SELECT id "
5582
                             " FROM tbl_spaces_tenants "
5583
                             " WHERE space_id = %s AND tenant_id = %s")
5584
                    cursor.execute(query, (new_id, tenant['id'],))
5585
                    if cursor.fetchone() is not None:
5586
                        cursor.close()
5587
                        cnx.close()
5588
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5589
                                               description='API.SPACE_TENANT_RELATION_EXISTS')
5590
5591
                    add_row = (" INSERT INTO tbl_spaces_tenants (space_id, tenant_id) "
5592
                               " VALUES (%s, %s) ")
5593
                    cursor.execute(add_row, (new_id, tenant['id'],))
5594
5595
            # associate stores with new space
5596
            if meta_result['stores'] is not None and len(meta_result['stores']) > 0:
5597
                for store in meta_result['stores']:
5598
                    cursor.execute(" SELECT name "
5599
                                   " FROM tbl_stores "
5600
                                   " WHERE id = %s ", (store['id'],))
5601
                    if cursor.fetchone() is None:
5602
                        cursor.close()
5603
                        cnx.close()
5604
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5605
                                               description='API.STORE_NOT_FOUND')
5606
5607
                    query = (" SELECT id "
5608
                             " FROM tbl_spaces_stores "
5609
                             " WHERE space_id = %s AND store_id = %s")
5610
                    cursor.execute(query, (new_id, store['id'],))
5611
                    if cursor.fetchone() is not None:
5612
                        cursor.close()
5613
                        cnx.close()
5614
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5615
                                               description='API.SPACE_STORE_RELATION_EXISTS')
5616
5617
                    add_row = (" INSERT INTO tbl_spaces_stores (space_id, store_id) "
5618
                               " VALUES (%s, %s) ")
5619
                    cursor.execute(add_row, (new_id, store['id'],))
5620
5621
            # associate working calendars with new space
5622
            if meta_result['working_calendars'] is not None and len(meta_result['working_calendars']) > 0:
5623
                for working_calendar in meta_result['working_calendars']:
5624
                    cursor.execute(" SELECT name "
5625
                                   " FROM tbl_working_calendars "
5626
                                   " WHERE id = %s ", (working_calendar['id'],))
5627
                    if cursor.fetchone() is None:
5628
                        cursor.close()
5629
                        cnx.close()
5630
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5631
                                               description='API.WORKING_CALENDAR_NOT_FOUND')
5632
5633
                    query = (" SELECT id "
5634
                             " FROM tbl_spaces_working_calendars "
5635
                             " WHERE space_id = %s AND working_calendar_id = %s")
5636
                    cursor.execute(query, (new_id, working_calendar['id'],))
5637
                    if cursor.fetchone() is not None:
5638
                        cursor.close()
5639
                        cnx.close()
5640
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5641
                                               description='API.SPACE_WORKING_CALENDAR_RELATION_EXISTS')
5642
5643
                    add_row = (" INSERT INTO tbl_spaces_working_calendars (space_id, working_calendar_id) "
5644
                               " VALUES (%s, %s) ")
5645
                    cursor.execute(add_row, (new_id, working_calendar['id'],))
5646
5647
            # todo: associate more objects with new space
5648
5649
            cnx.commit()
5650
            cursor.close()
5651
            cnx.close()
5652
5653
            # Clear cache after clone
5654
            clear_space_cache(space_id=new_id, parent_space_id=meta_result['parent_space_id'])
5655
5656
            resp.status = falcon.HTTP_201
5657
            resp.location = '/spaces/' + str(new_id)
5658
5659
5660 View Code Duplication
class SpaceEnergyFlowDiagramCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
5661
    def __init__(self):
5662
        pass
5663
5664
    @staticmethod
5665
    def on_options(req, resp, id_):
5666
        _ = req
5667
        resp.status = falcon.HTTP_200
5668
        _ = id_
5669
5670
    @staticmethod
5671
    def on_get(req, resp, id_):
5672
        if 'API-KEY' not in req.headers or \
5673
                not isinstance(req.headers['API-KEY'], str) or \
5674
                len(str.strip(req.headers['API-KEY'])) == 0:
5675
            access_control(req)
5676
        else:
5677
            api_key_control(req)
5678
        if not id_.isdigit() or int(id_) <= 0:
5679
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5680
                                   description='API.INVALID_SPACE_ID')
5681
5682
        cnx = mysql.connector.connect(**config.myems_system_db)
5683
        cursor = cnx.cursor()
5684
5685
        cursor.execute(" SELECT name "
5686
                       " FROM tbl_spaces "
5687
                       " WHERE id = %s ", (id_,))
5688
        if cursor.fetchone() is None:
5689
            cursor.close()
5690
            cnx.close()
5691
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5692
                                   description='API.SPACE_NOT_FOUND')
5693
5694
        query = (" SELECT e.id, e.name, e.uuid "
5695
                 " FROM tbl_spaces s, tbl_spaces_energy_flow_diagrams se, tbl_energy_flow_diagrams e "
5696
                 " WHERE se.space_id = s.id AND e.id = se.energy_flow_diagram_id AND s.id = %s "
5697
                 " ORDER BY e.id ")
5698
        cursor.execute(query, (id_,))
5699
        rows = cursor.fetchall()
5700
5701
        result = list()
5702
        if rows is not None and len(rows) > 0:
5703
            for row in rows:
5704
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
5705
                result.append(meta_result)
5706
5707
        resp.text = json.dumps(result)
5708
5709
    @staticmethod
5710
    @user_logger
5711
    def on_post(req, resp, id_):
5712
        """Handles POST requests"""
5713
        admin_control(req)
5714
        try:
5715
            raw_json = req.stream.read().decode('utf-8')
5716
        except UnicodeDecodeError as ex:
5717
            print("Failed to decode request")
5718
            raise falcon.HTTPError(status=falcon.HTTP_400,
5719
                                   title='API.BAD_REQUEST',
5720
                                   description='API.INVALID_ENCODING')
5721
        except Exception as ex:
5722
            print("Unexpected error reading request stream")
5723
            raise falcon.HTTPError(status=falcon.HTTP_400,
5724
                                   title='API.BAD_REQUEST',
5725
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
5726
5727
        if not id_.isdigit() or int(id_) <= 0:
5728
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5729
                                   description='API.INVALID_SPACE_ID')
5730
5731
        new_values = json.loads(raw_json)
5732
5733
        if 'energy_flow_diagram_id' not in new_values['data'].keys() or \
5734
                not isinstance(new_values['data']['energy_flow_diagram_id'], int) or \
5735
                new_values['data']['energy_flow_diagram_id'] <= 0:
5736
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5737
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
5738
        energy_flow_diagram_id = new_values['data']['energy_flow_diagram_id']
5739
5740
        cnx = mysql.connector.connect(**config.myems_system_db)
5741
        cursor = cnx.cursor()
5742
5743
        cursor.execute(" SELECT name "
5744
                       " from tbl_spaces "
5745
                       " WHERE id = %s ", (id_,))
5746
        if cursor.fetchone() is None:
5747
            cursor.close()
5748
            cnx.close()
5749
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5750
                                   description='API.SPACE_NOT_FOUND')
5751
5752
        cursor.execute(" SELECT name "
5753
                       " FROM tbl_energy_flow_diagrams "
5754
                       " WHERE id = %s ", (energy_flow_diagram_id,))
5755
        if cursor.fetchone() is None:
5756
            cursor.close()
5757
            cnx.close()
5758
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5759
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
5760
5761
        query = (" SELECT id "
5762
                 " FROM tbl_spaces_energy_flow_diagrams "
5763
                 " WHERE space_id = %s AND energy_flow_diagram_id = %s")
5764
        cursor.execute(query, (id_, energy_flow_diagram_id,))
5765
        if cursor.fetchone() is not None:
5766
            cursor.close()
5767
            cnx.close()
5768
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5769
                                   description='API.SPACE_ENERGY_FLOW_DIAGRAM_RELATION_EXISTS')
5770
5771
        add_row = (" INSERT INTO tbl_spaces_energy_flow_diagrams (space_id, energy_flow_diagram_id) "
5772
                   " VALUES (%s, %s) ")
5773
        cursor.execute(add_row, (id_, energy_flow_diagram_id,))
5774
        cnx.commit()
5775
        cursor.close()
5776
        cnx.close()
5777
5778
        resp.status = falcon.HTTP_201
5779
        resp.location = '/spaces/' + str(id_) + '/energyflowdiagrams/' + str(energy_flow_diagram_id)
5780
5781
5782
class SpaceEnergyFlowDiagramItem:
5783
    def __init__(self):
5784
        pass
5785
5786
    @staticmethod
5787
    def on_options(req, resp, id_, eid):
5788
        _ = req
5789
        resp.status = falcon.HTTP_200
5790
        _ = id_
5791
5792
    @staticmethod
5793
    @user_logger
5794
    def on_delete(req, resp, id_, eid):
5795
        admin_control(req)
5796
        if not id_.isdigit() or int(id_) <= 0:
5797
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5798
                                   description='API.INVALID_SPACE_ID')
5799
5800
        if not eid.isdigit() or int(eid) <= 0:
5801
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5802
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
5803
5804
        cnx = mysql.connector.connect(**config.myems_system_db)
5805
        cursor = cnx.cursor()
5806
5807
        cursor.execute(" SELECT name "
5808
                       " FROM tbl_spaces "
5809
                       " WHERE id = %s ", (id_,))
5810
        if cursor.fetchone() is None:
5811
            cursor.close()
5812
            cnx.close()
5813
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5814
                                   description='API.SPACE_NOT_FOUND')
5815
5816
        cursor.execute(" SELECT name "
5817
                       " FROM tbl_energy_flow_diagrams "
5818
                       " WHERE id = %s ", (eid,))
5819
        if cursor.fetchone() is None:
5820
            cursor.close()
5821
            cnx.close()
5822
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5823
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
5824
5825
        cursor.execute(" SELECT id "
5826
                       " FROM tbl_spaces_energy_flow_diagrams "
5827
                       " WHERE space_id = %s AND energy_flow_diagram_id = %s ", (id_, eid))
5828
        if cursor.fetchone() is None:
5829
            cursor.close()
5830
            cnx.close()
5831
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5832
                                   description='API.SPACE_ENERGY_FLOW_DIAGRAM_RELATION_NOT_FOUND')
5833
5834
        cursor.execute(" DELETE FROM tbl_spaces_energy_flow_diagrams "
5835
                       " WHERE space_id = %s AND energy_flow_diagram_id = %s ", (id_, eid))
5836
        cnx.commit()
5837
5838
        cursor.close()
5839
        cnx.close()
5840
5841
        resp.status = falcon.HTTP_204
5842
5843
5844
class DistributionSystemCollection:
5845
    def __init__(self):
5846
        pass
5847
5848
    @staticmethod
5849
    def on_options(req, resp, id_):
5850
        _ = req
5851
        resp.status = falcon.HTTP_200
5852
        _ = id_
5853
5854
    @staticmethod
5855
    def on_get(req, resp, id_):
5856
        if 'API-KEY' not in req.headers or \
5857
                not isinstance(req.headers['API-KEY'], str) or \
5858
                len(str.strip(req.headers['API-KEY'])) == 0:
5859
            access_control(req)
5860
        else:
5861
            api_key_control(req)
5862
        if not id_.isdigit() or int(id_) <= 0:
5863
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5864
                                   description='API.INVALID_SPACE_ID')
5865
5866
        cnx = mysql.connector.connect(**config.myems_system_db)
5867
        cursor = cnx.cursor()
5868
5869
        cursor.execute(" SELECT name "
5870
                       " FROM tbl_spaces "
5871
                       " WHERE id = %s ", (id_,))
5872
        if cursor.fetchone() is None:
5873
            cursor.close()
5874
            cnx.close()
5875
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5876
                                   description='API.SPACE_NOT_FOUND')
5877
5878
        svg_dict = dict()
5879
        cursor.execute(" SELECT id, name, uuid, source_code "
5880
                       " FROM tbl_svgs ")
5881
        rows_svgs = cursor.fetchall()
5882
        if rows_svgs is not None and len(rows_svgs) > 0:
5883
            for row in rows_svgs:
5884
                svg_dict[row[0]] = {
5885
                    "id": row[0],
5886
                    "name": row[1],
5887
                    "uuid": row[2],
5888
                    "source_code": row[3]
5889
                }
5890
5891
        query = (" SELECT d.id, d.name, d.uuid, d.svg_id, d.description "
5892
                 " FROM tbl_spaces s, tbl_spaces_distribution_systems sd, tbl_distribution_systems d "
5893
                 " WHERE sd.space_id = s.id AND d.id = sd.distribution_system_id AND s.id = %s "
5894
                 " ORDER BY d.id ")
5895
        cursor.execute(query, (id_,))
5896
        rows = cursor.fetchall()
5897
5898
        result = list()
5899
        if rows is not None and len(rows) > 0:
5900
            for row in rows:
5901
                svg_info = svg_dict.get(row[3], None)
5902
                meta_result = {
5903
                    "id": row[0],
5904
                    "name": row[1],
5905
                    "uuid": row[2],
5906
                    "svg": svg_info,
5907
                    "description": row[4]
5908
                }
5909
                result.append(meta_result)
5910
5911
        cursor.close()
5912
        cnx.close()
5913
        resp.text = json.dumps(result)
5914
5915
    @staticmethod
5916
    @user_logger
5917
    def on_post(req, resp, id_):
5918
        """Handles POST requests"""
5919
        admin_control(req)
5920
        try:
5921
            raw_json = req.stream.read().decode('utf-8')
5922
        except UnicodeDecodeError as ex:
5923
            print("Failed to decode request")
5924
            raise falcon.HTTPError(status=falcon.HTTP_400,
5925
                                   title='API.BAD_REQUEST',
5926
                                   description='API.INVALID_ENCODING')
5927
        except Exception as ex:
5928
            print("Unexpected error reading request stream")
5929
            raise falcon.HTTPError(status=falcon.HTTP_400,
5930
                                   title='API.BAD_REQUEST',
5931
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
5932
5933
        if not id_.isdigit() or int(id_) <= 0:
5934
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5935
                                   description='API.INVALID_SPACE_ID')
5936
5937
        new_values = json.loads(raw_json)
5938
5939
        if 'distribution_system_id' not in new_values['data'].keys() or \
5940
                not isinstance(new_values['data']['distribution_system_id'], int) or \
5941
                new_values['data']['distribution_system_id'] <= 0:
5942
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
5943
                                   description='API.INVALID_DISTRIBUTION_SYSTEM_ID')
5944
        distribution_system_id = new_values['data']['distribution_system_id']
5945
5946
        cnx = mysql.connector.connect(**config.myems_system_db)
5947
        cursor = cnx.cursor()
5948
5949
        cursor.execute(" SELECT name "
5950
                       " from tbl_spaces "
5951
                       " WHERE id = %s ", (id_,))
5952
        if cursor.fetchone() is None:
5953
            cursor.close()
5954
            cnx.close()
5955
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5956
                                   description='API.SPACE_NOT_FOUND')
5957
5958
        cursor.execute(" SELECT name "
5959
                       " FROM tbl_distribution_systems "
5960
                       " WHERE id = %s ", (distribution_system_id,))
5961
        if cursor.fetchone() is None:
5962
            cursor.close()
5963
            cnx.close()
5964
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
5965
                                   description='API.DISTRIBUTION_SYSTEM_NOT_FOUND')
5966
5967
        query = (" SELECT id "
5968
                 " FROM tbl_spaces_distribution_systems "
5969
                 " WHERE space_id = %s AND distribution_system_id = %s")
5970
        cursor.execute(query, (id_, distribution_system_id,))
5971
        if cursor.fetchone() is not None:
5972
            cursor.close()
5973
            cnx.close()
5974
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
5975
                                   description='API.SPACE_DISTRIBUTION_SYSTEM_RELATION_EXISTS')
5976
5977
        add_row = (" INSERT INTO tbl_spaces_distribution_systems (space_id, distribution_system_id) "
5978
                   " VALUES (%s, %s) ")
5979
        cursor.execute(add_row, (id_, distribution_system_id,))
5980
        cnx.commit()
5981
        cursor.close()
5982
        cnx.close()
5983
5984
        resp.status = falcon.HTTP_201
5985
        resp.location = '/spaces/' + str(id_) + '/distributionsystems/' + str(distribution_system_id)
5986
5987
5988
class DistributionSystemItem:
5989
    def __init__(self):
5990
        pass
5991
5992
    @staticmethod
5993
    def on_options(req, resp, id_, did):
5994
        _ = req
5995
        resp.status = falcon.HTTP_200
5996
        _ = id_
5997
5998
    @staticmethod
5999
    @user_logger
6000
    def on_delete(req, resp, id_, did):
6001
        admin_control(req)
6002
        if not id_.isdigit() or int(id_) <= 0:
6003
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
6004
                                   description='API.INVALID_SPACE_ID')
6005
6006
        if not did.isdigit() or int(did) <= 0:
6007
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
6008
                                   description='API.INVALID_DISTRIBUTION_SYSTEM_ID')
6009
6010
        cnx = mysql.connector.connect(**config.myems_system_db)
6011
        cursor = cnx.cursor()
6012
6013
        cursor.execute(" SELECT name "
6014
                       " FROM tbl_spaces "
6015
                       " WHERE id = %s ", (id_,))
6016
        if cursor.fetchone() is None:
6017
            cursor.close()
6018
            cnx.close()
6019
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
6020
                                   description='API.SPACE_NOT_FOUND')
6021
6022
        cursor.execute(" SELECT name "
6023
                       " FROM tbl_distribution_systems "
6024
                       " WHERE id = %s ", (did,))
6025
        if cursor.fetchone() is None:
6026
            cursor.close()
6027
            cnx.close()
6028
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
6029
                                   description='API.DISTRIBUTION_SYSTEM_NOT_FOUND')
6030
6031
        cursor.execute(" SELECT id "
6032
                       " FROM tbl_spaces_distribution_systems "
6033
                       " WHERE space_id = %s AND distribution_system_id = %s ", (id_, did))
6034
        if cursor.fetchone() is None:
6035
            cursor.close()
6036
            cnx.close()
6037
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
6038
                                   description='API.SPACE_DISTRIBUTION_SYSTEM_RELATION_NOT_FOUND')
6039
6040
        cursor.execute(" DELETE FROM tbl_spaces_distribution_systems "
6041
                       " WHERE space_id = %s AND distribution_system_id = %s ", (id_, did))
6042
        cnx.commit()
6043
6044
        cursor.close()
6045
        cnx.close()
6046
6047
        resp.status = falcon.HTTP_204
6048