core.tenant.TenantMeterCollection.on_post()   C
last analyzed

Complexity

Conditions 10

Size

Total Lines 66
Code Lines 51

Duplication

Lines 66
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 51
dl 66
loc 66
rs 5.8036
c 0
b 0
f 0
cc 10
nop 3

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

Complexity

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

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

1
import uuid
2
from datetime import datetime, timedelta, timezone
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
from core.useractivity import user_logger, admin_control, access_control, api_key_control
7
import config
8
9
10
class TenantCollection:
11
    """
12
    Tenant Collection Resource
13
14
    This class handles CRUD operations for tenant collection.
15
    It provides endpoints for listing all tenants and creating new ones.
16
    Tenants represent organizations or entities that occupy spaces within
17
    facilities, with associated energy consumption patterns, billing,
18
    and management requirements.
19
    """
20
    def __init__(self):
21
        pass
22
23
    @staticmethod
24
    def on_options(req, resp):
25
        """
26
        Handle OPTIONS request for CORS preflight
27
28
        Args:
29
            req: Falcon request object
30
            resp: Falcon response object
31
        """
32
        _ = req
33
        resp.status = falcon.HTTP_200
34
35
    @staticmethod
36
    def on_get(req, resp):
37
        """
38
        Handle GET requests to retrieve all tenants
39
40
        Returns a list of all tenants with their complete information including:
41
        - Tenant ID, name, and UUID
42
        - Associated tenant type, contact, and cost center information
43
        - Tenant specifications and parameters
44
        - Related spaces and meter associations
45
        - Billing and contract information
46
47
        Args:
48
            req: Falcon request object
49
            resp: Falcon response object
50
        """
51
        # Check authentication method (API key or session)
52
        if 'API-KEY' not in req.headers or \
53
                not isinstance(req.headers['API-KEY'], str) or \
54
                len(str.strip(req.headers['API-KEY'])) == 0:
55
            access_control(req)
56
        else:
57
            api_key_control(req)
58
        search_query = req.get_param('q', default=None)
59
        if search_query is not None:
60
            search_query = search_query.strip()
61
        else:
62
            search_query = ''
63
        cnx = mysql.connector.connect(**config.myems_system_db)
64
        cursor = cnx.cursor()
65
66
        query = (" SELECT id, name, uuid "
67
                 " FROM tbl_tenant_types ")
68
        cursor.execute(query)
69
        rows_tenant_types = cursor.fetchall()
70
71
        tenant_type_dict = dict()
72
        if rows_tenant_types is not None and len(rows_tenant_types) > 0:
73
            for row in rows_tenant_types:
74
                tenant_type_dict[row[0]] = {"id": row[0],
75
                                            "name": row[1],
76
                                            "uuid": row[2]}
77
78
        query = (" SELECT id, name, uuid "
79
                 " FROM tbl_contacts ")
80
        cursor.execute(query)
81
        rows_contacts = cursor.fetchall()
82
83
        contact_dict = dict()
84
        if rows_contacts is not None and len(rows_contacts) > 0:
85
            for row in rows_contacts:
86
                contact_dict[row[0]] = {"id": row[0],
87
                                        "name": row[1],
88
                                        "uuid": row[2]}
89
90
        query = (" SELECT id, name, uuid "
91
                 " FROM tbl_cost_centers ")
92
        cursor.execute(query)
93
        rows_cost_centers = cursor.fetchall()
94
95
        cost_center_dict = dict()
96
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
97
            for row in rows_cost_centers:
98
                cost_center_dict[row[0]] = {"id": row[0],
99
                                            "name": row[1],
100
                                            "uuid": row[2]}
101
102
        query = (" SELECT id, name, uuid, "
103
                 "        buildings, floors, rooms, area, tenant_type_id, "
104
                 "        is_input_counted, is_key_tenant, "
105
                 "        lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
106
                 "        contact_id, cost_center_id, description "
107
                 " FROM tbl_tenants ")
108
        params = []
109
110
        if search_query:
111
            query += " WHERE name LIKE %s OR description LIKE %s OR buildings LIKE %s OR floors LIKE %s OR rooms LIKE %s OR lease_number LIKE %s "
112
            params = [f'%{search_query}%', f'%{search_query}%', f'%{search_query}%', f'%{search_query}%', f'%{search_query}%', f'%{search_query}%']
113
        query += " ORDER BY id "
114
115
        cursor.execute(query,params)
116
        rows_spaces = cursor.fetchall()
117
        cursor.close()
118
        cnx.close()
119
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
120
        if config.utc_offset[0] == '-':
121
            timezone_offset = -timezone_offset
122
123
        result = list()
124
        if rows_spaces is not None and len(rows_spaces) > 0:
125
            for row in rows_spaces:
126
127
                meta_result = {"id": row[0],
128
                               "name": row[1],
129
                               "uuid": row[2],
130
                               "buildings": row[3],
131
                               "floors": row[4],
132
                               "rooms": row[5],
133
                               "area": row[6],
134
                               "tenant_type": tenant_type_dict.get(row[7], None),
135
                               "is_input_counted": bool(row[8]),
136
                               "is_key_tenant": bool(row[9]),
137
                               "lease_number": row[10],
138
                               "lease_start_datetime":
139
                                   (row[11].replace(tzinfo=timezone.utc) +
140
                                    timedelta(minutes=timezone_offset)).isoformat()[0:19],
141
                               "lease_end_datetime": (row[12].replace(tzinfo=timezone.utc) +
142
                                                      timedelta(minutes=timezone_offset)).isoformat()[0:19],
143
                               "is_in_lease": bool(row[13]),
144
                               "contact": contact_dict.get(row[14], None),
145
                               "cost_center": cost_center_dict.get(row[15], None),
146
                               "description": row[16],
147
                               "qrcode": 'tenant:' + row[2]}
148
                result.append(meta_result)
149
150
        resp.text = json.dumps(result)
151
152
    @staticmethod
153
    @user_logger
154
    def on_post(req, resp):
155
        """Handles POST requests"""
156
        admin_control(req)
157
        try:
158
            raw_json = req.stream.read().decode('utf-8')
159
        except Exception as ex:
160
            print(str(ex))
161
            raise falcon.HTTPError(status=falcon.HTTP_400,
162
                                   title='API.BAD_REQUEST',
163
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
164
165
        new_values = json.loads(raw_json)
166
167
        if 'name' not in new_values['data'].keys() or \
168
                not isinstance(new_values['data']['name'], str) or \
169
                len(str.strip(new_values['data']['name'])) == 0:
170
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
171
                                   description='API.INVALID_TENANT_NAME')
172
        name = str.strip(new_values['data']['name'])
173
174
        if 'buildings' not in new_values['data'].keys() or \
175
                not isinstance(new_values['data']['buildings'], str) or \
176
                len(str.strip(new_values['data']['buildings'])) == 0:
177
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
178
                                   description='API.INVALID_BUILDINGS_VALUE')
179
        buildings = str.strip(new_values['data']['buildings'])
180
181
        if 'floors' not in new_values['data'].keys() or \
182
                not isinstance(new_values['data']['floors'], str) or \
183
                len(str.strip(new_values['data']['floors'])) == 0:
184
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
185
                                   description='API.INVALID_FLOORS_VALUE')
186
        floors = str.strip(new_values['data']['floors'])
187
188
        if 'rooms' not in new_values['data'].keys() or \
189
                not isinstance(new_values['data']['rooms'], str) or \
190
                len(str.strip(new_values['data']['rooms'])) == 0:
191
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
192
                                   description='API.INVALID_ROOMS_VALUE')
193
        rooms = str.strip(new_values['data']['rooms'])
194
195
        if 'area' not in new_values['data'].keys() or \
196
                not (isinstance(new_values['data']['area'], float) or
197
                     isinstance(new_values['data']['area'], int)) or \
198
                new_values['data']['area'] <= 0.0:
199
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
200
                                   description='API.INVALID_AREA_VALUE')
201
        area = new_values['data']['area']
202
203
        if 'tenant_type_id' not in new_values['data'].keys() or \
204
                not isinstance(new_values['data']['tenant_type_id'], int) or \
205
                new_values['data']['tenant_type_id'] <= 0:
206
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
207
                                   description='API.INVALID_TENANT_TYPE_ID')
208
        tenant_type_id = new_values['data']['tenant_type_id']
209
210
        if 'is_input_counted' not in new_values['data'].keys() or \
211
                not isinstance(new_values['data']['is_input_counted'], bool):
212
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
213
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
214
        is_input_counted = new_values['data']['is_input_counted']
215
216
        if 'is_key_tenant' not in new_values['data'].keys() or \
217
                not isinstance(new_values['data']['is_key_tenant'], bool):
218
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
219
                                   description='API.INVALID_IS_KEY_TENANT_VALUE')
220
        is_key_tenant = new_values['data']['is_key_tenant']
221
222
        if 'lease_number' not in new_values['data'].keys() or \
223
                not isinstance(new_values['data']['lease_number'], str) or \
224
                len(str.strip(new_values['data']['lease_number'])) == 0:
225
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
226
                                   description='API.INVALID_LEASE_NUMBER_VALUE')
227
        lease_number = str.strip(new_values['data']['lease_number'])
228
229
        if 'is_in_lease' not in new_values['data'].keys() or \
230
                not isinstance(new_values['data']['is_in_lease'], bool):
231
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
232
                                   description='API.INVALID_IS_IN_LEASE_VALUE')
233
        is_in_lease = new_values['data']['is_in_lease']
234
235
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
236
        if config.utc_offset[0] == '-':
237
            timezone_offset = -timezone_offset
238
239
        # todo: validate datetime values
240
        lease_start_datetime_utc = datetime.strptime(new_values['data']['lease_start_datetime'],
241
                                                     '%Y-%m-%dT%H:%M:%S')
242
        lease_start_datetime_utc = lease_start_datetime_utc.replace(tzinfo=timezone.utc)
243
        lease_start_datetime_utc -= timedelta(minutes=timezone_offset)
244
245
        lease_end_datetime_utc = datetime.strptime(new_values['data']['lease_end_datetime'],
246
                                                   '%Y-%m-%dT%H:%M:%S')
247
        lease_end_datetime_utc = lease_end_datetime_utc.replace(tzinfo=timezone.utc)
248
        lease_end_datetime_utc -= timedelta(minutes=timezone_offset)
249
250
        if 'contact_id' not in new_values['data'].keys() or \
251
                not isinstance(new_values['data']['contact_id'], int) or \
252
                new_values['data']['contact_id'] <= 0:
253
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
254
                                   description='API.INVALID_CONTACT_ID')
255
        contact_id = new_values['data']['contact_id']
256
257
        if 'cost_center_id' not in new_values['data'].keys() or \
258
                not isinstance(new_values['data']['cost_center_id'], int) or \
259
                new_values['data']['cost_center_id'] <= 0:
260
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
261
                                   description='API.INVALID_COST_CENTER_ID')
262
        cost_center_id = new_values['data']['cost_center_id']
263
264
        if 'description' in new_values['data'].keys() and \
265
                new_values['data']['description'] is not None and \
266
                len(str(new_values['data']['description'])) > 0:
267
            description = str.strip(new_values['data']['description'])
268
        else:
269
            description = None
270
271
        cnx = mysql.connector.connect(**config.myems_system_db)
272
        cursor = cnx.cursor()
273
274
        cursor.execute(" SELECT name "
275
                       " FROM tbl_tenants "
276
                       " WHERE name = %s ", (name,))
277
        if cursor.fetchone() is not None:
278
            cursor.close()
279
            cnx.close()
280
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
281
                                   description='API.TENANT_NAME_IS_ALREADY_IN_USE')
282
283
        cursor.execute(" SELECT name "
284
                       " FROM tbl_tenant_types "
285
                       " WHERE id = %s ",
286
                       (tenant_type_id,))
287
        if cursor.fetchone() is None:
288
            cursor.close()
289
            cnx.close()
290
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
291
                                   description='API.TENANT_TYPE_NOT_FOUND')
292
293
        cursor.execute(" SELECT name "
294
                       " FROM tbl_contacts "
295
                       " WHERE id = %s ",
296
                       (new_values['data']['contact_id'],))
297
        row = cursor.fetchone()
298
        if row is None:
299
            cursor.close()
300
            cnx.close()
301
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
302
                                   description='API.CONTACT_NOT_FOUND')
303
304
        cursor.execute(" SELECT name "
305
                       " FROM tbl_cost_centers "
306
                       " WHERE id = %s ",
307
                       (new_values['data']['cost_center_id'],))
308
        row = cursor.fetchone()
309
        if row is None:
310
            cursor.close()
311
            cnx.close()
312
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
313
                                   description='API.COST_CENTER_NOT_FOUND')
314
315
        add_values = (" INSERT INTO tbl_tenants "
316
                      "    (name, uuid, buildings, floors, rooms, area, tenant_type_id, "
317
                      "     is_input_counted, is_key_tenant, "
318
                      "     lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
319
                      "     contact_id, cost_center_id, description) "
320
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
321
        cursor.execute(add_values, (name,
322
                                    str(uuid.uuid4()),
323
                                    buildings,
324
                                    floors,
325
                                    rooms,
326
                                    area,
327
                                    tenant_type_id,
328
                                    is_input_counted,
329
                                    is_key_tenant,
330
                                    lease_number,
331
                                    lease_start_datetime_utc,
332
                                    lease_end_datetime_utc,
333
                                    is_in_lease,
334
                                    contact_id,
335
                                    cost_center_id,
336
                                    description))
337
        new_id = cursor.lastrowid
338
        cnx.commit()
339
        cursor.close()
340
        cnx.close()
341
342
        resp.status = falcon.HTTP_201
343
        resp.location = '/tenants/' + str(new_id)
344
345
346
class TenantItem:
347
    def __init__(self):
348
        pass
349
350
    @staticmethod
351
    def on_options(req, resp, id_):
352
        _ = req
353
        resp.status = falcon.HTTP_200
354
        _ = id_
355
356
    @staticmethod
357
    def on_get(req, resp, id_):
358
        if 'API-KEY' not in req.headers or \
359
                not isinstance(req.headers['API-KEY'], str) or \
360
                len(str.strip(req.headers['API-KEY'])) == 0:
361
            access_control(req)
362
        else:
363
            api_key_control(req)
364
        if not id_.isdigit() or int(id_) <= 0:
365
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
366
                                   description='API.INVALID_TENANT_ID')
367
368
        cnx = mysql.connector.connect(**config.myems_system_db)
369
        cursor = cnx.cursor()
370
371
        query = (" SELECT id, name, uuid "
372
                 " FROM tbl_tenant_types ")
373
        cursor.execute(query)
374
        rows_tenant_types = cursor.fetchall()
375
376
        tenant_type_dict = dict()
377
        if rows_tenant_types is not None and len(rows_tenant_types) > 0:
378
            for row in rows_tenant_types:
379
                tenant_type_dict[row[0]] = {"id": row[0],
380
                                            "name": row[1],
381
                                            "uuid": row[2]}
382
383
        query = (" SELECT id, name, uuid "
384
                 " FROM tbl_contacts ")
385
        cursor.execute(query)
386
        rows_contacts = cursor.fetchall()
387
388
        contact_dict = dict()
389
        if rows_contacts is not None and len(rows_contacts) > 0:
390
            for row in rows_contacts:
391
                contact_dict[row[0]] = {"id": row[0],
392
                                        "name": row[1],
393
                                        "uuid": row[2]}
394
395
        query = (" SELECT id, name, uuid "
396
                 " FROM tbl_cost_centers ")
397
        cursor.execute(query)
398
        rows_cost_centers = cursor.fetchall()
399
400
        cost_center_dict = dict()
401
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
402
            for row in rows_cost_centers:
403
                cost_center_dict[row[0]] = {"id": row[0],
404
                                            "name": row[1],
405
                                            "uuid": row[2]}
406
407
        query = (" SELECT id, name, uuid, "
408
                 "        buildings, floors, rooms, area, tenant_type_id,"
409
                 "        is_key_tenant, is_input_counted, "
410
                 "        lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
411
                 "        contact_id, cost_center_id, description "
412
                 " FROM tbl_tenants "
413
                 " WHERE id = %s ")
414
        cursor.execute(query, (id_,))
415
        row = cursor.fetchone()
416
        cursor.close()
417
        cnx.close()
418
419
        if row is None:
420
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
421
                                   description='API.TENANT_NOT_FOUND')
422
        else:
423
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
424
            if config.utc_offset[0] == '-':
425
                timezone_offset = -timezone_offset
426
427
            meta_result = {"id": row[0],
428
                           "name": row[1],
429
                           "uuid": row[2],
430
                           "buildings": row[3],
431
                           "floors": row[4],
432
                           "rooms": row[5],
433
                           "area": row[6],
434
                           "tenant_type": tenant_type_dict.get(row[7], None),
435
                           "is_key_tenant": bool(row[8]),
436
                           "is_input_counted": bool(row[9]),
437
                           "lease_number": row[10],
438
                           "lease_start_datetime": (row[11].replace(tzinfo=timezone.utc) +
439
                                                    timedelta(minutes=timezone_offset)).isoformat()[0:19],
440
                           "lease_end_datetime": (row[12].replace(tzinfo=timezone.utc) +
441
                                                  timedelta(minutes=timezone_offset)).isoformat()[0:19],
442
                           "is_in_lease": bool(row[13]),
443
                           "contact": contact_dict.get(row[14], None),
444
                           "cost_center": cost_center_dict.get(row[15], None),
445
                           "description": row[16],
446
                           "qrcode": 'tenant:' + row[2]}
447
448
        resp.text = json.dumps(meta_result)
449
450 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
451
    @user_logger
452
    def on_delete(req, resp, id_):
453
        admin_control(req)
454
        if not id_.isdigit() or int(id_) <= 0:
455
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
456
                                   description='API.INVALID_TENANT_ID')
457
458
        cnx = mysql.connector.connect(**config.myems_system_db)
459
        cursor = cnx.cursor()
460
461
        cursor.execute(" SELECT name "
462
                       " FROM tbl_tenants "
463
                       " WHERE id = %s ", (id_,))
464
        if cursor.fetchone() is None:
465
            cursor.close()
466
            cnx.close()
467
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
468
                                   description='API.TENANT_NOT_FOUND')
469
470
        # check relation with space
471
        cursor.execute(" SELECT space_id "
472
                       " FROM tbl_spaces_tenants "
473
                       " WHERE tenant_id = %s ",
474
                       (id_,))
475
        rows_spaces = cursor.fetchall()
476
        if rows_spaces is not None and len(rows_spaces) > 0:
477
            cursor.close()
478
            cnx.close()
479
            raise falcon.HTTPError(status=falcon.HTTP_400,
480
                                   title='API.BAD_REQUEST',
481
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
482
483
        # delete relation with meter
484
        cursor.execute(" DELETE FROM tbl_tenants_meters WHERE tenant_id = %s ", (id_,))
485
486
        # delete relation with offline meter
487
        cursor.execute(" DELETE FROM tbl_tenants_offline_meters WHERE tenant_id = %s ", (id_,))
488
489
        # delete relation with points
490
        cursor.execute(" DELETE FROM tbl_tenants_points WHERE tenant_id = %s ", (id_,))
491
492
        # delete relation with sensor
493
        cursor.execute(" DELETE FROM tbl_tenants_sensors WHERE tenant_id = %s ", (id_,))
494
495
        # delete relation with virtual meter
496
        cursor.execute(" DELETE FROM tbl_tenants_virtual_meters WHERE tenant_id = %s ", (id_,))
497
498
        # delete relation with command
499
        cursor.execute(" DELETE FROM tbl_tenants_commands WHERE tenant_id = %s ", (id_,))
500
501
        # delete relation with working calendar
502
        cursor.execute(" DELETE FROM tbl_tenants_working_calendars WHERE tenant_id = %s ", (id_,))
503
504
        cursor.execute(" DELETE FROM tbl_tenants WHERE id = %s ", (id_,))
505
        cnx.commit()
506
507
        cursor.close()
508
        cnx.close()
509
510
        resp.status = falcon.HTTP_204
511
512
    @staticmethod
513
    @user_logger
514
    def on_put(req, resp, id_):
515
        """Handles PUT requests"""
516
        admin_control(req)
517
        try:
518
            raw_json = req.stream.read().decode('utf-8')
519
        except Exception as ex:
520
            print(str(ex))
521
            raise falcon.HTTPError(status=falcon.HTTP_400,
522
                                   title='API.BAD_REQUEST',
523
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
524
525
        if not id_.isdigit() or int(id_) <= 0:
526
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
527
                                   description='API.INVALID_TENANT_ID')
528
529
        new_values = json.loads(raw_json)
530
531
        if 'name' not in new_values['data'].keys() or \
532
                not isinstance(new_values['data']['name'], str) or \
533
                len(str.strip(new_values['data']['name'])) == 0:
534
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
535
                                   description='API.INVALID_TENANT_NAME')
536
        name = str.strip(new_values['data']['name'])
537
538
        if 'buildings' not in new_values['data'].keys() or \
539
                not isinstance(new_values['data']['buildings'], str) or \
540
                len(str.strip(new_values['data']['buildings'])) == 0:
541
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
542
                                   description='API.INVALID_BUILDINGS_VALUE')
543
        buildings = str.strip(new_values['data']['buildings'])
544
545
        if 'floors' not in new_values['data'].keys() or \
546
                not isinstance(new_values['data']['floors'], str) or \
547
                len(str.strip(new_values['data']['floors'])) == 0:
548
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
549
                                   description='API.INVALID_FLOORS_VALUE')
550
        floors = str.strip(new_values['data']['floors'])
551
552
        if 'rooms' not in new_values['data'].keys() or \
553
                not isinstance(new_values['data']['rooms'], str) or \
554
                len(str.strip(new_values['data']['rooms'])) == 0:
555
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
556
                                   description='API.INVALID_ROOMS_VALUE')
557
        rooms = str.strip(new_values['data']['rooms'])
558
559
        if 'area' not in new_values['data'].keys() or \
560
                not (isinstance(new_values['data']['area'], float) or
561
                     isinstance(new_values['data']['area'], int)) or \
562
                new_values['data']['area'] <= 0.0:
563
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
564
                                   description='API.INVALID_AREA_VALUE')
565
        area = new_values['data']['area']
566
567
        if 'tenant_type_id' not in new_values['data'].keys() or \
568
                not isinstance(new_values['data']['tenant_type_id'], int) or \
569
                new_values['data']['tenant_type_id'] <= 0:
570
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
571
                                   description='API.INVALID_TENANT_TYPE_ID')
572
        tenant_type_id = new_values['data']['tenant_type_id']
573
574
        if 'is_input_counted' not in new_values['data'].keys() or \
575
                not isinstance(new_values['data']['is_input_counted'], bool):
576
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
577
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
578
        is_input_counted = new_values['data']['is_input_counted']
579
580
        if 'is_key_tenant' not in new_values['data'].keys() or \
581
                not isinstance(new_values['data']['is_key_tenant'], bool):
582
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
583
                                   description='API.INVALID_IS_KEY_TENANT_VALUE')
584
        is_key_tenant = new_values['data']['is_key_tenant']
585
586
        if 'lease_number' not in new_values['data'].keys() or \
587
                not isinstance(new_values['data']['lease_number'], str) or \
588
                len(str.strip(new_values['data']['lease_number'])) == 0:
589
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
590
                                   description='API.INVALID_LEASE_NUMBER_VALUE')
591
        lease_number = str.strip(new_values['data']['lease_number'])
592
593
        if 'is_in_lease' not in new_values['data'].keys() or \
594
                not isinstance(new_values['data']['is_in_lease'], bool):
595
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
596
                                   description='API.INVALID_IS_IN_LEASE_VALUE')
597
        is_in_lease = new_values['data']['is_in_lease']
598
599
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
600
        if config.utc_offset[0] == '-':
601
            timezone_offset = -timezone_offset
602
603
        # todo: validate datetime values
604
        lease_start_datetime_utc = datetime.strptime(new_values['data']['lease_start_datetime'],
605
                                                     '%Y-%m-%dT%H:%M:%S')
606
        lease_start_datetime_utc = lease_start_datetime_utc.replace(tzinfo=timezone.utc)
607
        lease_start_datetime_utc -= timedelta(minutes=timezone_offset)
608
609
        lease_end_datetime_utc = datetime.strptime(new_values['data']['lease_end_datetime'],
610
                                                   '%Y-%m-%dT%H:%M:%S')
611
        lease_end_datetime_utc = lease_end_datetime_utc.replace(tzinfo=timezone.utc)
612
        lease_end_datetime_utc -= timedelta(minutes=timezone_offset)
613
614
        if 'contact_id' not in new_values['data'].keys() or \
615
                not isinstance(new_values['data']['contact_id'], int) or \
616
                new_values['data']['contact_id'] <= 0:
617
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
618
                                   description='API.INVALID_CONTACT_ID')
619
        contact_id = new_values['data']['contact_id']
620
621
        if 'cost_center_id' not in new_values['data'].keys() or \
622
                not isinstance(new_values['data']['cost_center_id'], int) or \
623
                new_values['data']['cost_center_id'] <= 0:
624
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
625
                                   description='API.INVALID_COST_CENTER_ID')
626
        cost_center_id = new_values['data']['cost_center_id']
627
628
        if 'description' in new_values['data'].keys() and \
629
                new_values['data']['description'] is not None and \
630
                len(str(new_values['data']['description'])) > 0:
631
            description = str.strip(new_values['data']['description'])
632
        else:
633
            description = None
634
635
        cnx = mysql.connector.connect(**config.myems_system_db)
636
        cursor = cnx.cursor()
637
638
        cursor.execute(" SELECT name "
639
                       " FROM tbl_tenants "
640
                       " WHERE id = %s ", (id_,))
641
        if cursor.fetchone() is None:
642
            cursor.close()
643
            cnx.close()
644
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
645
                                   description='API.TENANT_NOT_FOUND')
646
647
        cursor.execute(" SELECT name "
648
                       " FROM tbl_tenants "
649
                       " WHERE name = %s AND id != %s ", (name, id_))
650
        if cursor.fetchone() is not None:
651
            cursor.close()
652
            cnx.close()
653
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
654
                                   description='API.TENANT_NAME_IS_ALREADY_IN_USE')
655
656
        cursor.execute(" SELECT name "
657
                       " FROM tbl_tenant_types "
658
                       " WHERE id = %s ",
659
                       (tenant_type_id,))
660
        if cursor.fetchone() is None:
661
            cursor.close()
662
            cnx.close()
663
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
664
                                   description='API.TENANT_TYPE_NOT_FOUND')
665
666
        cursor.execute(" SELECT name "
667
                       " FROM tbl_contacts "
668
                       " WHERE id = %s ",
669
                       (new_values['data']['contact_id'],))
670
        row = cursor.fetchone()
671
        if row is None:
672
            cursor.close()
673
            cnx.close()
674
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
675
                                   description='API.CONTACT_NOT_FOUND')
676
677
        cursor.execute(" SELECT name "
678
                       " FROM tbl_cost_centers "
679
                       " WHERE id = %s ",
680
                       (new_values['data']['cost_center_id'],))
681
        row = cursor.fetchone()
682
        if row is None:
683
            cursor.close()
684
            cnx.close()
685
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
686
                                   description='API.COST_CENTER_NOT_FOUND')
687
688
        update_row = (" UPDATE tbl_tenants "
689
                      " SET name = %s, buildings = %s, floors = %s, rooms = %s, area = %s, "
690
                      "     tenant_type_id = %s, is_input_counted = %s, "
691
                      "     is_key_tenant = %s, lease_number = %s, lease_start_datetime_utc = %s, "
692
                      "     lease_end_datetime_utc = %s, is_in_lease = %s, contact_id = %s, cost_center_id = %s, "
693
                      "     description = %s "
694
                      " WHERE id = %s ")
695
        cursor.execute(update_row, (name,
696
                                    buildings,
697
                                    floors,
698
                                    rooms,
699
                                    area,
700
                                    tenant_type_id,
701
                                    is_input_counted,
702
                                    is_key_tenant,
703
                                    lease_number,
704
                                    lease_start_datetime_utc,
705
                                    lease_end_datetime_utc,
706
                                    is_in_lease,
707
                                    contact_id,
708
                                    cost_center_id,
709
                                    description,
710
                                    id_))
711
        cnx.commit()
712
713
        cursor.close()
714
        cnx.close()
715
716
        resp.status = falcon.HTTP_200
717
718
719 View Code Duplication
class TenantMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
720
    def __init__(self):
721
        pass
722
723
    @staticmethod
724
    def on_options(req, resp, id_):
725
        _ = req
726
        resp.status = falcon.HTTP_200
727
        _ = id_
728
729
    @staticmethod
730
    def on_get(req, resp, id_):
731
        if 'API-KEY' not in req.headers or \
732
                not isinstance(req.headers['API-KEY'], str) or \
733
                len(str.strip(req.headers['API-KEY'])) == 0:
734
            access_control(req)
735
        else:
736
            api_key_control(req)
737
        if not id_.isdigit() or int(id_) <= 0:
738
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
739
                                   description='API.INVALID_TENANT_ID')
740
741
        cnx = mysql.connector.connect(**config.myems_system_db)
742
        cursor = cnx.cursor()
743
744
        cursor.execute(" SELECT name "
745
                       " FROM tbl_tenants "
746
                       " WHERE id = %s ", (id_,))
747
        if cursor.fetchone() is None:
748
            cursor.close()
749
            cnx.close()
750
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
751
                                   description='API.TENANT_NOT_FOUND')
752
753
        query = (" SELECT id, name, uuid "
754
                 " FROM tbl_energy_categories ")
755
        cursor.execute(query)
756
        rows_energy_categories = cursor.fetchall()
757
758
        energy_category_dict = dict()
759
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
760
            for row in rows_energy_categories:
761
                energy_category_dict[row[0]] = {"id": row[0],
762
                                                "name": row[1],
763
                                                "uuid": row[2]}
764
765
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
766
                 " FROM tbl_tenants t, tbl_tenants_meters tm, tbl_meters m "
767
                 " WHERE tm.tenant_id = t.id AND m.id = tm.meter_id AND t.id = %s "
768
                 " ORDER BY m.id ")
769
        cursor.execute(query, (id_,))
770
        rows = cursor.fetchall()
771
772
        result = list()
773
        if rows is not None and len(rows) > 0:
774
            for row in rows:
775
                meta_result = {"id": row[0],
776
                               "name": row[1],
777
                               "uuid": row[2],
778
                               "energy_category": energy_category_dict.get(row[3], None)}
779
                result.append(meta_result)
780
781
        resp.text = json.dumps(result)
782
783
    @staticmethod
784
    @user_logger
785
    def on_post(req, resp, id_):
786
        """Handles POST requests"""
787
        admin_control(req)
788
        try:
789
            raw_json = req.stream.read().decode('utf-8')
790
        except Exception as ex:
791
            print(str(ex))
792
            raise falcon.HTTPError(status=falcon.HTTP_400,
793
                                   title='API.BAD_REQUEST',
794
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
795
796
        if not id_.isdigit() or int(id_) <= 0:
797
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
798
                                   description='API.INVALID_TENANT_ID')
799
800
        new_values = json.loads(raw_json)
801
802
        if 'meter_id' not in new_values['data'].keys() or \
803
                not isinstance(new_values['data']['meter_id'], int) or \
804
                new_values['data']['meter_id'] <= 0:
805
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
806
                                   description='API.INVALID_METER_ID')
807
        meter_id = new_values['data']['meter_id']
808
809
        cnx = mysql.connector.connect(**config.myems_system_db)
810
        cursor = cnx.cursor()
811
812
        cursor.execute(" SELECT name "
813
                       " from tbl_tenants "
814
                       " WHERE id = %s ", (id_,))
815
        if cursor.fetchone() is None:
816
            cursor.close()
817
            cnx.close()
818
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
819
                                   description='API.TENANT_NOT_FOUND')
820
821
        cursor.execute(" SELECT name "
822
                       " FROM tbl_meters "
823
                       " WHERE id = %s ", (meter_id,))
824
        if cursor.fetchone() is None:
825
            cursor.close()
826
            cnx.close()
827
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
828
                                   description='API.METER_NOT_FOUND')
829
830
        query = (" SELECT id "
831
                 " FROM tbl_tenants_meters "
832
                 " WHERE tenant_id = %s AND meter_id = %s")
833
        cursor.execute(query, (id_, meter_id,))
834
        if cursor.fetchone() is not None:
835
            cursor.close()
836
            cnx.close()
837
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
838
                                   description='API.TENANT_METER_RELATION_EXISTS')
839
840
        add_row = (" INSERT INTO tbl_tenants_meters (tenant_id, meter_id) "
841
                   " VALUES (%s, %s) ")
842
        cursor.execute(add_row, (id_, meter_id,))
843
        cnx.commit()
844
        cursor.close()
845
        cnx.close()
846
847
        resp.status = falcon.HTTP_201
848
        resp.location = '/tenants/' + str(id_) + '/meters/' + str(meter_id)
849
850
851
class TenantMeterItem:
852
    def __init__(self):
853
        pass
854
855
    @staticmethod
856
    def on_options(req, resp, id_, mid):
857
        _ = req
858
        resp.status = falcon.HTTP_200
859
        _ = id_
860
861
    @staticmethod
862
    @user_logger
863
    def on_delete(req, resp, id_, mid):
864
        admin_control(req)
865
        if not id_.isdigit() or int(id_) <= 0:
866
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
867
                                   description='API.INVALID_TENANT_ID')
868
869
        if not mid.isdigit() or int(mid) <= 0:
870
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
871
                                   description='API.INVALID_METER_ID')
872
873
        cnx = mysql.connector.connect(**config.myems_system_db)
874
        cursor = cnx.cursor()
875
876
        cursor.execute(" SELECT name "
877
                       " FROM tbl_tenants "
878
                       " WHERE id = %s ", (id_,))
879
        if cursor.fetchone() is None:
880
            cursor.close()
881
            cnx.close()
882
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
883
                                   description='API.TENANT_NOT_FOUND')
884
885
        cursor.execute(" SELECT name "
886
                       " FROM tbl_meters "
887
                       " WHERE id = %s ", (mid,))
888
        if cursor.fetchone() is None:
889
            cursor.close()
890
            cnx.close()
891
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
892
                                   description='API.METER_NOT_FOUND')
893
894
        cursor.execute(" SELECT id "
895
                       " FROM tbl_tenants_meters "
896
                       " WHERE tenant_id = %s AND meter_id = %s ", (id_, mid))
897
        if cursor.fetchone() is None:
898
            cursor.close()
899
            cnx.close()
900
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
901
                                   description='API.TENANT_METER_RELATION_NOT_FOUND')
902
903
        cursor.execute(" DELETE FROM tbl_tenants_meters WHERE tenant_id = %s AND meter_id = %s ", (id_, mid))
904
        cnx.commit()
905
906
        cursor.close()
907
        cnx.close()
908
909
        resp.status = falcon.HTTP_204
910
911
912 View Code Duplication
class TenantOfflineMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
913
    def __init__(self):
914
        pass
915
916
    @staticmethod
917
    def on_options(req, resp, id_):
918
        _ = req
919
        resp.status = falcon.HTTP_200
920
        _ = id_
921
922
    @staticmethod
923
    def on_get(req, resp, id_):
924
        if 'API-KEY' not in req.headers or \
925
                not isinstance(req.headers['API-KEY'], str) or \
926
                len(str.strip(req.headers['API-KEY'])) == 0:
927
            access_control(req)
928
        else:
929
            api_key_control(req)
930
        if not id_.isdigit() or int(id_) <= 0:
931
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
932
                                   description='API.INVALID_TENANT_ID')
933
934
        cnx = mysql.connector.connect(**config.myems_system_db)
935
        cursor = cnx.cursor()
936
937
        cursor.execute(" SELECT name "
938
                       " FROM tbl_tenants "
939
                       " WHERE id = %s ", (id_,))
940
        if cursor.fetchone() is None:
941
            cursor.close()
942
            cnx.close()
943
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
944
                                   description='API.TENANT_NOT_FOUND')
945
946
        query = (" SELECT id, name, uuid "
947
                 " FROM tbl_energy_categories ")
948
        cursor.execute(query)
949
        rows_energy_categories = cursor.fetchall()
950
951
        energy_category_dict = dict()
952
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
953
            for row in rows_energy_categories:
954
                energy_category_dict[row[0]] = {"id": row[0],
955
                                                "name": row[1],
956
                                                "uuid": row[2]}
957
958
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
959
                 " FROM tbl_tenants s, tbl_tenants_offline_meters sm, tbl_offline_meters m "
960
                 " WHERE sm.tenant_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
961
                 " ORDER BY m.id ")
962
        cursor.execute(query, (id_,))
963
        rows = cursor.fetchall()
964
965
        result = list()
966
        if rows is not None and len(rows) > 0:
967
            for row in rows:
968
                meta_result = {"id": row[0],
969
                               "name": row[1],
970
                               "uuid": row[2],
971
                               "energy_category": energy_category_dict.get(row[3], None)}
972
                result.append(meta_result)
973
974
        resp.text = json.dumps(result)
975
976
    @staticmethod
977
    @user_logger
978
    def on_post(req, resp, id_):
979
        """Handles POST requests"""
980
        admin_control(req)
981
        try:
982
            raw_json = req.stream.read().decode('utf-8')
983
        except Exception as ex:
984
            print(str(ex))
985
            raise falcon.HTTPError(status=falcon.HTTP_400,
986
                                   title='API.BAD_REQUEST',
987
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
988
989
        if not id_.isdigit() or int(id_) <= 0:
990
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
991
                                   description='API.INVALID_TENANT_ID')
992
993
        new_values = json.loads(raw_json)
994
995
        if 'offline_meter_id' not in new_values['data'].keys() or \
996
                not isinstance(new_values['data']['offline_meter_id'], int) or \
997
                new_values['data']['offline_meter_id'] <= 0:
998
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
999
                                   description='API.INVALID_OFFLINE_METER_ID')
1000
        offline_meter_id = new_values['data']['offline_meter_id']
1001
1002
        cnx = mysql.connector.connect(**config.myems_system_db)
1003
        cursor = cnx.cursor()
1004
1005
        cursor.execute(" SELECT name "
1006
                       " from tbl_tenants "
1007
                       " WHERE id = %s ", (id_,))
1008
        if cursor.fetchone() is None:
1009
            cursor.close()
1010
            cnx.close()
1011
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1012
                                   description='API.TENANT_NOT_FOUND')
1013
1014
        cursor.execute(" SELECT name "
1015
                       " FROM tbl_offline_meters "
1016
                       " WHERE id = %s ", (offline_meter_id,))
1017
        if cursor.fetchone() is None:
1018
            cursor.close()
1019
            cnx.close()
1020
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1021
                                   description='API.OFFLINE_METER_NOT_FOUND')
1022
1023
        query = (" SELECT id "
1024
                 " FROM tbl_tenants_offline_meters "
1025
                 " WHERE tenant_id = %s AND offline_meter_id = %s")
1026
        cursor.execute(query, (id_, offline_meter_id,))
1027
        if cursor.fetchone() is not None:
1028
            cursor.close()
1029
            cnx.close()
1030
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1031
                                   description='API.TENANT_OFFLINE_METER_RELATION_EXISTS')
1032
1033
        add_row = (" INSERT INTO tbl_tenants_offline_meters (tenant_id, offline_meter_id) "
1034
                   " VALUES (%s, %s) ")
1035
        cursor.execute(add_row, (id_, offline_meter_id,))
1036
        cnx.commit()
1037
        cursor.close()
1038
        cnx.close()
1039
1040
        resp.status = falcon.HTTP_201
1041
        resp.location = '/tenants/' + str(id_) + '/offlinemeters/' + str(offline_meter_id)
1042
1043
1044
class TenantOfflineMeterItem:
1045
    def __init__(self):
1046
        pass
1047
1048
    @staticmethod
1049
    def on_options(req, resp, id_, mid):
1050
        _ = req
1051
        resp.status = falcon.HTTP_200
1052
        _ = id_
1053
1054
    @staticmethod
1055
    @user_logger
1056
    def on_delete(req, resp, id_, mid):
1057
        admin_control(req)
1058
        if not id_.isdigit() or int(id_) <= 0:
1059
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1060
                                   description='API.INVALID_TENANT_ID')
1061
1062
        if not mid.isdigit() or int(mid) <= 0:
1063
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1064
                                   description='API.INVALID_OFFLINE_METER_ID')
1065
1066
        cnx = mysql.connector.connect(**config.myems_system_db)
1067
        cursor = cnx.cursor()
1068
1069
        cursor.execute(" SELECT name "
1070
                       " FROM tbl_tenants "
1071
                       " WHERE id = %s ", (id_,))
1072
        if cursor.fetchone() is None:
1073
            cursor.close()
1074
            cnx.close()
1075
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1076
                                   description='API.TENANT_NOT_FOUND')
1077
1078
        cursor.execute(" SELECT name "
1079
                       " FROM tbl_offline_meters "
1080
                       " WHERE id = %s ", (mid,))
1081
        if cursor.fetchone() is None:
1082
            cursor.close()
1083
            cnx.close()
1084
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1085
                                   description='API.OFFLINE_METER_NOT_FOUND')
1086
1087
        cursor.execute(" SELECT id "
1088
                       " FROM tbl_tenants_offline_meters "
1089
                       " WHERE tenant_id = %s AND offline_meter_id = %s ", (id_, mid))
1090
        if cursor.fetchone() is None:
1091
            cursor.close()
1092
            cnx.close()
1093
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1094
                                   description='API.TENANT_OFFLINE_METER_RELATION_NOT_FOUND')
1095
1096
        cursor.execute(" DELETE FROM tbl_tenants_offline_meters "
1097
                       " WHERE tenant_id = %s AND offline_meter_id = %s ", (id_, mid))
1098
        cnx.commit()
1099
1100
        cursor.close()
1101
        cnx.close()
1102
1103
        resp.status = falcon.HTTP_204
1104
1105
1106 View Code Duplication
class TenantPointCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1107
    def __init__(self):
1108
        pass
1109
1110
    @staticmethod
1111
    def on_options(req, resp, id_):
1112
        _ = req
1113
        resp.status = falcon.HTTP_200
1114
        _ = id_
1115
1116
    @staticmethod
1117
    def on_get(req, resp, id_):
1118
        if 'API-KEY' not in req.headers or \
1119
                not isinstance(req.headers['API-KEY'], str) or \
1120
                len(str.strip(req.headers['API-KEY'])) == 0:
1121
            access_control(req)
1122
        else:
1123
            api_key_control(req)
1124
        if not id_.isdigit() or int(id_) <= 0:
1125
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1126
                                   description='API.INVALID_TENANT_ID')
1127
1128
        cnx = mysql.connector.connect(**config.myems_system_db)
1129
        cursor = cnx.cursor()
1130
1131
        cursor.execute(" SELECT name "
1132
                       " FROM tbl_tenants "
1133
                       " WHERE id = %s ", (id_,))
1134
        if cursor.fetchone() is None:
1135
            cursor.close()
1136
            cnx.close()
1137
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1138
                                   description='API.TENANT_NOT_FOUND')
1139
1140
        query = (" SELECT id, name, uuid "
1141
                 " FROM tbl_data_sources ")
1142
        cursor.execute(query)
1143
        rows_data_sources = cursor.fetchall()
1144
1145
        data_source_dict = dict()
1146
        if rows_data_sources is not None and len(rows_data_sources) > 0:
1147
            for row in rows_data_sources:
1148
                data_source_dict[row[0]] = {"id": row[0],
1149
                                            "name": row[1],
1150
                                            "uuid": row[2]}
1151
1152
        query = (" SELECT p.id, p.name, p.data_source_id "
1153
                 " FROM tbl_tenants t, tbl_tenants_points tp, tbl_points p "
1154
                 " WHERE tp.tenant_id = t.id AND p.id = tp.point_id AND t.id = %s "
1155
                 " ORDER BY p.id ")
1156
        cursor.execute(query, (id_,))
1157
        rows = cursor.fetchall()
1158
1159
        result = list()
1160
        if rows is not None and len(rows) > 0:
1161
            for row in rows:
1162
                meta_result = {"id": row[0],
1163
                               "name": row[1],
1164
                               "data_source": data_source_dict.get(row[2], None)}
1165
                result.append(meta_result)
1166
1167
        resp.text = json.dumps(result)
1168
1169
    @staticmethod
1170
    @user_logger
1171
    def on_post(req, resp, id_):
1172
        """Handles POST requests"""
1173
        admin_control(req)
1174
        try:
1175
            raw_json = req.stream.read().decode('utf-8')
1176
        except Exception as ex:
1177
            print(str(ex))
1178
            raise falcon.HTTPError(status=falcon.HTTP_400,
1179
                                   title='API.BAD_REQUEST',
1180
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1181
1182
        if not id_.isdigit() or int(id_) <= 0:
1183
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1184
                                   description='API.INVALID_TENANT_ID')
1185
1186
        new_values = json.loads(raw_json)
1187
1188
        if 'point_id' not in new_values['data'].keys() or \
1189
                not isinstance(new_values['data']['point_id'], int) or \
1190
                new_values['data']['point_id'] <= 0:
1191
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1192
                                   description='API.INVALID_POINT_ID')
1193
        point_id = new_values['data']['point_id']
1194
1195
        cnx = mysql.connector.connect(**config.myems_system_db)
1196
        cursor = cnx.cursor()
1197
1198
        cursor.execute(" SELECT name "
1199
                       " from tbl_tenants "
1200
                       " WHERE id = %s ", (id_,))
1201
        if cursor.fetchone() is None:
1202
            cursor.close()
1203
            cnx.close()
1204
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1205
                                   description='API.TENANT_NOT_FOUND')
1206
1207
        cursor.execute(" SELECT name "
1208
                       " FROM tbl_points "
1209
                       " WHERE id = %s ", (point_id,))
1210
        if cursor.fetchone() is None:
1211
            cursor.close()
1212
            cnx.close()
1213
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1214
                                   description='API.POINT_NOT_FOUND')
1215
1216
        query = (" SELECT id "
1217
                 " FROM tbl_tenants_points "
1218
                 " WHERE tenant_id = %s AND point_id = %s")
1219
        cursor.execute(query, (id_, point_id,))
1220
        if cursor.fetchone() is not None:
1221
            cursor.close()
1222
            cnx.close()
1223
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1224
                                   description='API.TENANT_POINT_RELATION_EXISTS')
1225
1226
        add_row = (" INSERT INTO tbl_tenants_points (tenant_id, point_id) "
1227
                   " VALUES (%s, %s) ")
1228
        cursor.execute(add_row, (id_, point_id,))
1229
        cnx.commit()
1230
        cursor.close()
1231
        cnx.close()
1232
1233
        resp.status = falcon.HTTP_201
1234
        resp.location = '/tenants/' + str(id_) + '/points/' + str(point_id)
1235
1236
1237
class TenantPointItem:
1238
    def __init__(self):
1239
        pass
1240
1241
    @staticmethod
1242
    def on_options(req, resp, id_, pid):
1243
        _ = req
1244
        resp.status = falcon.HTTP_200
1245
        _ = id_
1246
1247
    @staticmethod
1248
    @user_logger
1249
    def on_delete(req, resp, id_, pid):
1250
        admin_control(req)
1251
        if not id_.isdigit() or int(id_) <= 0:
1252
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1253
                                   description='API.INVALID_TENANT_ID')
1254
1255
        if not pid.isdigit() or int(pid) <= 0:
1256
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1257
                                   description='API.INVALID_POINT_ID')
1258
1259
        cnx = mysql.connector.connect(**config.myems_system_db)
1260
        cursor = cnx.cursor()
1261
1262
        cursor.execute(" SELECT name "
1263
                       " FROM tbl_tenants "
1264
                       " WHERE id = %s ", (id_,))
1265
        if cursor.fetchone() is None:
1266
            cursor.close()
1267
            cnx.close()
1268
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1269
                                   description='API.TENANT_NOT_FOUND')
1270
1271
        cursor.execute(" SELECT name "
1272
                       " FROM tbl_points "
1273
                       " WHERE id = %s ", (pid,))
1274
        if cursor.fetchone() is None:
1275
            cursor.close()
1276
            cnx.close()
1277
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1278
                                   description='API.POINT_NOT_FOUND')
1279
1280
        cursor.execute(" SELECT id "
1281
                       " FROM tbl_tenants_points "
1282
                       " WHERE tenant_id = %s AND point_id = %s ", (id_, pid))
1283
        if cursor.fetchone() is None:
1284
            cursor.close()
1285
            cnx.close()
1286
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1287
                                   description='API.TENANT_POINT_RELATION_NOT_FOUND')
1288
1289
        cursor.execute(" DELETE FROM tbl_tenants_points "
1290
                       " WHERE tenant_id = %s AND point_id = %s ", (id_, pid))
1291
        cnx.commit()
1292
1293
        cursor.close()
1294
        cnx.close()
1295
1296
        resp.status = falcon.HTTP_204
1297
1298
1299 View Code Duplication
class TenantSensorCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1300
    def __init__(self):
1301
        pass
1302
1303
    @staticmethod
1304
    def on_options(req, resp, id_):
1305
        _ = req
1306
        resp.status = falcon.HTTP_200
1307
        _ = id_
1308
1309
    @staticmethod
1310
    def on_get(req, resp, id_):
1311
        if 'API-KEY' not in req.headers or \
1312
                not isinstance(req.headers['API-KEY'], str) or \
1313
                len(str.strip(req.headers['API-KEY'])) == 0:
1314
            access_control(req)
1315
        else:
1316
            api_key_control(req)
1317
        if not id_.isdigit() or int(id_) <= 0:
1318
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1319
                                   description='API.INVALID_TENANT_ID')
1320
1321
        cnx = mysql.connector.connect(**config.myems_system_db)
1322
        cursor = cnx.cursor()
1323
1324
        cursor.execute(" SELECT name "
1325
                       " FROM tbl_tenants "
1326
                       " WHERE id = %s ", (id_,))
1327
        if cursor.fetchone() is None:
1328
            cursor.close()
1329
            cnx.close()
1330
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1331
                                   description='API.TENANT_NOT_FOUND')
1332
1333
        query = (" SELECT s.id, s.name, s.uuid "
1334
                 " FROM tbl_tenants t, tbl_tenants_sensors ts, tbl_sensors s "
1335
                 " WHERE ts.tenant_id = t.id AND s.id = ts.sensor_id AND t.id = %s "
1336
                 " ORDER BY s.id ")
1337
        cursor.execute(query, (id_,))
1338
        rows = cursor.fetchall()
1339
1340
        result = list()
1341
        if rows is not None and len(rows) > 0:
1342
            for row in rows:
1343
                meta_result = {"id": row[0],
1344
                               "name": row[1],
1345
                               "uuid": row[2]}
1346
                result.append(meta_result)
1347
1348
        resp.text = json.dumps(result)
1349
1350
    @staticmethod
1351
    @user_logger
1352
    def on_post(req, resp, id_):
1353
        """Handles POST requests"""
1354
        admin_control(req)
1355
        try:
1356
            raw_json = req.stream.read().decode('utf-8')
1357
        except Exception as ex:
1358
            print(str(ex))
1359
            raise falcon.HTTPError(status=falcon.HTTP_400,
1360
                                   title='API.BAD_REQUEST',
1361
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1362
1363
        if not id_.isdigit() or int(id_) <= 0:
1364
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1365
                                   description='API.INVALID_TENANT_ID')
1366
1367
        new_values = json.loads(raw_json)
1368
1369
        if 'sensor_id' not in new_values['data'].keys() or \
1370
                not isinstance(new_values['data']['sensor_id'], int) or \
1371
                new_values['data']['sensor_id'] <= 0:
1372
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1373
                                   description='API.INVALID_SENSOR_ID')
1374
        sensor_id = new_values['data']['sensor_id']
1375
1376
        cnx = mysql.connector.connect(**config.myems_system_db)
1377
        cursor = cnx.cursor()
1378
1379
        cursor.execute(" SELECT name "
1380
                       " from tbl_tenants "
1381
                       " WHERE id = %s ", (id_,))
1382
        if cursor.fetchone() is None:
1383
            cursor.close()
1384
            cnx.close()
1385
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1386
                                   description='API.TENANT_NOT_FOUND')
1387
1388
        cursor.execute(" SELECT name "
1389
                       " FROM tbl_sensors "
1390
                       " WHERE id = %s ", (sensor_id,))
1391
        if cursor.fetchone() is None:
1392
            cursor.close()
1393
            cnx.close()
1394
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1395
                                   description='API.SENSOR_NOT_FOUND')
1396
1397
        query = (" SELECT id "
1398
                 " FROM tbl_tenants_sensors "
1399
                 " WHERE tenant_id = %s AND sensor_id = %s")
1400
        cursor.execute(query, (id_, sensor_id,))
1401
        if cursor.fetchone() is not None:
1402
            cursor.close()
1403
            cnx.close()
1404
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1405
                                   description='API.TENANT_SENSOR_RELATION_EXISTS')
1406
1407
        add_row = (" INSERT INTO tbl_tenants_sensors (tenant_id, sensor_id) "
1408
                   " VALUES (%s, %s) ")
1409
        cursor.execute(add_row, (id_, sensor_id,))
1410
        cnx.commit()
1411
        cursor.close()
1412
        cnx.close()
1413
1414
        resp.status = falcon.HTTP_201
1415
        resp.location = '/tenants/' + str(id_) + '/sensors/' + str(sensor_id)
1416
1417
1418
class TenantSensorItem:
1419
    def __init__(self):
1420
        pass
1421
1422
    @staticmethod
1423
    def on_options(req, resp, id_, sid):
1424
        _ = req
1425
        resp.status = falcon.HTTP_200
1426
        _ = id_
1427
1428
    @staticmethod
1429
    @user_logger
1430
    def on_delete(req, resp, id_, sid):
1431
        admin_control(req)
1432
        if not id_.isdigit() or int(id_) <= 0:
1433
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1434
                                   description='API.INVALID_TENANT_ID')
1435
1436
        if not sid.isdigit() or int(sid) <= 0:
1437
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1438
                                   description='API.INVALID_SENSOR_ID')
1439
1440
        cnx = mysql.connector.connect(**config.myems_system_db)
1441
        cursor = cnx.cursor()
1442
1443
        cursor.execute(" SELECT name "
1444
                       " FROM tbl_tenants "
1445
                       " WHERE id = %s ", (id_,))
1446
        if cursor.fetchone() is None:
1447
            cursor.close()
1448
            cnx.close()
1449
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1450
                                   description='API.TENANT_NOT_FOUND')
1451
1452
        cursor.execute(" SELECT name "
1453
                       " FROM tbl_sensors "
1454
                       " WHERE id = %s ", (sid,))
1455
        if cursor.fetchone() is None:
1456
            cursor.close()
1457
            cnx.close()
1458
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1459
                                   description='API.SENSOR_NOT_FOUND')
1460
1461
        cursor.execute(" SELECT id "
1462
                       " FROM tbl_tenants_sensors "
1463
                       " WHERE tenant_id = %s AND sensor_id = %s ", (id_, sid))
1464
        if cursor.fetchone() is None:
1465
            cursor.close()
1466
            cnx.close()
1467
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1468
                                   description='API.TENANT_SENSOR_RELATION_NOT_FOUND')
1469
1470
        cursor.execute(" DELETE FROM tbl_tenants_sensors WHERE tenant_id = %s AND sensor_id = %s ", (id_, sid))
1471
        cnx.commit()
1472
1473
        cursor.close()
1474
        cnx.close()
1475
1476
        resp.status = falcon.HTTP_204
1477
1478
1479 View Code Duplication
class TenantVirtualMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1480
    def __init__(self):
1481
        pass
1482
1483
    @staticmethod
1484
    def on_options(req, resp, id_):
1485
        _ = req
1486
        resp.status = falcon.HTTP_200
1487
        _ = id_
1488
1489
    @staticmethod
1490
    def on_get(req, resp, id_):
1491
        if 'API-KEY' not in req.headers or \
1492
                not isinstance(req.headers['API-KEY'], str) or \
1493
                len(str.strip(req.headers['API-KEY'])) == 0:
1494
            access_control(req)
1495
        else:
1496
            api_key_control(req)
1497
        if not id_.isdigit() or int(id_) <= 0:
1498
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1499
                                   description='API.INVALID_TENANT_ID')
1500
1501
        cnx = mysql.connector.connect(**config.myems_system_db)
1502
        cursor = cnx.cursor()
1503
1504
        cursor.execute(" SELECT name "
1505
                       " FROM tbl_tenants "
1506
                       " WHERE id = %s ", (id_,))
1507
        if cursor.fetchone() is None:
1508
            cursor.close()
1509
            cnx.close()
1510
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1511
                                   description='API.TENANT_NOT_FOUND')
1512
1513
        query = (" SELECT id, name, uuid "
1514
                 " FROM tbl_energy_categories ")
1515
        cursor.execute(query)
1516
        rows_energy_categories = cursor.fetchall()
1517
1518
        energy_category_dict = dict()
1519
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1520
            for row in rows_energy_categories:
1521
                energy_category_dict[row[0]] = {"id": row[0],
1522
                                                "name": row[1],
1523
                                                "uuid": row[2]}
1524
1525
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
1526
                 " FROM tbl_tenants t, tbl_tenants_virtual_meters tm, tbl_virtual_meters m "
1527
                 " WHERE tm.tenant_id = t.id AND m.id = tm.virtual_meter_id AND t.id = %s "
1528
                 " ORDER BY m.id ")
1529
        cursor.execute(query, (id_,))
1530
        rows = cursor.fetchall()
1531
1532
        result = list()
1533
        if rows is not None and len(rows) > 0:
1534
            for row in rows:
1535
                meta_result = {"id": row[0],
1536
                               "name": row[1],
1537
                               "uuid": row[2],
1538
                               "energy_category": energy_category_dict.get(row[3], None)}
1539
                result.append(meta_result)
1540
1541
        resp.text = json.dumps(result)
1542
1543
    @staticmethod
1544
    @user_logger
1545
    def on_post(req, resp, id_):
1546
        """Handles POST requests"""
1547
        admin_control(req)
1548
        try:
1549
            raw_json = req.stream.read().decode('utf-8')
1550
        except Exception as ex:
1551
            print(str(ex))
1552
            raise falcon.HTTPError(status=falcon.HTTP_400,
1553
                                   title='API.BAD_REQUEST',
1554
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1555
1556
        if not id_.isdigit() or int(id_) <= 0:
1557
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1558
                                   description='API.INVALID_TENANT_ID')
1559
1560
        new_values = json.loads(raw_json)
1561
1562
        if 'virtual_meter_id' not in new_values['data'].keys() or \
1563
                not isinstance(new_values['data']['virtual_meter_id'], int) or \
1564
                new_values['data']['virtual_meter_id'] <= 0:
1565
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1566
                                   description='API.INVALID_VIRTUAL_METER_ID')
1567
        virtual_meter_id = new_values['data']['virtual_meter_id']
1568
1569
        cnx = mysql.connector.connect(**config.myems_system_db)
1570
        cursor = cnx.cursor()
1571
1572
        cursor.execute(" SELECT name "
1573
                       " from tbl_tenants "
1574
                       " WHERE id = %s ", (id_,))
1575
        if cursor.fetchone() is None:
1576
            cursor.close()
1577
            cnx.close()
1578
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1579
                                   description='API.TENANT_NOT_FOUND')
1580
1581
        cursor.execute(" SELECT name "
1582
                       " FROM tbl_virtual_meters "
1583
                       " WHERE id = %s ", (virtual_meter_id,))
1584
        if cursor.fetchone() is None:
1585
            cursor.close()
1586
            cnx.close()
1587
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1588
                                   description='API.VIRTUAL_METER_NOT_FOUND')
1589
1590
        query = (" SELECT id "
1591
                 " FROM tbl_tenants_virtual_meters "
1592
                 " WHERE tenant_id = %s AND virtual_meter_id = %s")
1593
        cursor.execute(query, (id_, virtual_meter_id,))
1594
        if cursor.fetchone() is not None:
1595
            cursor.close()
1596
            cnx.close()
1597
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1598
                                   description='API.TENANT_VIRTUAL_METER_RELATION_EXISTS')
1599
1600
        add_row = (" INSERT INTO tbl_tenants_virtual_meters (tenant_id, virtual_meter_id) "
1601
                   " VALUES (%s, %s) ")
1602
        cursor.execute(add_row, (id_, virtual_meter_id,))
1603
        cnx.commit()
1604
        cursor.close()
1605
        cnx.close()
1606
1607
        resp.status = falcon.HTTP_201
1608
        resp.location = '/tenants/' + str(id_) + '/virtualmeters/' + str(virtual_meter_id)
1609
1610
1611
class TenantVirtualMeterItem:
1612
    def __init__(self):
1613
        pass
1614
1615
    @staticmethod
1616
    def on_options(req, resp, id_, mid):
1617
        _ = req
1618
        resp.status = falcon.HTTP_200
1619
        _ = id_
1620
1621
    @staticmethod
1622
    @user_logger
1623
    def on_delete(req, resp, id_, mid):
1624
        admin_control(req)
1625
        if not id_.isdigit() or int(id_) <= 0:
1626
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1627
                                   description='API.INVALID_TENANT_ID')
1628
1629
        if not mid.isdigit() or int(mid) <= 0:
1630
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1631
                                   description='API.INVALID_VIRTUAL_METER_ID')
1632
1633
        cnx = mysql.connector.connect(**config.myems_system_db)
1634
        cursor = cnx.cursor()
1635
1636
        cursor.execute(" SELECT name "
1637
                       " FROM tbl_tenants "
1638
                       " WHERE id = %s ", (id_,))
1639
        if cursor.fetchone() is None:
1640
            cursor.close()
1641
            cnx.close()
1642
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1643
                                   description='API.TENANT_NOT_FOUND')
1644
1645
        cursor.execute(" SELECT name "
1646
                       " FROM tbl_virtual_meters "
1647
                       " WHERE id = %s ", (mid,))
1648
        if cursor.fetchone() is None:
1649
            cursor.close()
1650
            cnx.close()
1651
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1652
                                   description='API.VIRTUAL_METER_NOT_FOUND')
1653
1654
        cursor.execute(" SELECT id "
1655
                       " FROM tbl_tenants_virtual_meters "
1656
                       " WHERE tenant_id = %s AND virtual_meter_id = %s ", (id_, mid))
1657
        if cursor.fetchone() is None:
1658
            cursor.close()
1659
            cnx.close()
1660
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1661
                                   description='API.TENANT_VIRTUAL_METER_RELATION_NOT_FOUND')
1662
1663
        cursor.execute(" DELETE FROM tbl_tenants_virtual_meters "
1664
                       " WHERE tenant_id = %s AND virtual_meter_id = %s ", (id_, mid))
1665
        cnx.commit()
1666
1667
        cursor.close()
1668
        cnx.close()
1669
1670
        resp.status = falcon.HTTP_204
1671
1672
1673 View Code Duplication
class TenantWorkingCalendarCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1674
    def __init__(self):
1675
        pass
1676
1677
    @staticmethod
1678
    def on_options(req, resp, id_):
1679
        _ = req
1680
        resp.status = falcon.HTTP_200
1681
        _ = id_
1682
1683
    @staticmethod
1684
    def on_get(req, resp, id_):
1685
        if 'API-KEY' not in req.headers or \
1686
                not isinstance(req.headers['API-KEY'], str) or \
1687
                len(str.strip(req.headers['API-KEY'])) == 0:
1688
            access_control(req)
1689
        else:
1690
            api_key_control(req)
1691
        if not id_.isdigit() or int(id_) <= 0:
1692
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1693
                                   description='API.INVALID_TENANT_ID')
1694
1695
        cnx = mysql.connector.connect(**config.myems_system_db)
1696
        cursor = cnx.cursor()
1697
1698
        cursor.execute(" SELECT name "
1699
                       " FROM tbl_tenants "
1700
                       " WHERE id = %s ", (id_,))
1701
        if cursor.fetchone() is None:
1702
            cursor.close()
1703
            cnx.close()
1704
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1705
                                   description='API.TENANT_NOT_FOUND')
1706
1707
        query = (" SELECT wc.id, wc.name, wc.description "
1708
                 " FROM tbl_tenants t, tbl_tenants_working_calendars twc, tbl_working_calendars wc "
1709
                 " WHERE twc.tenant_id = t.id AND wc.id = twc.working_calendar_id AND t.id = %s "
1710
                 " ORDER BY wc.id ")
1711
        cursor.execute(query, (id_,))
1712
        rows = cursor.fetchall()
1713
1714
        result = list()
1715
        if rows is not None and len(rows) > 0:
1716
            for row in rows:
1717
                meta_result = {"id": row[0],
1718
                               "name": row[1],
1719
                               "description": row[2]}
1720
                result.append(meta_result)
1721
1722
        resp.text = json.dumps(result)
1723
1724
    @staticmethod
1725
    @user_logger
1726
    def on_post(req, resp, id_):
1727
        """Handles POST requests"""
1728
        admin_control(req)
1729
        try:
1730
            raw_json = req.stream.read().decode('utf-8')
1731
        except Exception as ex:
1732
            print(str(ex))
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_TENANT_ID')
1740
1741
        new_values = json.loads(raw_json)
1742
1743
        if 'working_calendar_id' not in new_values['data'].keys() or \
1744
                not isinstance(new_values['data']['working_calendar_id'], int) or \
1745
                new_values['data']['working_calendar_id'] <= 0:
1746
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1747
                                   description='API.INVALID_WORKING_CALENDAR_ID')
1748
        working_calendar_id = new_values['data']['working_calendar_id']
1749
1750
        cnx = mysql.connector.connect(**config.myems_system_db)
1751
        cursor = cnx.cursor()
1752
1753
        cursor.execute(" SELECT name "
1754
                       " from tbl_tenants "
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.TENANT_NOT_FOUND')
1761
1762
        cursor.execute(" SELECT name "
1763
                       " FROM tbl_working_calendars "
1764
                       " WHERE id = %s ", (working_calendar_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.WORKING_CALENDAR_NOT_FOUND')
1770
1771
        query = (" SELECT id "
1772
                 " FROM tbl_tenants_working_calendars "
1773
                 " WHERE tenant_id = %s AND working_calendar_id = %s")
1774
        cursor.execute(query, (id_, working_calendar_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.TENANT_WORKING_CALENDAR_RELATION_EXISTS')
1780
1781
        add_row = (" INSERT INTO tbl_tenants_working_calendars (tenant_id, working_calendar_id) "
1782
                   " VALUES (%s, %s) ")
1783
        cursor.execute(add_row, (id_, working_calendar_id,))
1784
        cnx.commit()
1785
        cursor.close()
1786
        cnx.close()
1787
1788
        resp.status = falcon.HTTP_201
1789
        resp.location = '/tenants/' + str(id_) + '/workingcalendars/' + str(working_calendar_id)
1790
1791
1792
class TenantWorkingCalendarItem:
1793
    def __init__(self):
1794
        pass
1795
1796
    @staticmethod
1797
    def on_options(req, resp, id_, wcid):
1798
        _ = req
1799
        resp.status = falcon.HTTP_200
1800
        _ = id_
1801
1802
    @staticmethod
1803
    @user_logger
1804
    def on_delete(req, resp, id_, wcid):
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_TENANT_ID')
1809
1810
        if not wcid.isdigit() or int(wcid) <= 0:
1811
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1812
                                   description='API.INVALID_WORKING_CALENDAR_ID')
1813
1814
        cnx = mysql.connector.connect(**config.myems_system_db)
1815
        cursor = cnx.cursor()
1816
1817
        cursor.execute(" SELECT name "
1818
                       " FROM tbl_tenants "
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.TENANT_NOT_FOUND')
1825
1826
        cursor.execute(" SELECT name "
1827
                       " FROM tbl_working_calendars "
1828
                       " WHERE id = %s ", (wcid,))
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.WORKING_CALENDAR_NOT_FOUND')
1834
1835
        cursor.execute(" SELECT id "
1836
                       " FROM tbl_tenants_working_calendars "
1837
                       " WHERE tenant_id = %s AND working_calendar_id = %s ", (id_, wcid))
1838
        if cursor.fetchone() is None:
1839
            cursor.close()
1840
            cnx.close()
1841
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1842
                                   description='API.TENANT_WORKING_CALENDAR_RELATION_NOT_FOUND')
1843
1844
        cursor.execute(" DELETE FROM tbl_tenants_working_calendars "
1845
                       " WHERE tenant_id = %s AND working_calendar_id = %s ", (id_, wcid))
1846
        cnx.commit()
1847
1848
        cursor.close()
1849
        cnx.close()
1850
1851
        resp.status = falcon.HTTP_204
1852
1853
1854 View Code Duplication
class TenantCommandCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1855
    def __init__(self):
1856
        pass
1857
1858
    @staticmethod
1859
    def on_options(req, resp, id_):
1860
        _ = req
1861
        resp.status = falcon.HTTP_200
1862
        _ = id_
1863
1864
    @staticmethod
1865
    def on_get(req, resp, id_):
1866
        if 'API-KEY' not in req.headers or \
1867
                not isinstance(req.headers['API-KEY'], str) or \
1868
                len(str.strip(req.headers['API-KEY'])) == 0:
1869
            access_control(req)
1870
        else:
1871
            api_key_control(req)
1872
        if not id_.isdigit() or int(id_) <= 0:
1873
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1874
                                   description='API.INVALID_TENANT_ID')
1875
1876
        cnx = mysql.connector.connect(**config.myems_system_db)
1877
        cursor = cnx.cursor()
1878
1879
        cursor.execute(" SELECT name "
1880
                       " FROM tbl_tenants "
1881
                       " WHERE id = %s ", (id_,))
1882
        if cursor.fetchone() is None:
1883
            cursor.close()
1884
            cnx.close()
1885
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1886
                                   description='API.TENANT_NOT_FOUND')
1887
1888
        query = (" SELECT c.id, c.name, c.uuid "
1889
                 " FROM tbl_tenants t, tbl_tenants_commands tc, tbl_commands c "
1890
                 " WHERE tc.tenant_id = t.id AND c.id = tc.command_id AND t.id = %s "
1891
                 " ORDER BY c.id ")
1892
        cursor.execute(query, (id_,))
1893
        rows = cursor.fetchall()
1894
1895
        result = list()
1896
        if rows is not None and len(rows) > 0:
1897
            for row in rows:
1898
                meta_result = {"id": row[0],
1899
                               "name": row[1],
1900
                               "uuid": row[2]}
1901
                result.append(meta_result)
1902
1903
        resp.text = json.dumps(result)
1904
1905
    @staticmethod
1906
    @user_logger
1907
    def on_post(req, resp, id_):
1908
        """Handles POST requests"""
1909
        admin_control(req)
1910
        try:
1911
            raw_json = req.stream.read().decode('utf-8')
1912
        except Exception as ex:
1913
            print(str(ex))
1914
            raise falcon.HTTPError(status=falcon.HTTP_400,
1915
                                   title='API.BAD_REQUEST',
1916
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1917
1918
        if not id_.isdigit() or int(id_) <= 0:
1919
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1920
                                   description='API.INVALID_TENANT_ID')
1921
1922
        new_values = json.loads(raw_json)
1923
1924
        if 'command_id' not in new_values['data'].keys() or \
1925
                not isinstance(new_values['data']['command_id'], int) or \
1926
                new_values['data']['command_id'] <= 0:
1927
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1928
                                   description='API.INVALID_COMMAND_ID')
1929
        command_id = new_values['data']['command_id']
1930
1931
        cnx = mysql.connector.connect(**config.myems_system_db)
1932
        cursor = cnx.cursor()
1933
1934
        cursor.execute(" SELECT name "
1935
                       " from tbl_tenants "
1936
                       " WHERE id = %s ", (id_,))
1937
        if cursor.fetchone() is None:
1938
            cursor.close()
1939
            cnx.close()
1940
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1941
                                   description='API.TENANT_NOT_FOUND')
1942
1943
        cursor.execute(" SELECT name "
1944
                       " FROM tbl_commands "
1945
                       " WHERE id = %s ", (command_id,))
1946
        if cursor.fetchone() is None:
1947
            cursor.close()
1948
            cnx.close()
1949
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1950
                                   description='API.COMMAND_NOT_FOUND')
1951
1952
        query = (" SELECT id "
1953
                 " FROM tbl_tenants_commands "
1954
                 " WHERE tenant_id = %s AND command_id = %s")
1955
        cursor.execute(query, (id_, command_id,))
1956
        if cursor.fetchone() is not None:
1957
            cursor.close()
1958
            cnx.close()
1959
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1960
                                   description='API.TENANT_COMMAND_RELATION_EXISTS')
1961
1962
        add_row = (" INSERT INTO tbl_tenants_commands (tenant_id, command_id) "
1963
                   " VALUES (%s, %s) ")
1964
        cursor.execute(add_row, (id_, command_id,))
1965
        cnx.commit()
1966
        cursor.close()
1967
        cnx.close()
1968
1969
        resp.status = falcon.HTTP_201
1970
        resp.location = '/tenants/' + str(id_) + '/commands/' + str(command_id)
1971
1972
1973
class TenantCommandItem:
1974
    def __init__(self):
1975
        pass
1976
1977
    @staticmethod
1978
    def on_options(req, resp, id_, cid):
1979
        _ = req
1980
        resp.status = falcon.HTTP_200
1981
        _ = id_
1982
1983
    @staticmethod
1984
    @user_logger
1985
    def on_delete(req, resp, id_, cid):
1986
        admin_control(req)
1987
        if not id_.isdigit() or int(id_) <= 0:
1988
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1989
                                   description='API.INVALID_TENANT_ID')
1990
1991
        if not cid.isdigit() or int(cid) <= 0:
1992
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1993
                                   description='API.INVALID_COMMAND_ID')
1994
1995
        cnx = mysql.connector.connect(**config.myems_system_db)
1996
        cursor = cnx.cursor()
1997
1998
        cursor.execute(" SELECT name "
1999
                       " FROM tbl_tenants "
2000
                       " WHERE id = %s ", (id_,))
2001
        if cursor.fetchone() is None:
2002
            cursor.close()
2003
            cnx.close()
2004
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2005
                                   description='API.TENANT_NOT_FOUND')
2006
2007
        cursor.execute(" SELECT name "
2008
                       " FROM tbl_commands "
2009
                       " WHERE id = %s ", (cid,))
2010
        if cursor.fetchone() is None:
2011
            cursor.close()
2012
            cnx.close()
2013
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2014
                                   description='API.COMMAND_NOT_FOUND')
2015
2016
        cursor.execute(" SELECT id "
2017
                       " FROM tbl_tenants_commands "
2018
                       " WHERE tenant_id = %s AND command_id = %s ", (id_, cid))
2019
        if cursor.fetchone() is None:
2020
            cursor.close()
2021
            cnx.close()
2022
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2023
                                   description='API.TENANT_COMMAND_RELATION_NOT_FOUND')
2024
2025
        cursor.execute(" DELETE FROM tbl_tenants_commands WHERE tenant_id = %s AND command_id = %s ", (id_, cid))
2026
        cnx.commit()
2027
2028
        cursor.close()
2029
        cnx.close()
2030
2031
        resp.status = falcon.HTTP_204
2032
2033
2034
class TenantExport:
2035
    def __init__(self):
2036
        pass
2037
2038
    @staticmethod
2039
    def on_options(req, resp, id_):
2040
        _ = req
2041
        resp.status = falcon.HTTP_200
2042
        _ = id_
2043
2044
    @staticmethod
2045
    def on_get(req, resp, id_):
2046
        if 'API-KEY' not in req.headers or \
2047
                not isinstance(req.headers['API-KEY'], str) or \
2048
                len(str.strip(req.headers['API-KEY'])) == 0:
2049
            access_control(req)
2050
        else:
2051
            api_key_control(req)
2052
        if not id_.isdigit() or int(id_) <= 0:
2053
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2054
                                   description='API.INVALID_TENANT_ID')
2055
2056
        cnx = mysql.connector.connect(**config.myems_system_db)
2057
        cursor = cnx.cursor()
2058
2059
        query = (" SELECT id, name, uuid "
2060
                 " FROM tbl_tenant_types ")
2061
        cursor.execute(query)
2062
        rows_tenant_types = cursor.fetchall()
2063
2064
        tenant_type_dict = dict()
2065
        if rows_tenant_types is not None and len(rows_tenant_types) > 0:
2066
            for row in rows_tenant_types:
2067
                tenant_type_dict[row[0]] = {"id": row[0],
2068
                                            "name": row[1],
2069
                                            "uuid": row[2]}
2070
2071
        query = (" SELECT id, name, uuid "
2072
                 " FROM tbl_contacts ")
2073
        cursor.execute(query)
2074
        rows_contacts = cursor.fetchall()
2075
2076
        contact_dict = dict()
2077
        if rows_contacts is not None and len(rows_contacts) > 0:
2078
            for row in rows_contacts:
2079
                contact_dict[row[0]] = {"id": row[0],
2080
                                        "name": row[1],
2081
                                        "uuid": row[2]}
2082
2083
        query = (" SELECT id, name, uuid "
2084
                 " FROM tbl_cost_centers ")
2085
        cursor.execute(query)
2086
        rows_cost_centers = cursor.fetchall()
2087
2088
        cost_center_dict = dict()
2089
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
2090
            for row in rows_cost_centers:
2091
                cost_center_dict[row[0]] = {"id": row[0],
2092
                                            "name": row[1],
2093
                                            "uuid": row[2]}
2094
2095
        query = (" SELECT id, name, uuid, "
2096
                 "        buildings, floors, rooms, area, tenant_type_id,"
2097
                 "        is_key_tenant, is_input_counted, "
2098
                 "        lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
2099
                 "        contact_id, cost_center_id, description "
2100
                 " FROM tbl_tenants "
2101
                 " WHERE id = %s ")
2102
        cursor.execute(query, (id_,))
2103
        row = cursor.fetchone()
2104
2105
        if row is None:
2106
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2107
                                   description='API.TENANT_NOT_FOUND')
2108
        else:
2109
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
2110
            if config.utc_offset[0] == '-':
2111
                timezone_offset = -timezone_offset
2112
2113
            meta_result = {"id": row[0],
2114
                           "name": row[1],
2115
                           "uuid": row[2],
2116
                           "buildings": row[3],
2117
                           "floors": row[4],
2118
                           "rooms": row[5],
2119
                           "area": row[6],
2120
                           "tenant_type": tenant_type_dict.get(row[7], None),
2121
                           "is_key_tenant": bool(row[8]),
2122
                           "is_input_counted": bool(row[9]),
2123
                           "lease_number": row[10],
2124
                           "lease_start_datetime": (row[11].replace(tzinfo=timezone.utc) +
2125
                                                    timedelta(minutes=timezone_offset)).isoformat()[0:19],
2126
                           "lease_end_datetime": (row[12].replace(tzinfo=timezone.utc) +
2127
                                                  timedelta(minutes=timezone_offset)).isoformat()[0:19],
2128
                           "is_in_lease": bool(row[13]),
2129
                           "contact": contact_dict.get(row[14], None),
2130
                           "cost_center": cost_center_dict.get(row[15], None),
2131
                           "description": row[16],
2132
                           "commands": None,
2133
                           "meters": None,
2134
                           "offline_meters": None,
2135
                           "virtual_meters": None,
2136
                           "points": None,
2137
                           "sensors": None,
2138
                           "working_calendars": None
2139
                           }
2140
            query = (" SELECT c.id, c.name, c.uuid "
2141
                     " FROM tbl_tenants t, tbl_tenants_commands tc, tbl_commands c "
2142
                     " WHERE tc.tenant_id = t.id AND c.id = tc.command_id AND t.id = %s "
2143
                     " ORDER BY c.id ")
2144
            cursor.execute(query, (id_,))
2145
            rows = cursor.fetchall()
2146
2147
            command_result = list()
2148
            if rows is not None and len(rows) > 0:
2149
                for row in rows:
2150
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
2151
                    command_result.append(result)
2152
                meta_result['commands'] = command_result
2153
            query = (" SELECT id, name, uuid "
2154
                     " FROM tbl_energy_categories ")
2155
            cursor.execute(query)
2156
            rows_energy_categories = cursor.fetchall()
2157
2158
            energy_category_dict = dict()
2159
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2160
                for row in rows_energy_categories:
2161
                    energy_category_dict[row[0]] = {"id": row[0],
2162
                                                    "name": row[1],
2163
                                                    "uuid": row[2]}
2164
2165
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2166
                     " FROM tbl_tenants t, tbl_tenants_meters tm, tbl_meters m "
2167
                     " WHERE tm.tenant_id = t.id AND m.id = tm.meter_id AND t.id = %s "
2168
                     " ORDER BY m.id ")
2169
            cursor.execute(query, (id_,))
2170
            rows = cursor.fetchall()
2171
2172
            meter_result = list()
2173
            if rows is not None and len(rows) > 0:
2174
                for row in rows:
2175
                    energy_category = energy_category_dict.get(row[3], None)
2176
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2177
                              "energy_category": energy_category}
2178
                    meter_result.append(result)
2179
                meta_result['meters'] = meter_result
2180
            query = (" SELECT id, name, uuid "
2181
                     " FROM tbl_energy_categories ")
2182
            cursor.execute(query)
2183
            rows_energy_categories = cursor.fetchall()
2184
2185
            energy_category_dict = dict()
2186
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2187
                for row in rows_energy_categories:
2188
                    energy_category_dict[row[0]] = {"id": row[0],
2189
                                                    "name": row[1],
2190
                                                    "uuid": row[2]}
2191
2192
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2193
                     " FROM tbl_tenants s, tbl_tenants_offline_meters sm, tbl_offline_meters m "
2194
                     " WHERE sm.tenant_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
2195
                     " ORDER BY m.id ")
2196
            cursor.execute(query, (id_,))
2197
            rows = cursor.fetchall()
2198
2199
            offlinemeter_result = list()
2200
            if rows is not None and len(rows) > 0:
2201
                for row in rows:
2202
                    energy_category = energy_category_dict.get(row[3], None)
2203
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2204
                              "energy_category": energy_category}
2205
                    offlinemeter_result.append(result)
2206
                meta_result['offline_meters'] = offlinemeter_result
2207
            query = (" SELECT id, name, uuid "
2208
                     " FROM tbl_energy_categories ")
2209
            cursor.execute(query)
2210
            rows_energy_categories = cursor.fetchall()
2211
2212
            energy_category_dict = dict()
2213
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2214
                for row in rows_energy_categories:
2215
                    energy_category_dict[row[0]] = {"id": row[0],
2216
                                                    "name": row[1],
2217
                                                    "uuid": row[2]}
2218
2219
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2220
                     " FROM tbl_tenants t, tbl_tenants_virtual_meters tm, tbl_virtual_meters m "
2221
                     " WHERE tm.tenant_id = t.id AND m.id = tm.virtual_meter_id AND t.id = %s "
2222
                     " ORDER BY m.id ")
2223
            cursor.execute(query, (id_,))
2224
            rows = cursor.fetchall()
2225
2226
            virtualmeter_result = list()
2227
            if rows is not None and len(rows) > 0:
2228
                for row in rows:
2229
                    energy_category = energy_category_dict.get(row[3], None)
2230
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2231
                              "energy_category": energy_category}
2232
                    virtualmeter_result.append(result)
2233
                meta_result['virtual_meters'] = virtualmeter_result
2234
            query = (" SELECT id, name, uuid "
2235
                     " FROM tbl_data_sources ")
2236
            cursor.execute(query)
2237
            rows_data_sources = cursor.fetchall()
2238
2239
            data_source_dict = dict()
2240
            if rows_data_sources is not None and len(rows_data_sources) > 0:
2241
                for row in rows_data_sources:
2242
                    data_source_dict[row[0]] = {"id": row[0],
2243
                                                "name": row[1],
2244
                                                "uuid": row[2]}
2245
2246
            query = (" SELECT p.id, p.name, p.data_source_id "
2247
                     " FROM tbl_tenants t, tbl_tenants_points tp, tbl_points p "
2248
                     " WHERE tp.tenant_id = t.id AND p.id = tp.point_id AND t.id = %s "
2249
                     " ORDER BY p.id ")
2250
            cursor.execute(query, (id_,))
2251
            rows = cursor.fetchall()
2252
2253
            point_result = list()
2254
            if rows is not None and len(rows) > 0:
2255
                for row in rows:
2256
                    data_source = data_source_dict.get(row[2], None)
2257
                    result = {"id": row[0], "name": row[1], "data_source": data_source}
2258
                    point_result.append(result)
2259
                meta_result['points'] = point_result
2260
            query = (" SELECT s.id, s.name, s.uuid "
2261
                     " FROM tbl_tenants t, tbl_tenants_sensors ts, tbl_sensors s "
2262
                     " WHERE ts.tenant_id = t.id AND s.id = ts.sensor_id AND t.id = %s "
2263
                     " ORDER BY s.id ")
2264
            cursor.execute(query, (id_,))
2265
            rows = cursor.fetchall()
2266
2267
            sensor_result = list()
2268
            if rows is not None and len(rows) > 0:
2269
                for row in rows:
2270
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
2271
                    sensor_result.append(result)
2272
                meta_result['sensors'] = sensor_result
2273
            query = (" SELECT wc.id, wc.name, wc.description "
2274
                     " FROM tbl_tenants t, tbl_tenants_working_calendars twc, tbl_working_calendars wc "
2275
                     " WHERE twc.tenant_id = t.id AND wc.id = twc.working_calendar_id AND t.id = %s "
2276
                     " ORDER BY wc.id ")
2277
            cursor.execute(query, (id_,))
2278
            rows = cursor.fetchall()
2279
2280
            workingcalendars_result = list()
2281
            if rows is not None and len(rows) > 0:
2282
                for row in rows:
2283
                    result = {"id": row[0], "name": row[1], "description": row[2]}
2284
                    workingcalendars_result.append(result)
2285
                meta_result['working_calendars'] = workingcalendars_result
2286
2287
        cursor.close()
2288
        cnx.close()
2289
        resp.text = json.dumps(meta_result)
2290
2291
2292
class TenantImport:
2293
    def __init__(self):
2294
        pass
2295
2296
    @staticmethod
2297
    def on_options(req, resp):
2298
        _ = req
2299
        resp.status = falcon.HTTP_200
2300
2301
    @staticmethod
2302
    @user_logger
2303
    def on_post(req, resp):
2304
        """Handles POST requests"""
2305
        admin_control(req)
2306
        try:
2307
            raw_json = req.stream.read().decode('utf-8')
2308
        except Exception as ex:
2309
            print(str(ex))
2310
            raise falcon.HTTPError(status=falcon.HTTP_400,
2311
                                   title='API.BAD_REQUEST',
2312
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2313
2314
        new_values = json.loads(raw_json)
2315
2316
        if 'name' not in new_values.keys() or \
2317
                not isinstance(new_values['name'], str) or \
2318
                len(str.strip(new_values['name'])) == 0:
2319
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2320
                                   description='API.INVALID_TENANT_NAME')
2321
        name = str.strip(new_values['name'])
2322
2323
        if 'buildings' not in new_values.keys() or \
2324
                not isinstance(new_values['buildings'], str) or \
2325
                len(str.strip(new_values['buildings'])) == 0:
2326
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2327
                                   description='API.INVALID_BUILDINGS_VALUE')
2328
        buildings = str.strip(new_values['buildings'])
2329
2330
        if 'floors' not in new_values.keys() or \
2331
                not isinstance(new_values['floors'], str) or \
2332
                len(str.strip(new_values['floors'])) == 0:
2333
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2334
                                   description='API.INVALID_FLOORS_VALUE')
2335
        floors = str.strip(new_values['floors'])
2336
2337
        if 'rooms' not in new_values.keys() or \
2338
                not isinstance(new_values['rooms'], str) or \
2339
                len(str.strip(new_values['rooms'])) == 0:
2340
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2341
                                   description='API.INVALID_ROOMS_VALUE')
2342
        rooms = str.strip(new_values['rooms'])
2343
2344
        if 'area' not in new_values.keys() or \
2345
                not (isinstance(new_values['area'], float) or
2346
                     isinstance(new_values['area'], int)) or \
2347
                new_values['area'] <= 0.0:
2348
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2349
                                   description='API.INVALID_AREA_VALUE')
2350
        area = new_values['area']
2351
2352
        if 'id' not in new_values['tenant_type'].keys() or \
2353
                not isinstance(new_values['tenant_type']['id'], int) or \
2354
                new_values['tenant_type']['id'] <= 0:
2355
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2356
                                   description='API.INVALID_TENANT_TYPE_ID')
2357
        tenant_type_id = new_values['tenant_type']['id']
2358
2359
        if 'is_input_counted' not in new_values.keys() or \
2360
                not isinstance(new_values['is_input_counted'], bool):
2361
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2362
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
2363
        is_input_counted = new_values['is_input_counted']
2364
2365
        if 'is_key_tenant' not in new_values.keys() or \
2366
                not isinstance(new_values['is_key_tenant'], bool):
2367
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2368
                                   description='API.INVALID_IS_KEY_TENANT_VALUE')
2369
        is_key_tenant = new_values['is_key_tenant']
2370
2371
        if 'lease_number' not in new_values.keys() or \
2372
                not isinstance(new_values['lease_number'], str) or \
2373
                len(str.strip(new_values['lease_number'])) == 0:
2374
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2375
                                   description='API.INVALID_LEASE_NUMBER_VALUE')
2376
        lease_number = str.strip(new_values['lease_number'])
2377
2378
        if 'is_in_lease' not in new_values.keys() or \
2379
                not isinstance(new_values['is_in_lease'], bool):
2380
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2381
                                   description='API.INVALID_IS_IN_LEASE_VALUE')
2382
        is_in_lease = new_values['is_in_lease']
2383
2384
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
2385
        if config.utc_offset[0] == '-':
2386
            timezone_offset = -timezone_offset
2387
2388
        # todo: validate datetime values
2389
        lease_start_datetime_utc = datetime.strptime(new_values['lease_start_datetime'],
2390
                                                     '%Y-%m-%dT%H:%M:%S')
2391
        lease_start_datetime_utc = lease_start_datetime_utc.replace(tzinfo=timezone.utc)
2392
        lease_start_datetime_utc -= timedelta(minutes=timezone_offset)
2393
2394
        lease_end_datetime_utc = datetime.strptime(new_values['lease_end_datetime'],
2395
                                                   '%Y-%m-%dT%H:%M:%S')
2396
        lease_end_datetime_utc = lease_end_datetime_utc.replace(tzinfo=timezone.utc)
2397
        lease_end_datetime_utc -= timedelta(minutes=timezone_offset)
2398
2399
        if 'id' not in new_values['contact'].keys() or \
2400
                not isinstance(new_values['contact']['id'], int) or \
2401
                new_values['contact']['id'] <= 0:
2402
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2403
                                   description='API.INVALID_CONTACT_ID')
2404
        contact_id = new_values['contact']['id']
2405
2406
        if 'id' not in new_values['cost_center'].keys() or \
2407
                not isinstance(new_values['cost_center']['id'], int) or \
2408
                new_values['cost_center']['id'] <= 0:
2409
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2410
                                   description='API.INVALID_COST_CENTER_ID')
2411
        cost_center_id = new_values['cost_center']['id']
2412
2413
        if 'description' in new_values.keys() and \
2414
                new_values['description'] is not None and \
2415
                len(str(new_values['description'])) > 0:
2416
            description = str.strip(new_values['description'])
2417
        else:
2418
            description = None
2419
2420
        cnx = mysql.connector.connect(**config.myems_system_db)
2421
        cursor = cnx.cursor()
2422
2423
        cursor.execute(" SELECT name "
2424
                       " FROM tbl_tenants "
2425
                       " WHERE name = %s ", (name,))
2426
        if cursor.fetchone() is not None:
2427
            cursor.close()
2428
            cnx.close()
2429
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2430
                                   description='API.TENANT_NAME_IS_ALREADY_IN_USE')
2431
2432
        cursor.execute(" SELECT name "
2433
                       " FROM tbl_tenant_types "
2434
                       " WHERE id = %s ",
2435
                       (tenant_type_id,))
2436
        if cursor.fetchone() is None:
2437
            cursor.close()
2438
            cnx.close()
2439
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2440
                                   description='API.TENANT_TYPE_NOT_FOUND')
2441
2442
        cursor.execute(" SELECT name "
2443
                       " FROM tbl_contacts "
2444
                       " WHERE id = %s ",
2445
                       (new_values['contact']['id'],))
2446
        row = cursor.fetchone()
2447
        if row is None:
2448
            cursor.close()
2449
            cnx.close()
2450
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2451
                                   description='API.CONTACT_NOT_FOUND')
2452
2453
        cursor.execute(" SELECT name "
2454
                       " FROM tbl_cost_centers "
2455
                       " WHERE id = %s ",
2456
                       (new_values['cost_center']['id'],))
2457
        row = cursor.fetchone()
2458
        if row is None:
2459
            cursor.close()
2460
            cnx.close()
2461
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2462
                                   description='API.COST_CENTER_NOT_FOUND')
2463
2464
        add_values = (" INSERT INTO tbl_tenants "
2465
                      "    (name, uuid, buildings, floors, rooms, area, tenant_type_id, "
2466
                      "     is_input_counted, is_key_tenant, "
2467
                      "     lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
2468
                      "     contact_id, cost_center_id, description) "
2469
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
2470
        cursor.execute(add_values, (name,
2471
                                    str(uuid.uuid4()),
2472
                                    buildings,
2473
                                    floors,
2474
                                    rooms,
2475
                                    area,
2476
                                    tenant_type_id,
2477
                                    is_input_counted,
2478
                                    is_key_tenant,
2479
                                    lease_number,
2480
                                    lease_start_datetime_utc,
2481
                                    lease_end_datetime_utc,
2482
                                    is_in_lease,
2483
                                    contact_id,
2484
                                    cost_center_id,
2485
                                    description))
2486
        new_id = cursor.lastrowid
2487
        if new_values['commands'] is not None and len(new_values['commands']) > 0:
2488
            for command in new_values['commands']:
2489
                cursor.execute(" SELECT name "
2490
                               " FROM tbl_commands "
2491
                               " WHERE id = %s ", (command['id'],))
2492
                if cursor.fetchone() is None:
2493
                    cursor.close()
2494
                    cnx.close()
2495
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2496
                                           description='API.COMMAND_NOT_FOUND')
2497
2498
                query = (" SELECT id "
2499
                         " FROM tbl_tenants_commands "
2500
                         " WHERE tenant_id = %s AND command_id = %s")
2501
                cursor.execute(query, (new_id, command['id'],))
2502
                if cursor.fetchone() is not None:
2503
                    cursor.close()
2504
                    cnx.close()
2505
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2506
                                           description='API.TENANT_COMMAND_RELATION_EXISTS')
2507
2508
                add_row = (" INSERT INTO tbl_tenants_commands (tenant_id, command_id) "
2509
                           " VALUES (%s, %s) ")
2510
                cursor.execute(add_row, (new_id, command['id'],))
2511
        if new_values['meters'] is not None and len(new_values['meters']) > 0:
2512
            for meter in new_values['meters']:
2513
                cursor.execute(" SELECT name "
2514
                               " FROM tbl_meters "
2515
                               " WHERE id = %s ", (meter['id'],))
2516
                if cursor.fetchone() is None:
2517
                    cursor.close()
2518
                    cnx.close()
2519
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2520
                                           description='API.METER_NOT_FOUND')
2521
2522
                query = (" SELECT id "
2523
                         " FROM tbl_tenants_meters "
2524
                         " WHERE tenant_id = %s AND meter_id = %s")
2525
                cursor.execute(query, (new_id, meter['id'],))
2526
                if cursor.fetchone() is not None:
2527
                    cursor.close()
2528
                    cnx.close()
2529
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2530
                                           description='API.TENANT_METER_RELATION_EXISTS')
2531
2532
                add_row = (" INSERT INTO tbl_tenants_meters (tenant_id, meter_id) "
2533
                           " VALUES (%s, %s) ")
2534
                cursor.execute(add_row, (new_id, meter['id'],))
2535
        if new_values['offline_meters'] is not None and len(new_values['offline_meters']) > 0:
2536
            for offline_meter in new_values['offline_meters']:
2537
                cursor.execute(" SELECT name "
2538
                               " FROM tbl_offline_meters "
2539
                               " WHERE id = %s ", (offline_meter['id'],))
2540
                if cursor.fetchone() is None:
2541
                    cursor.close()
2542
                    cnx.close()
2543
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2544
                                           description='API.OFFLINE_METER_NOT_FOUND')
2545
2546
                query = (" SELECT id "
2547
                         " FROM tbl_tenants_offline_meters "
2548
                         " WHERE tenant_id = %s AND offline_meter_id = %s")
2549
                cursor.execute(query, (new_id, offline_meter['id'],))
2550
                if cursor.fetchone() is not None:
2551
                    cursor.close()
2552
                    cnx.close()
2553
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2554
                                           description='API.TENANT_OFFLINE_METER_RELATION_EXISTS')
2555
2556
                add_row = (" INSERT INTO tbl_tenants_offline_meters (tenant_id, offline_meter_id) "
2557
                           " VALUES (%s, %s) ")
2558
                cursor.execute(add_row, (new_id, offline_meter['id'],))
2559
        if new_values['virtual_meters'] is not None and len(new_values['virtual_meters']) > 0:
2560
            for virtual_meter in new_values['virtual_meters']:
2561
                cursor.execute(" SELECT name "
2562
                               " FROM tbl_virtual_meters "
2563
                               " WHERE id = %s ", (virtual_meter['id'],))
2564
                if cursor.fetchone() is None:
2565
                    cursor.close()
2566
                    cnx.close()
2567
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2568
                                           description='API.VIRTUAL_METER_NOT_FOUND')
2569
2570
                query = (" SELECT id "
2571
                         " FROM tbl_tenants_virtual_meters "
2572
                         " WHERE tenant_id = %s AND virtual_meter_id = %s")
2573
                cursor.execute(query, (new_id, virtual_meter['id'],))
2574
                if cursor.fetchone() is not None:
2575
                    cursor.close()
2576
                    cnx.close()
2577
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2578
                                           description='API.TENANT_VIRTUAL_METER_RELATION_EXISTS')
2579
2580
                add_row = (" INSERT INTO tbl_tenants_virtual_meters (tenant_id, virtual_meter_id) "
2581
                           " VALUES (%s, %s) ")
2582
                cursor.execute(add_row, (new_id, virtual_meter['id'],))
2583
        if new_values['points'] is not None and len(new_values['points']) > 0:
2584
            for point in new_values['points']:
2585
                cursor.execute(" SELECT name "
2586
                               " FROM tbl_points "
2587
                               " WHERE id = %s ", (point['id'],))
2588
                if cursor.fetchone() is None:
2589
                    cursor.close()
2590
                    cnx.close()
2591
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2592
                                           description='API.POINT_NOT_FOUND')
2593
2594
                query = (" SELECT id "
2595
                         " FROM tbl_tenants_points "
2596
                         " WHERE tenant_id = %s AND point_id = %s")
2597
                cursor.execute(query, (new_id, point['id'],))
2598
                if cursor.fetchone() is not None:
2599
                    cursor.close()
2600
                    cnx.close()
2601
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2602
                                           description='API.TENANT_POINT_RELATION_EXISTS')
2603
2604
                add_row = (" INSERT INTO tbl_tenants_points (tenant_id, point_id) "
2605
                           " VALUES (%s, %s) ")
2606
                cursor.execute(add_row, (new_id, point['id'],))
2607
        if new_values['sensors'] is not None and len(new_values['sensors']) > 0:
2608
            for sensor in new_values['sensors']:
2609
                cursor.execute(" SELECT name "
2610
                               " FROM tbl_sensors "
2611
                               " WHERE id = %s ", (sensor['id'],))
2612
                if cursor.fetchone() is None:
2613
                    cursor.close()
2614
                    cnx.close()
2615
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2616
                                           description='API.SENSOR_NOT_FOUND')
2617
2618
                query = (" SELECT id "
2619
                         " FROM tbl_tenants_sensors "
2620
                         " WHERE tenant_id = %s AND sensor_id = %s")
2621
                cursor.execute(query, (new_id, sensor['id'],))
2622
                if cursor.fetchone() is not None:
2623
                    cursor.close()
2624
                    cnx.close()
2625
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2626
                                           description='API.TENANT_SENSOR_RELATION_EXISTS')
2627
2628
                add_row = (" INSERT INTO tbl_tenants_sensors (tenant_id, sensor_id) "
2629
                           " VALUES (%s, %s) ")
2630
                cursor.execute(add_row, (new_id, sensor['id'],))
2631
        if new_values['working_calendars'] is not None and len(new_values['working_calendars']) > 0:
2632
            for working_calendar in new_values['working_calendars']:
2633
                cursor.execute(" SELECT name "
2634
                               " FROM tbl_working_calendars "
2635
                               " WHERE id = %s ", (working_calendar['id'],))
2636
                if cursor.fetchone() is None:
2637
                    cursor.close()
2638
                    cnx.close()
2639
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2640
                                           description='API.WORKING_CALENDAR_NOT_FOUND')
2641
2642
                query = (" SELECT id "
2643
                         " FROM tbl_tenants_working_calendars "
2644
                         " WHERE tenant_id = %s AND working_calendar_id = %s")
2645
                cursor.execute(query, (new_id, working_calendar['id'],))
2646
                if cursor.fetchone() is not None:
2647
                    cursor.close()
2648
                    cnx.close()
2649
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2650
                                           description='API.TENANT_WORKING_CALENDAR_RELATION_EXISTS')
2651
2652
                add_row = (" INSERT INTO tbl_tenants_working_calendars (tenant_id, working_calendar_id) "
2653
                           " VALUES (%s, %s) ")
2654
                cursor.execute(add_row, (new_id, working_calendar['id'],))
2655
        cnx.commit()
2656
        cursor.close()
2657
        cnx.close()
2658
2659
        resp.status = falcon.HTTP_201
2660
        resp.location = '/tenants/' + str(new_id)
2661
2662
2663
class TenantClone:
2664
    def __init__(self):
2665
        pass
2666
2667
    @staticmethod
2668
    def on_options(req, resp, id_):
2669
        _ = req
2670
        resp.status = falcon.HTTP_200
2671
        _ = id_
2672
2673
    @staticmethod
2674
    @user_logger
2675
    def on_post(req, resp, id_):
2676
        admin_control(req)
2677
        if not id_.isdigit() or int(id_) <= 0:
2678
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2679
                                   description='API.INVALID_TENANT_ID')
2680
2681
        cnx = mysql.connector.connect(**config.myems_system_db)
2682
        cursor = cnx.cursor()
2683
2684
        query = (" SELECT id, name, uuid "
2685
                 " FROM tbl_tenant_types ")
2686
        cursor.execute(query)
2687
        rows_tenant_types = cursor.fetchall()
2688
2689
        tenant_type_dict = dict()
2690
        if rows_tenant_types is not None and len(rows_tenant_types) > 0:
2691
            for row in rows_tenant_types:
2692
                tenant_type_dict[row[0]] = {"id": row[0],
2693
                                            "name": row[1],
2694
                                            "uuid": row[2]}
2695
2696
        query = (" SELECT id, name, uuid "
2697
                 " FROM tbl_contacts ")
2698
        cursor.execute(query)
2699
        rows_contacts = cursor.fetchall()
2700
2701
        contact_dict = dict()
2702
        if rows_contacts is not None and len(rows_contacts) > 0:
2703
            for row in rows_contacts:
2704
                contact_dict[row[0]] = {"id": row[0],
2705
                                        "name": row[1],
2706
                                        "uuid": row[2]}
2707
2708
        query = (" SELECT id, name, uuid "
2709
                 " FROM tbl_cost_centers ")
2710
        cursor.execute(query)
2711
        rows_cost_centers = cursor.fetchall()
2712
2713
        cost_center_dict = dict()
2714
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
2715
            for row in rows_cost_centers:
2716
                cost_center_dict[row[0]] = {"id": row[0],
2717
                                            "name": row[1],
2718
                                            "uuid": row[2]}
2719
2720
        query = (" SELECT id, name, uuid, "
2721
                 "        buildings, floors, rooms, area, tenant_type_id,"
2722
                 "        is_key_tenant, is_input_counted, "
2723
                 "        lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
2724
                 "        contact_id, cost_center_id, description "
2725
                 " FROM tbl_tenants "
2726
                 " WHERE id = %s ")
2727
        cursor.execute(query, (id_,))
2728
        row = cursor.fetchone()
2729
2730
        if row is None:
2731
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2732
                                   description='API.TENANT_NOT_FOUND')
2733
        else:
2734
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
2735
            if config.utc_offset[0] == '-':
2736
                timezone_offset = -timezone_offset
2737
2738
            meta_result = {"id": row[0],
2739
                           "name": row[1],
2740
                           "uuid": row[2],
2741
                           "buildings": row[3],
2742
                           "floors": row[4],
2743
                           "rooms": row[5],
2744
                           "area": row[6],
2745
                           "tenant_type": tenant_type_dict.get(row[7], None),
2746
                           "is_key_tenant": bool(row[8]),
2747
                           "is_input_counted": bool(row[9]),
2748
                           "lease_number": row[10],
2749
                           "lease_start_datetime": (row[11].replace(tzinfo=timezone.utc) +
2750
                                                    timedelta(minutes=timezone_offset)).isoformat()[0:19],
2751
                           "lease_end_datetime": (row[12].replace(tzinfo=timezone.utc) +
2752
                                                  timedelta(minutes=timezone_offset)).isoformat()[0:19],
2753
                           "is_in_lease": bool(row[13]),
2754
                           "contact": contact_dict.get(row[14], None),
2755
                           "cost_center": cost_center_dict.get(row[15], None),
2756
                           "description": row[16],
2757
                           "commands": None,
2758
                           "meters": None,
2759
                           "offline_meters": None,
2760
                           "virtual_meters": None,
2761
                           "points": None,
2762
                           "sensors": None,
2763
                           "working_calendars": None
2764
                           }
2765
            query = (" SELECT c.id, c.name, c.uuid "
2766
                     " FROM tbl_tenants t, tbl_tenants_commands tc, tbl_commands c "
2767
                     " WHERE tc.tenant_id = t.id AND c.id = tc.command_id AND t.id = %s "
2768
                     " ORDER BY c.id ")
2769
            cursor.execute(query, (id_,))
2770
            rows = cursor.fetchall()
2771
2772
            command_result = list()
2773
            if rows is not None and len(rows) > 0:
2774
                for row in rows:
2775
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
2776
                    command_result.append(result)
2777
                meta_result['commands'] = command_result
2778
            query = (" SELECT id, name, uuid "
2779
                     " FROM tbl_energy_categories ")
2780
            cursor.execute(query)
2781
            rows_energy_categories = cursor.fetchall()
2782
2783
            energy_category_dict = dict()
2784
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2785
                for row in rows_energy_categories:
2786
                    energy_category_dict[row[0]] = {"id": row[0],
2787
                                                    "name": row[1],
2788
                                                    "uuid": row[2]}
2789
2790
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2791
                     " FROM tbl_tenants t, tbl_tenants_meters tm, tbl_meters m "
2792
                     " WHERE tm.tenant_id = t.id AND m.id = tm.meter_id AND t.id = %s "
2793
                     " ORDER BY m.id ")
2794
            cursor.execute(query, (id_,))
2795
            rows = cursor.fetchall()
2796
2797
            meter_result = list()
2798
            if rows is not None and len(rows) > 0:
2799
                for row in rows:
2800
                    energy_category = energy_category_dict.get(row[3], None)
2801
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2802
                              "energy_category": energy_category}
2803
                    meter_result.append(result)
2804
                meta_result['meters'] = meter_result
2805
            query = (" SELECT id, name, uuid "
2806
                     " FROM tbl_energy_categories ")
2807
            cursor.execute(query)
2808
            rows_energy_categories = cursor.fetchall()
2809
2810
            energy_category_dict = dict()
2811
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2812
                for row in rows_energy_categories:
2813
                    energy_category_dict[row[0]] = {"id": row[0],
2814
                                                    "name": row[1],
2815
                                                    "uuid": row[2]}
2816
2817
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2818
                     " FROM tbl_tenants s, tbl_tenants_offline_meters sm, tbl_offline_meters m "
2819
                     " WHERE sm.tenant_id = s.id AND m.id = sm.offline_meter_id AND s.id = %s "
2820
                     " ORDER BY m.id ")
2821
            cursor.execute(query, (id_,))
2822
            rows = cursor.fetchall()
2823
2824
            offlinemeter_result = list()
2825
            if rows is not None and len(rows) > 0:
2826
                for row in rows:
2827
                    energy_category = energy_category_dict.get(row[3], None)
2828
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2829
                              "energy_category": energy_category}
2830
                    offlinemeter_result.append(result)
2831
                meta_result['offline_meters'] = offlinemeter_result
2832
            query = (" SELECT id, name, uuid "
2833
                     " FROM tbl_energy_categories ")
2834
            cursor.execute(query)
2835
            rows_energy_categories = cursor.fetchall()
2836
2837
            energy_category_dict = dict()
2838
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2839
                for row in rows_energy_categories:
2840
                    energy_category_dict[row[0]] = {"id": row[0],
2841
                                                    "name": row[1],
2842
                                                    "uuid": row[2]}
2843
2844
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id "
2845
                     " FROM tbl_tenants t, tbl_tenants_virtual_meters tm, tbl_virtual_meters m "
2846
                     " WHERE tm.tenant_id = t.id AND m.id = tm.virtual_meter_id AND t.id = %s "
2847
                     " ORDER BY m.id ")
2848
            cursor.execute(query, (id_,))
2849
            rows = cursor.fetchall()
2850
2851
            virtualmeter_result = list()
2852
            if rows is not None and len(rows) > 0:
2853
                for row in rows:
2854
                    energy_category = energy_category_dict.get(row[3], None)
2855
                    result = {"id": row[0], "name": row[1], "uuid": row[2],
2856
                              "energy_category": energy_category}
2857
                    virtualmeter_result.append(result)
2858
                meta_result['virtual_meters'] = virtualmeter_result
2859
            query = (" SELECT id, name, uuid "
2860
                     " FROM tbl_data_sources ")
2861
            cursor.execute(query)
2862
            rows_data_sources = cursor.fetchall()
2863
2864
            data_source_dict = dict()
2865
            if rows_data_sources is not None and len(rows_data_sources) > 0:
2866
                for row in rows_data_sources:
2867
                    data_source_dict[row[0]] = {"id": row[0],
2868
                                                "name": row[1],
2869
                                                "uuid": row[2]}
2870
2871
            query = (" SELECT p.id, p.name, p.data_source_id "
2872
                     " FROM tbl_tenants t, tbl_tenants_points tp, tbl_points p "
2873
                     " WHERE tp.tenant_id = t.id AND p.id = tp.point_id AND t.id = %s "
2874
                     " ORDER BY p.id ")
2875
            cursor.execute(query, (id_,))
2876
            rows = cursor.fetchall()
2877
2878
            point_result = list()
2879
            if rows is not None and len(rows) > 0:
2880
                for row in rows:
2881
                    data_source = data_source_dict.get(row[2], None)
2882
                    result = {"id": row[0], "name": row[1], "data_source": data_source}
2883
                    point_result.append(result)
2884
                meta_result['points'] = point_result
2885
            query = (" SELECT s.id, s.name, s.uuid "
2886
                     " FROM tbl_tenants t, tbl_tenants_sensors ts, tbl_sensors s "
2887
                     " WHERE ts.tenant_id = t.id AND s.id = ts.sensor_id AND t.id = %s "
2888
                     " ORDER BY s.id ")
2889
            cursor.execute(query, (id_,))
2890
            rows = cursor.fetchall()
2891
2892
            sensor_result = list()
2893
            if rows is not None and len(rows) > 0:
2894
                for row in rows:
2895
                    result = {"id": row[0], "name": row[1], "uuid": row[2]}
2896
                    sensor_result.append(result)
2897
                meta_result['sensors'] = sensor_result
2898
            query = (" SELECT wc.id, wc.name, wc.description "
2899
                     " FROM tbl_tenants t, tbl_tenants_working_calendars twc, tbl_working_calendars wc "
2900
                     " WHERE twc.tenant_id = t.id AND wc.id = twc.working_calendar_id AND t.id = %s "
2901
                     " ORDER BY wc.id ")
2902
            cursor.execute(query, (id_,))
2903
            rows = cursor.fetchall()
2904
2905
            workingcalendars_result = list()
2906
            if rows is not None and len(rows) > 0:
2907
                for row in rows:
2908
                    result = {"id": row[0], "name": row[1], "description": row[2]}
2909
                    workingcalendars_result.append(result)
2910
                meta_result['working_calendars'] = workingcalendars_result
2911
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
2912
            if config.utc_offset[0] == '-':
2913
                timezone_offset = -timezone_offset
2914
            new_name = (str.strip(meta_result['name']) +
2915
                        (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
2916
            add_values = (" INSERT INTO tbl_tenants "
2917
                          "    (name, uuid, buildings, floors, rooms, area, tenant_type_id, "
2918
                          "     is_input_counted, is_key_tenant, "
2919
                          "     lease_number, lease_start_datetime_utc, lease_end_datetime_utc, is_in_lease, "
2920
                          "     contact_id, cost_center_id, description) "
2921
                          " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ")
2922
            cursor.execute(add_values, (new_name,
2923
                                        str(uuid.uuid4()),
2924
                                        meta_result['buildings'],
2925
                                        meta_result['floors'],
2926
                                        meta_result['rooms'],
2927
                                        meta_result['area'],
2928
                                        meta_result['tenant_type']['id'],
2929
                                        meta_result['is_input_counted'],
2930
                                        meta_result['is_key_tenant'],
2931
                                        meta_result['lease_number'],
2932
                                        meta_result['lease_start_datetime'],
2933
                                        meta_result['lease_end_datetime'],
2934
                                        meta_result['is_in_lease'],
2935
                                        meta_result['contact']['id'],
2936
                                        meta_result['cost_center']['id'],
2937
                                        meta_result['description']))
2938
            new_id = cursor.lastrowid
2939
            if meta_result['commands'] is not None and len(meta_result['commands']) > 0:
2940
                for command in meta_result['commands']:
2941
                    cursor.execute(" SELECT name "
2942
                                   " FROM tbl_commands "
2943
                                   " WHERE id = %s ", (command['id'],))
2944
                    if cursor.fetchone() is None:
2945
                        cursor.close()
2946
                        cnx.close()
2947
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2948
                                               description='API.COMMAND_NOT_FOUND')
2949
2950
                    query = (" SELECT id "
2951
                             " FROM tbl_tenants_commands "
2952
                             " WHERE tenant_id = %s AND command_id = %s")
2953
                    cursor.execute(query, (new_id, command['id'],))
2954
                    if cursor.fetchone() is not None:
2955
                        cursor.close()
2956
                        cnx.close()
2957
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2958
                                               description='API.TENANT_COMMAND_RELATION_EXISTS')
2959
2960
                    add_row = (" INSERT INTO tbl_tenants_commands (tenant_id, command_id) "
2961
                               " VALUES (%s, %s) ")
2962
                    cursor.execute(add_row, (new_id, command['id'],))
2963
            if meta_result['meters'] is not None and len(meta_result['meters']) > 0:
2964
                for meter in meta_result['meters']:
2965
                    cursor.execute(" SELECT name "
2966
                                   " FROM tbl_meters "
2967
                                   " WHERE id = %s ", (meter['id'],))
2968
                    if cursor.fetchone() is None:
2969
                        cursor.close()
2970
                        cnx.close()
2971
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2972
                                               description='API.METER_NOT_FOUND')
2973
2974
                    query = (" SELECT id "
2975
                             " FROM tbl_tenants_meters "
2976
                             " WHERE tenant_id = %s AND meter_id = %s")
2977
                    cursor.execute(query, (new_id, meter['id'],))
2978
                    if cursor.fetchone() is not None:
2979
                        cursor.close()
2980
                        cnx.close()
2981
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2982
                                               description='API.TENANT_METER_RELATION_EXISTS')
2983
2984
                    add_row = (" INSERT INTO tbl_tenants_meters (tenant_id, meter_id) "
2985
                               " VALUES (%s, %s) ")
2986
                    cursor.execute(add_row, (new_id, meter['id'],))
2987
            if meta_result['offline_meters'] is not None and len(meta_result['offline_meters']) > 0:
2988
                for offline_meter in meta_result['offline_meters']:
2989
                    cursor.execute(" SELECT name "
2990
                                   " FROM tbl_offline_meters "
2991
                                   " WHERE id = %s ", (offline_meter['id'],))
2992
                    if cursor.fetchone() is None:
2993
                        cursor.close()
2994
                        cnx.close()
2995
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2996
                                               description='API.OFFLINE_METER_NOT_FOUND')
2997
2998
                    query = (" SELECT id "
2999
                             " FROM tbl_tenants_offline_meters "
3000
                             " WHERE tenant_id = %s AND offline_meter_id = %s")
3001
                    cursor.execute(query, (new_id, offline_meter['id'],))
3002
                    if cursor.fetchone() is not None:
3003
                        cursor.close()
3004
                        cnx.close()
3005
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3006
                                               description='API.TENANT_OFFLINE_METER_RELATION_EXISTS')
3007
3008
                    add_row = (" INSERT INTO tbl_tenants_offline_meters (tenant_id, offline_meter_id) "
3009
                               " VALUES (%s, %s) ")
3010
                    cursor.execute(add_row, (new_id, offline_meter['id'],))
3011
            if meta_result['virtual_meters'] is not None and len(meta_result['virtual_meters']) > 0:
3012
                for virtual_meter in meta_result['virtual_meters']:
3013
                    cursor.execute(" SELECT name "
3014
                                   " FROM tbl_virtual_meters "
3015
                                   " WHERE id = %s ", (virtual_meter['id'],))
3016
                    if cursor.fetchone() is None:
3017
                        cursor.close()
3018
                        cnx.close()
3019
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3020
                                               description='API.VIRTUAL_METER_NOT_FOUND')
3021
3022
                    query = (" SELECT id "
3023
                             " FROM tbl_tenants_virtual_meters "
3024
                             " WHERE tenant_id = %s AND virtual_meter_id = %s")
3025
                    cursor.execute(query, (new_id, virtual_meter['id'],))
3026
                    if cursor.fetchone() is not None:
3027
                        cursor.close()
3028
                        cnx.close()
3029
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3030
                                               description='API.TENANT_VIRTUAL_METER_RELATION_EXISTS')
3031
3032
                    add_row = (" INSERT INTO tbl_tenants_virtual_meters (tenant_id, virtual_meter_id) "
3033
                               " VALUES (%s, %s) ")
3034
                    cursor.execute(add_row, (new_id, virtual_meter['id'],))
3035
            if meta_result['points'] is not None and len(meta_result['points']) > 0:
3036
                for point in meta_result['points']:
3037
                    cursor.execute(" SELECT name "
3038
                                   " FROM tbl_points "
3039
                                   " WHERE id = %s ", (point['id'],))
3040
                    if cursor.fetchone() is None:
3041
                        cursor.close()
3042
                        cnx.close()
3043
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3044
                                               description='API.POINT_NOT_FOUND')
3045
3046
                    query = (" SELECT id "
3047
                             " FROM tbl_tenants_points "
3048
                             " WHERE tenant_id = %s AND point_id = %s")
3049
                    cursor.execute(query, (new_id, point['id'],))
3050
                    if cursor.fetchone() is not None:
3051
                        cursor.close()
3052
                        cnx.close()
3053
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3054
                                               description='API.TENANT_POINT_RELATION_EXISTS')
3055
3056
                    add_row = (" INSERT INTO tbl_tenants_points (tenant_id, point_id) "
3057
                               " VALUES (%s, %s) ")
3058
                    cursor.execute(add_row, (new_id, point['id'],))
3059
            if meta_result['sensors'] is not None and len(meta_result['sensors']) > 0:
3060
                for sensor in meta_result['sensors']:
3061
                    cursor.execute(" SELECT name "
3062
                                   " FROM tbl_sensors "
3063
                                   " WHERE id = %s ", (sensor['id'],))
3064
                    if cursor.fetchone() is None:
3065
                        cursor.close()
3066
                        cnx.close()
3067
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3068
                                               description='API.SENSOR_NOT_FOUND')
3069
3070
                    query = (" SELECT id "
3071
                             " FROM tbl_tenants_sensors "
3072
                             " WHERE tenant_id = %s AND sensor_id = %s")
3073
                    cursor.execute(query, (new_id, sensor['id'],))
3074
                    if cursor.fetchone() is not None:
3075
                        cursor.close()
3076
                        cnx.close()
3077
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3078
                                               description='API.TENANT_SENSOR_RELATION_EXISTS')
3079
3080
                    add_row = (" INSERT INTO tbl_tenants_sensors (tenant_id, sensor_id) "
3081
                               " VALUES (%s, %s) ")
3082
                    cursor.execute(add_row, (new_id, sensor['id'],))
3083
            if meta_result['working_calendars'] is not None and len(meta_result['working_calendars']) > 0:
3084
                for working_calendar in meta_result['working_calendars']:
3085
                    cursor.execute(" SELECT name "
3086
                                   " FROM tbl_working_calendars "
3087
                                   " WHERE id = %s ", (working_calendar['id'],))
3088
                    if cursor.fetchone() is None:
3089
                        cursor.close()
3090
                        cnx.close()
3091
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3092
                                               description='API.WORKING_CALENDAR_NOT_FOUND')
3093
3094
                    query = (" SELECT id "
3095
                             " FROM tbl_tenants_working_calendars "
3096
                             " WHERE tenant_id = %s AND working_calendar_id = %s")
3097
                    cursor.execute(query, (new_id, working_calendar['id'],))
3098
                    if cursor.fetchone() is not None:
3099
                        cursor.close()
3100
                        cnx.close()
3101
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3102
                                               description='API.TENANT_WORKING_CALENDAR_RELATION_EXISTS')
3103
3104
                    add_row = (" INSERT INTO tbl_tenants_working_calendars (tenant_id, working_calendar_id) "
3105
                               " VALUES (%s, %s) ")
3106
                    cursor.execute(add_row, (new_id, working_calendar['id'],))
3107
            cnx.commit()
3108
            cursor.close()
3109
            cnx.close()
3110
3111
            resp.status = falcon.HTTP_201
3112
            resp.location = '/tenants/' + str(new_id)
3113