added Combined Equipment Batch Analysis report

Merge branch 'PR45' into develop
pull/42/MERGE
13621160019@163.com 2021-05-21 11:38:34 +08:00
commit 44c0cf6b1c
8 changed files with 801 additions and 44 deletions

View File

@ -7079,6 +7079,38 @@
}, },
"response": [] "response": []
}, },
{
"name": "GET Combined Equipment Batch Analysis Report",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/reports/combinedequipmentbatch?spaceid=1&reportingperiodstartdatetime=2020-10-01T00:00:00&reportingperiodenddatetime=2020-11-01T00:00:00",
"host": [
"{{base_url}}"
],
"path": [
"reports",
"combinedequipmentbatch"
],
"query": [
{
"key": "spaceid",
"value": "1"
},
{
"key": "reportingperiodstartdatetime",
"value": "2020-10-01T00:00:00"
},
{
"key": "reportingperiodenddatetime",
"value": "2020-11-01T00:00:00"
}
]
}
},
"response": []
},
{ {
"name": "GET Combined Equipment Cost Report", "name": "GET Combined Equipment Cost Report",
"request": { "request": {
@ -9755,50 +9787,6 @@
} }
}, },
"response": [] "response": []
},
{
"name": "GET Equipment Efficiency Report Copy",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/reports/equipmentefficiency?equipmentid=1&periodtype=daily&baseperiodstartdatetime=2020-08-01T00:00:00&baseperiodenddatetime=2020-09-01T00:00:00&reportingperiodstartdatetime=2020-09-01T00:00:00&reportingperiodenddatetime=2020-10-01T00:00:00",
"host": [
"{{base_url}}"
],
"path": [
"reports",
"equipmentefficiency"
],
"query": [
{
"key": "equipmentid",
"value": "1"
},
{
"key": "periodtype",
"value": "daily"
},
{
"key": "baseperiodstartdatetime",
"value": "2020-08-01T00:00:00"
},
{
"key": "baseperiodenddatetime",
"value": "2020-09-01T00:00:00"
},
{
"key": "reportingperiodstartdatetime",
"value": "2020-09-01T00:00:00"
},
{
"key": "reportingperiodenddatetime",
"value": "2020-10-01T00:00:00"
}
]
}
},
"response": []
} }
] ]
}, },

View File

@ -2040,6 +2040,10 @@ $ curl -i -X GET {{base_url}}/reports/advancedreports/{id}
``` ```
$ curl -i -X GET {{base_url}}/reports/advancedreports/{id} $ curl -i -X GET {{base_url}}/reports/advancedreports/{id}
``` ```
* GET Combined Equipment Batch Analysis Report
```
$ curl -i -X GET {{base_url}}/reports/combinedequipmentbatch?spaceid=1&reportingperiodstartdatetime=2021-05-01T00:00:00&reportingperiodenddatetime=2021-05-20T11:41:09
```
* GET Combined Equipment Cost Report * GET Combined Equipment Cost Report
``` ```
$ curl -i -X GET {{base_url}}/reports/combinedequipmentcost?combinedequipmentid=1&periodtype=daily&baseperiodstartdatetime=2020-08-01T00:00:00&baseperiodenddatetime=2020-09-01T00:00:00&reportingperiodstartdatetime=2020-09-01T00:00:00&reportingperiodenddatetime=2020-10-01T00:00:00 $ curl -i -X GET {{base_url}}/reports/combinedequipmentcost?combinedequipmentid=1&periodtype=daily&baseperiodstartdatetime=2020-08-01T00:00:00&baseperiodenddatetime=2020-09-01T00:00:00&reportingperiodstartdatetime=2020-09-01T00:00:00&reportingperiodenddatetime=2020-10-01T00:00:00

View File

@ -18,6 +18,7 @@ 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 equipmentcost from reports import equipmentcost
from reports import equipmentefficiency from reports import equipmentefficiency
@ -500,6 +501,8 @@ 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/equipmentcost', api.add_route('/reports/equipmentcost',

View File

@ -0,0 +1,188 @@
import base64
import uuid
import os
from openpyxl.styles import PatternFill, Border, Side, Alignment, Protection, Font
from openpyxl.drawing.image import Image
from openpyxl import Workbook
####################################################################################################################
# PROCEDURES
# Step 1: Validate the report data
# Step 2: Generate excelexporters file
# Step 3: Encode the excelexporters file to Base64
####################################################################################################################
def export(result, space_name, reporting_start_datetime_local, reporting_end_datetime_local):
####################################################################################################################
# Step 1: Validate the report data
####################################################################################################################
if result is None:
return None
####################################################################################################################
# Step 2: Generate excel file from the report data
####################################################################################################################
filename = generate_excel(result,
space_name,
reporting_start_datetime_local,
reporting_end_datetime_local)
####################################################################################################################
# Step 3: Encode the excel file to Base64
####################################################################################################################
try:
with open(filename, 'rb') as binary_file:
binary_file_data = binary_file.read()
except IOError as ex:
pass
# Base64 encode the bytes
base64_encoded_data = base64.b64encode(binary_file_data)
# get the Base64 encoded data using human-readable characters.
base64_message = base64_encoded_data.decode('utf-8')
# delete the file from server
try:
os.remove(filename)
except NotImplementedError as ex:
pass
return base64_message
def generate_excel(report, space_name, reporting_start_datetime_local, reporting_end_datetime_local):
wb = Workbook()
ws = wb.active
# Row height
ws.row_dimensions[1].height = 102
for i in range(2, 5 + 1):
ws.row_dimensions[i].height = 42
for i in range(6, len(report['combined_equipments']) + 15):
ws.row_dimensions[i].height = 60
# Col width
ws.column_dimensions['A'].width = 1.5
ws.column_dimensions['B'].width = 25.0
for i in range(ord('C'), ord('L')):
ws.column_dimensions[chr(i)].width = 15.0
# Font
name_font = Font(name='Constantia', size=15, bold=True)
title_font = Font(name='宋体', size=15, bold=True)
data_font = Font(name='Franklin Gothic Book', size=11)
table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
f_border = Border(left=Side(border_style='medium', color='00000000'),
right=Side(border_style='medium', color='00000000'),
bottom=Side(border_style='medium', color='00000000'),
top=Side(border_style='medium', color='00000000')
)
b_border = Border(
bottom=Side(border_style='medium', color='00000000'),
)
b_c_alignment = Alignment(vertical='bottom',
horizontal='center',
text_rotation=0,
wrap_text=True,
shrink_to_fit=False,
indent=0)
c_c_alignment = Alignment(vertical='center',
horizontal='center',
text_rotation=0,
wrap_text=True,
shrink_to_fit=False,
indent=0)
b_r_alignment = Alignment(vertical='bottom',
horizontal='right',
text_rotation=0,
wrap_text=True,
shrink_to_fit=False,
indent=0)
c_r_alignment = Alignment(vertical='bottom',
horizontal='center',
text_rotation=0,
wrap_text=True,
shrink_to_fit=False,
indent=0)
# Img
img = Image("excelexporters/myems.png")
img.width = img.width * 0.85
img.height = img.height * 0.85
ws.add_image(img, 'B1')
# Title
ws.row_dimensions[3].height = 60
ws['B3'].font = name_font
ws['B3'].alignment = b_r_alignment
ws['B3'] = '空间:'
ws['C3'].border = b_border
ws['C3'].alignment = b_c_alignment
ws['C3'].font = name_font
ws['C3'] = space_name
ws['F3'].font = name_font
ws['F3'].alignment = b_r_alignment
ws['F3'] = '日期:'
ws['G3'].border = b_border
ws['G3'].alignment = b_c_alignment
ws['G3'].font = name_font
ws['G3'] = reporting_start_datetime_local + "~" + reporting_end_datetime_local
ws.merge_cells("G3:H3")
# Title
ws['B6'].border = f_border
ws['B6'].font = name_font
ws['B6'].alignment = c_c_alignment
ws['B6'].fill = table_fill
ws['B6'] = '名称'
ws['C6'].border = f_border
ws['C6'].alignment = c_c_alignment
ws['C6'].font = name_font
ws['C6'].fill = table_fill
ws['C6'] = '空间'
ca_len = len(report['energycategories'])
for i in range(0, ca_len):
col = chr(ord('D') + i)
ws[col + '6'].fill = table_fill
ws[col + '6'].font = name_font
ws[col + '6'].alignment = c_c_alignment
ws[col + '6'] = report['energycategories'][i]['name'] + \
" (" + report['energycategories'][i]['unit_of_measure'] + ")"
ws[col + '6'].border = f_border
current_row_number = 7
for i in range(0, len(report['combined_equipments'])):
ws['B' + str(current_row_number)].font = title_font
ws['B' + str(current_row_number)].border = f_border
ws['B' + str(current_row_number)].alignment = c_c_alignment
ws['B' + str(current_row_number)] = report['combined_equipments'][i]['combined_equipment_name']
ws['C' + str(current_row_number)].font = title_font
ws['C' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)].alignment = c_c_alignment
ws['C' + str(current_row_number)] = report['combined_equipments'][i]['space_name']
ca_len = len(report['combined_equipments'][i]['values'])
for j in range(0, ca_len):
col = chr(ord('D') + j)
ws[col + str(current_row_number)].font = data_font
ws[col + str(current_row_number)].border = f_border
ws[col + str(current_row_number)].alignment = c_c_alignment
ws[col + str(current_row_number)] = round(report['combined_equipments'][i]['values'][j], 2)
current_row_number += 1
filename = str(uuid.uuid4()) + '.xlsx'
wb.save(filename)
return filename

View File

@ -0,0 +1,241 @@
import falcon
import simplejson as json
import mysql.connector
import config
from anytree import Node, AnyNode, LevelOrderIter
from datetime import datetime, timedelta, timezone
from decimal import Decimal
import excelexporters.combinedequipmentbatch
class Reporting:
@staticmethod
def __init__():
pass
@staticmethod
def on_options(req, resp):
resp.status = falcon.HTTP_200
####################################################################################################################
# PROCEDURES
# Step 1: valid parameters
# Step 2: build a space tree
# Step 3: query all combined equipments in the space tree
# Step 4: query energy categories
# Step 5: query reporting period energy input
# Step 6: construct the report
####################################################################################################################
@staticmethod
def on_get(req, resp):
print(req.params)
space_id = req.params.get('spaceid')
reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
################################################################################################################
# Step 1: valid parameters
################################################################################################################
if space_id is None:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_SPACE_ID')
else:
space_id = str.strip(space_id)
if not space_id.isdigit() or int(space_id) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_SPACE_ID')
else:
space_id = int(space_id)
timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
if config.utc_offset[0] == '-':
timezone_offset = -timezone_offset
if reporting_period_start_datetime_local is None:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
else:
reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
try:
reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
'%Y-%m-%dT%H:%M:%S')
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
reporting_start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - \
timedelta(minutes=timezone_offset)
if reporting_period_end_datetime_local is None:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
else:
reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
try:
reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
'%Y-%m-%dT%H:%M:%S')
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
reporting_end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) - \
timedelta(minutes=timezone_offset)
if reporting_start_datetime_utc >= reporting_end_datetime_utc:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
cnx_system_db = mysql.connector.connect(**config.myems_system_db)
cursor_system_db = cnx_system_db.cursor(dictionary=True)
cursor_system_db.execute(" SELECT name "
" FROM tbl_spaces "
" WHERE id = %s ", (space_id,))
row = cursor_system_db.fetchone()
if row is None:
if cursor_system_db:
cursor_system_db.close()
if cnx_system_db:
cnx_system_db.disconnect()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.SPACE_NOT_FOUND')
else:
space_name = row['name']
################################################################################################################
# Step 2: build a space tree
################################################################################################################
query = (" SELECT id, name, parent_space_id "
" FROM tbl_spaces "
" ORDER BY id ")
cursor_system_db.execute(query)
rows_spaces = cursor_system_db.fetchall()
node_dict = dict()
if rows_spaces is not None and len(rows_spaces) > 0:
for row in rows_spaces:
parent_node = node_dict[row['parent_space_id']] if row['parent_space_id'] is not None else None
node_dict[row['id']] = AnyNode(id=row['id'], parent=parent_node, name=row['name'])
################################################################################################################
# Step 3: query all combined equipments in the space tree
################################################################################################################
combined_equipment_dict = dict()
space_dict = dict()
for node in LevelOrderIter(node_dict[space_id]):
space_dict[node.id] = node.name
cursor_system_db.execute(" SELECT ce.id, ce.name AS combined_equipment_name, s.name AS space_name, "
" cc.name AS cost_center_name, ce.description "
" FROM tbl_spaces s, tbl_spaces_combined_equipments sce, "
" tbl_combined_equipments ce, tbl_cost_centers cc "
" WHERE s.id IN ( " + ', '.join(map(str, space_dict.keys())) + ") "
" AND sce.space_id = s.id AND sce.combined_equipment_id = ce.id "
" AND ce.cost_center_id = cc.id ", )
rows_combined_equipments = cursor_system_db.fetchall()
if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
for row in rows_combined_equipments:
combined_equipment_dict[row['id']] = {"combined_equipment_name": row['combined_equipment_name'],
"space_name": row['space_name'],
"cost_center_name": row['cost_center_name'],
"description": row['description'],
"values": list()}
################################################################################################################
# Step 4: query energy categories
################################################################################################################
cnx_energy_db = mysql.connector.connect(**config.myems_energy_db)
cursor_energy_db = cnx_energy_db.cursor()
# query energy categories in reporting period
energy_category_set = set()
cursor_energy_db.execute(" SELECT DISTINCT(energy_category_id) "
" FROM tbl_combined_equipment_input_category_hourly "
" WHERE start_datetime_utc >= %s AND start_datetime_utc < %s ",
(reporting_start_datetime_utc, reporting_end_datetime_utc))
rows_energy_categories = cursor_energy_db.fetchall()
if rows_energy_categories is not None or len(rows_energy_categories) > 0:
for row_energy_category in rows_energy_categories:
energy_category_set.add(row_energy_category[0])
# query all energy categories
cursor_system_db.execute(" SELECT id, name, unit_of_measure "
" FROM tbl_energy_categories "
" ORDER BY id ", )
rows_energy_categories = cursor_system_db.fetchall()
if rows_energy_categories is None or len(rows_energy_categories) == 0:
if cursor_system_db:
cursor_system_db.close()
if cnx_system_db:
cnx_system_db.disconnect()
if cursor_energy_db:
cursor_energy_db.close()
if cnx_energy_db:
cnx_energy_db.disconnect()
raise falcon.HTTPError(falcon.HTTP_404,
title='API.NOT_FOUND',
description='API.ENERGY_CATEGORY_NOT_FOUND')
energy_category_list = list()
for row_energy_category in rows_energy_categories:
if row_energy_category['id'] in energy_category_set:
energy_category_list.append({"id": row_energy_category['id'],
"name": row_energy_category['name'],
"unit_of_measure": row_energy_category['unit_of_measure']})
################################################################################################################
# Step 5: query reporting period energy input
################################################################################################################
for combined_equipment_id in combined_equipment_dict:
cursor_energy_db.execute(" SELECT energy_category_id, SUM(actual_value) "
" FROM tbl_combined_equipment_input_category_hourly "
" WHERE combined_equipment_id = %s "
" AND start_datetime_utc >= %s "
" AND start_datetime_utc < %s "
" GROUP BY energy_category_id ",
(combined_equipment_id,
reporting_start_datetime_utc,
reporting_end_datetime_utc))
rows_combined_equipment_energy = cursor_energy_db.fetchall()
for energy_category in energy_category_list:
subtotal = Decimal(0.0)
for row_combined_equipment_energy in rows_combined_equipment_energy:
if energy_category['id'] == row_combined_equipment_energy[0]:
subtotal = row_combined_equipment_energy[1]
break
combined_equipment_dict[combined_equipment_id]['values'].append(subtotal)
if cursor_system_db:
cursor_system_db.close()
if cnx_system_db:
cnx_system_db.disconnect()
if cursor_energy_db:
cursor_energy_db.close()
if cnx_energy_db:
cnx_energy_db.disconnect()
################################################################################################################
# Step 6: construct the report
################################################################################################################
combined_equipment_list = list()
for combined_equipment_id, combined_equipment in combined_equipment_dict.items():
combined_equipment_list.append({
"id": combined_equipment_id,
"combined_equipment_name": combined_equipment['combined_equipment_name'],
"space_name": combined_equipment['space_name'],
"cost_center_name": combined_equipment['cost_center_name'],
"description": combined_equipment['description'],
"values": combined_equipment['values'],
})
result = {'combined_equipments': combined_equipment_list,
'energycategories': energy_category_list}
# export result to Excel file and then encode the file to base64 string
result['excel_bytes_base64'] = \
excelexporters.combinedequipmentbatch.export(result,
space_name,
reporting_period_start_datetime_local,
reporting_period_end_datetime_local)
resp.body = json.dumps(result)

View File

@ -0,0 +1,330 @@
import React, { Fragment, useEffect, useState } from 'react';
import {
Breadcrumb,
BreadcrumbItem,
Row,
Col,
Card,
CardBody,
Button,
ButtonGroup,
Form,
FormGroup,
Input,
Label,
CustomInput,
Spinner,
} from 'reactstrap';
import Datetime from 'react-datetime';
import moment from 'moment';
import loadable from '@loadable/component';
import Cascader from 'rc-cascader';
import { getCookieValue, createCookie } from '../../../helpers/utils';
import withRedirect from '../../../hoc/withRedirect';
import { withTranslation } from 'react-i18next';
import { toast } from 'react-toastify';
import ButtonIcon from '../../common/ButtonIcon';
import { APIBaseURL } from '../../../config';
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const CombinedEquipmentBatch = ({ setRedirect, setRedirectUrl, t }) => {
let current_moment = moment();
useEffect(() => {
let is_logged_in = getCookieValue('is_logged_in');
let user_name = getCookieValue('user_name');
let user_display_name = getCookieValue('user_display_name');
let user_uuid = getCookieValue('user_uuid');
let token = getCookieValue('token');
if (is_logged_in === null || !is_logged_in) {
setRedirectUrl(`/authentication/basic/login`);
setRedirect(true);
} else {
//update expires time of cookies
createCookie('is_logged_in', true, 1000 * 60 * 60 * 8);
createCookie('user_name', user_name, 1000 * 60 * 60 * 8);
createCookie('user_display_name', user_display_name, 1000 * 60 * 60 * 8);
createCookie('user_uuid', user_uuid, 1000 * 60 * 60 * 8);
createCookie('token', token, 1000 * 60 * 60 * 8);
}
});
// State
// Query Parameters
const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
const [selectedSpaceID, setSelectedSpaceID] = useState(undefined);
const [combinedEquipmentList, setCombinedEquipmentList] = useState([]);
const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('month'));
const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment);
const [cascaderOptions, setCascaderOptions] = useState(undefined);
// buttons
const [submitButtonDisabled, setSubmitButtonDisabled] = useState(false);
const [spinnerHidden, setSpinnerHidden] = useState(true);
const [exportButtonHidden, setExportButtonHidden] = useState(true);
//Results
const [detailedDataTableColumns, setDetailedDataTableColumns] = useState(
[{dataField: 'name', text: t('Name'), sort: true}, {dataField: 'space', text: t('Space'), sort: true}]);
const [excelBytesBase64, setExcelBytesBase64] = useState(undefined);
useEffect(() => {
let isResponseOK = false;
fetch(APIBaseURL + '/spaces/tree', {
method: 'GET',
headers: {
"Content-type": "application/json",
"User-UUID": getCookieValue('user_uuid'),
"Token": getCookieValue('token')
},
body: null,
}).then(response => {
console.log(response);
if (response.ok) {
isResponseOK = true;
}
return response.json();
}).then(json => {
console.log(json);
if (isResponseOK) {
// rename keys
json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":'));
setCascaderOptions(json);
// set the default selected space
setSelectedSpaceName([json[0]].map(o => o.label));
setSelectedSpaceID([json[0]].map(o => o.value));
setSubmitButtonDisabled(false);
setSpinnerHidden(true);
} else {
toast.error(json.description);
}
}).catch(err => {
console.log(err);
});
}, []);
const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
let onSpaceCascaderChange = (value, selectedOptions) => {
setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
setSelectedSpaceID(value[value.length - 1]);
setCombinedEquipmentList([]);
setExportButtonHidden(true);
setSubmitButtonDisabled(false);
}
let onReportingPeriodBeginsDatetimeChange = (newDateTime) => {
setReportingPeriodBeginsDatetime(newDateTime);
}
let onReportingPeriodEndsDatetimeChange = (newDateTime) => {
setReportingPeriodEndsDatetime(newDateTime);
}
var getValidReportingPeriodBeginsDatetimes = function (currentDate) {
return currentDate.isBefore(moment(reportingPeriodEndsDatetime, 'MM/DD/YYYY, hh:mm:ss a'));
}
var getValidReportingPeriodEndsDatetimes = function (currentDate) {
return currentDate.isAfter(moment(reportingPeriodBeginsDatetime, 'MM/DD/YYYY, hh:mm:ss a'));
}
// Handler
const handleSubmit = e => {
e.preventDefault();
console.log('handleSubmit');
console.log(selectedSpaceID);
console.log(reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss'));
console.log(reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss'));
// disable submit button
setSubmitButtonDisabled(true);
// show spinner
setSpinnerHidden(false);
// hide export buttion
setExportButtonHidden(true)
// Reinitialize tables
setCombinedEquipmentList([]);
let isResponseOK = false;
fetch(APIBaseURL + '/reports/combinedequipmentbatch?' +
'spaceid=' + selectedSpaceID +
'&reportingperiodstartdatetime=' + reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') +
'&reportingperiodenddatetime=' + reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss'), {
method: 'GET',
headers: {
"Content-type": "application/json",
"User-UUID": getCookieValue('user_uuid'),
"Token": getCookieValue('token')
},
body: null,
}).then(response => {
if (response.ok) {
isResponseOK = true;
};
return response.json();
}).then(json => {
if (isResponseOK) {
console.log(json)
let combined_equipments = [];
if (json['combined_equipments'].length > 0) {
json['combined_equipments'].forEach((currentCombinedEquipment, index) => {
let detailed_value = {};
detailed_value['id'] = currentCombinedEquipment['id'];
detailed_value['name'] = currentCombinedEquipment['combined_equipment_name'];
detailed_value['space'] = currentCombinedEquipment['space_name'];
detailed_value['costcenter'] = currentCombinedEquipment['cost_center_name'];
currentCombinedEquipment['values'].forEach((currentValue, energyCategoryIndex) => {
detailed_value['a' + energyCategoryIndex] = currentValue.toFixed(2);
});
combined_equipments.push(detailed_value);
});
};
setCombinedEquipmentList(combined_equipments);
let detailed_column_list = [];
detailed_column_list.push({
dataField: 'name',
text: t('Name'),
sort: true
});
detailed_column_list.push({
dataField: 'space',
text: t('Space'),
sort: true
});
json['energycategories'].forEach((currentValue, index) => {
detailed_column_list.push({
dataField: 'a' + index,
text: currentValue['name'] + ' (' + currentValue['unit_of_measure'] + ')',
sort: true
})
});
setDetailedDataTableColumns(detailed_column_list);
setExcelBytesBase64(json['excel_bytes_base64']);
// enable submit button
setSubmitButtonDisabled(false);
// hide spinner
setSpinnerHidden(true);
// show export buttion
setExportButtonHidden(false);
} else {
toast.error(json.description)
}
}).catch(err => {
console.log(err);
});
};
const handleExport = e => {
e.preventDefault();
const mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const fileName = 'combinedequipmentbatch.xlsx'
var fileUrl = "data:" + mimeType + ";base64," + excelBytesBase64;
fetch(fileUrl)
.then(response => response.blob())
.then(blob => {
var link = window.document.createElement("a");
link.href = window.URL.createObjectURL(blob, { type: mimeType });
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
};
return (
<Fragment>
<div>
<Breadcrumb>
<BreadcrumbItem>{t('Combined Equipment Data')}</BreadcrumbItem><BreadcrumbItem active>{t('Batch Analysis')}</BreadcrumbItem>
</Breadcrumb>
</div>
<Card className="bg-light mb-3">
<CardBody className="p-3">
<Form onSubmit={handleSubmit}>
<Row form>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="space">
{t('Space')}
</Label>
<br />
<Cascader options={cascaderOptions}
onChange={onSpaceCascaderChange}
changeOnSelect
expandTrigger="hover">
<Input value={selectedSpaceName || ''} readOnly />
</Cascader>
</FormGroup>
</Col>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="reportingPeriodBeginsDatetime">
{t('Reporting Period Begins')}
</Label>
<Datetime id='reportingPeriodBeginsDatetime'
value={reportingPeriodBeginsDatetime}
onChange={onReportingPeriodBeginsDatetimeChange}
isValidDate={getValidReportingPeriodBeginsDatetimes}
closeOnSelect={true} />
</FormGroup>
</Col>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="reportingPeriodEndsDatetime">
{t('Reporting Period Ends')}
</Label>
<Datetime id='reportingPeriodEndsDatetime'
value={reportingPeriodEndsDatetime}
onChange={onReportingPeriodEndsDatetimeChange}
isValidDate={getValidReportingPeriodEndsDatetimes}
closeOnSelect={true} />
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br></br>
<ButtonGroup id="submit">
<Button color="success" disabled={submitButtonDisabled} >{t('Submit')}</Button>
</ButtonGroup>
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br></br>
<Spinner color="primary" hidden={spinnerHidden} />
</FormGroup>
</Col>
<Col xs="auto">
<br></br>
<ButtonIcon icon="external-link-alt" transform="shrink-3 down-2" color="falcon-default"
hidden={exportButtonHidden}
onClick={handleExport} >
{t('Export')}
</ButtonIcon>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<DetailedDataTable data={combinedEquipmentList} title={t('Detailed Data')} columns={detailedDataTableColumns} pagesize={50} >
</DetailedDataTable>
</Fragment>
);
};
export default withTranslation()(withRedirect(CombinedEquipmentBatch));

View File

@ -169,6 +169,7 @@ import CombinedEquipmentEfficiency from '../components/MyEMS/CombinedEquipment/C
import CombinedEquipmentLoad from '../components/MyEMS/CombinedEquipment/CombinedEquipmentLoad'; import CombinedEquipmentLoad from '../components/MyEMS/CombinedEquipment/CombinedEquipmentLoad';
import CombinedEquipmentStatistics from '../components/MyEMS/CombinedEquipment/CombinedEquipmentStatistics'; import CombinedEquipmentStatistics from '../components/MyEMS/CombinedEquipment/CombinedEquipmentStatistics';
import CombinedEquipmentSaving from '../components/MyEMS/CombinedEquipment/CombinedEquipmentSaving'; import CombinedEquipmentSaving from '../components/MyEMS/CombinedEquipment/CombinedEquipmentSaving';
import CombinedEquipmentBatch from '../components/MyEMS/CombinedEquipment/CombinedEquipmentBatch'
// Auxiliary System // Auxiliary System
import EnergyFlowDiagram from '../components/MyEMS/AuxiliarySystem/EnergyFlowDiagram'; import EnergyFlowDiagram from '../components/MyEMS/AuxiliarySystem/EnergyFlowDiagram';
import DistributionSystem from '../components/MyEMS/AuxiliarySystem/DistributionSystem'; import DistributionSystem from '../components/MyEMS/AuxiliarySystem/DistributionSystem';
@ -408,6 +409,7 @@ const MyEMSRoutes = () => (
<Route path="/combinedequipment/load" exact component={CombinedEquipmentLoad} /> <Route path="/combinedequipment/load" exact component={CombinedEquipmentLoad} />
<Route path="/combinedequipment/statistics" exact component={CombinedEquipmentStatistics} /> <Route path="/combinedequipment/statistics" exact component={CombinedEquipmentStatistics} />
<Route path="/combinedequipment/saving" exact component={CombinedEquipmentSaving} /> <Route path="/combinedequipment/saving" exact component={CombinedEquipmentSaving} />
<Route path="/combinedequipment/batch" exact component={CombinedEquipmentBatch} />
{/*Auxiliary System*/} {/*Auxiliary System*/}
<Route path="/auxiliarysystem/energyflowdiagram" exact component={EnergyFlowDiagram} /> <Route path="/auxiliarysystem/energyflowdiagram" exact component={EnergyFlowDiagram} />

View File

@ -423,6 +423,7 @@ export const combinedEquipmentRoutes = {
{ to: '/combinedequipment/load', name: 'Load' }, { to: '/combinedequipment/load', name: 'Load' },
{ to: '/combinedequipment/statistics', name: 'Statistics' }, { to: '/combinedequipment/statistics', name: 'Statistics' },
{ to: '/combinedequipment/saving', name: 'Saving' }, { to: '/combinedequipment/saving', name: 'Saving' },
{ to: '/combinedequipment/batch', name: 'Batch Analysis'},
] ]
}; };