added Offline Cost File actions to API
parent
00a17b0d71
commit
9443eca6f0
|
@ -3322,6 +3322,102 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Offline Cost File",
|
||||
"item": [
|
||||
{
|
||||
"name": "GET All Offline Cost Files",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/offlinecostfiles",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"offlinecostfiles"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "GET a Offline Cost File by ID",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/offlinecostfiles/1",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"offlinecostfiles",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "POST Upload a Offline Cost File",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "User_UUID",
|
||||
"value": "dcdb67d1-6116-4987-916f-6fc6cf2bc0e4",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "Token",
|
||||
"value": "6b0622f8974b2e6f2d7a7470baf073b78bddffd4",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "formdata",
|
||||
"formdata": [
|
||||
{
|
||||
"key": "file",
|
||||
"type": "file",
|
||||
"src": "/zh/myems/myems-doc/offlinemeters.xlsx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{base_url}}/offlinecostfiles",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"offlinecostfiles"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "DELETE a Offline Cost File by ID",
|
||||
"request": {
|
||||
"method": "DELETE",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/offlinecostfiles/1",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"offlinecostfiles",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Point",
|
||||
"item": [
|
||||
|
|
|
@ -159,7 +159,7 @@ View in Postman: import the file MyEMS.postman_collection.json with Postman
|
|||
|
||||
[Data Source](#Data-Source) | [Point](#Point)
|
||||
|
||||
[Tariff](#Tariff) | [Cost Center](#Cost-Center)
|
||||
[Tariff](#Tariff) | [Cost Center](#Cost-Center) | [Offline Cost File](#Offline-Cost-File)
|
||||
|
||||
[Meter](#Meter) | [Virtual Meter](#Virtual-Meter) | [Offline Meter](#Offline-Meter) | [Offline Meter File](#Offline-Meter-File)
|
||||
|
||||
|
@ -250,6 +250,37 @@ $ curl -i -H "Content-Type: application/json" -X POST -d '{"data":{"tariff_id":"
|
|||
$ curl -i -X DELETE {{base_url}}/costcenters/{id}/tariffs/{tid}
|
||||
```
|
||||
|
||||
### Offline Cost File
|
||||
* GET an Offline Cost File by ID
|
||||
|
||||
```bash
|
||||
$ curl -i -X GET {{base_url}}/offlinecostfiles/{id}
|
||||
```
|
||||
Result
|
||||
|
||||
| Name | Data Type | Description |
|
||||
|---------------|-----------|-------------------------------------------|
|
||||
| id | integer | Offline Cost File ID |
|
||||
| file_name | string | Offline Cost File name |
|
||||
| uuid | string | Offline Cost File UUID |
|
||||
| upload_datetime | float | the number of milliseconds since January 1, 1970, 00:00:00, universal time |
|
||||
| status | string | Offline Cost File processing status (new, done, error) |
|
||||
| file_object | BLOB | Offline Cost File Object |
|
||||
|
||||
* GET All Offline Cost Files
|
||||
```bash
|
||||
$ curl -i -X GET {{base_url}}/offlinecostfiles
|
||||
```
|
||||
* DELETE an Offline Cost File by ID
|
||||
```bash
|
||||
$ curl -i -X DELETE {{base_url}}/offlinecostfiles/{id}
|
||||
```
|
||||
* POST Upload an Offline Cost File
|
||||
(user must login first to get cookie)
|
||||
```bash
|
||||
$ curl -i -H "Content-Type: application/TBD" -X POST -d 'file: (binary)' {{base_url}}/offlinecostfiles
|
||||
```
|
||||
|
||||
### Data Source
|
||||
* GET Data Source by ID
|
||||
|
||||
|
@ -1076,7 +1107,7 @@ $ curl -i -X DELETE {{base_url}}/offlinemeterfiles/{id}
|
|||
* POST Upload an Offline Meter File
|
||||
(user must login first to get cookie)
|
||||
```bash
|
||||
$ curl -i -H "Content-Type: application/TBD" -X POST -d 'file: (binary)' {{base_url}}/offlinemeters
|
||||
$ curl -i -H "Content-Type: application/TBD" -X POST -d 'file: (binary)' {{base_url}}/offlinemeterfiles
|
||||
```
|
||||
|
||||
### Point
|
||||
|
|
|
@ -3,12 +3,13 @@ from falcon_cors import CORS
|
|||
from falcon_multipart.middleware import MultipartMiddleware
|
||||
from core import energyflowdiagram, privilege, textmessage, distributioncircuit, virtualmeter, \
|
||||
costcenter, point, knowledgefile, meter, gsmmodem, tariff, user, storetype, timezone, \
|
||||
offlinemeterfile, version, contact, emailserver, combinedequipment, datasource, equipment, tenant, shopfloor, \
|
||||
offlinecostfile, offlinemeterfile, version, contact, emailserver, combinedequipment, datasource, equipment, tenant, shopfloor, \
|
||||
webmessage, distributionsystem, store, emailmessage, tenanttype, wechatmessage, space, gateway, offlinemeter, \
|
||||
rule, energycategory, sensor, energyitem, notification
|
||||
from reports import advancedreport
|
||||
from reports import distributionsystem as distributionsystemreport
|
||||
from reports import energyflowdiagram as energyflowdiagramreport
|
||||
from reports import combinedequipmentbatch
|
||||
from reports import combinedequipmentcost
|
||||
from reports import combinedequipmentefficiency
|
||||
from reports import combinedequipmentenergycategory
|
||||
|
@ -18,8 +19,8 @@ from reports import combinedequipmentload
|
|||
from reports import combinedequipmentoutput
|
||||
from reports import combinedequipmentsaving
|
||||
from reports import combinedequipmentstatistics
|
||||
from reports import combinedequipmentbatch
|
||||
from reports import dashboard
|
||||
from reports import equipmentbatch
|
||||
from reports import equipmentcost
|
||||
from reports import equipmentefficiency
|
||||
from reports import equipmentenergycategory
|
||||
|
@ -139,6 +140,11 @@ api.add_route('/costcenters/{id_}/tariffs',
|
|||
api.add_route('/costcenters/{id_}/tariffs/{tid}',
|
||||
costcenter.CostCenterTariffItem())
|
||||
|
||||
api.add_route('/offlinecostfiles',
|
||||
offlinecostfile.OfflineCostFileCollection())
|
||||
api.add_route('/offlinecostfiles/{id_}',
|
||||
offlinecostfile.OfflineCostFileItem())
|
||||
|
||||
api.add_route('/datasources',
|
||||
datasource.DataSourceCollection())
|
||||
api.add_route('/datasources/{id_}',
|
||||
|
@ -483,6 +489,8 @@ api.add_route('/reports/distributionsystem',
|
|||
distributionsystemreport.Reporting())
|
||||
api.add_route('/reports/energyflowdiagram',
|
||||
energyflowdiagramreport.Reporting())
|
||||
api.add_route('/reports/combinedequipmentbatch',
|
||||
combinedequipmentbatch.Reporting())
|
||||
api.add_route('/reports/combinedequipmentcost',
|
||||
combinedequipmentcost.Reporting())
|
||||
api.add_route('/reports/combinedequipmentefficiency',
|
||||
|
@ -501,10 +509,10 @@ api.add_route('/reports/combinedequipmentsaving',
|
|||
combinedequipmentsaving.Reporting())
|
||||
api.add_route('/reports/combinedequipmentstatistics',
|
||||
combinedequipmentstatistics.Reporting())
|
||||
api.add_route('/reports/combinedequipmentbatch',
|
||||
combinedequipmentbatch.Reporting())
|
||||
api.add_route('/reports/dashboard',
|
||||
dashboard.Reporting())
|
||||
api.add_route('/reports/equipmentbatch',
|
||||
equipmentbatch.Reporting())
|
||||
api.add_route('/reports/equipmentcost',
|
||||
equipmentcost.Reporting())
|
||||
api.add_route('/reports/equipmentefficiency',
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
import falcon
|
||||
import json
|
||||
import mysql.connector
|
||||
import config
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
import os
|
||||
|
||||
|
||||
class OfflineCostFileCollection:
|
||||
@staticmethod
|
||||
def __init__():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def on_options(req, resp):
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
@staticmethod
|
||||
def on_get(req, resp):
|
||||
cnx = mysql.connector.connect(**config.myems_historical_db)
|
||||
cursor = cnx.cursor()
|
||||
|
||||
query = (" SELECT id, file_name, uuid, upload_datetime_utc, status "
|
||||
" FROM tbl_offline_cost_files "
|
||||
" ORDER BY upload_datetime_utc desc ")
|
||||
cursor.execute(query)
|
||||
rows = cursor.fetchall()
|
||||
cursor.close()
|
||||
cnx.disconnect()
|
||||
|
||||
result = list()
|
||||
if rows is not None and len(rows) > 0:
|
||||
for row in rows:
|
||||
upload_datetime = row[3]
|
||||
upload_datetime = upload_datetime.replace(tzinfo=timezone.utc)
|
||||
meta_result = {"id": row[0],
|
||||
"file_name": row[1],
|
||||
"uuid": row[2],
|
||||
"upload_datetime": upload_datetime.timestamp() * 1000,
|
||||
"status": row[4]}
|
||||
result.append(meta_result)
|
||||
|
||||
resp.body = json.dumps(result)
|
||||
|
||||
@staticmethod
|
||||
def on_post(req, resp):
|
||||
"""Handles POST requests"""
|
||||
try:
|
||||
upload = req.get_param('file')
|
||||
# Read upload file as binary
|
||||
raw_blob = upload.file.read()
|
||||
# Retrieve filename
|
||||
filename = upload.filename
|
||||
file_uuid = str(uuid.uuid4())
|
||||
|
||||
# Define file_path
|
||||
file_path = os.path.join(config.upload_path, file_uuid)
|
||||
|
||||
# Write to a temporary file to prevent incomplete files from
|
||||
# being used.
|
||||
temp_file_path = file_path + '~'
|
||||
|
||||
open(temp_file_path, 'wb').write(raw_blob)
|
||||
|
||||
# Now that we know the file has been fully saved to disk
|
||||
# move it into place.
|
||||
os.rename(temp_file_path, file_path)
|
||||
except Exception as ex:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR',
|
||||
description='API.FAILED_TO_UPLOAD_OFFLINE_COST_FILE')
|
||||
|
||||
# Verify User Session
|
||||
token = req.headers.get('TOKEN')
|
||||
user_uuid = req.headers.get('USER-UUID')
|
||||
if token is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
|
||||
if user_uuid is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
|
||||
|
||||
cnx = mysql.connector.connect(**config.myems_user_db)
|
||||
cursor = cnx.cursor()
|
||||
|
||||
query = (" SELECT utc_expires "
|
||||
" FROM tbl_sessions "
|
||||
" WHERE user_uuid = %s AND token = %s")
|
||||
cursor.execute(query, (user_uuid, token,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if row is None:
|
||||
if cursor:
|
||||
cursor.close()
|
||||
if cnx:
|
||||
cnx.disconnect()
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
|
||||
else:
|
||||
utc_expires = row[0]
|
||||
if datetime.utcnow() > utc_expires:
|
||||
if cursor:
|
||||
cursor.close()
|
||||
if cnx:
|
||||
cnx.disconnect()
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.USER_SESSION_TIMEOUT')
|
||||
|
||||
cursor.execute(" SELECT id "
|
||||
" FROM tbl_users "
|
||||
" WHERE uuid = %s ",
|
||||
(user_uuid,))
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
if cursor:
|
||||
cursor.close()
|
||||
if cnx:
|
||||
cnx.disconnect()
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.INVALID_USER_PLEASE_RE_LOGIN')
|
||||
else:
|
||||
user_id = row[0]
|
||||
|
||||
cnx = mysql.connector.connect(**config.myems_historical_db)
|
||||
cursor = cnx.cursor()
|
||||
|
||||
add_values = (" INSERT INTO tbl_offline_cost_files "
|
||||
" (file_name, uuid, upload_datetime_utc, status, file_object ) "
|
||||
" VALUES (%s, %s, %s, %s, %s) ")
|
||||
cursor.execute(add_values, (filename,
|
||||
file_uuid,
|
||||
datetime.utcnow(),
|
||||
'new',
|
||||
raw_blob))
|
||||
new_id = cursor.lastrowid
|
||||
cnx.commit()
|
||||
cursor.close()
|
||||
cnx.disconnect()
|
||||
|
||||
resp.status = falcon.HTTP_201
|
||||
resp.location = '/offlinecostfiles/' + str(new_id)
|
||||
|
||||
|
||||
class OfflineCostFileItem:
|
||||
@staticmethod
|
||||
def __init__():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def on_options(req, resp, id_):
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
@staticmethod
|
||||
def on_get(req, resp, id_):
|
||||
if not id_.isdigit() or int(id_) <= 0:
|
||||
raise falcon.HTTPError(falcon.HTTP_400,
|
||||
title='API.BAD_REQUEST',
|
||||
description='API.INVALID_OFFLINE_COST_FILE_ID')
|
||||
|
||||
cnx = mysql.connector.connect(**config.myems_historical_db)
|
||||
cursor = cnx.cursor()
|
||||
|
||||
query = (" SELECT id, file_name, uuid, upload_datetime_utc, status "
|
||||
" FROM tbl_offline_cost_files "
|
||||
" WHERE id = %s ")
|
||||
cursor.execute(query, (id_,))
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
cnx.disconnect()
|
||||
if row is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
|
||||
description='API.OFFLINE_COST_FILE_NOT_FOUND')
|
||||
|
||||
upload_datetime = row[3]
|
||||
upload_datetime = upload_datetime.replace(tzinfo=timezone.utc)
|
||||
|
||||
result = {"id": row[0],
|
||||
"file_name": row[1],
|
||||
"uuid": row[2],
|
||||
"upload_datetime": upload_datetime.timestamp() * 1000,
|
||||
"status": row[4]}
|
||||
resp.body = json.dumps(result)
|
||||
|
||||
@staticmethod
|
||||
def on_delete(req, resp, id_):
|
||||
if not id_.isdigit() or int(id_) <= 0:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.INVALID_OFFLINE_COST_FILE_ID')
|
||||
|
||||
cnx = mysql.connector.connect(**config.myems_historical_db)
|
||||
cursor = cnx.cursor()
|
||||
|
||||
cursor.execute(" SELECT uuid "
|
||||
" FROM tbl_offline_cost_files "
|
||||
" WHERE id = %s ", (id_,))
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
cursor.close()
|
||||
cnx.disconnect()
|
||||
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
|
||||
description='API.OFFLINE_COST_FILE_NOT_FOUND')
|
||||
|
||||
try:
|
||||
file_uuid = row[0]
|
||||
# Define file_path
|
||||
file_path = os.path.join(config.upload_path, file_uuid)
|
||||
|
||||
# remove the file from disk
|
||||
os.remove(file_path)
|
||||
except Exception as ex:
|
||||
# ignore exception and don't return API.OFFLINE_COST_FILE_NOT_FOUND error
|
||||
pass
|
||||
|
||||
# Note: the energy data imported from the deleted file will not be deleted
|
||||
cursor.execute(" DELETE FROM tbl_offline_cost_files WHERE id = %s ", (id_,))
|
||||
cnx.commit()
|
||||
|
||||
cursor.close()
|
||||
cnx.disconnect()
|
||||
|
||||
resp.status = falcon.HTTP_204
|
Loading…
Reference in New Issue