refactor(ticket): isEditable, canEdit
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
e4b61f81a9
commit
fe8ae164eb
|
@ -0,0 +1,33 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('aclFunc', {
|
||||||
|
description: 'Get the user information and permissions',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'property',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The user name or email',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/aclFunc`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.aclFunc = async function(ctx, property) {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const models = Self.app.models;
|
||||||
|
|
||||||
|
const [acl] = await Self.rawSql(
|
||||||
|
`SELECT a.principalId
|
||||||
|
FROM salix.ACL a
|
||||||
|
WHERE a.property = ?`, [property]);
|
||||||
|
|
||||||
|
return await models.Account.hasRole(userId, acl.principalId);
|
||||||
|
};
|
||||||
|
};
|
|
@ -7,6 +7,7 @@ module.exports = Self => {
|
||||||
require('../methods/account/change-password')(Self);
|
require('../methods/account/change-password')(Self);
|
||||||
require('../methods/account/set-password')(Self);
|
require('../methods/account/set-password')(Self);
|
||||||
require('../methods/account/validate-token')(Self);
|
require('../methods/account/validate-token')(Self);
|
||||||
|
require('../methods/account/aclFunc')(Self);
|
||||||
|
|
||||||
// Validations
|
// Validations
|
||||||
|
|
||||||
|
|
|
@ -2651,3 +2651,9 @@ INSERT INTO `vn`.`collection` (`id`, `created`, `workerFk`, `stateFk`, `itemPack
|
||||||
INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `created`, `level`, `wagon`, `smartTagFk`, `usedShelves`, `itemCount`, `liters`)
|
INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `created`, `level`, `wagon`, `smartTagFk`, `usedShelves`, `itemCount`, `liters`)
|
||||||
VALUES
|
VALUES
|
||||||
(9, 3, util.VN_NOW(), NULL, 0, NULL, NULL, NULL, NULL);
|
(9, 3, util.VN_NOW(), NULL, 0, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
INSERT INTO salix.ACL
|
||||||
|
(model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('Sale', 'editTracked', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Sale', 'editCloned', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('canEdit', {
|
Self.remoteMethodCtx('canEdit', {
|
||||||
description: 'Check if all the received sales are aditable',
|
description: 'Check if all the received sales are aditable',
|
||||||
|
@ -25,16 +27,26 @@ module.exports = Self => {
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const idsCollection = sales.map(sale => sale.id);
|
/* const firstSale = await models.Sale.findById(sales[0], null, myOptions);
|
||||||
|
const isTicketEditable = await models.Ticket.isEditable(ctx, firstSale.ticketFk, myOptions);
|
||||||
const saleTracking = await models.SaleTracking.find({where: {saleFk: {inq: idsCollection}}}, myOptions);
|
if (!isTicketEditable)
|
||||||
|
throw new UserError(`The sales of this ticket can't be modified`);*/
|
||||||
|
|
||||||
|
const saleTracking = await models.SaleTracking.find({where: {saleFk: {inq: sales}}}, myOptions);
|
||||||
const hasSaleTracking = saleTracking.length;
|
const hasSaleTracking = saleTracking.length;
|
||||||
|
|
||||||
const isProductionRole = await models.Account.hasRole(userId, 'production', myOptions);
|
const saleCloned = await models.SaleCloned.find({where: {saleClonedFk: {inq: sales}}}, myOptions);
|
||||||
|
const hasSaleCloned = saleCloned.length;
|
||||||
|
|
||||||
const canEdit = (isProductionRole || !hasSaleTracking);
|
/* const isProductionRole = await models.Account.hasRole(userId, 'production', myOptions);
|
||||||
|
const canEdit = (isProductionRole || !hasSaleTracking);// && (isRole || !hasSaleCloned);
|
||||||
|
|
||||||
return canEdit;
|
const isRole = await models.Account.hasRole(userId, 'developer', myOptions);*/
|
||||||
|
const editTracked = await models.Account.aclFunc(ctx, 'editTracked');
|
||||||
|
const editCloned = await models.Account.aclFunc(ctx, 'editCloned');
|
||||||
|
console.log(editTracked);
|
||||||
|
const canEdit = (editTracked || !hasSaleTracking) && (editCloned || !hasSaleCloned);
|
||||||
|
|
||||||
|
return canEdit;// && isTicketEditable;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,8 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const canEditSales = await models.Sale.canEdit(ctx, sales, myOptions);
|
const saleIds = sales.map(sale => sale.id);
|
||||||
|
const canEditSales = await models.Sale.canEdit(ctx, saleIds, myOptions);
|
||||||
|
|
||||||
const ticket = await models.Ticket.findById(ticketId, {
|
const ticket = await models.Ticket.findById(ticketId, {
|
||||||
include: {
|
include: {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('recalculatePrice', {
|
Self.remoteMethodCtx('recalculatePrice', {
|
||||||
description: 'Calculates the price of sales and its components',
|
description: 'Calculates the price of sales and its components',
|
||||||
|
@ -34,15 +35,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const salesIds = [];
|
const salesIds = sales.map(sale => sale.id);
|
||||||
for (let sale of sales)
|
|
||||||
salesIds.push(sale.id);
|
|
||||||
|
|
||||||
const isEditable = await models.Ticket.isEditable(ctx, sales[0].ticketFk, myOptions);
|
const isEditable = await models.Ticket.isEditable(ctx, sales[0].ticketFk, myOptions);
|
||||||
if (!isEditable)
|
if (!isEditable)
|
||||||
throw new UserError(`The sales of this ticket can't be modified`);
|
throw new UserError(`The sales of this ticket can't be modified`);
|
||||||
|
|
||||||
const canEditSale = await models.Sale.canEdit(ctx, sales, myOptions);
|
const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions);
|
||||||
if (!canEditSale)
|
if (!canEditSale)
|
||||||
throw new UserError(`Sale(s) blocked, please contact production`);
|
throw new UserError(`Sale(s) blocked, please contact production`);
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ module.exports = Self => {
|
||||||
if (!isTicketEditable)
|
if (!isTicketEditable)
|
||||||
throw new UserError(`The sales of this ticket can't be modified`);
|
throw new UserError(`The sales of this ticket can't be modified`);
|
||||||
|
|
||||||
const canEditSale = await models.Sale.canEdit(ctx, sales, myOptions);
|
const salesIds = sales.map(sale => sale.id);
|
||||||
|
const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions);
|
||||||
|
|
||||||
if (!canEditSale)
|
if (!canEditSale)
|
||||||
throw new UserError(`Sale(s) blocked, please contact production`);
|
throw new UserError(`Sale(s) blocked, please contact production`);
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe('sale canEdit()', () => {
|
||||||
const productionUserID = 49;
|
const productionUserID = 49;
|
||||||
const ctx = {req: {accessToken: {userId: productionUserID}}};
|
const ctx = {req: {accessToken: {userId: productionUserID}}};
|
||||||
|
|
||||||
const sales = [{id: 3}];
|
const sales = [3];
|
||||||
|
|
||||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ describe('sale canEdit()', () => {
|
||||||
const salesPersonUserID = 18;
|
const salesPersonUserID = 18;
|
||||||
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
||||||
|
|
||||||
const sales = [{id: 10}];
|
const sales = [10];
|
||||||
|
|
||||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ describe('sale canEdit()', () => {
|
||||||
const salesPersonUserID = 18;
|
const salesPersonUserID = 18;
|
||||||
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
||||||
|
|
||||||
const sales = [{id: 3}];
|
const sales = [3];
|
||||||
|
|
||||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||||
|
|
||||||
|
|
|
@ -20,24 +20,20 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.isEditable = async(ctx, id, options) => {
|
Self.isEditable = async(ctx, id, options) => {
|
||||||
const userId = ctx.req.accessToken.userId;
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
let state = await Self.app.models.TicketState.findOne({
|
const state = await models.TicketState.findOne({
|
||||||
where: {ticketFk: id}
|
where: {ticketFk: id}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
const isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant', myOptions);
|
const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, myOptions);
|
||||||
const isDeliveryBoss = await Self.app.models.Account.hasRole(userId, 'deliveryBoss', myOptions);
|
|
||||||
const isBuyer = await Self.app.models.Account.hasRole(userId, 'buyer', myOptions);
|
|
||||||
|
|
||||||
const isValidRole = isSalesAssistant || isDeliveryBoss || isBuyer;
|
const alertLevel = state ? state.alertLevel : null;
|
||||||
|
const ticket = await models.Ticket.findById(id, {
|
||||||
let alertLevel = state ? state.alertLevel : null;
|
|
||||||
let ticket = await Self.app.models.Ticket.findById(id, {
|
|
||||||
fields: ['clientFk'],
|
fields: ['clientFk'],
|
||||||
include: [{
|
include: [{
|
||||||
relation: 'client',
|
relation: 'client',
|
||||||
|
@ -48,15 +44,15 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
const isLocked = await Self.app.models.Ticket.isLocked(id, myOptions);
|
const isLocked = await models.Ticket.isLocked(id, myOptions);
|
||||||
|
|
||||||
const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0);
|
const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0);
|
||||||
const isNormalClient = ticket && ticket.client().type().code == 'normal';
|
const isNormalClient = ticket && ticket.client().type().code == 'normal';
|
||||||
const validAlertAndRoleNormalClient = (alertLevelGreaterThanZero && isNormalClient && !isValidRole);
|
const isEditable = !(alertLevelGreaterThanZero && isNormalClient);
|
||||||
|
|
||||||
if (!ticket || validAlertAndRoleNormalClient || isLocked)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
if (ticket && (isEditable || isRoleAdvanced) && !isLocked)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('isRoleAdvanced', {
|
||||||
|
description: 'Check if a ticket is editable',
|
||||||
|
accessType: 'READ',
|
||||||
|
returns: {
|
||||||
|
type: 'boolean',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/isRoleAdvanced`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.isRoleAdvanced = async(ctx, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', myOptions);
|
||||||
|
const isDeliveryBoss = await models.Account.hasRole(userId, 'deliveryBoss', myOptions);
|
||||||
|
const isBuyer = await models.Account.hasRole(userId, 'buyer', myOptions);
|
||||||
|
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
||||||
|
|
||||||
|
const isRoleAdvanced = isSalesAssistant || isDeliveryBoss || isBuyer || isClaimManager;
|
||||||
|
|
||||||
|
return isRoleAdvanced;
|
||||||
|
};
|
||||||
|
};
|
|
@ -29,6 +29,9 @@
|
||||||
"SaleChecked": {
|
"SaleChecked": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"SaleCloned": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"SaleComponent": {
|
"SaleComponent": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "SaleCloned",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "saleCloned"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"saleClonedFk": {
|
||||||
|
"id": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"saleOriginal": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Sale",
|
||||||
|
"foreignKey": "saleOriginalFk"
|
||||||
|
},
|
||||||
|
"saleCloned": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Sale",
|
||||||
|
"foreignKey": "saleClonedFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ module.exports = Self => {
|
||||||
require('../methods/ticket/freightCost')(Self);
|
require('../methods/ticket/freightCost')(Self);
|
||||||
require('../methods/ticket/getComponentsSum')(Self);
|
require('../methods/ticket/getComponentsSum')(Self);
|
||||||
require('../methods/ticket/refund')(Self);
|
require('../methods/ticket/refund')(Self);
|
||||||
|
require('../methods/ticket/isRoleAdvanced')(Self);
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
Self.observe('before save', async function(ctx) {
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
|
|
Loading…
Reference in New Issue