| @@ 218-348 (lines=131) @@ | ||
| 215 | resp.location = '/offlinemeterfiles/' + str(new_id) |
|
| 216 | ||
| 217 | ||
| 218 | class OfflineMeterFileItem: |
|
| 219 | """ |
|
| 220 | Offline Meter File Item Resource |
|
| 221 | ||
| 222 | This class handles individual offline meter file operations. |
|
| 223 | It provides endpoints for retrieving and deleting specific offline meter files. |
|
| 224 | """ |
|
| 225 | ||
| 226 | def __init__(self): |
|
| 227 | """Initialize OfflineMeterFileItem""" |
|
| 228 | pass |
|
| 229 | ||
| 230 | @staticmethod |
|
| 231 | def on_options(req, resp, id_): |
|
| 232 | """Handle OPTIONS requests for CORS preflight""" |
|
| 233 | _ = req |
|
| 234 | resp.status = falcon.HTTP_200 |
|
| 235 | _ = id_ |
|
| 236 | ||
| 237 | @staticmethod |
|
| 238 | def on_get(req, resp, id_): |
|
| 239 | """ |
|
| 240 | Handle GET requests to retrieve a specific offline meter file |
|
| 241 | ||
| 242 | Returns the offline meter file details for the specified ID. |
|
| 243 | ||
| 244 | Args: |
|
| 245 | req: Falcon request object |
|
| 246 | resp: Falcon response object |
|
| 247 | id_: Offline meter file ID to retrieve |
|
| 248 | """ |
|
| 249 | admin_control(req) |
|
| 250 | ||
| 251 | # Validate file ID |
|
| 252 | if not id_.isdigit() or int(id_) <= 0: |
|
| 253 | raise falcon.HTTPError(status=falcon.HTTP_400, |
|
| 254 | title='API.BAD_REQUEST', |
|
| 255 | description='API.INVALID_OFFLINE_METER_FILE_ID') |
|
| 256 | ||
| 257 | # Connect to historical database |
|
| 258 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 259 | cursor = cnx.cursor() |
|
| 260 | ||
| 261 | # Get file details |
|
| 262 | query = (" SELECT id, file_name, uuid, upload_datetime_utc, status " |
|
| 263 | " FROM tbl_offline_meter_files " |
|
| 264 | " WHERE id = %s ") |
|
| 265 | cursor.execute(query, (id_,)) |
|
| 266 | row = cursor.fetchone() |
|
| 267 | cursor.close() |
|
| 268 | cnx.close() |
|
| 269 | ||
| 270 | # Check if file exists |
|
| 271 | if row is None: |
|
| 272 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 273 | description='API.OFFLINE_METER_FILE_NOT_FOUND') |
|
| 274 | ||
| 275 | # Calculate timezone offset for datetime conversion |
|
| 276 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
|
| 277 | if config.utc_offset[0] == '-': |
|
| 278 | timezone_offset = -timezone_offset |
|
| 279 | ||
| 280 | # Build result with converted datetime |
|
| 281 | result = {"id": row[0], |
|
| 282 | "file_name": row[1], |
|
| 283 | "uuid": row[2], |
|
| 284 | "upload_datetime": (row[3].replace(tzinfo=timezone.utc) + |
|
| 285 | timedelta(minutes=timezone_offset)).isoformat()[0:19], |
|
| 286 | "status": row[4]} |
|
| 287 | resp.text = json.dumps(result) |
|
| 288 | ||
| 289 | @staticmethod |
|
| 290 | @user_logger |
|
| 291 | def on_delete(req, resp, id_): |
|
| 292 | """ |
|
| 293 | Handle DELETE requests to delete a specific offline meter file |
|
| 294 | ||
| 295 | Deletes the offline meter file with the specified ID. |
|
| 296 | Removes both the file from disk and metadata from database. |
|
| 297 | Note: Energy data imported from the deleted file will not be deleted. |
|
| 298 | ||
| 299 | Args: |
|
| 300 | req: Falcon request object |
|
| 301 | resp: Falcon response object |
|
| 302 | id_: Offline meter file ID to delete |
|
| 303 | """ |
|
| 304 | admin_control(req) |
|
| 305 | ||
| 306 | # Validate file ID |
|
| 307 | if not id_.isdigit() or int(id_) <= 0: |
|
| 308 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
|
| 309 | description='API.INVALID_OFFLINE_METER_FILE_ID') |
|
| 310 | ||
| 311 | # Connect to historical database |
|
| 312 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 313 | cursor = cnx.cursor() |
|
| 314 | ||
| 315 | # Get file UUID for file deletion |
|
| 316 | cursor.execute(" SELECT uuid " |
|
| 317 | " FROM tbl_offline_meter_files " |
|
| 318 | " WHERE id = %s ", (id_,)) |
|
| 319 | row = cursor.fetchone() |
|
| 320 | if row is None: |
|
| 321 | cursor.close() |
|
| 322 | cnx.close() |
|
| 323 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 324 | description='API.OFFLINE_METER_FILE_NOT_FOUND') |
|
| 325 | ||
| 326 | # Remove file from disk |
|
| 327 | try: |
|
| 328 | file_uuid = row[0] |
|
| 329 | # Define file_path |
|
| 330 | file_path = os.path.join(config.upload_path, file_uuid) |
|
| 331 | ||
| 332 | # remove the file from disk |
|
| 333 | os.remove(file_path) |
|
| 334 | except OSError as ex: |
|
| 335 | print("Failed to stream request") |
|
| 336 | except Exception as ex: |
|
| 337 | print("Unexpected error reading request stream") |
|
| 338 | # ignore exception and don't return API.OFFLINE_METER_FILE_NOT_FOUND error |
|
| 339 | pass |
|
| 340 | ||
| 341 | # Note: the energy data imported from the deleted file will not be deleted |
|
| 342 | cursor.execute(" DELETE FROM tbl_offline_meter_files WHERE id = %s ", (id_,)) |
|
| 343 | cnx.commit() |
|
| 344 | ||
| 345 | cursor.close() |
|
| 346 | cnx.close() |
|
| 347 | ||
| 348 | resp.status = falcon.HTTP_204 |
|
| 349 | ||
| 350 | ||
| 351 | class OfflineMeterFileRestore: |
|
| @@ 161-249 (lines=89) @@ | ||
| 158 | resp.location = '/costfiles/' + str(new_id) |
|
| 159 | ||
| 160 | ||
| 161 | class CostFileItem: |
|
| 162 | def __init__(self): |
|
| 163 | pass |
|
| 164 | ||
| 165 | @staticmethod |
|
| 166 | def on_options(req, resp, id_): |
|
| 167 | _ = req |
|
| 168 | resp.status = falcon.HTTP_200 |
|
| 169 | _ = id_ |
|
| 170 | ||
| 171 | @staticmethod |
|
| 172 | def on_get(req, resp, id_): |
|
| 173 | """Handles GET requests""" |
|
| 174 | admin_control(req) |
|
| 175 | if not id_.isdigit() or int(id_) <= 0: |
|
| 176 | raise falcon.HTTPError(status=falcon.HTTP_400, |
|
| 177 | title='API.BAD_REQUEST', |
|
| 178 | description='API.INVALID_COST_FILE_ID') |
|
| 179 | ||
| 180 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 181 | cursor = cnx.cursor() |
|
| 182 | ||
| 183 | query = (" SELECT id, file_name, uuid, upload_datetime_utc, status " |
|
| 184 | " FROM tbl_cost_files " |
|
| 185 | " WHERE id = %s ") |
|
| 186 | cursor.execute(query, (id_,)) |
|
| 187 | row = cursor.fetchone() |
|
| 188 | cursor.close() |
|
| 189 | cnx.close() |
|
| 190 | if row is None: |
|
| 191 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 192 | description='API.COST_FILE_NOT_FOUND') |
|
| 193 | ||
| 194 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
|
| 195 | if config.utc_offset[0] == '-': |
|
| 196 | timezone_offset = -timezone_offset |
|
| 197 | ||
| 198 | result = {"id": row[0], |
|
| 199 | "file_name": row[1], |
|
| 200 | "uuid": row[2], |
|
| 201 | "upload_datetime": (row[3].replace(tzinfo=timezone.utc) |
|
| 202 | + timedelta(minutes=timezone_offset)).isoformat()[0:19], |
|
| 203 | "status": row[4]} |
|
| 204 | resp.text = json.dumps(result) |
|
| 205 | ||
| 206 | @staticmethod |
|
| 207 | @user_logger |
|
| 208 | def on_delete(req, resp, id_): |
|
| 209 | """Handles DELETE requests""" |
|
| 210 | admin_control(req) |
|
| 211 | if not id_.isdigit() or int(id_) <= 0: |
|
| 212 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
|
| 213 | description='API.INVALID_COST_FILE_ID') |
|
| 214 | ||
| 215 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 216 | cursor = cnx.cursor() |
|
| 217 | ||
| 218 | cursor.execute(" SELECT uuid " |
|
| 219 | " FROM tbl_cost_files " |
|
| 220 | " WHERE id = %s ", (id_,)) |
|
| 221 | row = cursor.fetchone() |
|
| 222 | if row is None: |
|
| 223 | cursor.close() |
|
| 224 | cnx.close() |
|
| 225 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 226 | description='API.COST_FILE_NOT_FOUND') |
|
| 227 | ||
| 228 | try: |
|
| 229 | file_uuid = row[0] |
|
| 230 | # Define file_path |
|
| 231 | file_path = os.path.join(config.upload_path, file_uuid) |
|
| 232 | ||
| 233 | # remove the file from disk |
|
| 234 | os.remove(file_path) |
|
| 235 | except OSError as ex: |
|
| 236 | print("Failed to stream request") |
|
| 237 | except Exception as ex: |
|
| 238 | print(str(ex)) |
|
| 239 | # ignore exception and don't return API.COST_FILE_NOT_FOUND error |
|
| 240 | pass |
|
| 241 | ||
| 242 | # Note: the energy data imported from the deleted file will not be deleted |
|
| 243 | cursor.execute(" DELETE FROM tbl_cost_files WHERE id = %s ", (id_,)) |
|
| 244 | cnx.commit() |
|
| 245 | ||
| 246 | cursor.close() |
|
| 247 | cnx.close() |
|
| 248 | ||
| 249 | resp.status = falcon.HTTP_204 |
|
| 250 | ||
| 251 | ||
| 252 | class CostFileRestore: |
|
| @@ 186-272 (lines=87) @@ | ||
| 183 | resp.location = '/energyplanfiles/' + str(new_id) |
|
| 184 | ||
| 185 | ||
| 186 | class EnergyPlanFileItem: |
|
| 187 | def __init__(self): |
|
| 188 | pass |
|
| 189 | ||
| 190 | @staticmethod |
|
| 191 | def on_options(req, resp, id_): |
|
| 192 | _ = req |
|
| 193 | resp.status = falcon.HTTP_200 |
|
| 194 | _ = id_ |
|
| 195 | ||
| 196 | @staticmethod |
|
| 197 | def on_get(req, resp, id_): |
|
| 198 | admin_control(req) |
|
| 199 | if not id_.isdigit() or int(id_) <= 0: |
|
| 200 | raise falcon.HTTPError(status=falcon.HTTP_400, |
|
| 201 | title='API.BAD_REQUEST', |
|
| 202 | description='API.INVALID_ENERGY_PLAN_FILE_ID') |
|
| 203 | ||
| 204 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 205 | cursor = cnx.cursor() |
|
| 206 | ||
| 207 | query = (" SELECT id, file_name, uuid, upload_datetime_utc, status " |
|
| 208 | " FROM tbl_energy_plan_files " |
|
| 209 | " WHERE id = %s ") |
|
| 210 | cursor.execute(query, (id_,)) |
|
| 211 | row = cursor.fetchone() |
|
| 212 | cursor.close() |
|
| 213 | cnx.close() |
|
| 214 | if row is None: |
|
| 215 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 216 | description='API.ENERGY_PLAN_FILE_NOT_FOUND') |
|
| 217 | ||
| 218 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
|
| 219 | if config.utc_offset[0] == '-': |
|
| 220 | timezone_offset = -timezone_offset |
|
| 221 | ||
| 222 | result = {"id": row[0], |
|
| 223 | "file_name": row[1], |
|
| 224 | "uuid": row[2], |
|
| 225 | "upload_datetime": (row[3].replace(tzinfo=timezone.utc) + |
|
| 226 | timedelta(minutes=timezone_offset)).isoformat()[0:19], |
|
| 227 | "status": row[4]} |
|
| 228 | resp.text = json.dumps(result) |
|
| 229 | ||
| 230 | @staticmethod |
|
| 231 | @user_logger |
|
| 232 | def on_delete(req, resp, id_): |
|
| 233 | admin_control(req) |
|
| 234 | if not id_.isdigit() or int(id_) <= 0: |
|
| 235 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
|
| 236 | description='API.INVALID_ENERGY_PLAN_FILE_ID') |
|
| 237 | ||
| 238 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 239 | cursor = cnx.cursor() |
|
| 240 | ||
| 241 | cursor.execute(" SELECT uuid " |
|
| 242 | " FROM tbl_energy_plan_files " |
|
| 243 | " WHERE id = %s ", (id_,)) |
|
| 244 | row = cursor.fetchone() |
|
| 245 | if row is None: |
|
| 246 | cursor.close() |
|
| 247 | cnx.close() |
|
| 248 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 249 | description='API.ENERGY_PLAN_FILE_NOT_FOUND') |
|
| 250 | ||
| 251 | try: |
|
| 252 | file_uuid = row[0] |
|
| 253 | # Define file_path |
|
| 254 | file_path = os.path.join(config.upload_path, file_uuid) |
|
| 255 | ||
| 256 | # remove the file from disk |
|
| 257 | os.remove(file_path) |
|
| 258 | except OSError as ex: |
|
| 259 | print("Failed to stream request") |
|
| 260 | except Exception as ex: |
|
| 261 | print("Unexpected error reading request stream") |
|
| 262 | # ignore exception and don't return API.ENERGY_PLAN_FILE_NOT_FOUND error |
|
| 263 | pass |
|
| 264 | ||
| 265 | # Note: the energy data imported from the deleted file will not be deleted |
|
| 266 | cursor.execute(" DELETE FROM tbl_energy_plan_files WHERE id = %s ", (id_,)) |
|
| 267 | cnx.commit() |
|
| 268 | ||
| 269 | cursor.close() |
|
| 270 | cnx.close() |
|
| 271 | ||
| 272 | resp.status = falcon.HTTP_204 |
|
| 273 | ||
| 274 | ||
| 275 | class EnergyPlanFileRestore: |
|
| @@ 152-238 (lines=87) @@ | ||
| 149 | resp.location = '/datarepairfiles/' + str(new_id) |
|
| 150 | ||
| 151 | ||
| 152 | class DataRepairFileItem: |
|
| 153 | def __init__(self): |
|
| 154 | pass |
|
| 155 | ||
| 156 | @staticmethod |
|
| 157 | def on_options(req, resp, id_): |
|
| 158 | _ = req |
|
| 159 | resp.status = falcon.HTTP_200 |
|
| 160 | _ = id_ |
|
| 161 | ||
| 162 | @staticmethod |
|
| 163 | def on_get(req, resp, id_): |
|
| 164 | admin_control(req) |
|
| 165 | if not id_.isdigit() or int(id_) <= 0: |
|
| 166 | raise falcon.HTTPError(status=falcon.HTTP_400, |
|
| 167 | title='API.BAD_REQUEST', |
|
| 168 | description='API.INVALID_DATA_REPAIR_FILE_ID') |
|
| 169 | ||
| 170 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 171 | cursor = cnx.cursor() |
|
| 172 | ||
| 173 | query = (" SELECT id, file_name, uuid, upload_datetime_utc, status " |
|
| 174 | " FROM tbl_data_repair_files " |
|
| 175 | " WHERE id = %s ") |
|
| 176 | cursor.execute(query, (id_,)) |
|
| 177 | row = cursor.fetchone() |
|
| 178 | cursor.close() |
|
| 179 | cnx.close() |
|
| 180 | if row is None: |
|
| 181 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 182 | description='API.DATA_REPAIR_FILE_NOT_FOUND') |
|
| 183 | ||
| 184 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
|
| 185 | if config.utc_offset[0] == '-': |
|
| 186 | timezone_offset = -timezone_offset |
|
| 187 | ||
| 188 | result = {"id": row[0], |
|
| 189 | "file_name": row[1], |
|
| 190 | "uuid": row[2], |
|
| 191 | "upload_datetime": (row[3].replace(tzinfo=timezone.utc) |
|
| 192 | + timedelta(minutes=timezone_offset)).isoformat()[0:19], |
|
| 193 | "status": row[4]} |
|
| 194 | resp.text = json.dumps(result) |
|
| 195 | ||
| 196 | @staticmethod |
|
| 197 | @user_logger |
|
| 198 | def on_delete(req, resp, id_): |
|
| 199 | admin_control(req) |
|
| 200 | if not id_.isdigit() or int(id_) <= 0: |
|
| 201 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
|
| 202 | description='API.INVALID_DATA_REPAIR_FILE_ID') |
|
| 203 | ||
| 204 | cnx = mysql.connector.connect(**config.myems_historical_db) |
|
| 205 | cursor = cnx.cursor() |
|
| 206 | ||
| 207 | cursor.execute(" SELECT uuid " |
|
| 208 | " FROM tbl_data_repair_files " |
|
| 209 | " WHERE id = %s ", (id_,)) |
|
| 210 | row = cursor.fetchone() |
|
| 211 | if row is None: |
|
| 212 | cursor.close() |
|
| 213 | cnx.close() |
|
| 214 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
|
| 215 | description='API.DATA_REPAIR_FILE_NOT_FOUND') |
|
| 216 | ||
| 217 | try: |
|
| 218 | file_uuid = row[0] |
|
| 219 | # Define file_path |
|
| 220 | file_path = os.path.join(config.upload_path, file_uuid) |
|
| 221 | ||
| 222 | # remove the file from disk |
|
| 223 | os.remove(file_path) |
|
| 224 | except OSError as ex: |
|
| 225 | print("Failed to stream request") |
|
| 226 | except Exception as ex: |
|
| 227 | print(str(ex)) |
|
| 228 | # ignore exception and don't return API.DATA_REPAIR_FILE_NOT_FOUND error |
|
| 229 | pass |
|
| 230 | ||
| 231 | # Note: the energy data imported from the deleted file will not be deleted |
|
| 232 | cursor.execute(" DELETE FROM tbl_data_repair_files WHERE id = %s ", (id_,)) |
|
| 233 | cnx.commit() |
|
| 234 | ||
| 235 | cursor.close() |
|
| 236 | cnx.close() |
|
| 237 | ||
| 238 | resp.status = falcon.HTTP_204 |
|
| 239 | ||
| 240 | ||
| 241 | class DataRepairFileRestore: |
|