Issues (1577)

myems-api/reports/offlinemeterdaily.py (3 issues)

1
import re
2
import falcon
3
import simplejson as json
4
import mysql.connector
5
import config
6
from datetime import datetime, timedelta, timezone
7
from core.useractivity import access_control, api_key_control
8
from decimal import Decimal
9
10
11
class Reporting:
12
    def __init__(self):
13
        """"Initializes Reporting"""
14
        pass
15
16
    @staticmethod
17
    def on_options(req, resp):
18
        _ = req
19
        resp.status = falcon.HTTP_200
20
21
    ####################################################################################################################
22
    # PROCEDURES
23
    # Step 1: valid parameters
24
    # Step 2: query the offline meter
25
    # Step 3: query associated points
26
    # Step 4: query reporting period points trends
27
    # Step 5: query tariff data
28
    # Step 6: construct the report
29
    ####################################################################################################################
30
    @staticmethod
31
    def on_get(req, resp):
32
        if 'API-KEY' not in req.headers or \
33
                not isinstance(req.headers['API-KEY'], str) or \
34
                len(str.strip(req.headers['API-KEY'])) == 0:
35
            access_control(req)
36
        else:
37
            api_key_control(req)
38
        print(req.params)
39
        offline_meter_id = req.params.get('offlinemeterid')
40
        offline_meter_uuid = req.params.get('offlinemeteruuid')
41
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
42
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
43
44
        ################################################################################################################
45
        # Step 1: valid parameters
46
        ################################################################################################################
47
        if offline_meter_id is None and offline_meter_uuid is None:
48
            raise falcon.HTTPError(status=falcon.HTTP_400,
49
                                   title='API.BAD_REQUEST',
50
                                   description='API.INVALID_OFFLINE_METER_ID')
51
52
        if offline_meter_id is not None:
53
            offline_meter_id = str.strip(offline_meter_id)
54
            if not offline_meter_id.isdigit() or int(offline_meter_id) <= 0:
55
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
56
                                       description='API.INVALID_OFFLINE_METER_ID')
57
58
        if offline_meter_uuid is not None:
59
            regex = re.compile('^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\\Z', re.I)
60
            match = regex.match(str.strip(offline_meter_uuid))
61
            if not bool(match):
62
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
63
                                       description='API.INVALID_OFFLINE_METER_UUID')
64
65
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
66
        if config.utc_offset[0] == '-':
67
            timezone_offset = -timezone_offset
68
69 View Code Duplication
        if reporting_period_start_datetime_local is None:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
70
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
71
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
72
        else:
73
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
74
            try:
75
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
76
                                                                 '%Y-%m-%dT%H:%M:%S')
77
            except ValueError:
78
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
79
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
80
            reporting_start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - \
81
                timedelta(minutes=timezone_offset)
82
83
        if reporting_period_end_datetime_local is None:
84
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
85
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
86
        else:
87
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
88
            try:
89
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
90
                                                               '%Y-%m-%dT%H:%M:%S')
91
            except ValueError:
92
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
93
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
94
            reporting_end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) - \
95
                timedelta(minutes=timezone_offset)
96
97
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
98
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
99
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
100
101
        ################################################################################################################
102
        # Step 2: query the offline meter
103
        ################################################################################################################
104
        cnx_system = mysql.connector.connect(**config.myems_system_db)
105
        cursor_system = cnx_system.cursor()
106
107
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
108
        cursor_historical = cnx_energy.cursor()
109
        if offline_meter_id is not None:
110
            cursor_system.execute(" SELECT id, name   "
111
                                  " FROM  tbl_offline_meters  "
112
                                  " WHERE id = %s ", (offline_meter_id,))
113
            row_offline_meter = cursor_system.fetchone()
114
        if row_offline_meter is None:
0 ignored issues
show
The variable row_offline_meter does not seem to be defined in case offline_meter_id is not None on line 109 is False. Are you sure this can never be the case?
Loading history...
115
            if cursor_system:
116
                cursor_system.close()
117
            if cnx_system:
118
                cnx_system.disconnect()
119
120
            if cursor_historical:
121
                cursor_historical.close()
122
            if cnx_energy:
123
                cnx_energy.disconnect()
124
            raise falcon.HTTPError(status=falcon.HTTP_404,
125
                                   title='API.NOT_FOUND',
126
                                   description='API.OFFLINE_METER_NOT_FOUND')
127
128
        #######################################################
129
        # Step 4: query reporting period points trends
130
        #######################################################
131
        reporting_date_list = list()
132
        reporting_daily_values = list()
133
134
        query = (" SELECT start_datetime_utc, actual_value "
135
                 " FROM tbl_offline_meter_hourly "
136
                 " WHERE offline_meter_id = %s "
137
                 " AND start_datetime_utc >= %s "
138
                 " AND start_datetime_utc < %s "
139
                 " ORDER BY start_datetime_utc ")
140
        cursor_historical.execute(query, (row_offline_meter[0],
141
                                          reporting_start_datetime_utc,
142
                                          reporting_end_datetime_utc))
143
        rows_offline_meter_hourly = cursor_historical.fetchall()
144
145
        start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=None)
146
        end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=None)
147
148
        start_datetime_local = start_datetime_utc + timedelta(hours=int(config.utc_offset[1:3]))
149
        current_datetime_utc = start_datetime_local.replace(hour=0) - timedelta(hours=int(config.utc_offset[1:3]))
150
151 View Code Duplication
        while current_datetime_utc <= end_datetime_utc:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
152
            flag = True
153
            subtotal = Decimal(0.0)
154
            for row in rows_offline_meter_hourly:
155
                if current_datetime_utc <= row[0] < current_datetime_utc + timedelta(days=1):
156
                    flag = False
157
                    subtotal += row[1]
158
            if flag:
159
                subtotal = None
160
            current_datetime = start_datetime_local.isoformat()[0:10]
161
162
            reporting_date_list.append(current_datetime)
163
            reporting_daily_values.append(subtotal)
164
            current_datetime_utc += timedelta(days=1)
165
            start_datetime_local += timedelta(days=1)
166
        
167
        ################################################################################################################
168
        # Step 6: construct the report
169
        ################################################################################################################
170
        if cursor_system:
171
            cursor_system.close()
172
        if cnx_system:
173
            cnx_system.disconnect()
174
175
        if cursor_historical:
176
            cursor_historical.close()
177
        if cnx_energy:
178
            cnx_energy.disconnect()
179
180
        result_values = []
181
        for date, daily_value in zip(reporting_date_list, reporting_daily_values):
182
            result_values.append({
183
                "monthdate": date,
184
                "daily_value": daily_value
185
            })
186
187
        resp.text = json.dumps(result_values)
188