Passed
Push — master ( 30351b...c101ad )
by Guangyu
02:29 queued 12s
created

reports.metersubmetersbalance   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 116
dl 0
loc 181
rs 10
c 0
b 0
f 0
wmc 23

3 Methods

Rating   Name   Duplication   Size   Complexity  
A Reporting.on_options() 0 3 1
A Reporting.__init__() 0 3 1
F Reporting.on_get() 0 152 21
1
import falcon
2
import simplejson as json
3
import mysql.connector
4
import config
5
from datetime import datetime, timedelta, timezone
6
from core import utilities
7
from decimal import Decimal
8
9
10
class Reporting:
11
    @staticmethod
12
    def __init__():
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        resp.status = falcon.HTTP_200
18
19
    ####################################################################################################################
20
    # PROCEDURES
21
    # Step 1: valid parameters
22
    # Step 2: query the meter and energy category
23
    # Step 3: query associated submeters
24
    # Step 4: query reporting period master meter energy consumption
25
    # Step 5: query reporting period submeters energy consumption
26
    # Step 6: calculate reporting period master meter and submeters difference
27
    # Step 7: construct the report
28
    ####################################################################################################################
29
    @staticmethod
30
    def on_get(req, resp):
31
        print(req.params)
32
        meter_id = req.params.get('meterid')
33
        period_type = req.params.get('periodtype')
34
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
35
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
36
37
        ################################################################################################################
38
        # Step 1: valid parameters
39
        ################################################################################################################
40
        if meter_id is None:
41
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_ID')
42
        else:
43
            meter_id = str.strip(meter_id)
44
            if not meter_id.isdigit() or int(meter_id) <= 0:
45
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_ID')
46
47
        if period_type is None:
48
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
49
        else:
50
            period_type = str.strip(period_type)
51
            if period_type not in ['hourly', 'daily', 'monthly', 'yearly']:
52
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
53
54
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
55
        if config.utc_offset[0] == '-':
56
            timezone_offset = -timezone_offset
57
58
        if reporting_period_start_datetime_local is None:
59
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
60
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
61
        else:
62
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
63
            try:
64
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
65
                                                                 '%Y-%m-%dT%H:%M:%S')
66
            except ValueError:
67
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
68
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
69
            reporting_start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - \
70
                timedelta(minutes=timezone_offset)
71
72
        if reporting_period_end_datetime_local is None:
73
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
74
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
75
        else:
76
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
77
            try:
78
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
79
                                                               '%Y-%m-%dT%H:%M:%S')
80
            except ValueError:
81
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
82
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
83
            reporting_end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) - \
84
                timedelta(minutes=timezone_offset)
85
86
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
87
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
88
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
89
90
        ################################################################################################################
91
        # Step 2: query the meter and energy category
92
        ################################################################################################################
93
        cnx_system = mysql.connector.connect(**config.myems_system_db)
94
        cursor_system = cnx_system.cursor()
95
96
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
97
        cursor_energy = cnx_energy.cursor()
98
99
        cursor_system.execute(" SELECT m.id, m.name, m.cost_center_id, m.energy_category_id, "
100
                              "        ec.name, ec.unit_of_measure, ec.kgce, ec.kgco2e "
101
                              " FROM tbl_meters m, tbl_energy_categories ec "
102
                              " WHERE m.id = %s AND m.energy_category_id = ec.id ", (meter_id,))
103
        row_meter = cursor_system.fetchone()
104
        if row_meter is None:
105
            if cursor_system:
106
                cursor_system.close()
107
            if cnx_system:
108
                cnx_system.disconnect()
109
110
            if cursor_energy:
111
                cursor_energy.close()
112
            if cnx_energy:
113
                cnx_energy.disconnect()
114
115
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.METER_NOT_FOUND')
116
117
        meter = dict()
118
        meter['id'] = row_meter[0]
119
        meter['name'] = row_meter[1]
120
        meter['cost_center_id'] = row_meter[2]
121
        meter['energy_category_id'] = row_meter[3]
122
        meter['energy_category_name'] = row_meter[4]
123
        meter['unit_of_measure'] = row_meter[5]
124
        meter['kgce'] = row_meter[6]
125
        meter['kgco2e'] = row_meter[7]
126
127
        ################################################################################################################
128
        # Step 3: query associated submeters
129
        ################################################################################################################
130
131
        ################################################################################################################
132
        # Step 4: query reporting period master meter energy consumption
133
        ################################################################################################################
134
135
        ################################################################################################################
136
        # Step 5: query reporting period submeters energy consumption
137
        ################################################################################################################
138
139
        ################################################################################################################
140
        # Step 6: calculate reporting period master meter and submeters difference
141
        ################################################################################################################
142
143
        ################################################################################################################
144
        # Step 7: construct the report
145
        ################################################################################################################
146
        if cursor_system:
147
            cursor_system.close()
148
        if cnx_system:
149
            cnx_system.disconnect()
150
151
        if cursor_energy:
152
            cursor_energy.close()
153
        if cnx_energy:
154
            cnx_energy.disconnect()
155
156
        result = {
157
            "meter": {
158
                "cost_center_id": meter['cost_center_id'],
159
                "energy_category_id": meter['energy_category_id'],
160
                "energy_category_name": meter['energy_category_name'],
161
                "unit_of_measure": meter['unit_of_measure'],
162
                "kgce": meter['kgce'],
163
                "kgco2e": meter['kgco2e'],
164
            },
165
            "reporting_period": {
166
                "master_meter_consumption_in_category": Decimal(0.0),
167
                "submeters_consumption_in_category": Decimal(0.0),
168
                "difference_in_category": Decimal(0.0),
169
                "percentage_difference": Decimal(0.0),
170
                "timestamps": [],
171
                "values": [],
172
            },
173
            "parameters": {
174
                "names": [],
175
                "timestamps": [],
176
                "values": []
177
            },
178
        }
179
180
        resp.body = json.dumps(result)
181