提交 5ba24fb1 编写于 作者: nengyuangzhang's avatar nengyuangzhang

Merge branch 'develop'

......@@ -7,13 +7,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- added working-days/non-working-days data into tenant energy categroy report
- added working-days/non-working-days data into store energy categroy report
-
- added working-days/non-working-days data into shopfloor energy categroy report
### Changed
- None
### Fixed
- fixed null tooltip issue in MultiTrendChart.js
-
### Removed
- None
## [v3.0.0] - 2023-02-25
### Added
......
......@@ -911,6 +911,8 @@ app
'app/services/settings/shopfloor/shopfloormeter.service.js',
'app/services/settings/shopfloor/shopfloorpoint.service.js',
'app/services/settings/shopfloor/shopfloorsensor.service.js',
'app/services/settings/shopfloor/shopfloorworkingcalendar.service.js',
'app/services/settings/workingcalendar/workingcalendar.service.js',
'app/services/settings/datasource/datasource.service.js',
'app/services/settings/datasource/point.service.js',
'app/services/settings/equipment/equipment.service.js',
......@@ -921,6 +923,7 @@ app
'app/controllers/settings/shopfloor/shopfloormeter.controller.js',
'app/controllers/settings/shopfloor/shopfloorpoint.controller.js',
'app/controllers/settings/shopfloor/shopfloorsensor.controller.js',
'app/controllers/settings/shopfloor/shopfloorworkingcalendar.controller.js',
]
}]);
}
......
'use strict';
app.controller('ShopfloorWorkingCalendarController', function(
$scope ,
$window,
$timeout,
$translate,
ShopfloorService,
WorkingCalendarService,
ShopfloorWorkingCalendarService, toaster,SweetAlert) {
$scope.shopfloors = [];
$scope.currentShopfloorID = 1;
$scope.shopfloorworkingcalendars = [];
$scope.cur_user = JSON.parse($window.localStorage.getItem("myems_admin_ui_current_user"));
$scope.changeShopfloor=function(item,model){
$scope.currentShopfloor=item;
$scope.currentShopfloor.selected=model;
$scope.getWorkingCalendarsByShopfloorID($scope.currentShopfloor.id);
};
$scope.getAllShopfloors = function(id) {
ShopfloorService.getAllShopfloors(function (response) {
if (angular.isDefined(response.status) && response.status === 200) {
$scope.shopfloors = response.data;
} else {
$scope.shopfloors = [];
}
});
};
$scope.getWorkingCalendarsByShopfloorID = function(id) {
$scope.shopfloorworkingcalendars=[];
ShopfloorWorkingCalendarService.getWorkingCalendarsByShopfloorID(id, function (response) {
if (angular.isDefined(response.status) && response.status === 200) {
$scope.shopfloorworkingcalendars = response.data;
}
});
};
$scope.getAllWorkingCalendars = function() {
WorkingCalendarService.getAllWorkingCalendars(function (response) {
if (angular.isDefined(response.status) && response.status === 200) {
$scope.workingcalendars = response.data;
} else {
$scope.workingcalendars = [];
}
});
};
$scope.pairWorkingCalendar=function(dragEl,dropEl){
var workingcalendarid=angular.element('#'+dragEl).scope().workingcalendar.id;
var shopfloorid = $scope.currentShopfloor.id;
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
ShopfloorWorkingCalendarService.addPair(shopfloorid, workingcalendarid, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 201) {
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.BIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByShopfloorID(shopfloorid);
} else {
toaster.pop({
type: "error",
title: $translate.instant(response.data.title),
body: $translate.instant(response.data.description),
showCloseButton: true,
});
}
});
};
$scope.deleteWorkingCalendarPair=function(dragEl,dropEl){
if(angular.element('#'+dragEl).hasClass('source')){
return;
}
var shopfloorworkingcalendarid = angular.element('#' + dragEl).scope().shopfloorworkingcalendar.id;
var shopfloorid = $scope.currentShopfloor.id;
let headers = { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token };
ShopfloorWorkingCalendarService.deletePair(shopfloorid, shopfloorworkingcalendarid, headers, function (response) {
if (angular.isDefined(response.status) && response.status === 204) {
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.UNBIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByShopfloorID(shopfloorid);
} else {
toaster.pop({
type: "error",
title: $translate.instant(response.data.title),
body: $translate.instant(response.data.description),
showCloseButton: true,
});
}
});
};
$scope.getAllShopfloors();
$scope.getAllWorkingCalendars();
$scope.$on('handleBroadcastShopfloorChanged', function(event) {
$scope.shopfloorworkingcalendars = [];
$scope.getAllShopfloors();
});
});
......@@ -77,7 +77,7 @@ app.controller('SpaceWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.BIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.BIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsBySpaceID(spaceid);
......@@ -104,7 +104,7 @@ app.controller('SpaceWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.UNBIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.UNBIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsBySpaceID(spaceid);
......
......@@ -58,7 +58,7 @@ app.controller('StoreWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.BIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.BIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByStoreID(storeid);
......@@ -85,7 +85,7 @@ app.controller('StoreWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.UNBIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.UNBIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByStoreID(storeid);
......
......@@ -58,7 +58,7 @@ app.controller('TenantWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.BIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.BIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByTenantID(tenantid);
......@@ -85,7 +85,7 @@ app.controller('TenantWorkingCalendarController', function(
toaster.pop({
type: "success",
title: $translate.instant("TOASTER.SUCCESS_TITLE"),
body: $translate.instant("TOASTER.UNBIND_METER_SUCCESS"),
body: $translate.instant("TOASTER.UNBIND_WORKING_CALENDAR_SUCCESS"),
showCloseButton: true,
});
$scope.getWorkingCalendarsByTenantID(tenantid);
......
'use strict';
app.factory('ShopfloorWorkingCalendarService', function($http) {
return {
addPair: function(shopfloorID, workingcalendarID, headers, callback) {
$http.post(getAPI()+'shopfloors/'+shopfloorID+'/workingcalendars', {data: {"working_calendar_id": workingcalendarID}}, {headers})
.then(function (response) {
callback(response);
}, function (response) {
callback(response);
});
},
deletePair: function(shopfloorID, workingcalendarID, headers, callback) {
$http.delete(getAPI()+'shopfloors/'+shopfloorID+'/workingcalendars'+'/'+workingcalendarID, {headers})
.then(function (response) {
callback(response);
}, function (response) {
callback(response);
});
},
getWorkingCalendarsByShopfloorID: function(id, callback) {
$http.get(getAPI()+'shopfloors/'+id+'/workingcalendars')
.then(function (response) {
callback(response);
}, function (response) {
callback(response);
});
}
};
});
......@@ -363,6 +363,79 @@
</div>
</uib-tab>
<uib-tab heading="{{'WORKING_CALENDAR.BIND_WORKING_CALENDAR' | translate}}">
<div class="panel-body" ng-controller="ShopfloorWorkingCalendarController">
<div class="row">
<div class="col-lg-3">
<div class="panel panel-info">
<div class="panel-heading">
{{'COMMON.SHOPFLOOR' | translate}}
</div>
<div class="panel-body">
<form role="form">
<div class="form-group no-margin">
<label>{{'SHOPFLOOR.SELECT_SHOPFLOOR' | translate}}</label>
<ui-select on-select="changeShopfloor($item,$model)"
ng-model="currentShopfloor.selected" theme="bootstrap">
<ui-select-match
placeholder="{{'COMMON.PLACEHOLDER' | translate}}">
{{$select.selected.name}}</ui-select-match>
<ui-select-choices
repeat="shopfloor.id as shopfloor in shopfloors | filter: $select.search">
<div ng-bind-html="shopfloor.name | highlight: $select.search">
</div>
</ui-select-choices>
</ui-select>
</div>
</form>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="panel panel-primary">
<div class="panel-heading">
{{'WORKING_CALENDAR.N_S_WORKING_CALENDAR' | translate}}
</div>
<div class="panel-body maxheight"
x-hjc-drop-target="true"
x-on-drop="pairWorkingCalendar(dragEl,dropEl)"
uib-tooltip="{{'SETTING.DRAG_TO_UNBIND' | translate}}">
<div class="btn btn-primary btn-rounded btn-block"
ng-repeat="shopfloorworkingcalendar in shopfloorworkingcalendars" x-hjc-draggable="true"
title="{{shopfloorworkingcalendar.name}}">
({{shopfloorworkingcalendar.name}})</div>
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
{{'SETTING.TRASH' | translate}}
</div>
<div class="panel-body trash">
<img class="trashcan" src="img/trashcan.png" x-hjc-drop-target="true"
x-on-drop="deleteWorkingCalendarPair(dragEl,dropEl)">
</div>
</div>
</div>
<div class="col-lg-4">
<!-- according panel-->
<div class="panel panel-primary">
<div class="panel-heading">
{{'SETTING.WORKING_CALENDAR' | translate}}
</div>
<div class="panel-body" uib-tooltip="{{'SETTING.DRAG_TO_BIND' | translate}}"
slim-scroll box-height="765px">
<div class="source btn btn-primary btn-rounded btn-block"
ng-repeat="workingcalendar in workingcalendars" x-hjc-draggable="true">
{{workingcalendar.name}}</div>
</div>
</div>
</div>
</div>
</div>
</uib-tab>
</uib-tabset>
</div>
</div>
......
......@@ -345,6 +345,10 @@ api.add_route('/shopfloors/{id_}/virtualmeters',
shopfloor.ShopfloorVirtualMeterCollection())
api.add_route('/shopfloors/{id_}/virtualmeters/{mid}',
shopfloor.ShopfloorVirtualMeterItem())
api.add_route('/shopfloors/{id_}/workingcalendars',
shopfloor.ShopfloorWorkingCalendarCollection())
api.add_route('/shopfloors/{id_}/workingcalendars/{wcid}',
shopfloor.ShopfloorWorkingCalendarItem())
api.add_route('/spaces',
space.SpaceCollection())
......
......@@ -1572,3 +1572,170 @@ class ShopfloorVirtualMeterItem:
resp.status = falcon.HTTP_204
class ShopfloorWorkingCalendarCollection:
@staticmethod
def __init__():
"""Initializes ShopfloorWorkingCalendarCollection Class"""
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_SHOPFLOOR_ID')
cnx = mysql.connector.connect(**config.myems_system_db)
cursor = cnx.cursor()
cursor.execute(" SELECT name "
" FROM tbl_shopfloors "
" WHERE id = %s ", (id_,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.SHOPFLOOR_NOT_FOUND')
query = (" SELECT wc.id, wc.name, wc.description "
" FROM tbl_shopfloors s, tbl_shopfloors_working_calendars swc, tbl_working_calendars wc "
" WHERE swc.shopfloor_id = s.id AND wc.id = swc.working_calendar_id AND s.id = %s "
" ORDER BY wc.id ")
cursor.execute(query, (id_,))
rows = cursor.fetchall()
result = list()
if rows is not None and len(rows) > 0:
for row in rows:
meta_result = {"id": row[0], "name": row[1], "description": row[2]}
result.append(meta_result)
resp.text = json.dumps(result)
@staticmethod
@user_logger
def on_post(req, resp, id_):
"""Handles POST requests"""
access_control(req)
try:
raw_json = req.stream.read().decode('utf-8')
except Exception as ex:
raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=str(ex))
if not id_.isdigit() or int(id_) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_SHOPFLOOR_ID')
new_values = json.loads(raw_json)
if 'working_calendar_id' not in new_values['data'].keys() or \
not isinstance(new_values['data']['working_calendar_id'], int) or \
new_values['data']['working_calendar_id'] <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_WORKING_CALENDAR_ID')
working_calendar_id = new_values['data']['working_calendar_id']
cnx = mysql.connector.connect(**config.myems_system_db)
cursor = cnx.cursor()
cursor.execute(" SELECT name "
" from tbl_shopfloors "
" WHERE id = %s ", (id_,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.SHOPFLOOR_NOT_FOUND')
cursor.execute(" SELECT name "
" FROM tbl_working_calendars "
" WHERE id = %s ", (working_calendar_id,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.WORKING_CALENDAR_NOT_FOUND')
query = (" SELECT id "
" FROM tbl_shopfloors_working_calendars "
" WHERE shopfloor_id = %s AND working_calendar_id = %s")
cursor.execute(query, (id_, working_calendar_id,))
if cursor.fetchone() is not None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR',
description='API.SHOPFLOOR_WORKING_CALENDAR_RELATION_EXISTS')
add_row = (" INSERT INTO tbl_shopfloors_working_calendars (shopfloor_id, working_calendar_id) "
" VALUES (%s, %s) ")
cursor.execute(add_row, (id_, working_calendar_id,))
cnx.commit()
cursor.close()
cnx.close()
resp.status = falcon.HTTP_201
resp.location = '/shopfloors/' + str(id_) + '/workingcalendars/' + str(working_calendar_id)
class ShopfloorWorkingCalendarItem:
@staticmethod
def __init__():
"""Initializes ShopfloorWorkingCalendarItem Class"""
pass
@staticmethod
def on_options(req, resp, id_, wcid):
resp.status = falcon.HTTP_200
@staticmethod
@user_logger
def on_delete(req, resp, id_, wcid):
access_control(req)
if not id_.isdigit() or int(id_) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_SHOPFLOOR_ID')
if not wcid.isdigit() or int(wcid) <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_WORKING_CALENDAR_ID')
cnx = mysql.connector.connect(**config.myems_system_db)
cursor = cnx.cursor()
cursor.execute(" SELECT name "
" FROM tbl_shopfloors "
" WHERE id = %s ", (id_,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.SHOPFLOOR_NOT_FOUND')
cursor.execute(" SELECT name "
" FROM tbl_working_calendars "
" WHERE id = %s ", (wcid,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.WORKING_CALENDAR_NOT_FOUND')
cursor.execute(" SELECT id "
" FROM tbl_shopfloors_working_calendars "
" WHERE shopfloor_id = %s AND working_calendar_id = %s ", (id_, wcid))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.SHOPFLOOR_WORKING_CALENDAR_RELATION_NOT_FOUND')
cursor.execute(" DELETE FROM tbl_shopfloors_working_calendars WHERE shopfloor_id = %s AND working_calendar_id = %s ", (id_, wcid))
cnx.commit()
cursor.close()
cnx.close()
resp.status = falcon.HTTP_204
\ No newline at end of file
......@@ -134,6 +134,15 @@ class WorkingCalendarItem:
cnx = mysql.connector.connect(**config.myems_system_db)
cursor = cnx.cursor()
cursor.execute(" SELECT id "
" FROM tbl_working_calendars "
" WHERE id = %s ", (id_,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.WORKING_CALENDAR_NOT_FOUND')
# check relation with space
cursor.execute(" SELECT id FROM tbl_spaces_working_calendars"
" WHERE working_calendar_id = %s ", (id_,))
......@@ -169,6 +178,18 @@ class WorkingCalendarItem:
raise falcon.HTTPError(falcon.HTTP_400,
title='API.BAD_REQUEST',
description='API.THERE_IS_RELATION_WITH_STORES')
# check relation with shopfloors
cursor.execute(" SELECT shopfloor_id "
" FROM tbl_shopfloors_working_calendars "
" WHERE working_calendar_id = %s ", (id_,))
rows_shopfloors = cursor.fetchall()
if rows_shopfloors is not None and len(rows_shopfloors) > 0:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_400,
title='API.BAD_REQUEST',
description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
# check relation with non working days
cursor.execute(" SELECT id FROM tbl_working_calendars_non_working_days"
......@@ -387,6 +408,15 @@ class NonWorkingDayItem:
cnx = mysql.connector.connect(**config.myems_system_db)
cursor = cnx.cursor()
cursor.execute(" SELECT id "
" FROM tbl_working_calendars_non_working_days "
" WHERE id = %s ", (id_,))
if cursor.fetchone() is None:
cursor.close()
cnx.close()
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.NON_WORKING_DAY_NOT_FOUND')
cursor.execute(" DELETE FROM tbl_working_calendars_non_working_days WHERE id = %s ", (id_,))
cnx.commit()
......@@ -413,7 +443,7 @@ class NonWorkingDayItem:
not isinstance(new_values['data']['working_calendar_id'], int) or \
new_values['data']['working_calendar_id'] <= 0:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description='API.INVALID_WORKING_CALENDAR_NAME')
description='API.INVALID_WORKING_CALENDAR_ID')
working_calendar_id = new_values['data']['working_calendar_id']
if 'date_local' in new_values['data'].keys() and \
......
......@@ -534,6 +534,130 @@ def generate_excel(report,
current_row_number += 1
####################################################################################################################
if "non_working_days_subtotals" not in report['base_period'].keys() or \
report['base_period']['non_working_days_subtotals'] is None or \
len(report['base_period']['non_working_days_subtotals']) == 0 or \
"working_days_subtotals" not in report['base_period'].keys() or \
report['base_period']['working_days_subtotals'] is None or \
len(report['base_period']['working_days_subtotals']) == 0 or \
base_period_start_datetime_local is None or \
len(str.strip(base_period_start_datetime_local)) == 0 or \
base_period_end_datetime_local is None or \
len(str.strip(base_period_end_datetime_local)) == 0:
pass
else:
ws['B' + str(current_row_number)].font = title_font
ws['B' + str(current_row_number)] = name + ' ' + _('Base Period Consumption')
current_row_number += 1
ws.row_dimensions[current_row_number].height = 60
ws['B' + str(current_row_number)].fill = table_fill
ws['B' + str(current_row_number)].font = name_font
ws['B' + str(current_row_number)].alignment = c_c_alignment
ws['B' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)].fill = table_fill
ws['C' + str(current_row_number)].font = name_font
ws['C' + str(current_row_number)].alignment = c_c_alignment
ws['C' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)] = _('Non Working Days') + _('Consumption')
ws['D' + str(current_row_number)].fill = table_fill
ws['D' + str(current_row_number)].font = name_font
ws['D' + str(current_row_number)].alignment = c_c_alignment
ws['D' + str(current_row_number)].border = f_border
ws['D' + str(current_row_number)] = _('Working Days') + _('Consumption')
current_row_number += 1
ca_len = len(report['base_period']['names'])
for i in range(0, ca_len):
ws['B' + str(current_row_number)].font = title_font
ws['B' + str(current_row_number)].alignment = c_c_alignment
ws['B' + str(current_row_number)] = report['base_period']['names'][i] + " (" + report['base_period']['units'][i] + ")"
ws['B' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)].font = title_font
ws['C' + str(current_row_number)].alignment = c_c_alignment
ws['C' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)] = report['base_period']['non_working_days_subtotals'][i] if \
len(report['shopfloor']['working_calendars']) > 0 and \
report['base_period']['non_working_days_subtotals'][i] > 0 else '-'
ws['D' + str(current_row_number)].font = title_font
ws['D' + str(current_row_number)].alignment = c_c_alignment
ws['D' + str(current_row_number)].border = f_border
ws['D' + str(current_row_number)] = report['base_period']['working_days_subtotals'][i] if \
len(report['shopfloor']['working_calendars']) > 0 and \
report['base_period']['working_days_subtotals'][i] > 0 else '-'
current_row_number += 1
current_row_number += 1
if "non_working_days_subtotals" not in report['reporting_period'].keys() or \
report['reporting_period']['non_working_days_subtotals'] is None or \
len(report['reporting_period']['non_working_days_subtotals']) == 0 or \
"working_days_subtotals" not in report['reporting_period'].keys() or \
report['reporting_period']['working_days_subtotals'] is None or \
len(report['reporting_period']['working_days_subtotals']) == 0:
pass
else:
ws['B' + str(current_row_number)].font = title_font
ws['B' + str(current_row_number)] = name + ' ' + _('Reporting Period Consumption')
current_row_number += 1
ws.row_dimensions[current_row_number].height = 60
ws['B' + str(current_row_number)].fill = table_fill
ws['B' + str(current_row_number)].font = name_font
ws['B' + str(current_row_number)].alignment = c_c_alignment
ws['B' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)].fill = table_fill
ws['C' + str(current_row_number)].font = name_font
ws['C' + str(current_row_number)].alignment = c_c_alignment
ws['C' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)] = _('Non Working Days') + _('Consumption')
ws['D' + str(current_row_number)].fill = table_fill
ws['D' + str(current_row_number)].font = name_font
ws['D' + str(current_row_number)].alignment = c_c_alignment
ws['D' + str(current_row_number)].border = f_border
ws['D' + str(current_row_number)] = _('Working Days') + _('Consumption')
current_row_number += 1
ca_len = len(report['reporting_period']['names'])
for i in range(0, ca_len):
ws['B' + str(current_row_number)].font = title_font
ws['B' + str(current_row_number)].alignment = c_c_alignment
ws['B' + str(current_row_number)] = report['reporting_period']['names'][i] + " (" + report['reporting_period']['units'][i] + ")"
ws['B' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)].font = title_font
ws['C' + str(current_row_number)].alignment = c_c_alignment
ws['C' + str(current_row_number)].border = f_border
ws['C' + str(current_row_number)] = report['reporting_period']['non_working_days_subtotals'][i] if \
len(report['shopfloor']['working_calendars']) > 0 and \
report['reporting_period']['non_working_days_subtotals'][i] > 0 else '-'
ws['D' + str(current_row_number)].font = title_font
ws['D' + str(current_row_number)].alignment = c_c_alignment
ws['D' + str(current_row_number)].border = f_border
ws['D' + str(current_row_number)] = report['reporting_period']['working_days_subtotals'][i] if \
len(report['shopfloor']['working_calendars']) > 0 and \
report['reporting_period']['working_days_subtotals'][i] > 0 else '-'
current_row_number += 1
current_row_number += 2
####################################################################################################################
# Fifth: Detailed Data
####################################################################################################################
......
......@@ -29,11 +29,12 @@ class Reporting:
# Step 3: query energy categories
# Step 4: query associated sensors
# Step 5: query associated points
# Step 6: query base period energy input
# Step 7: query reporting period energy input
# Step 8: query tariff data
# Step 9: query associated sensors and points data
# Step 10: construct the report
# Step 6: query associated working calendars
# Step 7: query base period energy input
# Step 8: query reporting period energy input
# Step 9: query tariff data
# Step 10: query associated sensors and points data
# Step 11: construct the report
####################################################################################################################
@staticmethod
def on_get(req, resp):
......@@ -87,6 +88,7 @@ class Reporting:
base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
try:
base_start_datetime_utc = datetime.strptime(base_period_start_datetime_local, '%Y-%m-%dT%H:%M:%S')
base_start_datetime_non_working_day = str(base_period_start_datetime_local).split('T')[0]
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_BASE_PERIOD_START_DATETIME")
......@@ -103,6 +105,7 @@ class Reporting:
base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
try:
base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
base_end_datetime_non_working_day = str(base_period_end_datetime_local).split('T')[0]
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_BASE_PERIOD_END_DATETIME")
......@@ -122,6 +125,7 @@ class Reporting:
try:
reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
'%Y-%m-%dT%H:%M:%S')
reporting_start_datetime_non_working_day = str(reporting_period_start_datetime_local).split('T')[0]
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
......@@ -142,6 +146,7 @@ class Reporting:
reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
'%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
timedelta(minutes=timezone_offset)
reporting_end_datetime_non_working_day = str(reporting_period_end_datetime_local).split('T')[0]
except ValueError:
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
......@@ -302,10 +307,40 @@ class Reporting:
point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
################################################################################################################
# Step 6: query base period energy input
# Step 6: query associated working calendars
################################################################################################################
working_calendar_list = list()
cursor_system.execute(" SELECT swc.id "
" FROM tbl_shopfloors sp, tbl_shopfloors_working_calendars swc "
" WHERE sp.id = %s AND sp.id = swc.shopfloor_id "
, (shopfloor['id'], ))
rows = cursor_system.fetchall()
if rows is not None and len(rows) > 0:
for row in rows:
working_calendar_list.append(row[0])
################################################################################################################
# Step 7: query base period energy input
################################################################################################################
base = dict()
base['non_working_days'] = list()
if energy_category_set is not None and len(energy_category_set) > 0:
if base_start_datetime_utc is not None and base_end_datetime_utc is not None:
cursor_system.execute(" SELECT nwd.date_local "
" FROM tbl_shopfloors sp, tbl_shopfloors_working_calendars spwc, "
" tbl_working_calendars_non_working_days nwd "
" WHERE sp.id = %s AND "
" sp.id = spwc.shopfloor_id AND "
" spwc.working_calendar_id = nwd.working_calendar_id AND"
" nwd.date_local >= %s AND"
" nwd.date_local <= %s ",
(shopfloor['id'],
base_start_datetime_non_working_day,
base_end_datetime_non_working_day))
rows = cursor_system.fetchall()
for row in rows:
row_datetime = row[0].strftime('%Y-%m-%d')
base['non_working_days'].append(row_datetime)
for energy_category_id in energy_category_set:
kgce = energy_category_dict[energy_category_id]['kgce']
kgco2e = energy_category_dict[energy_category_id]['kgco2e']
......@@ -316,6 +351,8 @@ class Reporting:
base[energy_category_id]['subtotal'] = Decimal(0.0)
base[energy_category_id]['subtotal_in_kgce'] = Decimal(0.0)
base[energy_category_id]['subtotal_in_kgco2e'] = Decimal(0.0)
base[energy_category_id]['non_working_days_subtotal'] = Decimal(0.0)
base[energy_category_id]['working_days_subtotal'] = Decimal(0.0)
cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
" FROM tbl_shopfloor_input_category_hourly "
......@@ -355,12 +392,32 @@ class Reporting:
base[energy_category_id]['subtotal'] += actual_value
base[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
base[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
if current_datetime in base['non_working_days']:
base[energy_category_id]['non_working_days_subtotal'] += actual_value
else:
base[energy_category_id]['working_days_subtotal'] += actual_value
################################################################################################################
# Step 8: query reporting period energy input
################################################################################################################
reporting = dict()
reporting['non_working_days'] = list()
if energy_category_set is not None and len(energy_category_set) > 0:
cursor_system.execute(" SELECT nwd.date_local "
" FROM tbl_shopfloors sp, tbl_shopfloors_working_calendars spwc, "
" tbl_working_calendars_non_working_days nwd "
" WHERE sp.id = %s AND "
" sp.id = spwc.shopfloor_id AND "
" spwc.working_calendar_id = nwd.working_calendar_id AND"
" nwd.date_local >= %s AND"
" nwd.date_local <= %s ",
(shopfloor['id'],
reporting_start_datetime_non_working_day,
reporting_end_datetime_non_working_day))
rows = cursor_system.fetchall()
for row in rows:
row_datetime = row[0].strftime('%Y-%m-%d')
reporting['non_working_days'].append(row_datetime)
for energy_category_id in energy_category_set:
kgce = energy_category_dict[energy_category_id]['kgce']
kgco2e = energy_category_dict[energy_category_id]['kgco2e']
......@@ -375,6 +432,8 @@ class Reporting:
reporting[energy_category_id]['onpeak'] = Decimal(0.0)
reporting[energy_category_id]['midpeak'] = Decimal(0.0)
reporting[energy_category_id]['offpeak'] = Decimal(0.0)
reporting[energy_category_id]['non_working_days_subtotal'] = Decimal(0.0)
reporting[energy_category_id]['working_days_subtotal'] = Decimal(0.0)
cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
" FROM tbl_shopfloor_input_category_hourly "
......@@ -414,6 +473,10 @@ class Reporting:
reporting[energy_category_id]['subtotal'] += actual_value
reporting[energy_category_id]['subtotal_in_kgce'] += actual_value * kgce
reporting[energy_category_id]['subtotal_in_kgco2e'] += actual_value * kgco2e
if current_datetime in reporting['non_working_days']:
reporting[energy_category_id]['non_working_days_subtotal'] += actual_value
else:
reporting[energy_category_id]['working_days_subtotal'] += actual_value
energy_category_tariff_dict = utilities.get_energy_category_peak_types(shopfloor['cost_center_id'],
energy_category_id,
......@@ -523,7 +586,7 @@ class Reporting:
parameters_data['values'].append(point_values)
################################################################################################################
# Step 12: construct the report
# Step 11: construct the report
################################################################################################################
if cursor_system:
cursor_system.close()
......@@ -545,6 +608,7 @@ class Reporting:
result['shopfloor'] = dict()
result['shopfloor']['name'] = shopfloor['name']
result['shopfloor']['area'] = shopfloor['area']
result['shopfloor']['working_calendars'] = working_calendar_list
result['base_period'] = dict()
result['base_period']['names'] = list()
......@@ -556,6 +620,10 @@ class Reporting:
result['base_period']['subtotals_in_kgco2e'] = list()
result['base_period']['total_in_kgce'] = Decimal(0.0)
result['base_period']['total_in_kgco2e'] = Decimal(0.0)
result['base_period']['non_working_days_subtotals'] = list()
result['base_period']['working_days_subtotals'] = list()
result['base_period']['non_working_days_total'] = Decimal(0.0)
result['base_period']['working_days_total'] = Decimal(0.0)
if energy_category_set is not None and len(energy_category_set) > 0:
for energy_category_id in energy_category_set:
result['base_period']['names'].append(energy_category_dict[energy_category_id]['name'])
......@@ -567,6 +635,10 @@ class Reporting:
result['base_period']['subtotals_in_kgco2e'].append(base[energy_category_id]['subtotal_in_kgco2e'])
result['base_period']['total_in_kgce'] += base[energy_category_id]['subtotal_in_kgce']
result['base_period']['total_in_kgco2e'] += base[energy_category_id]['subtotal_in_kgco2e']
result['base_period']['non_working_days_subtotals'].append(base[energy_category_id]['non_working_days_subtotal'])
result['base_period']['working_days_subtotals'].append(base[energy_category_id]['working_days_subtotal'])
result['base_period']['non_working_days_total'] += base[energy_category_id]['non_working_days_subtotal']
result['base_period']['working_days_total'] += base[energy_category_id]['working_days_subtotal']
result['reporting_period'] = dict()
result['reporting_period']['names'] = list()
......@@ -588,6 +660,10 @@ class Reporting:
result['reporting_period']['total_in_kgco2e'] = Decimal(0.0)
result['reporting_period']['increment_rate_in_kgce'] = Decimal(0.0)
result['reporting_period']['increment_rate_in_kgco2e'] = Decimal(0.0)
result['reporting_period']['non_working_days_subtotals'] = list()
result['reporting_period']['working_days_subtotals'] = list()
result['reporting_period']['non_working_days_total'] = Decimal(0.0)
result['reporting_period']['working_days_total'] = Decimal(0.0)
if energy_category_set is not None and len(energy_category_set) > 0:
for energy_category_id in energy_category_set:
......@@ -613,6 +689,10 @@ class Reporting:
if base[energy_category_id]['subtotal'] > 0.0 else None)
result['reporting_period']['total_in_kgce'] += reporting[energy_category_id]['subtotal_in_kgce']
result['reporting_period']['total_in_kgco2e'] += reporting[energy_category_id]['subtotal_in_kgco2e']
result['reporting_period']['non_working_days_subtotals'].append(reporting[energy_category_id]['non_working_days_subtotal'])
result['reporting_period']['working_days_subtotals'].append(reporting[energy_category_id]['working_days_subtotal'])
result['reporting_period']['non_working_days_total'] += reporting[energy_category_id]['non_working_days_subtotal']
result['reporting_period']['working_days_total'] += reporting[energy_category_id]['working_days_subtotal']
rate = list()
for index, value in enumerate(reporting[energy_category_id]['values']):
......
......@@ -36,6 +36,7 @@ import AppContext from '../../../context/Context';
import MultipleLineChart from '../common/MultipleLineChart';
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const WorkingDaysConsumptionTable = loadable(() => import('../common/WorkingDaysConsumptionTable'));
const ShopfloorEnergyCategory = ({ setRedirect, setRedirectUrl, t }) => {
let current_moment = moment();
......@@ -137,6 +138,9 @@ const ShopfloorEnergyCategory = ({ setRedirect, setRedirectUrl, t }) => {
const [detailedDataTableColumns, setDetailedDataTableColumns] = useState([{dataField: 'startdatetime', text: t('Datetime'), sort: true}]);
const [excelBytesBase64, setExcelBytesBase64] = useState(undefined);
const [workingDaysConsumptionTableData, setWorkingDaysConsumptionTableData] = useState([]);
const [workingDaysConsumptionTableColumns, setWorkingDaysConsumptionTableColumns] = useState([{dataField: 'name', text: t('Energy Category'), sort: true }]);
useEffect(() => {
let isResponseOK = false;
fetch(APIBaseURL + '/spaces/tree', {
......@@ -595,6 +599,59 @@ const ShopfloorEnergyCategory = ({ setRedirect, setRedirectUrl, t }) => {
});
});
setDetailedDataTableColumns(detailed_column_list);
let workding_days_table_column_list = [];
workding_days_table_column_list.push({
dataField: 'name',
text: t('Energy Category'),
sort: true
});
workding_days_table_column_list.push({
dataField: 'b0',
text: t('Reporting Period') + ' - ' + t('Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
workding_days_table_column_list.push({
dataField: 'b1',
text: t('Reporting Period') + ' - ' + t('Non Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
setWorkingDaysConsumptionTableColumns(workding_days_table_column_list);
let working_days_table_value_list = [];
json['reporting_period']['names'].forEach((currentValue, index) => {
let working_days_table_value = {};
let unit = json['reporting_period']['units'][index];
working_days_table_value['name'] = currentValue + ' (' + unit + ')';
working_days_table_value['b0'] = json['shopfloor']['working_calendars'].length > 0 ? json['reporting_period']['working_days_subtotals'][index] : "-";
working_days_table_value['b1'] = json['shopfloor']['working_calendars'].length > 0 ? json['reporting_period']['non_working_days_subtotals'][index] : "-";
working_days_table_value_list.push(working_days_table_value);
});
setWorkingDaysConsumptionTableData(working_days_table_value_list);
}else {
/*
* Tip:
......@@ -680,6 +737,90 @@ const ShopfloorEnergyCategory = ({ setRedirect, setRedirectUrl, t }) => {
setDetailedDataTableData(detailed_value_list);
}, 0)
}
let workding_days_table_column_list = [];
workding_days_table_column_list.push({
dataField: 'name',
text: t('Energy Category'),
sort: true
});
workding_days_table_column_list.push({
dataField: 'a0',
text: t('Base Period') + ' - ' + t('Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
workding_days_table_column_list.push({
dataField: 'a1',
text: t('Base Period') + ' - ' + t('Non Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
workding_days_table_column_list.push({
dataField: 'b0',
text: t('Reporting Period') + ' - ' + t('Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
workding_days_table_column_list.push({
dataField: 'b1',
text: t('Reporting Period') + ' - ' + t('Non Working Days'),
sort: false,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
if (decimalValue === 0) {
return '-'
}
return decimalValue.toFixed(2);
} else {
return decimalValue;
}
}
});
setWorkingDaysConsumptionTableColumns(workding_days_table_column_list);
let working_days_table_value_list = [];
json['base_period']['names'].forEach((currentValue, index) => {
let working_days_table_value = {};
let unit = json['base_period']['units'][index];
working_days_table_value['name'] = currentValue + ' (' + unit + ')';
working_days_table_value['a0'] = json['shopfloor']['working_calendars'].length > 0 ? json['base_period']['working_days_subtotals'][index] : "-";
working_days_table_value['a1'] = json['shopfloor']['working_calendars'].length > 0 ? json['base_period']['non_working_days_subtotals'][index] : "-";
working_days_table_value['b0'] = json['shopfloor']['working_calendars'].length > 0 ? json['reporting_period']['working_days_subtotals'][index] : "-";
working_days_table_value['b1'] = json['shopfloor']['working_calendars'].length > 0 ? json['reporting_period']['non_working_days_subtotals'][index] : "-";
working_days_table_value_list.push(working_days_table_value);
});
setWorkingDaysConsumptionTableData(working_days_table_value_list);
}
setExcelBytesBase64(json['excel_bytes_base64']);
......@@ -912,6 +1053,11 @@ const ShopfloorEnergyCategory = ({ setRedirect, setRedirectUrl, t }) => {
options={parameterLineChartOptions}>
</MultipleLineChart>
<br />
<WorkingDaysConsumptionTable
data={workingDaysConsumptionTableData}
title={t('CATEGORY Consumption UNIT', { 'CATEGORY': t('Working Days') + '/' + t('Non Working Days') })}
columns={workingDaysConsumptionTableColumns}>
</WorkingDaysConsumptionTable>
<DetailedDataTable data={detailedDataTableData} title={t('Detailed Data')} columns={detailedDataTableColumns} pagesize={50} >
</DetailedDataTable>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册