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",
|
"name": "Point",
|
||||||
"item": [
|
"item": [
|
||||||
|
|
|
@ -159,7 +159,7 @@ View in Postman: import the file MyEMS.postman_collection.json with Postman
|
||||||
|
|
||||||
[Data Source](#Data-Source) | [Point](#Point)
|
[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)
|
[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}
|
$ 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
|
### Data Source
|
||||||
* GET Data Source by ID
|
* GET Data Source by ID
|
||||||
|
|
||||||
|
@ -1076,7 +1107,7 @@ $ curl -i -X DELETE {{base_url}}/offlinemeterfiles/{id}
|
||||||
* POST Upload an Offline Meter File
|
* POST Upload an Offline Meter File
|
||||||
(user must login first to get cookie)
|
(user must login first to get cookie)
|
||||||
```bash
|
```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
|
### Point
|
||||||
|
|
|
@ -3,12 +3,13 @@ from falcon_cors import CORS
|
||||||
from falcon_multipart.middleware import MultipartMiddleware
|
from falcon_multipart.middleware import MultipartMiddleware
|
||||||
from core import energyflowdiagram, privilege, textmessage, distributioncircuit, virtualmeter, \
|
from core import energyflowdiagram, privilege, textmessage, distributioncircuit, virtualmeter, \
|
||||||
costcenter, point, knowledgefile, meter, gsmmodem, tariff, user, storetype, timezone, \
|
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, \
|
webmessage, distributionsystem, store, emailmessage, tenanttype, wechatmessage, space, gateway, offlinemeter, \
|
||||||
rule, energycategory, sensor, energyitem, notification
|
rule, energycategory, sensor, energyitem, notification
|
||||||
from reports import advancedreport
|
from reports import advancedreport
|
||||||
from reports import distributionsystem as distributionsystemreport
|
from reports import distributionsystem as distributionsystemreport
|
||||||
from reports import energyflowdiagram as energyflowdiagramreport
|
from reports import energyflowdiagram as energyflowdiagramreport
|
||||||
|
from reports import combinedequipmentbatch
|
||||||
from reports import combinedequipmentcost
|
from reports import combinedequipmentcost
|
||||||
from reports import combinedequipmentefficiency
|
from reports import combinedequipmentefficiency
|
||||||
from reports import combinedequipmentenergycategory
|
from reports import combinedequipmentenergycategory
|
||||||
|
@ -18,8 +19,8 @@ from reports import combinedequipmentload
|
||||||
from reports import combinedequipmentoutput
|
from reports import combinedequipmentoutput
|
||||||
from reports import combinedequipmentsaving
|
from reports import combinedequipmentsaving
|
||||||
from reports import combinedequipmentstatistics
|
from reports import combinedequipmentstatistics
|
||||||
from reports import combinedequipmentbatch
|
|
||||||
from reports import dashboard
|
from reports import dashboard
|
||||||
|
from reports import equipmentbatch
|
||||||
from reports import equipmentcost
|
from reports import equipmentcost
|
||||||
from reports import equipmentefficiency
|
from reports import equipmentefficiency
|
||||||
from reports import equipmentenergycategory
|
from reports import equipmentenergycategory
|
||||||
|
@ -139,6 +140,11 @@ api.add_route('/costcenters/{id_}/tariffs',
|
||||||
api.add_route('/costcenters/{id_}/tariffs/{tid}',
|
api.add_route('/costcenters/{id_}/tariffs/{tid}',
|
||||||
costcenter.CostCenterTariffItem())
|
costcenter.CostCenterTariffItem())
|
||||||
|
|
||||||
|
api.add_route('/offlinecostfiles',
|
||||||
|
offlinecostfile.OfflineCostFileCollection())
|
||||||
|
api.add_route('/offlinecostfiles/{id_}',
|
||||||
|
offlinecostfile.OfflineCostFileItem())
|
||||||
|
|
||||||
api.add_route('/datasources',
|
api.add_route('/datasources',
|
||||||
datasource.DataSourceCollection())
|
datasource.DataSourceCollection())
|
||||||
api.add_route('/datasources/{id_}',
|
api.add_route('/datasources/{id_}',
|
||||||
|
@ -483,6 +489,8 @@ api.add_route('/reports/distributionsystem',
|
||||||
distributionsystemreport.Reporting())
|
distributionsystemreport.Reporting())
|
||||||
api.add_route('/reports/energyflowdiagram',
|
api.add_route('/reports/energyflowdiagram',
|
||||||
energyflowdiagramreport.Reporting())
|
energyflowdiagramreport.Reporting())
|
||||||
|
api.add_route('/reports/combinedequipmentbatch',
|
||||||
|
combinedequipmentbatch.Reporting())
|
||||||
api.add_route('/reports/combinedequipmentcost',
|
api.add_route('/reports/combinedequipmentcost',
|
||||||
combinedequipmentcost.Reporting())
|
combinedequipmentcost.Reporting())
|
||||||
api.add_route('/reports/combinedequipmentefficiency',
|
api.add_route('/reports/combinedequipmentefficiency',
|
||||||
|
@ -501,10 +509,10 @@ api.add_route('/reports/combinedequipmentsaving',
|
||||||
combinedequipmentsaving.Reporting())
|
combinedequipmentsaving.Reporting())
|
||||||
api.add_route('/reports/combinedequipmentstatistics',
|
api.add_route('/reports/combinedequipmentstatistics',
|
||||||
combinedequipmentstatistics.Reporting())
|
combinedequipmentstatistics.Reporting())
|
||||||
api.add_route('/reports/combinedequipmentbatch',
|
|
||||||
combinedequipmentbatch.Reporting())
|
|
||||||
api.add_route('/reports/dashboard',
|
api.add_route('/reports/dashboard',
|
||||||
dashboard.Reporting())
|
dashboard.Reporting())
|
||||||
|
api.add_route('/reports/equipmentbatch',
|
||||||
|
equipmentbatch.Reporting())
|
||||||
api.add_route('/reports/equipmentcost',
|
api.add_route('/reports/equipmentcost',
|
||||||
equipmentcost.Reporting())
|
equipmentcost.Reporting())
|
||||||
api.add_route('/reports/equipmentefficiency',
|
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