added Cost File to API and Admin UI and upgraded to v1.1.4

pull/53/MERGE
13621160019@163.com 2021-07-19 19:48:00 +08:00
parent 44403742a5
commit abb45dadbc
26 changed files with 485 additions and 1711 deletions

View File

@ -16,6 +16,41 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed
- None.
## [v1.1.4] - 2021-07-19
### Added
- added tbl_email_messages to myems_reporting_db
- added data sort to FDD messages in Admin UI
- added new category to FDD rule in API & Admin UI
- added Search Input for meters in Web UI
- added last year data to dashboard
- added ChildSpaceProportion SharePies to Space Energy Category report of Web UI
- added ORDER BY utc_date_time to all digital parameters data in API
- added the pagination for meter realtime page
- added pagination to MeterRealtime in Web UI
- added internationalization of Vertical Navigation Bar in Web UI
- added Equipment Batch Analysis report API
- added Cost File to API and Admin UI
- added restore button to offline meter file in API and Admin UI
### Changed
- changed GET Data Source Point Collection to order by ID
- changed equipment and combined equipment associated points name to parameters name in reports API
- updated validate expression of rule in API
- updated i18n in Web UI
- upgraded Web UI library to 2.10.2
### Fixed
- fixed typo for deleting email messages in Admin UI
- fixed issues of deleting text message and wechat message in Admin UI
- fixed base period cost units issue of Dashboard API
- fixed selected meter issues in onSearchMeter of Web UI
- fixed wrong HTTP Status Code issues in API
- fixed Child Space Share Pie issue in excel exporter of spaceenergycategory
### Removed
- Drop table tbl_sms_recipients from myems_fdd_db
- deleted parameters data from Dashboard
## [v1.1.3] - 2021-05-25
### Added
- added Combined Equipment Batch Analysis Report
@ -256,7 +291,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed
- None.
[Unreleased]: https://github.com/MyEMS/myems/compare/v1.1.3...HEAD
[Unreleased]: https://github.com/MyEMS/myems/compare/v1.1.4...HEAD
[v1.1.4]: https://github.com/MyEMS/myems/compare/v1.1.3...v1.1.4
[v1.1.3]: https://github.com/MyEMS/myems/compare/v1.1.2...v1.1.3
[v1.1.2]: https://github.com/MyEMS/myems/compare/v1.1.1...v1.1.2
[v1.1.1]: https://github.com/MyEMS/myems/compare/v1.1.0...v1.1.1

View File

@ -430,8 +430,8 @@ app
'app/services/settings/datasource/datasource.service.js',
'app/services/settings/datasource/point.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/equipment/equipment.service.js',
'app/services/settings/combinedequipment/combinedequipment.service.js',
'app/services/settings/tenant/tenant.service.js',
@ -497,8 +497,8 @@ app
'app/services/settings/tenant/tenant.service.js',
'app/services/settings/tenant/tenanttype.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/costcenter/costcenter.service.js',
'app/services/settings/contact/contact.service.js',
'app/services/settings/tenant/tenantmeter.service.js',
@ -553,8 +553,8 @@ app
'app/services/settings/store/store.service.js',
'app/services/settings/store/storetype.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/costcenter/costcenter.service.js',
'app/services/settings/contact/contact.service.js',
'app/services/settings/store/storemeter.service.js',
@ -608,8 +608,8 @@ app
files: [
'app/services/settings/shopfloor/shopfloor.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/costcenter/costcenter.service.js',
'app/services/settings/contact/contact.service.js',
'app/services/settings/shopfloor/shopfloorequipment.service.js',
@ -660,8 +660,8 @@ app
'app/services/settings/costcenter/costcenter.service.js',
'app/services/settings/datasource/point.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/equipment/equipmentmeter.service.js',
'app/services/settings/equipment/equipmentparameter.service.js',
'app/controllers/settings/equipment/equipment.master.controller.js',
@ -702,8 +702,8 @@ app
'app/services/settings/datasource/point.service.js',
'app/services/settings/equipment/equipment.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/combinedequipment/combinedequipmentequipment.service.js',
'app/services/settings/combinedequipment/combinedequipmentmeter.service.js',
'app/services/settings/combinedequipment/combinedequipmentparameter.service.js',
@ -749,17 +749,17 @@ app
'app/services/settings/category/category.service.js',
'app/services/settings/category/energyitem.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/offline-meter-file.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/meter/offlinemeterfile.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/services/settings/meter/meterpoint.service.js',
'app/services/settings/datasource/datasource.service.js',
'app/services/settings/datasource/point.service.js',
'app/controllers/settings/meter/meter.master.controller.js',
'app/controllers/settings/meter/meter.controller.js',
'app/controllers/settings/meter/offline-meter.controller.js',
'app/controllers/settings/meter/offline-meter-file.controller.js',
'app/controllers/settings/meter/virtual-meter.controller.js',
'app/controllers/settings/meter/offlinemeter.controller.js',
'app/controllers/settings/meter/offlinemeterfile.controller.js',
'app/controllers/settings/meter/virtualmeter.controller.js',
'app/controllers/settings/meter/meterpoint.controller.js'
]
}]);
@ -832,11 +832,11 @@ app
'app/services/settings/costcenter/costcenter.service.js',
'app/services/settings/costcenter/costcentertariff.service.js',
'app/services/settings/tariff/tariff.service.js',
'app/services/settings/costcenter/cost-file.service.js',
'app/services/settings/costcenter/costfile.service.js',
'app/controllers/settings/costcenter/costcenter.master.controller.js',
'app/controllers/settings/costcenter/costcenter.controller.js',
'app/controllers/settings/costcenter/costcentertariff.controller.js',
'app/controllers/settings/costcenter/cost-file.controller.js'
'app/controllers/settings/costcenter/costfile.controller.js'
]
}]);
}
@ -936,8 +936,8 @@ app
'app/services/settings/energyflowdiagram/energyflowdiagramnode.service.js',
'app/services/settings/energyflowdiagram/energyflowdiagramlink.service.js',
'app/services/settings/meter/meter.service.js',
'app/services/settings/meter/offline-meter.service.js',
'app/services/settings/meter/virtual-meter.service.js',
'app/services/settings/meter/offlinemeter.service.js',
'app/services/settings/meter/virtualmeter.service.js',
'app/controllers/settings/energyflowdiagram/energyflowdiagram.master.controller.js',
'app/controllers/settings/energyflowdiagram/energyflowdiagram.controller.js',
'app/controllers/settings/energyflowdiagram/energyflowdiagramnode.controller.js',

View File

@ -1,181 +0,0 @@
'use strict';
app.controller('CostFileController', function (
$scope,
$window,
$common,
$translate,
$uibModal,
$interval,
CostFileService,
toaster,
SweetAlert) {
$scope.cur_user = JSON.parse($window.localStorage.getItem("currentUser"));
$scope.getAllCostFiles = function () {
CostFileService.getAllCostFiles(function (error, data) {
if (!error) {
$scope.costfiles = data;
} else {
$scope.costfiles = [];
}
});
};
$scope.dzOptions = {
url: getAPI() + 'offlinecostfiles',
acceptedFiles: '.xlsx',
dictDefaultMessage: 'Click(or Drop) to add files',
maxFilesize: '100',
headers: { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token }
};
$scope.dzCallbacks = {
'addedfile': function (file) {
console.info('File added.', file);
},
'success': function (file, xhr) {
//console.log('File success to upload from dropzone', file, xhr);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_add_body.format(file.name);
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
// toaster.pop({
// type: 'success',
// title: $common.toaster.success_title,
// body: $common.toaster.success_add_body.format(file.name),
// showCloseButton: true,
// });
$scope.getAllCostFiles();
},
'error': function (file, xhr) {
//console.warn('File failed to upload from dropzone', file, xhr);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_add_body.format(file.name);
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
// toaster.pop({
// type: 'error',
// title: $common.toaster.error_title,
// body: $common.toaster.error_add_body.format(file.name),
// showCloseButton: true,
// });
}
};
$scope.deleteCostFile = function (costfile) {
SweetAlert.swal({
title: $translate.instant($common.sweet.title),
text: $translate.instant($common.sweet.text),
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: $translate.instant($common.sweet.confirmButtonText),
cancelButtonText: $translate.instant($common.sweet.cancelButtonText),
closeOnConfirm: true,
closeOnCancel: true
},
function (isConfirm) {
if (isConfirm) {
CostFileService.deleteCostFile(costfile, function (error, status) {
if (angular.isDefined(status) && status == 204) {
var templateName = "TOASTER.COST_FILE";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllCostFiles();
} else if (angular.isDefined(status) && status == 400) {
var popType = 'TOASTER.ERROR';
var popTitle = error.title;
var popBody = error.description;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
} else {
var templateName = "TOASTER.COST_FILE";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}
});
};
$scope.getAllCostFiles();
$interval.cancel();
$scope.$on('$destroy', function () {
// Make sure that the interval is destroyed too
if (angular.isDefined($scope.refeshfiles)) {
$interval.cancel($scope.refeshfiles);
$scope.refeshfiles = undefined;
}
});
$scope.refeshfiles = $interval($scope.getAllCostFiles, 1000 * 8);
});

View File

@ -56,8 +56,6 @@ app.controller('KnowledgeFileController', function (
$scope.getAllKnowledgeFiles();
},
'error': function (file, xhr) {
//console.warn('File failed to upload from dropzone', file, xhr);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_add_body.format(file.name);

View File

@ -1,195 +0,0 @@
'use strict';
app.controller('OfflineMeterFileController', function(
$scope,
$window,
$common,
$translate,
$uibModal,
$interval,
OfflineMeterFileService,
toaster,
SweetAlert) {
$scope.cur_user = JSON.parse($window.localStorage.getItem("currentUser"));
$scope.getAllOfflineMeterFiles = function() {
OfflineMeterFileService.getAllOfflineMeterFiles(function(error, data) {
if (!error) {
$scope.offlinemeterfiles = data;
} else {
$scope.offlinemeterfiles = [];
}
});
};
$scope.dzOptions = {
url: getAPI() + 'offlinemeterfiles',
acceptedFiles: '.xlsx',
dictDefaultMessage: 'Click(or Drop) to add files',
maxFilesize: '100',
headers: { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token }
};
$scope.dzCallbacks = {
'addedfile': function(file) {
console.info('File added.', file);
},
'success': function(file, xhr) {
//console.log('File success to upload from dropzone', file, xhr);
var templateName = file.name;
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
// toaster.pop({
// type: 'success',
// title: $common.toaster.success_title,
// body: $common.toaster.success_add_body.format(file.name),
// showCloseButton: true,
// });
$scope.getAllOfflineMeterFiles();
},
'error': function (file, xhr) {
//console.warn('File failed to upload from dropzone', file, xhr);
var templateName = file.name;
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
};
$scope.restoreOfflineMeterFile = function (offlinemeterfile) {
OfflineMeterFileService.restoreOfflineMeterFile(offlinemeterfile, function (error, data) {
if (!error) {
toaster.pop({
type: $translate.instant('TOASTER.SUCCESS'),
title: $translate.instant('TOASTER.SUCCESS_TITLE'),
body: $translate.instant('SETTING.RESTORE_SUCCESS'),
showCloseButton: true,
});
$scope.getAllOfflineMeterFiles();
} else {
toaster.pop({
type: $translate.instant('TOASTER.ERROR'),
title: $translate.instant(error.title),
body: $translate.instant(error.description),
showCloseButton: true,
});
}
});
};
$scope.deleteOfflineMeterFile = function(offlinemeterfile) {
SweetAlert.swal({
title: $translate.instant($common.sweet.title),
text: $translate.instant($common.sweet.text),
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: $translate.instant($common.sweet.confirmButtonText),
cancelButtonText: $translate.instant($common.sweet.cancelButtonText),
closeOnConfirm: true,
closeOnCancel: true
},
function(isConfirm) {
if (isConfirm) {
OfflineMeterFileService.deleteOfflineMeterFile(offlinemeterfile, function(error, status) {
if (angular.isDefined(status) && status == 204) {
var templateName = "SETTING.OFFLINE_METER_FILE";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllOfflineMeterFiles();
} else if (angular.isDefined(status) && status == 400) {
var popType = 'TOASTER.ERROR';
var popTitle = error.title;
var popBody = error.description;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
} else {
var templateName = "SETTING.OFFLINE_METER_FILE";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}
});
};
$scope.getAllOfflineMeterFiles();
$interval.cancel();
$scope.$on('$destroy', function() {
// Make sure that the interval is destroyed too
if (angular.isDefined($scope.refeshfiles)) {
$interval.cancel($scope.refeshfiles);
$scope.refeshfiles = undefined;
}
});
$scope.refeshfiles=$interval($scope.getAllOfflineMeterFiles,1000*8);
});

View File

@ -1,302 +0,0 @@
'use strict';
app.controller('OfflineMeterController', function($scope, $common, $translate, $uibModal, OfflineMeterService, CategoryService, EnergyItemService, CostCenterService, toaster, SweetAlert) {
$scope.getAllCostCenters = function() {
CostCenterService.getAllCostCenters(function(error, data) {
if (!error) {
$scope.costcenters = data;
} else {
$scope.costcenters = [];
}
});
};
$scope.getAllCategories = function() {
CategoryService.getAllCategories(function(error, data) {
if (!error) {
$scope.categories = data;
} else {
$scope.categories = [];
}
});
};
$scope.getAllEnergyItems = function() {
EnergyItemService.getAllEnergyItems(function(error, data) {
if (!error) {
$scope.energyitems = data;
} else {
$scope.energyitems = [];
}
});
};
$scope.getAllOfflineMeters = function() {
OfflineMeterService.getAllOfflineMeters(function(error, data) {
if (!error) {
$scope.offlinemeters = data;
} else {
$scope.offlinemeters = [];
}
});
};
$scope.addOfflineMeter = function() {
var modalInstance = $uibModal.open({
templateUrl: 'views/settings/meter/offline-meter.model.html',
controller: 'ModalAddOfflineMeterCtrl',
windowClass: "animated fadeIn",
resolve: {
params: function() {
return {
offlinemeters: angular.copy($scope.offlinemeters),
categories: angular.copy($scope.categories),
energyitems: angular.copy($scope.energyitems),
costcenters: angular.copy($scope.costcenters)
};
}
}
});
modalInstance.result.then(function(offlinemeter) {
offlinemeter.energy_category_id = offlinemeter.energy_category.id;
if(angular.isDefined(offlinemeter.energy_item)) {
offlinemeter.energy_item_id = offlinemeter.energy_item.id;
} else {
offlinemeter.energy_item_id = undefined;
}
offlinemeter.cost_center_id = offlinemeter.cost_center.id;
OfflineMeterService.addOfflineMeter(offlinemeter, function(error, status) {
if (angular.isDefined(status) && status == 201) {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllOfflineMeters();
$scope.$emit('handleEmitOfflineMeterChanged');
} else {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}, function() {
});
};
$scope.editOfflineMeter = function(offlinemeter) {
var modalInstance = $uibModal.open({
windowClass: "animated fadeIn",
templateUrl: 'views/settings/meter/offline-meter.model.html',
controller: 'ModalEditOfflineMeterCtrl',
resolve: {
params: function() {
return {
offlinemeter: angular.copy(offlinemeter),
offlinemeters: angular.copy($scope.offlinemeters),
categories: angular.copy($scope.categories),
energyitems: angular.copy($scope.energyitems),
costcenters: angular.copy($scope.costcenters)
};
}
}
});
modalInstance.result.then(function(modifiedOfflineMeter) {
modifiedOfflineMeter.energy_category_id = modifiedOfflineMeter.energy_category.id;
if (modifiedOfflineMeter.energy_item != null && modifiedOfflineMeter.energy_item.id != null ) {
modifiedOfflineMeter.energy_item_id = modifiedOfflineMeter.energy_item.id;
} else {
modifiedOfflineMeter.energy_item_id = undefined;
}
modifiedOfflineMeter.cost_center_id = modifiedOfflineMeter.cost_center.id;
OfflineMeterService.editOfflineMeter(modifiedOfflineMeter, function(error, status) {
if (angular.isDefined(status) && status == 200) {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_update_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllOfflineMeters();
$scope.$emit('handleEmitOfflineMeterChanged');
} else {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_update_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}, function() {
//do nothing;
});
};
$scope.deleteOfflineMeter = function(offlinemeter) {
SweetAlert.swal({
title: $translate.instant($common.sweet.title),
text: $translate.instant($common.sweet.text),
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: $translate.instant($common.sweet.confirmButtonText),
cancelButtonText: $translate.instant($common.sweet.cancelButtonText),
closeOnConfirm: true,
closeOnCancel: true
},
function(isConfirm) {
if (isConfirm) {
OfflineMeterService.deleteOfflineMeter(offlinemeter, function(error, status) {
if (angular.isDefined(status) && status == 204) {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllOfflineMeters();
$scope.$emit('handleEmitOfflineMeterChanged');
} else if (angular.isDefined(status) && status == 400) {
var popType = 'TOASTER.ERROR';
var popTitle = error.title;
var popBody = error.description;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
} else {
var templateName = "SETTING.OFFLINE_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}
});
};
$scope.getAllOfflineMeters();
$scope.getAllCategories();
$scope.getAllEnergyItems();
$scope.getAllCostCenters();
});
app.controller('ModalAddOfflineMeterCtrl', function($scope, $uibModalInstance, params) {
$scope.operation = "SETTING.ADD_OFFLINE_METER";
$scope.categories = params.categories;
$scope.energyitems = params.energyitems;
$scope.costcenters = params.costcenters;
$scope.offlinemeter = {
is_counted: false
};
$scope.ok = function() {
$uibModalInstance.close($scope.offlinemeter);
};
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
});
app.controller('ModalEditOfflineMeterCtrl', function($scope, $uibModalInstance, params) {
$scope.operation = "SETTING.EDIT_OFFLINE_METER";
$scope.offlinemeter = params.offlinemeter;
$scope.offlinemeters = params.offlinemeters;
$scope.categories = params.categories;
$scope.energyitems = params.energyitems;
$scope.costcenters = params.costcenters;
$scope.ok = function() {
$uibModalInstance.close($scope.offlinemeter);
};
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
});

View File

@ -1,494 +0,0 @@
'use strict';
app.controller('VirtualMeterController', function($scope, $common, $uibModal, $translate, MeterService, VirtualMeterService, OfflineMeterService, CategoryService, EnergyItemService, CostCenterService, toaster, SweetAlert) {
$scope.getAllCostCenters = function() {
CostCenterService.getAllCostCenters(function(error, data) {
if (!error) {
$scope.costcenters = data;
} else {
$scope.costcenters = [];
}
});
};
$scope.getAllCategories = function() {
CategoryService.getAllCategories(function(error, data) {
if (!error) {
$scope.categories = data;
} else {
$scope.categories = [];
}
});
};
$scope.getAllEnergyItems = function() {
EnergyItemService.getAllEnergyItems(function(error, data) {
if (!error) {
$scope.energyitems = data;
} else {
$scope.energyitems = [];
}
});
};
$scope.getAllVirtualMeters = function() {
VirtualMeterService.getAllVirtualMeters(function(error, data) {
if (!error) {
$scope.virtualmeters = data;
} else {
$scope.virtualmeters = [];
}
});
};
$scope.getAllMeters = function() {
MeterService.getAllMeters(function(error, data) {
if (!error) {
$scope.meters = data;
} else {
$scope.meters = [];
}
});
};
$scope.getAllOfflineMeters = function() {
OfflineMeterService.getAllOfflineMeters(function(error, data) {
if (!error) {
$scope.offlinemeters = data;
} else {
$scope.offlinemeters = [];
}
});
};
$scope.addVirtualMeter = function() {
var modalInstance = $uibModal.open({
templateUrl: 'views/settings/meter/virtual-meter.model.html',
controller: 'ModalAddVirtualMeterCtrl',
windowClass: 'animated fadeIn',
size: 'lg',
resolve: {
params: function() {
return {
virtualmeters: angular.copy($scope.virtualmeters),
meters: angular.copy($scope.meters),
offlinemeters: angular.copy($scope.offlinemeters),
categories: angular.copy($scope.categories),
energyitems: angular.copy($scope.energyitems),
costcenters: angular.copy($scope.costcenters)
};
}
}
});
modalInstance.result.then(function(virtualmeter) {
virtualmeter.energy_category_id = virtualmeter.energy_category.id;
if(angular.isDefined(virtualmeter.energy_item)) {
virtualmeter.energy_item_id = virtualmeter.energy_item.id;
} else {
virtualmeter.energy_item_id = undefined;
}
virtualmeter.cost_center_id = virtualmeter.cost_center.id;
VirtualMeterService.addVirtualMeter(virtualmeter, function(error, status) {
if (angular.isDefined(status) && status == 201) {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllVirtualMeters();
$scope.$emit('handleEmitVirtualMeterChanged');
} else {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_add_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}, function() {
});
};
$scope.editVirtualMeter = function(virtualmeter) {
var modalInstance = $uibModal.open({
windowClass: "animated fadeIn",
templateUrl: 'views/settings/meter/virtual-meter.model.html',
controller: 'ModalEditVirtualMeterCtrl',
size: 'lg',
resolve: {
params: function() {
return {
virtualmeter: angular.copy(virtualmeter),
virtualmeters: angular.copy($scope.virtualmeters),
meters: angular.copy($scope.meters),
offlinemeters: angular.copy($scope.offlinemeters),
categories: angular.copy($scope.categories),
energyitems: angular.copy($scope.energyitems),
costcenters: angular.copy($scope.costcenters)
};
}
}
});
modalInstance.result.then(function(modifiedVirtualMeter) {
modifiedVirtualMeter.energy_category_id = modifiedVirtualMeter.energy_category.id;
if (modifiedVirtualMeter.energy_item != null && modifiedVirtualMeter.energy_item.id != null ) {
modifiedVirtualMeter.energy_item_id = modifiedVirtualMeter.energy_item.id;
} else {
modifiedVirtualMeter.energy_item_id = undefined;
}
modifiedVirtualMeter.cost_center_id = modifiedVirtualMeter.cost_center.id;
VirtualMeterService.editVirtualMeter(modifiedVirtualMeter, function(error, status) {
if (angular.isDefined(status) && status == 200) {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_update_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllVirtualMeters();
$scope.$emit('handleEmitVirtualMeterChanged');
} else {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_update_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody,{template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}, function() {
//do nothing;
});
};
$scope.deleteVirtualMeter = function(virtualmeter) {
SweetAlert.swal({
title: $translate.instant($common.sweet.title),
text: $translate.instant($common.sweet.text),
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: $translate.instant($common.sweet.confirmButtonText),
cancelButtonText: $translate.instant($common.sweet.cancelButtonText),
closeOnConfirm: true,
closeOnCancel: true
},
function(isConfirm) {
if (isConfirm) {
VirtualMeterService.deleteVirtualMeter(virtualmeter, function(error, status) {
if (angular.isDefined(status) && status == 204) {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.SUCCESS';
var popTitle = $common.toaster.success_title;
var popBody = $common.toaster.success_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
$scope.getAllVirtualMeters();
$scope.$emit('handleEmitVirtualMeterChanged');
} else if (angular.isDefined(status) && status == 400) {
var popType = 'TOASTER.ERROR';
var popTitle = error.title;
var popBody = error.description;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody);
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
} else {
var templateName = "SETTING.VIRTUAL_METER";
templateName = $translate.instant(templateName);
var popType = 'TOASTER.ERROR';
var popTitle = $common.toaster.error_title;
var popBody = $common.toaster.error_delete_body;
popType = $translate.instant(popType);
popTitle = $translate.instant(popTitle);
popBody = $translate.instant(popBody, {template: templateName});
toaster.pop({
type: popType,
title: popTitle,
body: popBody,
showCloseButton: true,
});
}
});
}
});
};
$scope.getAllMeters();
$scope.getAllVirtualMeters();
$scope.getAllOfflineMeters();
$scope.getAllCategories();
$scope.getAllEnergyItems();
$scope.getAllCostCenters();
$scope.$on('handleBroadcastMeterChanged', function(event) {
$scope.getAllMeters();
});
$scope.$on('handleBroadcastOfflineMeterChanged', function(event) {
$scope.getAllOfflineMeters();
});
$scope.$on('handleBroadcastVirtualMeterChanged', function(event) {
$scope.getAllVirtualMeters();
});
});
app.controller('ModalAddVirtualMeterCtrl', function($timeout, $scope,
$uibModalInstance,
params) {
$scope.operation = "SETTING.ADD_VIRTUAL_METER";
$scope.categories = params.categories;
$scope.energyitems = params.energyitems;
$scope.costcenters = params.costcenters;
$scope.meters = params.meters;
$scope.virtualmeters = params.virtualmeters;
$scope.offlinemeters = params.offlinemeters;
$scope.currentMeterType = {};
$scope.currentMeter = {};
$scope.virtualmeter = {
is_counted: false,
expression: {
variables: []
}
};
$scope.metertypes = [{
sid: 'meter',
name: 'SETTING.METER'
}, {
sid: 'virtual_meter',
name: 'SETTING.VIRTUAL_METER'
}, {
sid: 'offline_meter',
name: 'SETTING.OFFLINE_METER'
}];
$scope.metertypemap = {
meter: 'SETTING.METER',
virtual_meter: 'SETTING.VIRTUAL_METER',
offline_meter: 'SETTING.OFFLINE_METER'
};
$scope.counter = 1;
$scope.ok = function() {
$uibModalInstance.close($scope.virtualmeter);
};
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
$scope.add = function() {
var variable = {
name: 'x' + ($scope.counter),
meter_type: $scope.currentMeterType.selected.sid,
meter_id: $scope.currentMeter.selected.id,
//metertype:$scope.currentMeterType.selected.name,
meter_name: $scope.currentMeter.selected.name
}
if ($scope.virtualmeter.expression.variables.length > 0) {
$scope.virtualmeter.expression.variables.unshift(variable);
} else {
$scope.virtualmeter.expression.variables.push(variable);
}
$timeout(function() {
angular.element('#variablesTable').trigger('footable_redraw');
}, 10);
$scope.counter++;
$scope.currentMeter.selected=undefined;
};
$scope.delete = function(key) {
$scope.virtualmeter.expression.variables.splice(key, 1);
$timeout(function() {
angular.element('#variablesTable').trigger('footable_redraw');
}, 10);
};
$scope.changeMeterType = function() {
switch ($scope.currentMeterType.selected.sid) {
case 'meter':
$scope.currentmeters = $scope.meters;
break;
case 'virtual_meter':
$scope.currentmeters = $scope.virtualmeters;
break;
case 'offline_meter':
$scope.currentmeters = $scope.offlinemeters;
break;
}
};
});
app.controller('ModalEditVirtualMeterCtrl', function($timeout, $scope, $uibModalInstance, params) {
$scope.operation = "SETTING.EDIT_VIRTUAL_METER";
$scope.virtualmeter = params.virtualmeter;
$scope.virtualmeters = params.virtualmeters;
$scope.meters = params.meters;
$scope.offlinemeters = params.offlinemeters;
$scope.categories = params.categories;
$scope.energyitems = params.energyitems;
$scope.costcenters = params.costcenters;
$scope.currentMeterType = {};
$scope.currentMeter = {};
$scope.metertypes = [{
sid: 'meter',
name: 'SETTING.METER'
}, {
sid: 'virtual_meter',
name: 'SETTING.VIRTUAL_METER'
}, {
sid: 'offline_meter',
name: 'SETTING.OFFLINE_METER'
}];
$scope.metertypemap = {
meter: 'SETTING.METER',
virtual_meter: 'SETTING.VIRTUAL_METER',
offline_meter: 'SETTING.OFFLINE_METER'
};
$scope.counter = 1;
if (angular.isUndefined($scope.virtualmeter.expression.variables)) {
$scope.virtualmeter.expression.variables = [];
} else {
if ($scope.virtualmeter.expression.variables.length > 0) {
var arrIndex = [];
angular.forEach($scope.virtualmeter.expression.variables, function(item, index) {
arrIndex.push(parseInt(item.name.substr(1)));
});
var maxval = Math.max.apply(null, arrIndex);
$scope.counter = maxval + 1;
}
}
$scope.ok = function() {
$uibModalInstance.close($scope.virtualmeter);
};
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
$timeout(function() {
angular.element('#variablesTable').trigger('footable_redraw');
}, 100);
$scope.add = function() {
var variable = {
name: 'x' + ($scope.counter),
meter_type: $scope.currentMeterType.selected.sid,
meter_id: $scope.currentMeter.selected.id,
//metertype:$scope.currentMeterType.selected.name,
meter_name: $scope.currentMeter.selected.name
}
if ($scope.virtualmeter.expression.variables.length > 0) {
$scope.virtualmeter.expression.variables.unshift(variable);
} else {
$scope.virtualmeter.expression.variables.push(variable);
}
$timeout(function() {
angular.element('#variablesTable').trigger('footable_redraw');
}, 10);
$scope.counter++;
$scope.currentMeter.selected=undefined;
};
$scope.delete = function(key) {
$scope.virtualmeter.expression.variables.splice(key, 1);
$timeout(function() {
angular.element('#variablesTable').trigger('footable_redraw');
}, 10);
};
$scope.changeMeterType = function() {
switch ($scope.currentMeterType.selected.sid) {
case 'meter':
$scope.currentmeters = $scope.meters;
break;
case 'virtual_meter':
$scope.currentmeters = $scope.virtualmeters;
break;
case 'offline_meter':
$scope.currentmeters = $scope.offlinemeters;
break;
}
};
});

View File

@ -1,34 +0,0 @@
'use strict';
app.factory('CostFileService', function($http) {
return {
getAllCostFiles:function(callback){
$http.get(getAPI()+'offlinecostfiles')
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
addCostFile: function(costfile, callback) {
$http.post(getAPI()+'offlinecostfiles',{data:costfile})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
deleteCostFile: function(costfile, callback) {
$http.delete(getAPI()+'offlinecostfiles/'+costfile.id)
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
}
};
});

View File

@ -1,68 +0,0 @@
'use strict';
app.factory('OfflineMeterFileService', function($http) {
return {
getAllOfflineMeterFiles:function(callback){
$http.get(getAPI()+'offlinemeterfiles')
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
searchOfflineMeterFiles: function(query, callback) {
$http.get(getAPI()+'offlinemeterfiles', { params: { q: query } })
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
addOfflineMeterFile: function(offlinemeterfile, callback) {
$http.post(getAPI()+'offlinemeterfiles',{data:offlinemeterfile})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
editOfflineMeterFile: function(offlinemeterfile, callback) {
$http.put(getAPI()+'offlinemeterfiles/'+offlinemeterfile.id,{data:offlinemeterfile})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
restoreOfflineMeterFile: function (offlinemeterfile, callback) {
$http.get(getAPI() + 'offlinemeterfiles/' + offlinemeterfile.id + '/restore')
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e, status) {
callback(e, status);
});
},
deleteOfflineMeterFile: function(offlinemeterfile, callback) {
$http.delete(getAPI()+'offlinemeterfiles/'+offlinemeterfile.id)
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
getOfflineMeterFile: function(id, callback) {
$http.get(getAPI()+'offlinemeterfiles/'+id)
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
}
};
});

View File

@ -1,59 +0,0 @@
'use strict';
app.factory('OfflineMeterService', function($http) {
return {
getAllOfflineMeters:function(callback){
$http.get(getAPI()+'offlinemeters')
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
searchOfflineMeters: function(query, callback) {
$http.get(getAPI()+'offlinemeters', { params: { q: query } })
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
addOfflineMeter: function(offlinemeter, callback) {
$http.post(getAPI()+'offlinemeters',{data:offlinemeter})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
editOfflineMeter: function(offlinemeter, callback) {
$http.put(getAPI()+'offlinemeters/'+offlinemeter.id,{data:offlinemeter})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
deleteOfflineMeter: function(offlinemeter, callback) {
$http.delete(getAPI()+'offlinemeters/'+offlinemeter.id)
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
getOfflineMeter: function(id, callback) {
$http.get(getAPI()+'offlinemeters/'+id)
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
}
};
});

View File

@ -1,50 +0,0 @@
'use strict';
app.factory('VirtualMeterService', function($http) {
return {
getAllVirtualMeters:function(callback){
$http.get(getAPI()+'virtualmeters')
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
searchVirtualMeters: function(query, callback) {
$http.get(getAPI()+'virtualmeters', { params: { q: query } })
.success(function (response, status, headers, config) {
callback(null, response);
})
.error(function (e,status) {
callback(e,status);
});
},
addVirtualMeter: function(virtualmeter, callback) {
$http.post(getAPI()+'virtualmeters',{data:virtualmeter})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
editVirtualMeter: function(virtualmeter, callback) {
$http.put(getAPI()+'virtualmeters/'+virtualmeter.id,{data:virtualmeter})
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
},
deleteVirtualMeter: function(virtualmeter, callback) {
$http.delete(getAPI()+'virtualmeters/'+virtualmeter.id)
.success(function (response, status, headers, config) {
callback(null, status);
})
.error(function (e,status) {
callback(e,status);
});
}
};
});

View File

@ -298,7 +298,7 @@ function config($translateProvider) {
DRAG_TO_BIND: 'Drag to left to bind',
DRAG_TO_UNBIND: 'Drag to trash to unbind',
FINANCIAL_COST: 'Offline Cost File',
COST_FILE: 'Cost File',
NAME: 'Name',
AREA: 'Area',
UNIT: 'Unit',
@ -882,11 +882,10 @@ function config($translateProvider) {
INVALID_GROUP_ID: 'Invalid Group ID',
INVALID_KNOWLEDGE_FILE_ID: 'Invalid Knowledge File ID',
INVALID_ID: 'Invalid ID',
INVALID_LINE_ID: 'Invalid Line ID',
INVALID_MESSAGE_ID: 'Invalid Message ID',
INVALID_METER_ID: 'Invalid Meter ID',
INVALID_METER_UUID: 'Invalid Meter UUID',
INVALID_OFFLINE_COST_FILE_ID: 'Invalid Offline Cost File ID',
INVALID_COST_FILE_ID: 'Invalid Cost File ID',
INVALID_OFFLINE_METER_FILE__ID: 'Invalid Offline Meter File ID',
INVALID_OFFLINE_METER_FILE_ID: 'Invalid Offline Meter File ID',
INVALID_OFFLINE_METER_ID: 'Invalid Offline Meter ID',
@ -970,7 +969,7 @@ function config($translateProvider) {
METER_POINT_RELATIONSHIP_EXISTED: 'Meter Point Relationship Existed',
METER_POINT_RELATIONSHIP_NOT_FOUND: 'Meter Point Relationship Not Found',
METER_OF_VARIABLE_NOT_FOUND: 'Meter of Variable Not Found',
OFFLINE_COST_FILE_NOT_FOUND: 'Offline Cost File Not Found',
COST_FILE_NOT_FOUND: 'Cost File Not Found',
OFFLINE_METER_FILE_NOT_FOUND: 'Offline Meter File Not Found',
OFFLINE_METER_NOT_FOUND: 'Offline Meter Not Found',
OFFLINE_METER_OF_VARIABLE_NOT_FOUND: 'Offline Meter of Variable Not Found',
@ -1328,7 +1327,7 @@ function config($translateProvider) {
TRASH: '回收桶',
DRAG_TO_BIND: '请拖拽完成绑定',
DRAG_TO_UNBIND: '请拖拽至回收桶解除绑定',
FINANCIAL_COST: '财务分摊成本录入',
COST_FILE: '成本文件',
NAME: '名称',
AREA: '面积',
UNIT: '单位',
@ -1928,7 +1927,7 @@ function config($translateProvider) {
INVALID_MESSAGE_ID: '无效的消息ID',
INVALID_METER_ID: '无效的计量表ID',
INVALID_METER_UUID: '无效的计量表UUID',
INVALID_OFFLINE_COST_FILE_ID: '无效的离线成本文件ID',
INVALID_COST_FILE_ID: '无效的成本文件ID',
INVALID_OFFLINE_METER_FILE__ID: '无效的离线表文件ID',
INVALID_OFFLINE_METER_FILE_ID: '无效的离线表文件ID',
INVALID_OFFLINE_METER_ID: '无效的离线表ID',
@ -1994,7 +1993,7 @@ function config($translateProvider) {
METER_POINT_RELATIONSHIP_EXISTED: '存在计量表和点的关系',
METER_POINT_RELATIONSHIP_NOT_FOUND: '未找到计量表和点的关系',
METER_OF_VARIABLE_NOT_FOUND: '未找到变量关联的计量表',
OFFLINE_COST_FILE_NOT_FOUND: '未找到离线费用文件',
COST_FILE_NOT_FOUND: '未找到成本文件',
OFFLINE_METER_FILE_NOT_FOUND: '未找到离线表文件',
OFFLINE_METER_NOT_FOUND: '未找到离线表',
OFFLINE_METER_OF_VARIABLE_NOT_FOUND: '未找到变量关联的离线表',
@ -2346,7 +2345,7 @@ function config($translateProvider) {
TRASH: 'recyceln können',
DRAG_TO_BIND: 'Bitte ziehen und ablegen, um die Bindung abzuschließen',
DRAG_TO_UNBIND: 'Bitte ziehen Sie in den Papierkorb, um die Bindung aufzuheben',
FINANCIAL_COST: 'Erfassung der finanziellen Allokationskosten',
COST_FILE: 'Datei der Kosten',
NAME: 'Name',
AREA: 'Bereich',
UNIT: 'Einheit',
@ -2946,7 +2945,7 @@ function config($translateProvider) {
INVALID_MESSAGE_ID: 'Ungültige Nachrichten ID',
INVALID_METER_ID: 'Ungültige Zähler-ID',
INVALID_METER_UUID: 'Ungültige UUID des Messgeräts',
INVALID_OFFLINE_COST_FILE_ID: 'Ungültige Offline-Kostendatei-ID',
INVALID_COST_FILE_ID: 'Ungültige Kostendatei-ID',
INVALID_OFFLINE_METER_FILE__ID: 'Ungültige Offline-Tabellendatei-ID',
INVALID_OFFLINE_METER_FILE_ID: 'Ungültige Offline-Tabellendatei-ID',
INVALID_OFFLINE_METER_ID: 'Ungültige Offline-Tabellen-ID',
@ -3012,7 +3011,7 @@ function config($translateProvider) {
METER_POINT_RELATIONSHIP_EXISTED: 'Es gibt eine Beziehung zwischen Metern und Punkten',
METER_POINT_RELATIONSHIP_NOT_FOUND: 'Die Beziehung zwischen dem Messgerät und dem Punkt wurde nicht gefunden',
METER_OF_VARIABLE_NOT_FOUND: 'Kein mit der Variablen verknüpftes Messgerät gefunden',
OFFLINE_COST_FILE_NOT_FOUND: 'Offline-Kostendatei nicht gefunden',
COST_FILE_NOT_FOUND: 'Kostendatei nicht gefunden',
OFFLINE_METER_FILE_NOT_FOUND: 'Offline-Tabellendatei nicht gefunden',
OFFLINE_METER_NOT_FOUND: 'Offline-Tabelle nicht gefunden',
OFFLINE_METER_OF_VARIABLE_NOT_FOUND: 'Die der Variablen zugeordnete Offline-Tabelle wurde nicht gefunden',

View File

@ -1,5 +1,5 @@
<div class="footer-login">
<div>
<strong>{{'MY_EMS_NAME' | translate}} v1.1.3 <a href="https://myems.io">https://myems.io</a> </strong>
<strong>{{'MY_EMS_NAME' | translate}} v1.1.4 <a href="https://myems.io">https://myems.io</a> </strong>
</div>
</div>

View File

@ -3,6 +3,6 @@
<strong><a href="https://myems.io">https://myems.io</a></strong>
</div>
<div>
<strong>{{'MY_EMS_NAME' | translate}} v1.1.3</strong>
<strong>{{'MY_EMS_NAME' | translate}} v1.1.4</strong>
</div>
</div>

View File

@ -1,141 +1,140 @@
<div class="wrapper wrapper-content" ng-controller="CostCenterMasterController" >
<div class="wrapper wrapper-content" ng-controller="CostCenterMasterController" >
<div class="row">
<div class="col-lg-12">
<div class="tabs-container">
<div class="row">
<div class="col-lg-12">
<div class="tabs-container">
<uib-tabset>
<uib-tab heading="{{'SETTING.COSTCENTER' | translate}}">
<div class="panel-body" ng-controller="CostCenterController">
<a ng-click="addCostCenter()" class="btn btn-primary btn-rounded btn-outline" href=""><i class="fa fa-plus-circle"></i> {{'SETTING.ADD_COSTCENTER' | translate}}</a>
<table class="table table-bordered table-hover" >
<thead>
<tr>
<th class="text-center">{{'SETTING.ID' | translate}}</th>
<th class="text-center">{{'SETTING.NAME' | translate}}</th>
<th class="text-center">{{'COSTCENTER.EXTERNAL_ID' | translate}}</th>
<th class="text-center">{{'SETTING.ACTION' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="costcenter in costcenters">
<td class="text-center">{{ costcenter.id }}</td>
<td class="text-center">{{ costcenter.name }}</td>
<td class="text-center">{{ costcenter.external_id }}</td>
<td class="text-center">
<a class="btn btn-primary btn-rounded btn-xs" ng-click="editCostCenter(costcenter)" >{{'SETTING.EDIT' | translate}}</a>
<a ng-click="deleteCostCenter(costcenter)" class="btn btn-danger btn-rounded btn-xs" >{{'SETTING.DELETE' | translate}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</uib-tab>
<uib-tab heading="{{'SETTING.BIND_TARIFF' | translate}}">
<div class="panel-body" ng-controller="CostCenterTariffController">
<div class="row">
<div class="col-lg-3">
<div class="panel panel-info">
<div class="panel-heading">
{{'SETTING.SELECT_COSTCENTER' | translate}}
</div>
<div class="panel-body">
<div ng-repeat="costcenter in costcenters" class="radio radio-info">
<input type="radio" name="radiocostcenter" id="radiocostcenter{{costcenter.id}}" ng-value="costcenter" ng-model="$parent.currentCostCenter" ng-change="changeCostCenter()" >
<label for="radiocostcenter{{costcenter.id}}">
{{costcenter.name}}
</label>
</div>
</div>
</div>
<uib-tabset>
<uib-tab heading="{{'SETTING.COSTCENTER' | translate}}">
<div class="panel-body" ng-controller="CostCenterController">
<a ng-click="addCostCenter()" class="btn btn-primary btn-rounded btn-outline" href=""><i class="fa fa-plus-circle"></i> {{'SETTING.ADD_COSTCENTER' | translate}}</a>
<table class="table table-bordered table-hover" >
<thead>
<tr>
<th class="text-center">{{'SETTING.ID' | translate}}</th>
<th class="text-center">{{'SETTING.NAME' | translate}}</th>
<th class="text-center">{{'COSTCENTER.EXTERNAL_ID' | translate}}</th>
<th class="text-center">{{'SETTING.ACTION' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="costcenter in costcenters">
<td class="text-center">{{ costcenter.id }}</td>
<td class="text-center">{{ costcenter.name }}</td>
<td class="text-center">{{ costcenter.external_id }}</td>
<td class="text-center">
<a class="btn btn-primary btn-rounded btn-xs" ng-click="editCostCenter(costcenter)" >{{'SETTING.EDIT' | translate}}</a>
<a ng-click="deleteCostCenter(costcenter)" class="btn btn-danger btn-rounded btn-xs" >{{'SETTING.DELETE' | translate}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</uib-tab>
<uib-tab heading="{{'SETTING.BIND_TARIFF' | translate}}">
<div class="panel-body" ng-controller="CostCenterTariffController">
<div class="row">
<div class="col-lg-3">
<div class="panel panel-info">
<div class="panel-heading">
{{'SETTING.SELECT_COSTCENTER' | translate}}
</div>
<div class="col-lg-4">
<div class="panel panel-primary">
<div class="panel-heading">
{{currentCostCenter.name}}{{'SETTING.N_S_TARIFF' | translate}}
</div>
<div class="panel-body maxheight"
x-hjc-drop-target="true"
x-on-drop="pairTariff(dragEl,dropEl)"
uib-tooltip="{{'SETTING.DRAG_TO_UNBIND' | translate}}">
<div class="btn btn-primary btn-rounded btn-block"
ng-repeat="costcentertariff in costcentertariffs"
x-hjc-draggable="true"> {{costcentertariff.name}}</div>
<div class="panel-body">
<div ng-repeat="costcenter in costcenters" class="radio radio-info">
<input type="radio" name="radiocostcenter" id="radiocostcenter{{costcenter.id}}" ng-value="costcenter" ng-model="$parent.currentCostCenter" ng-change="changeCostCenter()" >
<label for="radiocostcenter{{costcenter.id}}">
{{costcenter.name}}
</label>
</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="deleteTariffPair(dragEl,dropEl)">
</div>
</div>
<div class="col-lg-4">
<div class="panel panel-primary">
<div class="panel-heading">
{{currentCostCenter.name}}{{'SETTING.N_S_TARIFF' | translate}}
</div>
<div class="panel-body maxheight"
x-hjc-drop-target="true"
x-on-drop="pairTariff(dragEl,dropEl)"
uib-tooltip="{{'SETTING.DRAG_TO_UNBIND' | translate}}">
<div class="btn btn-primary btn-rounded btn-block"
ng-repeat="costcentertariff in costcentertariffs"
x-hjc-draggable="true"> {{costcentertariff.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="deleteTariffPair(dragEl,dropEl)">
</div>
</div>
</div>
<div class="col-lg-4">
<div class="panel panel-info">
<div class="panel-heading">
{{'SETTING.TARIFF_LIST' | translate}}
</div>
<div class="panel-body" uib-tooltip="{{'SETTING.DRAG_TO_BIND' | translate}}"
<div class="col-lg-4">
<div class="panel panel-info">
<div class="panel-heading">
{{'SETTING.TARIFF_LIST' | translate}}
</div>
<div class="panel-body" uib-tooltip="{{'SETTING.DRAG_TO_BIND' | translate}}"
slim-scroll box-height="765px">
<div class="source btn btn-info btn-rounded btn-block"
<div class="source btn btn-info btn-rounded btn-block"
ng-repeat="tariff in tariffs"
x-hjc-draggable="true"> {{tariff.name}}</div>
x-hjc-draggable="true"> {{tariff.name}}
</div>
</div>
</div>
</div>
</div>
</uib-tab>
</div>
</uib-tab>
<uib-tab heading="{{'SETTING.FINANCIAL_COST' | translate}}">
<div class="panel-body" ng-controller="CostFileController">
<div id="dropzone1" class="dropzone" options="dzOptions" callbacks="dzCallbacks" ng-dropzone></div>
<table class="table table-bordered table-hover" >
<thead>
<tr>
<th class="text-center">{{'SETTING.NAME' | translate}}</th>
<th class="text-center">{{'SETTING.STATUS' | translate}}</th>
<th class="text-center">{{'SETTING.UPLOAD_TIME' | translate}}</th>
<th class="text-center">{{'SETTING.ACTION' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="costfile in costfiles">
<td class="text-center">{{ costfile.file_name }}</td>
<td class="text-center">{{ costfile.status }}</td>
<td class="text-center">{{ costfile.upload_datetime | date:'yyyy-MM-dd HH:mm'}}</td>
<uib-tab heading="{{'SETTING.COST_FILE' | translate}}">
<div class="panel-body" ng-controller="CostFileController">
<div id="dropzone1" class="dropzone" options="dzOptions" callbacks="dzCallbacks" ng-dropzone></div>
<table class="table table-bordered table-hover" >
<thead>
<tr>
<th class="text-center">{{'SETTING.ID' | translate}}</th>
<th class="text-center">{{'SETTING.NAME' | translate}}</th>
<th class="text-center">{{'SETTING.STATUS' | translate}}</th>
<th class="text-center">{{'SETTING.UPLOAD_TIME' | translate}}</th>
<th class="text-center">{{'SETTING.ACTION' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="costfile in costfiles">
<td class="text-center">{{ costfile.id }}</td>
<td class="text-center"><a href="./upload/{{costfile.uuid}}"
download="{{costfile.file_name}}">{{ costfile.file_name }}</a>
</td>
<td class="text-center">{{ costfile.status }}</td>
<td class="text-center">{{ costfile.upload_datetime | date:'yyyy-MM-dd HH:mm'}}</td>
<td class="text-center">
<a ng-click="deleteCostFile(costfile)" class="btn btn-danger btn-rounded btn-xs" >{{'SETTING.DELETE' | translate}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</uib-tab>
</uib-tabset>
</div>
<td class="text-center">
<a ng-click="restoreCostFile(costfile)"
class="btn btn-danger btn-rounded btn-xs">{{'SETTING.RESTORE' | translate}}</a>
<a ng-click="deleteCostFile(costfile)"
class="btn btn-danger btn-rounded btn-xs" >{{'SETTING.DELETE' | translate}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</uib-tab>
</uib-tabset>
</div>
</div>
</div>
</div>

View File

@ -36,6 +36,20 @@ CREATE TABLE IF NOT EXISTS `myems_historical_db`.`tbl_analog_value_latest` (
CREATE INDEX `tbl_analog_value_latest_index_1` ON `myems_historical_db`.`tbl_analog_value_latest` (`point_id` , `utc_date_time`);
CREATE INDEX `tbl_analog_value_latest_index_2` ON `myems_historical_db`.`tbl_analog_value_latest` (`utc_date_time`);
-- ---------------------------------------------------------------------------------------------------------------------
-- Table `myems_historical_db`.`tbl_cost_files`
-- ---------------------------------------------------------------------------------------------------------------------
DROP TABLE IF EXISTS `myems_historical_db`.`tbl_cost_files` ;
CREATE TABLE IF NOT EXISTS `myems_historical_db`.`tbl_cost_files` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(255) NOT NULL,
`uuid` CHAR(36) NOT NULL,
`upload_datetime_utc` DATETIME NOT NULL,
`status` VARCHAR(45) NOT NULL COMMENT 'new, done, error',
`file_object` LONGBLOB NOT NULL,
PRIMARY KEY (`id`));
-- ---------------------------------------------------------------------------------------------------------------------
-- Table `myems_historical_db`.`tbl_digital_value`
-- ---------------------------------------------------------------------------------------------------------------------
@ -109,18 +123,4 @@ CREATE TABLE IF NOT EXISTS `myems_historical_db`.`tbl_offline_meter_files` (
PRIMARY KEY (`id`));
-- ---------------------------------------------------------------------------------------------------------------------
-- Table `myems_historical_db`.`tbl_offline_cost_files`
-- ---------------------------------------------------------------------------------------------------------------------
DROP TABLE IF EXISTS `myems_historical_db`.`tbl_offline_cost_files` ;
CREATE TABLE IF NOT EXISTS `myems_historical_db`.`tbl_offline_cost_files` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`file_name` VARCHAR(255) NOT NULL,
`uuid` CHAR(36) NOT NULL,
`upload_datetime_utc` DATETIME NOT NULL,
`status` VARCHAR(45) NOT NULL COMMENT 'new, done, error',
`file_object` LONGBLOB NOT NULL,
PRIMARY KEY (`id`));
COMMIT;

View File

@ -2250,6 +2250,30 @@ USE `myems_system_db`;
INSERT INTO `myems_system_db`.`tbl_versions`
(`id`, `version`, `release_date`)
VALUES
(1, '1.1.3', '2021-05-25');
(1, '1.1.4', '2021-07-19');
COMMIT;
-- ---------------------------------------------------------------------------------------------------------------------
-- Table `myems_system_db`.`tbl_web_menus`
-- ---------------------------------------------------------------------------------------------------------------------
DROP TABLE IF EXISTS `myems_system_db`.`tbl_web_menus` ;
CREATE TABLE IF NOT EXISTS `myems_system_db`.`tbl_web_menus` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`version` VARCHAR(256) NOT NULL,
`release_date` DATE NOT NULL,
PRIMARY KEY (`id`));
-- ---------------------------------------------------------------------------------------------------------------------
-- Example Data for table `myems_system_db`.`tbl_versions`
-- ---------------------------------------------------------------------------------------------------------------------
START TRANSACTION;
USE `myems_system_db`;
INSERT INTO `myems_system_db`.`tbl_versions`
(`id`, `version`, `release_date`)
VALUES
(1, '1.1.4', '2021-07-19');
COMMIT;

21
database/upgrade1.1.4.sql Normal file
View File

@ -0,0 +1,21 @@
DROP TABLE myems_fdd_db.tbl_sms_recipients;
CREATE TABLE IF NOT EXISTS `myems_reporting_db`.`tbl_email_messages` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`recipient_name` VARCHAR(128) NOT NULL,
`recipient_email` VARCHAR(128) NOT NULL,
`subject` VARCHAR(128) NOT NULL,
`message` LONGTEXT NOT NULL,
`attachment_file_name` VARCHAR(128) NULL,
`attachment_file_object` LONGBLOB NULL,
`created_datetime_utc` DATETIME NOT NULL,
`scheduled_datetime_utc` DATETIME NOT NULL,
`status` VARCHAR(32) NOT NULL COMMENT 'new, sent, timeout',
PRIMARY KEY (`id`));
CREATE INDEX `tbl_email_messages_index_1` ON `myems_reporting_db`.`tbl_email_messages` (`status`, `scheduled_datetime_utc`);
RENAME TABLE myems_historical_db.tbl_offline_cost_files TO myems_historical_db.tbl_cost_files;
-- UPDATE VERSION NUMBER
UPDATE myems_system_db.tbl_versions SET version='1.1.4', release_date='2021-07-19' WHERE id=1;

View File

@ -837,6 +837,121 @@
}
]
},
{
"name": "Cost File",
"item": [
{
"name": "GET All Cost Files",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/costfiles",
"host": [
"{{base_url}}"
],
"path": [
"costfiles"
]
}
},
"response": []
},
{
"name": "GET a Cost File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/costfiles/1",
"host": [
"{{base_url}}"
],
"path": [
"costfiles",
"1"
]
}
},
"response": []
},
{
"name": "POST Upload a 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}}/costfiles",
"host": [
"{{base_url}}"
],
"path": [
"costfiles"
]
}
},
"response": []
},
{
"name": "DELETE a Cost File by ID",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "{{base_url}}/costfiles/1",
"host": [
"{{base_url}}"
],
"path": [
"costfiles",
"1"
]
}
},
"response": []
},
{
"name": "Rstore a Cost File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/costfiles/1/restore",
"host": [
"{{base_url}}"
],
"path": [
"costfiles",
"1",
"restore"
]
}
},
"response": []
}
]
},
{
"name": "Data Source",
"item": [
@ -2712,25 +2827,6 @@
},
"response": []
},
{
"name": "GET Rstore an Offline Meter File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/offlinemeterfiles/1/restore",
"host": [
"{{base_url}}"
],
"path": [
"offlinemeterfiles",
"1",
"restore"
]
}
},
"response": []
},
{
"name": "POST Upload a Knowledge File",
"request": {
@ -2786,6 +2882,25 @@
}
},
"response": []
},
{
"name": "Rstore a Knowledge File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/knowledgefiles/1/restore",
"host": [
"{{base_url}}"
],
"path": [
"knowledgefiles",
"1",
"restore"
]
}
},
"response": []
}
]
},
@ -3264,25 +3379,6 @@
},
"response": []
},
{
"name": "GET Rstore a Knowledge File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/knowledgefiles/1/restore",
"host": [
"{{base_url}}"
],
"path": [
"knowledgefiles",
"1",
"restore"
]
}
},
"response": []
},
{
"name": "POST Upload a Offline Meter File",
"request": {
@ -3338,98 +3434,21 @@
}
},
"response": []
}
]
},
{
"name": "Offline Cost File",
"item": [
},
{
"name": "GET All Offline Cost Files",
"name": "Rstore an Offline Meter File by ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/offlinecostfiles",
"raw": "{{base_url}}/offlinemeterfiles/1/restore",
"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"
"offlinemeterfiles",
"1",
"restore"
]
}
},

View File

@ -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) | [Offline Cost File](#Offline-Cost-File)
[Tariff](#Tariff) | [Cost Center](#Cost-Center) | [Cost File](#Offline-Cost-File)
[Meter](#Meter) | [Virtual Meter](#Virtual-Meter) | [Offline Meter](#Offline-Meter) | [Offline Meter File](#Offline-Meter-File)
@ -250,35 +250,39 @@ $ 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
### Cost File
* GET an Cost File by ID
```bash
$ curl -i -X GET {{base_url}}/offlinecostfiles/{id}
$ curl -i -X GET {{base_url}}/costfiles/{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 |
| id | integer | Cost File ID |
| file_name | string | Cost File name |
| uuid | string | 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 |
| status | string | Cost File processing status (new, done, error) |
| file_object | BLOB | Cost File Object |
* GET All Offline Cost Files
* GET All Cost Files
```bash
$ curl -i -X GET {{base_url}}/offlinecostfiles
$ curl -i -X GET {{base_url}}/costfiles
```
* DELETE an Offline Cost File by ID
* DELETE a Cost File by ID
```bash
$ curl -i -X DELETE {{base_url}}/offlinecostfiles/{id}
$ curl -i -X DELETE {{base_url}}/costfiles/{id}
```
* POST Upload an Offline Cost File
* POST Upload a 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
$ curl -i -H "Content-Type: application/TBD" -X POST -d 'file: (binary)' {{base_url}}/costfiles
```
* GET Restore a Cost File by ID from database to disk
```bash
$ curl -i -X GET {{base_url}}/costfiles/{id}/restore
```
### Data Source

View File

@ -3,7 +3,7 @@ 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, \
offlinecostfile, offlinemeterfile, version, contact, emailserver, combinedequipment, datasource, equipment, tenant, shopfloor, \
costfile, 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
@ -140,10 +140,12 @@ 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('/costfiles',
costfile.CostFileCollection())
api.add_route('/costfiles/{id_}',
costfile.CostFileItem())
api.add_route('/costfiles/{id_}/restore',
costfile.CostFileRestore())
api.add_route('/datasources',
datasource.DataSourceCollection())

View File

@ -7,7 +7,7 @@ from datetime import datetime, timezone
import os
class OfflineCostFileCollection:
class CostFileCollection:
@staticmethod
def __init__():
pass
@ -22,7 +22,7 @@ class OfflineCostFileCollection:
cursor = cnx.cursor()
query = (" SELECT id, file_name, uuid, upload_datetime_utc, status "
" FROM tbl_offline_cost_files "
" FROM tbl_cost_files "
" ORDER BY upload_datetime_utc desc ")
cursor.execute(query)
rows = cursor.fetchall()
@ -68,7 +68,7 @@ class OfflineCostFileCollection:
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')
description='API.FAILED_TO_UPLOAD_COST_FILE')
# Verify User Session
token = req.headers.get('TOKEN')
@ -124,7 +124,7 @@ class OfflineCostFileCollection:
cnx = mysql.connector.connect(**config.myems_historical_db)
cursor = cnx.cursor()
add_values = (" INSERT INTO tbl_offline_cost_files "
add_values = (" INSERT INTO tbl_cost_files "
" (file_name, uuid, upload_datetime_utc, status, file_object ) "
" VALUES (%s, %s, %s, %s, %s) ")
cursor.execute(add_values, (filename,
@ -138,10 +138,10 @@ class OfflineCostFileCollection:
cnx.disconnect()
resp.status = falcon.HTTP_201
resp.location = '/offlinecostfiles/' + str(new_id)
resp.location = '/costfiles/' + str(new_id)
class OfflineCostFileItem:
class CostFileItem:
@staticmethod
def __init__():
pass
@ -155,13 +155,13 @@ class OfflineCostFileItem:
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')
description='API.INVALID_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 "
" FROM tbl_cost_files "
" WHERE id = %s ")
cursor.execute(query, (id_,))
row = cursor.fetchone()
@ -169,7 +169,7 @@ class OfflineCostFileItem:
cnx.disconnect()
if row is None:
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
description='API.OFFLINE_COST_FILE_NOT_FOUND')
description='API.COST_FILE_NOT_FOUND')
upload_datetime = row[3]
upload_datetime = upload_datetime.replace(tzinfo=timezone.utc)
@ -185,20 +185,20 @@ class OfflineCostFileItem:
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')
description='API.INVALID_COST_FILE_ID')
cnx = mysql.connector.connect(**config.myems_historical_db)
cursor = cnx.cursor()
cursor.execute(" SELECT uuid "
" FROM tbl_offline_cost_files "
" FROM tbl_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')
description='API.COST_FILE_NOT_FOUND')
try:
file_uuid = row[0]
@ -208,14 +208,69 @@ class OfflineCostFileItem:
# 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
# ignore exception and don't return API.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_,))
cursor.execute(" DELETE FROM tbl_cost_files WHERE id = %s ", (id_,))
cnx.commit()
cursor.close()
cnx.disconnect()
resp.status = falcon.HTTP_204
class CostFileRestore:
@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_COST_FILE_ID')
cnx = mysql.connector.connect(**config.myems_historical_db)
cursor = cnx.cursor()
query = (" SELECT uuid, file_object "
" FROM tbl_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.COST_FILE_NOT_FOUND')
result = {"uuid": row[0],
"file_object": row[1]}
try:
raw_blob = result["file_object"]
file_uuid = result["uuid"]
# 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.replace(temp_file_path, file_path)
except Exception as ex:
raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR',
description='API.FAILED_TO_RESTORE_COST_FILE')
resp.body = 'success'
resp.status = falcon.HTTP_200

2
web/package-lock.json generated vendored
View File

@ -1,6 +1,6 @@
{
"name": "myems",
"version": "1.1.3",
"version": "1.1.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

2
web/package.json vendored
View File

@ -1,6 +1,6 @@
{
"name": "myems",
"version": "1.1.3",
"version": "1.1.4",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.1",

View File

@ -1,4 +1,4 @@
export const version = '1.1.3';
export const version = '1.1.4';
export const navbarBreakPoint = 'xl'; // Vertical navbar breakpoint
export const topNavbarBreakpoint = 'lg';
//export const APIBaseURL = 'http://127.0.0.1:8000';