Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(users): use GROUP_CONCAT for roles/depots #4165

Merged
merged 2 commits into from
Feb 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/src/i18n/en/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"CANCEL": "Cancel",
"CANCEL_EDIT": "Cancel Edit",
"CASHBOX_MANAGEMENT": "Cashbox Management",
"CASHBOXES": "Cashboxes",
"CLEAR": "Clear",
"CLOSE": "Close",
"CONFIGURE": "Configure",
Expand Down
1 change: 1 addition & 0 deletions client/src/i18n/fr/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"CANCEL": "Annuler",
"CANCEL_EDIT": "Annuler Modifier",
"CASHBOX_MANAGEMENT": "Gestion des Caisses",
"CASHBOXES": "Caisses",
"CLEAR": "Effacer",
"CLOSE": "Fermer",
"CONFIGURE": "Configurer",
Expand Down
6 changes: 3 additions & 3 deletions client/src/modules/payroll/rubrics/modals/rubric.modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
value="RubricModalCtrl.rubric.is_monetary_value"
on-change-callback="RubricModalCtrl.isMonetaryValueSetting(value)">
</bh-yes-no-radios>

<bh-yes-no-radios
label="PAYROLL_RUBRIC.INDICE_TO_GRAPE"
value="RubricModalCtrl.rubric.indice_to_grap"
Expand Down Expand Up @@ -325,7 +325,7 @@
</div>
</div>
</div>

</div>
</div>
<div class="modal-footer">
Expand All @@ -337,4 +337,4 @@
<span translate>FORM.BUTTONS.SUBMIT</span>
</bh-loading-button>
</div>
</form>
</form>
9 changes: 4 additions & 5 deletions client/src/modules/templates/bhRubricSelect.tmpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<div
class="form-group"
ng-class="{ 'has-error' : RubricSelectForm.$submitted && rubricForm.config_id.$invalid }">

<label class="control-label text-capitalize" translate>
{{ ::$ctrl.label }}
</label>
<ng-transclude></ng-transclude>

<ng-transclude></ng-transclude>
<ui-select
name="config_id"
ng-model="$ctrl.rubrics"
Expand All @@ -24,10 +24,9 @@
<span ng-bind-html="rubric.label | highlight:$select.search"></span>
</ui-select-choices>
</ui-select>

<div class="help-block" ng-messages="rubricForm.config_id.$error" ng-show="RubricSelectForm.$submitted">
<div ng-messages-include="modules/templates/messages.tmpl.html"></div>
</div>
</div>
</div>

7 changes: 7 additions & 0 deletions client/src/modules/users/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ function UsersController($state, $uibModal, Users, Notify, Modal, uiGridConstant
enableFiltering : true,
cellClass : muteDisabledCells,
},
{
field : 'cashboxes',
displayName : 'FORM.LABELS.CASHBOXES',
headerCellFilter : 'translate',
enableFiltering : true,
cellClass : muteDisabledCells,
},
{
field : 'action',
displayName : '',
Expand Down
3 changes: 3 additions & 0 deletions client/src/modules/users/users.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ function UserService(Api) {
delete user.lastLogin;
delete user.id;
delete user.active;
delete user.roles;
delete user.cashboxes;
delete user.depots;

return service.$http.put(`/users/${id}`, user)
.then(service.util.unwrapHttpResponse);
Expand Down
4 changes: 1 addition & 3 deletions client/src/modules/vouchers/complex-voucher.ctrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ ComplexJournalVoucherController.$inject = [
*
* @constructor
*
* TODO - Implement caching mechanism for incomplete forms (via AppCache)
* TODO/FIXME - this error notification system needs serious refactor.
*/
function ComplexJournalVoucherController(
Vouchers, Currencies, Session, FindEntity, FindReference, Notify, Toolkit,
Receipts, bhConstants, uiGridConstants, VoucherForm, $timeout, Rates
Receipts, bhConstants, uiGridConstants, VoucherForm, $timeout, Rates,
) {
const vm = this;

Expand Down Expand Up @@ -136,7 +135,6 @@ function ComplexJournalVoucherController(
* @param {object} result
*/
function updateView(result) {

$timeout(() => {
// transaction type
vm.Voucher.details.type_id = result.type_id || vm.Voucher.details.type_id;
Expand Down
2 changes: 1 addition & 1 deletion client/src/modules/vouchers/voucher-form.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ VoucherFormService.$inject = [
*/
function VoucherFormService(
Vouchers, Constants, Session, VoucherItem, AppCache, Store, Accounts,
$timeout, $translate, Exchange, FormatTreeData
$timeout, $translate, Exchange, FormatTreeData,
) {
// Error Flags
// must have transaction_type for certain cases
Expand Down
87 changes: 32 additions & 55 deletions server/controllers/admin/users/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,20 @@ async function lookupUser(id) {

let sql = `
SELECT user.id, user.username, user.email, user.display_name,
user.active, user.last_login AS lastLogin, user.deactivated
FROM user WHERE user.id = ?;
`;
user.active, user.last_login AS lastLogin, user.deactivated,
GROUP_CONCAT(DISTINCT role.label ORDER BY role.label DESC SEPARATOR ', ') AS roles,
GROUP_CONCAT(DISTINCT depot.text ORDER BY depot.text DESC SEPARATOR ', ') AS depots,
GROUP_CONCAT(DISTINCT cb.label ORDER BY cb.label DESC SEPARATOR ', ') AS cashboxes
FROM user
LEFT JOIN user_role ur ON user.id = ur.user_id
LEFT JOIN role ON role.uuid = ur.role_uuid
LEFT JOIN depot_permission dp ON dp.user_id = user.id
LEFT JOIN depot ON dp.depot_uuid = depot.uuid
LEFT JOIN cashbox_permission ON user.id = cashbox_permission.user_id
LEFT JOIN cash_box cb ON cashbox_permission.cashbox_id = cb.id
WHERE user.id = ?
GROUP BY user.id;
`.trim();

const user = await db.one(sql, [id]);

Expand All @@ -73,69 +84,35 @@ async function lookupUser(id) {
*
* @description
* If the client queries to /users endpoint, the API will respond with an array
* of zero or more JSON objects, with id, and username keys.
* of zero or more JSON objects, with id, username, display_name, activation state,
* roles and depots keys.
*
* GET /users
*/
async function list(req, res, next) {
try {
const sql = 'SELECT user.id, display_name, user.username, user.deactivated FROM user;';
let users = await db.exec(sql);
users = await setDepots(users);
users = await setRoles(users);
const sql = `
SELECT user.id, user.display_name, user.username, user.deactivated,
GROUP_CONCAT(DISTINCT role.label ORDER BY role.label DESC SEPARATOR ', ') AS roles,
GROUP_CONCAT(DISTINCT depot.text ORDER BY depot.text DESC SEPARATOR ', ') AS depots,
GROUP_CONCAT(DISTINCT cb.label ORDER BY cb.label DESC SEPARATOR ', ') AS cashboxes
FROM user
LEFT JOIN user_role ur ON user.id = ur.user_id
LEFT JOIN role ON role.uuid = ur.role_uuid
LEFT JOIN depot_permission dp ON dp.user_id = user.id
LEFT JOIN depot ON dp.depot_uuid = depot.uuid
LEFT JOIN cashbox_permission ON user.id = cashbox_permission.user_id
LEFT JOIN cash_box cb ON cashbox_permission.cashbox_id = cb.id
GROUP BY user.id;
`.trim();

const users = await db.exec(sql);
res.status(200).json(users);
} catch (error) {
next(error);
}
}

async function setRoles(users) {
const sql = `
SELECT ur.user_id, r.label
FROM user_role ur
JOIN role r ON r.uuid = ur.role_uuid`;

const userMap = {};
users.forEach(user => {
user.roles = '';
userMap[user.id] = user;
});

const roles = await db.exec(sql);

users.forEach(user => {
user.roles = roles
.filter(role => role.user_id === user.id)
.map(role => role.label)
.join(', ');
});
return users;
}

async function setDepots(users) {
const sql = `
SELECT d.text, dpp.user_id
FROM depot_permission dpp
JOIN depot d ON d.uuid = dpp.depot_uuid`;

const depotMap = {};
users.forEach(user => {
user.roles = '';
depotMap[user.id] = user;
});

const depots = await db.exec(sql);

users.forEach(user => {
user.depots = depots
.filter(depot => depot.user_id === user.id)
.map(depot => depot.text)
.join(', ');
});

return users;
}

/**
* @function detail
*
Expand Down
4 changes: 2 additions & 2 deletions server/controllers/payroll/rubricConfig/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function lookupRubricConfig(id) {
// Lists the Payroll RubricConfigs
function list(req, res, next) {
const sql = `
SELECT c.id, c.label FROM config_rubric AS c
SELECT c.id, c.label FROM config_rubric AS c
;`;

db.exec(sql)
Expand Down Expand Up @@ -98,7 +98,7 @@ function del(req, res, next) {
*/
function listConfig(req, res, next) {
const sql = `
SELECT config_rubric_item.id, config_rubric_item.config_rubric_id, config_rubric_item.rubric_payroll_id
SELECT config_rubric_item.id, config_rubric_item.config_rubric_id, config_rubric_item.rubric_payroll_id
FROM config_rubric_item
WHERE config_rubric_item.config_rubric_id = ?;
`;
Expand Down