diff --git a/client/src/i18n/en/cost_center.json b/client/src/i18n/en/cost_center.json
index e30e45e480..187903024f 100644
--- a/client/src/i18n/en/cost_center.json
+++ b/client/src/i18n/en/cost_center.json
@@ -17,10 +17,12 @@
"EDIT_ALLOCATION_BASIS": "Edit allocation basis",
"EDIT_ALLOCATION_KEYS" : "Edit Allocation Keys",
"EDIT_COST_CENTER" : "Update the Cost Center Information",
+ "EDIT_STEP_ORDER" : "Edit order of cost allocation steps",
"PRINCIPAL": "Principal Cost Center",
"NO_COST_CENTER_DEFINED": "** Cost Center Not Defined **",
"SELECT_ALLOCATION_BASIS": "Select allocation basis",
"STEP_DOWN_COST_ALLOCATION": "Step-down cost allocation",
+ "STEP_ORDER": "Allocation Step Order",
"ONLY_FOR_EXPLOITATION_ACCOUNTS": "Only for operating accounts (income and expenses). For others accounts, the cost center will not be considered",
"UPDATE_ALLOCATION_QUANTITIES": "Update",
"UPDATE_ALLOCATION_QUANTITIES_TOOLTIP": "Update system-computed cost center allocation quantities",
diff --git a/client/src/i18n/fr/cost_center.json b/client/src/i18n/fr/cost_center.json
index 3ec1c542be..e1bc6ec910 100644
--- a/client/src/i18n/fr/cost_center.json
+++ b/client/src/i18n/fr/cost_center.json
@@ -17,10 +17,12 @@
"EDIT_ALLOCATION_BASIS": "Modifier la base d'allocation",
"EDIT_ALLOCATION_KEYS" : "Modifier les clés de répartition",
"EDIT_COST_CENTER" : "Mise à jour des informations du centre de coût",
+ "EDIT_STEP_ORDER" : "Modifier l'ordre des étapes de l'allocation des coûts",
"PRINCIPAL": "Centre de coût Principal",
"NO_COST_CENTER_DEFINED": "** Aucun centre de cout **",
"SELECT_ALLOCATION_BASIS": "Sélectionnez la base d'allocation",
"STEP_DOWN_COST_ALLOCATION": "Allocation séquentielle des coûts",
+ "STEP_ORDER": "Ordre des étapes de l'allocation",
"ONLY_FOR_EXPLOITATION_ACCOUNTS": "Uniquement pour les comptes d'exploitations (produits et charges). Pour les autres comptes, le centre de cout ne sera pas pris en compte",
"UPDATE_ALLOCATION_QUANTITIES": "Mettre à jour",
"UPDATE_ALLOCATION_QUANTITIES_TOOLTIP": "Mettre à jour les quantités d'allocation des centres de coûts calculées par le système",
diff --git a/client/src/modules/cost_center/cost_center.html b/client/src/modules/cost_center/cost_center.html
index b6698556e6..921805ba25 100644
--- a/client/src/modules/cost_center/cost_center.html
+++ b/client/src/modules/cost_center/cost_center.html
@@ -21,6 +21,11 @@
ALLOCATION_BASES
+
+
+ COST_CENTER.EDIT_STEP_ORDER
+
+
diff --git a/client/src/modules/cost_center/cost_center.js b/client/src/modules/cost_center/cost_center.js
index f3f1ede40d..14037d0b0d 100644
--- a/client/src/modules/cost_center/cost_center.js
+++ b/client/src/modules/cost_center/cost_center.js
@@ -22,6 +22,7 @@ function CostCenterController(CostCenters, ModalService, Notify, uiGridConstants
vm.deleteCostCenter = deleteCostCenter;
vm.toggleFilter = toggleFilter;
vm.openEditAllocationBasisModal = openEditAllocationBasisModal;
+ vm.editAllocationStepOrder = editAllocationStepOrder;
// global variables
vm.gridApi = {};
@@ -159,5 +160,13 @@ function CostCenterController(CostCenters, ModalService, Notify, uiGridConstants
}).result.catch(angular.noop);
}
+ function editAllocationStepOrder() {
+ $uibModal.open({
+ templateUrl : 'modules/cost_center/modals/edit_allocation_step_order.modal.html',
+ controller : 'AllocationEditStepOrderController as ModalCtrl',
+ // size : 'lg',
+ }).result.catch(angular.noop);
+ }
+
loadCostCenters();
}
diff --git a/client/src/modules/cost_center/cost_center.service.js b/client/src/modules/cost_center/cost_center.service.js
index a472ac32c8..e1fa13a8aa 100644
--- a/client/src/modules/cost_center/cost_center.service.js
+++ b/client/src/modules/cost_center/cost_center.service.js
@@ -45,5 +45,11 @@ function CostCenterService(Api, $uibModal) {
.then(service.util.unwrapHttpResponse);
};
+ service.setAllocationStepOrder = (options) => {
+ const url = `/cost_center/step_order/multi`;
+ return service.$http.put(url, { params : options })
+ .then(service.util.unwrapHttpResponse);
+ };
+
return service;
}
diff --git a/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.html b/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.html
new file mode 100644
index 0000000000..1613e8640c
--- /dev/null
+++ b/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.html
@@ -0,0 +1,44 @@
+
\ No newline at end of file
diff --git a/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.js b/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.js
new file mode 100644
index 0000000000..65f46c6e4d
--- /dev/null
+++ b/client/src/modules/cost_center/modals/edit_allocation_step_order.modal.js
@@ -0,0 +1,115 @@
+angular.module('bhima.controllers')
+ .controller('AllocationEditStepOrderController', AllocationEditStepOrderController);
+
+AllocationEditStepOrderController.$inject = [
+ 'CostCenterService', 'NotifyService', '$uibModalInstance', 'uiGridConstants',
+];
+
+function AllocationEditStepOrderController(CostCenters, Notify, Instance, uiGridConstants) {
+
+ const vm = this;
+
+ vm.loading = false;
+ vm.cancel = Instance.close;
+ vm.loadCostCenters = loadCostCenters;
+ vm.moveStepDown = moveStepDown;
+ vm.moveStepUp = moveStepUp;
+ vm.submit = submit;
+
+ // global variables
+ vm.gridApi = {};
+ vm.filterEnabled = false;
+
+ // options for the UI grid
+ vm.gridOptions = {
+ appScopeProvider : vm,
+ enableColumnMenus : false,
+ flatEntityAccess : true,
+ enableRowReordering : true,
+ enableSorting : false,
+ onRegisterApi : onRegisterApiFn,
+ columnDefs : [
+ {
+ field : 'label',
+ displayName : 'FORM.LABELS.DESIGNATION',
+ headerCellFilter : 'translate',
+ enableSorting : false,
+ },
+ {
+ field : 'step_order',
+ displayName : 'COST_CENTER.STEP_ORDER',
+ headerCellFilter : 'translate',
+ headerCellClass : 'allocationBasisColHeader',
+ defaultSort : { direction : uiGridConstants.ASC, priority : 1 },
+ type : 'number',
+ visible : true,
+ },
+ {
+ field : 'reorder',
+ displayName : '',
+ cellTemplate : '/modules/cost_center/templates/reorder_allocation_steps.tmpl.html',
+ enableSorting : false,
+ enableFiltering : false,
+ },
+ ],
+ };
+
+ function loadCostCenters() {
+ vm.loading = true;
+ CostCenters.read()
+ .then((data) => {
+ const auxData = data.filter(item => !item.is_principal);
+ auxData.sort((a, b) => Number(a.step_order) - Number(b.step_order));
+
+ // rewrite the step order
+ auxData.forEach((value, idx) => {
+ value.step_order = idx + 1;
+ });
+
+ vm.data = auxData;
+ vm.gridOptions.data = vm.data;
+ })
+ .catch(Notify.handleError)
+ .finally(() => {
+ vm.loading = false;
+ });
+ }
+
+ function onRegisterApiFn(gridApi) {
+ vm.gridApi = gridApi;
+ }
+
+ function moveStepDown(row) {
+ const stepOrder = row.step_order;
+ const upper = vm.data.find(r => r.step_order === stepOrder + 1);
+ row.step_order++;
+ upper.step_order--;
+ vm.gridOptions.data = vm.data;
+ vm.gridApi.core.refreshRows();
+ }
+
+ function moveStepUp(row) {
+ const stepOrder = row.step_order;
+ const lower = vm.data.find(r => r.step_order === stepOrder - 1);
+ row.step_order--;
+ lower.step_order++;
+ vm.gridOptions.data = vm.data;
+ vm.gridApi.core.refreshRows();
+ }
+
+ function submit() {
+ vm.loading = true;
+ const newStepOrder = vm.gridOptions.data.map(row => ({
+ id : row.id,
+ step_order : row.step_order,
+ }));
+ CostCenters.setAllocationStepOrder({ new_order : newStepOrder })
+ .then(() => {
+ vm.loading = false;
+ Instance.close();
+ Notify.success('FORM.INFO.UPDATE_SUCCESS');
+ });
+ }
+
+ loadCostCenters();
+}
diff --git a/client/src/modules/cost_center/templates/reorder_allocation_steps.tmpl.html b/client/src/modules/cost_center/templates/reorder_allocation_steps.tmpl.html
new file mode 100644
index 0000000000..cb361524f1
--- /dev/null
+++ b/client/src/modules/cost_center/templates/reorder_allocation_steps.tmpl.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/server/config/routes.js b/server/config/routes.js
index aca7a72e1c..7d0138fb40 100644
--- a/server/config/routes.js
+++ b/server/config/routes.js
@@ -934,6 +934,7 @@ exports.configure = function configure(app) {
app.post('/cost_center', costCenter.create);
app.put('/cost_center/:id', costCenter.update);
app.delete('/cost_center/:id', costCenter.delete);
+ app.put('/cost_center/step_order/multi', costCenter.setAllocationStepOrder);
// Step-down allocation basis API
app.get('/cost_center_allocation_basis', costAllocationBasis.list);
diff --git a/server/controllers/finance/cost_center.js b/server/controllers/finance/cost_center.js
index 5f97b041cf..9db8f89c2d 100644
--- a/server/controllers/finance/cost_center.js
+++ b/server/controllers/finance/cost_center.js
@@ -12,7 +12,7 @@ const FilterParser = require('../../lib/filter');
async function lookupCostCenter(id) {
const sqlCostCenter = `
SELECT fc.id, fc.label, fc.is_principal, fc.project_id,
- fc.allocation_method, fc.allocation_basis_id,
+ fc.allocation_method, fc.allocation_basis_id, fc.step_order,
cab.name AS allocation_basis_name, cab.units as allocation_basis_units,
cab.is_predefined AS allocation_basis_is_predefined,
cabval.quantity AS allocation_basis_quantity
@@ -68,7 +68,7 @@ async function lookupCostCenter(id) {
function list(req, res, next) {
const filters = new FilterParser(req.query, { tableAlias : 'f' });
const sql = `
- SELECT f.id, f.label, f.is_principal, f.project_id,
+ SELECT f.id, f.label, f.is_principal, f.project_id, f.step_order,
f.allocation_method, f.allocation_basis_id,
GROUP_CONCAT(' ', LOWER(ar.description)) AS abbrs,
GROUP_CONCAT(' ', s.name) serviceNames, p.name AS projectName,
@@ -341,6 +341,23 @@ function assignCostCenterParams(accountsCostCenter, rubrics, key) {
return rubrics;
}
+
+// PUT /cost_center/step_order/multi
+function setAllocationStepOrder(req, res, next) {
+ const { params } = req.body;
+ const query = 'UPDATE `cost_center` SET `step_order` = ? WHERE `id` = ?';
+ const transaction = db.transaction();
+ params.new_order.forEach(row => {
+ transaction.addQuery(query, [row.step_order, row.id]);
+ });
+
+ transaction.execute()
+ .then(() => {
+ res.sendStatus(204);
+ })
+ .catch(next);
+}
+
// get list of costCenter
exports.list = list;
// get details of a costCenter
@@ -355,3 +372,5 @@ exports.delete = del;
exports.getAllCostCenterAccounts = getAllCostCenterAccounts;
// Assign Cost Center Params
exports.assignCostCenterParams = assignCostCenterParams;
+
+exports.setAllocationStepOrder = setAllocationStepOrder;