From 4a714a4b6fbc84c100bb16c03a08ca6cdfcf7c2c Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 12 Apr 2022 07:56:03 +0200 Subject: [PATCH] feat(client): add privileges to administrative role --- .../12_lock_of_verified_data.spec.js | 4 +-- .../client/specs/addressesPropagateRe.spec.js | 16 ++++++++++ .../client/specs/createAddress.spec.js | 16 ++++++++++ .../client/specs/createWithUser.spec.js | 16 ++++++++++ .../client/specs/updateAddress.spec.js | 19 ++++++++++- .../client/specs/updateFiscalData.spec.js | 15 +++++++++ .../back/methods/client/updateFiscalData.js | 4 +-- modules/client/back/models/client.js | 32 +++++++++++++++++-- .../client/back/models/specs/address.spec.js | 30 +++++++++++++---- modules/client/front/fiscal-data/index.html | 2 +- .../specs/createManualInvoice.spec.js | 4 ++- 11 files changed, 142 insertions(+), 16 deletions(-) diff --git a/e2e/paths/02-client/12_lock_of_verified_data.spec.js b/e2e/paths/02-client/12_lock_of_verified_data.spec.js index 701531c765..6bf6bd80b9 100644 --- a/e2e/paths/02-client/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client/12_lock_of_verified_data.spec.js @@ -126,7 +126,7 @@ describe('Client lock verified data path', () => { it('should confirm verified data button is enabled for salesAssistant', async() => { const isDisabled = await page.isDisabled(selectors.clientFiscalData.verifiedDataCheckbox); - expect(isDisabled).toBeFalsy(); + expect(isDisabled).toBeTruthy(); }); it('should now edit the social name', async() => { @@ -135,7 +135,7 @@ describe('Client lock verified data path', () => { await page.waitToClick(selectors.clientFiscalData.saveButton); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); + expect(message.text).toContain(`You can't make changes on a client with verified data`); }); it('should now confirm the social name have been edited once and for all', async() => { diff --git a/modules/client/back/methods/client/specs/addressesPropagateRe.spec.js b/modules/client/back/methods/client/specs/addressesPropagateRe.spec.js index 069c7bd250..74d80b964f 100644 --- a/modules/client/back/methods/client/specs/addressesPropagateRe.spec.js +++ b/modules/client/back/methods/client/specs/addressesPropagateRe.spec.js @@ -1,6 +1,22 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Client addressesPropagateRe', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should propagate the isEqualizated on both addresses of Mr Wayne and set hasToInvoiceByAddress to false', async() => { const tx = await models.Client.beginTransaction({}); diff --git a/modules/client/back/methods/client/specs/createAddress.spec.js b/modules/client/back/methods/client/specs/createAddress.spec.js index d6178ae0d8..0841ad98ce 100644 --- a/modules/client/back/methods/client/specs/createAddress.spec.js +++ b/modules/client/back/methods/client/specs/createAddress.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Address createAddress', () => { const clientFk = 1101; @@ -6,6 +7,21 @@ describe('Address createAddress', () => { const incotermsFk = 'FAS'; const customAgentOneId = 1; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should throw a non uee member error if no incoterms is defined', async() => { const tx = await models.Client.beginTransaction({}); diff --git a/modules/client/back/methods/client/specs/createWithUser.spec.js b/modules/client/back/methods/client/specs/createWithUser.spec.js index 4c827c7453..7d4261aeef 100644 --- a/modules/client/back/methods/client/specs/createWithUser.spec.js +++ b/modules/client/back/methods/client/specs/createWithUser.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Client Create', () => { const newAccount = { @@ -12,6 +13,21 @@ describe('Client Create', () => { businessTypeFk: 'florist' }; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it(`should not find Deadpool as he's not created yet`, async() => { const tx = await models.Client.beginTransaction({}); diff --git a/modules/client/back/methods/client/specs/updateAddress.spec.js b/modules/client/back/methods/client/specs/updateAddress.spec.js index 5597c6e5ad..5023c68f58 100644 --- a/modules/client/back/methods/client/specs/updateAddress.spec.js +++ b/modules/client/back/methods/client/specs/updateAddress.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Address updateAddress', () => { const clientId = 1101; @@ -13,6 +14,21 @@ describe('Address updateAddress', () => { } }; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should throw the non uee member error if no incoterms is defined', async() => { const tx = await models.Client.beginTransaction({}); @@ -90,9 +106,10 @@ describe('Address updateAddress', () => { it('should return an error for a user without enough privileges', async() => { const tx = await models.Client.beginTransaction({}); - + const employeeId = 1; try { const options = {transaction: tx}; + ctx.req.accessToken.userId = employeeId; ctx.args = { isLogifloraAllowed: true }; diff --git a/modules/client/back/methods/client/specs/updateFiscalData.spec.js b/modules/client/back/methods/client/specs/updateFiscalData.spec.js index 7c0bc05998..f608f6bd9e 100644 --- a/modules/client/back/methods/client/specs/updateFiscalData.spec.js +++ b/modules/client/back/methods/client/specs/updateFiscalData.spec.js @@ -1,10 +1,25 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Client updateFiscalData', () => { const clientId = 1101; const employeeId = 1; const salesAssistantId = 21; const administrativeId = 5; + const activeCtx = { + accessToken: {userId: employeeId}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); it('should return an error if the user is not salesAssistant and the isTaxDataChecked value is true', async() => { const tx = await models.Client.beginTransaction({}); diff --git a/modules/client/back/methods/client/updateFiscalData.js b/modules/client/back/methods/client/updateFiscalData.js index 539d89d3a8..3a3479405e 100644 --- a/modules/client/back/methods/client/updateFiscalData.js +++ b/modules/client/back/methods/client/updateFiscalData.js @@ -125,10 +125,10 @@ module.exports = Self => { } try { - const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', myOptions); + const isAdministrative = await models.Account.hasRole(userId, 'administrative', myOptions); const client = await models.Client.findById(clientId, null, myOptions); - if (!isSalesAssistant && client.isTaxDataChecked) + if (!isAdministrative && client.isTaxDataChecked) throw new UserError(`You can't make changes on a client with verified data`); // Sage data validation diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 5ccc1ec64e..bb0e54b8d2 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -208,6 +208,34 @@ module.exports = Self => { throw new UserError(`The type of business must be filled in basic data`); }); + Self.observe('before save', async ctx => { + const changes = ctx.data || ctx.instance; + const orgData = ctx.currentInstance; + const models = Self.app.models; + + const loopBackContext = LoopBackContext.getCurrentContext(); + const userId = loopBackContext.active.accessToken.userId; + + const isAdministrative = await models.Account.hasRole(userId, 'administrative', ctx.options); + const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', ctx.options); + const hasChanges = orgData && changes; + + const isTaxDataChecked = hasChanges && (changes.isTaxDataChecked || orgData.isTaxDataChecked); + const isTaxDataCheckedChanged = hasChanges && orgData.isTaxDataChecked != isTaxDataChecked; + + const sageTaxType = hasChanges && (changes.sageTaxTypeFk || orgData.sageTaxTypeFk); + const sageTaxTypeChanged = hasChanges && orgData.sageTaxTypeFk != sageTaxType; + + const sageTransactionType = hasChanges && (changes.sageTransactionTypeFk || orgData.sageTransactionTypeFk); + const sageTransactionTypeChanged = hasChanges && orgData.sageTransactionTypeFk != sageTransactionType; + + if (isTaxDataCheckedChanged && !isAdministrative) + throw new UserError(`You don't have enough privileges`); + + if ((sageTaxTypeChanged || sageTransactionTypeChanged) && !isSalesAssistant) + throw new UserError(`You don't have enough privileges`); + }); + Self.observe('before save', async function(ctx) { const changes = ctx.data || ctx.instance; const orgData = ctx.currentInstance; @@ -221,10 +249,10 @@ module.exports = Self => { const socialNameChanged = hasChanges && orgData.socialName != socialName; - const dataCheckedChanged = hasChanges + const isTaxDataCheckedChanged = hasChanges && orgData.isTaxDataChecked != isTaxDataChecked; - if ((socialNameChanged || dataCheckedChanged) && !isAlpha(socialName)) + if ((socialNameChanged || isTaxDataCheckedChanged) && !isAlpha(socialName)) throw new UserError(`The social name has an invalid format`); if (changes.salesPerson === null) { diff --git a/modules/client/back/models/specs/address.spec.js b/modules/client/back/models/specs/address.spec.js index cae18258f4..81af6ee283 100644 --- a/modules/client/back/models/specs/address.spec.js +++ b/modules/client/back/models/specs/address.spec.js @@ -1,20 +1,36 @@ -const app = require('vn-loopback/server/server'); +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('loopback model address', () => { let createdAddressId; const clientId = 1101; - afterAll(async() => { - let client = await app.models.Client.findById(clientId); + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; - await app.models.Address.destroyById(createdAddressId); + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + afterAll(async() => { + const client = await models.Client.findById(clientId); + + await models.Address.destroyById(createdAddressId); await client.updateAttribute('isEqualizated', false); }); describe('observe()', () => { it('should throw an error when deactivating a consignee if its the default address', async() => { let error; - let address = await app.models.Address.findById(1); + const address = await models.Address.findById(1); await address.updateAttribute('isActive', false) .catch(e => { @@ -27,13 +43,13 @@ describe('loopback model address', () => { }); it('should set isEqualizated to true of a given Client to trigger any new address to have it', async() => { - let client = await app.models.Client.findById(clientId); + const client = await models.Client.findById(clientId); expect(client.isEqualizated).toBeFalsy(); await client.updateAttribute('isEqualizated', true); - let newAddress = await app.models.Address.create({ + const newAddress = await models.Address.create({ clientFk: clientId, agencyModeFk: 5, city: 'here', diff --git a/modules/client/front/fiscal-data/index.html b/modules/client/front/fiscal-data/index.html index f3fd42e760..8556557e3b 100644 --- a/modules/client/front/fiscal-data/index.html +++ b/modules/client/front/fiscal-data/index.html @@ -182,7 +182,7 @@ vn-one label="Verified data" ng-model="$ctrl.client.isTaxDataChecked" - vn-acl="salesAssistant"> + vn-acl="administrative"> diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/createManualInvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/createManualInvoice.spec.js index f1c1bbab83..6b91593dbd 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/createManualInvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/createManualInvoice.spec.js @@ -93,10 +93,12 @@ describe('InvoiceOut createManualInvoice()', () => { it('should throw an error for a non-invoiceable client', async() => { spyOn(models.InvoiceOut, 'createPdf').and.returnValue(new Promise(resolve => resolve(true))); + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; - let error; try { const client = await models.Client.findById(clientId, null, options);