diff --git a/db/changes/10480-june/00-creditInsurance.sql b/db/changes/10470-family/00-creditInsurance.sql similarity index 100% rename from db/changes/10480-june/00-creditInsurance.sql rename to db/changes/10470-family/00-creditInsurance.sql diff --git a/db/changes/10480-june/01-creditInsuranceTriggers.sql b/db/changes/10470-family/01-creditInsuranceTriggers.sql similarity index 100% rename from db/changes/10480-june/01-creditInsuranceTriggers.sql rename to db/changes/10470-family/01-creditInsuranceTriggers.sql diff --git a/db/changes/10481-june/00-ACL.sql b/db/changes/10480-june/00-ACL.sql similarity index 100% rename from db/changes/10481-june/00-ACL.sql rename to db/changes/10480-june/00-ACL.sql diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2b22dcd0a..49db01140 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1129,19 +1129,17 @@ INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`) (1, 1106, 5, DATE_ADD(util.VN_CURDATE(),INTERVAL +1 DAY), 1), (2, 1106, 14, util.VN_CURDATE(), 1); -INSERT INTO `vn`.`ticketCollection`(`id`, `ticketFk`, `collectionFk`) +INSERT INTO `vn`.`ticketCollection`(`ticketFk`, `collectionFk`, `level`) VALUES - (2, 2, 1), - (3, 3, 2); + (1, 1, 1), + (2, 1, NULL), + (3, 2, NULL), + (23, 1, NULL); INSERT INTO `vn`.`parking` (`column`, `row`, `sectorFk`, `code`, `pickingOrder`) VALUES ('100', '01', 1, '100-01', 1); -INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `level`) - VALUES - (1, 1, 1); - INSERT INTO `vn`.`genus`(`id`, `name`) VALUES (1, 'Abelia'), @@ -2597,4 +2595,20 @@ INSERT INTO `vn`.`mdbBranch` (`name`) INSERT INTO `vn`.`mdbVersion` (`app`, `branchFk`, `version`) VALUES ('tpv', 'test', '1'), - ('lab', 'master', '1'); \ No newline at end of file + ('lab', 'master', '1'); + +INSERT INTO `vn`.`saleGroup` (`userFk`, `parkingFk`, `sectorFk`) + VALUES + (1, 1, 1); + +INSERT INTO `vn`.`saleGroupDetail` (`saleFk`, `saleGroupFk`) + VALUES + (31, 1); + +INSERT INTO `vn`.`sectorCollection` (`userFk`, `sectorFk`) + VALUES + (1, 1); + +INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk`) + VALUES + (1, 1); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 770911d0e..2cebffe02 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -55,6 +55,7 @@ export default { setPassword: '.vn-menu [name="setPassword"]', activateAccount: '.vn-menu [name="enableAccount"]', activateUser: '.vn-menu [name="activateUser"]', + deactivateUser: '.vn-menu [name="deactivateUser"]', newPassword: 'vn-textfield[ng-model="$ctrl.newPassword"]', repeatPassword: 'vn-textfield[ng-model="$ctrl.repeatPassword"]', newRole: 'vn-autocomplete[ng-model="$ctrl.newRole"]', diff --git a/e2e/paths/02-client/07_edit_web_access.spec.js b/e2e/paths/02-client/07_edit_web_access.spec.js index ad7c84a3e..70ec4b5ea 100644 --- a/e2e/paths/02-client/07_edit_web_access.spec.js +++ b/e2e/paths/02-client/07_edit_web_access.spec.js @@ -2,14 +2,13 @@ import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; describe('Client Edit web access path', () => { - pending('#4170 e2e account descriptor'); let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'client'); - await page.accessToSearchResult('Bruce Banner'); + await page.accessToSearchResult('1105'); await page.accessToSection('client.card.webAccess'); }); @@ -27,7 +26,7 @@ describe('Client Edit web access path', () => { it(`should update the name`, async() => { await page.clearInput(selectors.clientWebAccess.userName); - await page.write(selectors.clientWebAccess.userName, 'Hulk'); + await page.write(selectors.clientWebAccess.userName, 'Legion'); await page.waitToClick(selectors.clientWebAccess.saveButton); const message = await page.waitForSnackbar(); @@ -44,30 +43,30 @@ describe('Client Edit web access path', () => { it('should confirm web access name have been updated', async() => { const result = await page.waitToGetProperty(selectors.clientWebAccess.userName, 'value'); - expect(result).toEqual('Hulk'); + expect(result).toEqual('Legion'); }); it(`should navigate to the log section`, async() => { await page.accessToSection('client.card.log'); }); - it(`should confirm the last log is showing the updated client name and no modifications on the active checkbox`, async() => { + it(`should confirm the last log shows the updated client name and no modifications on active checkbox`, async() => { let lastModificationPreviousValue = await page .waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText'); let lastModificationCurrentValue = await page .waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText'); - expect(lastModificationPreviousValue).toEqual('name BruceBanner active false'); - expect(lastModificationCurrentValue).toEqual('name Hulk active false'); + expect(lastModificationPreviousValue).toEqual('name MaxEisenhardt active false'); + expect(lastModificationCurrentValue).toEqual('name Legion active false'); }); - it(`should confirm the penultimate log is showing the updated avtive field and no modifications on the client name`, async() => { + it(`should confirm the penultimate log shows the updated active and no modifications on client name`, async() => { let penultimateModificationPreviousValue = await page .waitToGetProperty(selectors.clientLog.penultimateModificationPreviousValue, 'innerText'); let penultimateModificationCurrentValue = await page .waitToGetProperty(selectors.clientLog.penultimateModificationCurrentValue, 'innerText'); - expect(penultimateModificationPreviousValue).toEqual('name BruceBanner active true'); - expect(penultimateModificationCurrentValue).toEqual('name BruceBanner active false'); + expect(penultimateModificationPreviousValue).toEqual('name MaxEisenhardt active true'); + expect(penultimateModificationCurrentValue).toEqual('name MaxEisenhardt active false'); }); }); diff --git a/e2e/paths/14-account/01_create_and_basic_data.spec.js b/e2e/paths/14-account/01_create_and_basic_data.spec.js index 4048413ba..0fc657375 100644 --- a/e2e/paths/14-account/01_create_and_basic_data.spec.js +++ b/e2e/paths/14-account/01_create_and_basic_data.spec.js @@ -36,8 +36,7 @@ describe('Account create and basic data path', () => { await page.waitForState('account.card.basicData'); }); - it('should reload the section and check the name is as expected', async() => { - await page.reloadSection('account.card.basicData'); + it('should check the name is as expected', async() => { const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value'); expect(result).toEqual('Remy'); @@ -103,25 +102,39 @@ describe('Account create and basic data path', () => { }); }); - // creating the account without the active property set to true seems to be creating an active user anyways - // describe('activate user', () => { - // it(`should check the inactive user icon is present in the descriptor`, async() => { - // await page.waitForSelector(selectors.accountDescriptor.activeUserIcon, {visible: true}); - // }); + describe('deactivate user', () => { + it(`should check the inactive user icon isn't present in the descriptor just yet`, async() => { + await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0); + }); - // it('should activate the user using the descriptor menu', async() => { - // await page.waitToClick(selectors.accountDescriptor.menuButton); - // await page.waitToClick(selectors.accountDescriptor.activateUser); - // await page.waitToClick(selectors.accountDescriptor.acceptButton); - // const message = await page.waitForSnackbar(); + it('should deactivate the user using the descriptor menu', async() => { + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.deactivateUser); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + const message = await page.waitForSnackbar(); - // expect(message.text).toContain('user enabled?'); - // }); + expect(message.text).toContain('User deactivated!'); + }); - // it('should check the inactive user icon is not present anymore', async() => { - // await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0); - // }); - // }); + it('should check the inactive user icon is now present', async() => { + await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 1); + }); + }); + + describe('activate user', () => { + it('should activate the user using the descriptor menu', async() => { + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.activateUser); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('User activated!'); + }); + + it('should check the inactive user icon is not present anymore', async() => { + await page.waitForNumberOfElements(selectors.accountDescriptor.activeUserIcon, 0); + }); + }); describe('mail forwarding', () => { it('should activate the mail forwarding and set the recipent email', async() => { diff --git a/e2e/paths/14-account/02_alias_create_and_basic_data.spec.js b/e2e/paths/14-account/02_alias_create_and_basic_data.spec.js index 0514899bc..dd35dd740 100644 --- a/e2e/paths/14-account/02_alias_create_and_basic_data.spec.js +++ b/e2e/paths/14-account/02_alias_create_and_basic_data.spec.js @@ -56,7 +56,7 @@ describe('Account Alias create and basic data path', () => { expect(result).toContain('psykers'); }); - it('should search for the IT alias group then access to the users section then check the role listed is the expected one', async() => { + it('should search IT alias then access the user section to check the role listed is the expected one', async() => { await page.accessToSearchResult('IT'); await page.accessToSection('account.alias.card.users'); const rolesCount = await page.countElement(selectors.accountAliasUsers.anyResult); diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 696934db7..746261626 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -456,7 +456,7 @@ module.exports = Self => { }); account.observe('after save', async ctx => { - let changes = ctx.data || ctx.instance; + const changes = ctx.data || ctx.instance; if (!ctx.isNewInstance && changes) { const oldData = ctx.hookState.oldInstance; const hasChanges = oldData.name != changes.name || oldData.active != changes.active; diff --git a/modules/entry/back/methods/entry/latestBuysFilter.js b/modules/entry/back/methods/entry/latestBuysFilter.js index 35252e107..9a21d4472 100644 --- a/modules/entry/back/methods/entry/latestBuysFilter.js +++ b/modules/entry/back/methods/entry/latestBuysFilter.js @@ -96,6 +96,7 @@ module.exports = Self => { }); Self.latestBuysFilter = async(ctx, filter, options) => { + const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') @@ -143,7 +144,9 @@ module.exports = Self => { const stmts = []; let stmt; - stmts.push('CALL cache.visible_refresh(@calc_id, FALSE, 1)'); + const warehouse = await models.Warehouse.findOne({where: {code: 'ALG'}}, myOptions); + stmt = new ParameterizedSQL(`CALL cache.visible_refresh(@calc_id, FALSE, ?)`, [warehouse.id]); + stmts.push(stmt); const date = new Date(); date.setHours(0, 0, 0, 0); diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index 38bd6e7b5..c683dcffd 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -142,6 +142,25 @@ module.exports = Self => { const updatedTicket = await ticket.updateAttribute('isDeleted', true, myOptions); + const [ticketCollection] = await models.TicketCollection.find({ + fields: ['id'], + where: { + ticketFk: ticket.id + } + }); + + if (ticketCollection) + await models.TicketCollection.destroyById(ticketCollection.id, myOptions); + + await Self.rawSql(` + DELETE sc + FROM vn.saleGroup sg + JOIN vn.sectorCollectionSaleGroup scsg ON scsg.saleGroupFk = sg.id + JOIN vn.sectorCollection sc ON sc.id = scsg.sectorCollectionFk + JOIN vn.saleGroupDetail sgd ON sgd.saleGroupFk = sg.id + JOIN vn.sale s ON s.id = sgd.saleFk + WHERE s.ticketFk = ?;`, [ticket.id], myOptions); + if (tx) await tx.commit(); return updatedTicket; diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index 4b583fc87..020bc5747 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -213,7 +213,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(2); + expect(result.length).toEqual(3); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js index 9b629e634..4551377df 100644 --- a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js +++ b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js @@ -8,6 +8,12 @@ describe('ticket setDeleted()', () => { accessToken: {userId: userId}, }; + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should throw an error if the given ticket has a claim', async() => { const tx = await models.Ticket.beginTransaction({}); @@ -29,6 +35,70 @@ describe('ticket setDeleted()', () => { expect(error.message).toEqual('You must delete the claim id %d first'); }); + it('should delete a sectorCollection row', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const ctx = { + req: { + accessToken: {userId: 9}, + headers: {origin: 'http://localhost:5000'}, + } + }; + ctx.req.__ = value => { + return value; + }; + const ticketId = 23; + + await models.Ticket.setDeleted(ctx, ticketId, options); + + const [sectorCollection] = await models.Ticket.rawSql( + `SELECT COUNT(*) numberRows + FROM vn.sectorCollection`, [], options); + + expect(sectorCollection.numberRows).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should delete a ticketCollection row', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const ctx = { + req: { + accessToken: {userId: 9}, + headers: {origin: 'http://localhost:5000'}, + } + }; + ctx.req.__ = value => { + return value; + }; + const ticketId = 23; + + await models.Ticket.setDeleted(ctx, ticketId, options); + + const [ticketCollection] = await models.Ticket.rawSql( + `SELECT COUNT(*) numberRows + FROM vn.ticketCollection`, [], options); + + expect(ticketCollection.numberRows).toEqual(3); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + it('should delete ticket, remove stowaway and itemshelving then change stowaway state to "FIXING" ', async() => { pending('test excluded by task #3693'); const tx = await models.Ticket.beginTransaction({}); diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json index 41885ee33..e75c7415e 100644 --- a/modules/ticket/back/model-config.json +++ b/modules/ticket/back/model-config.json @@ -44,6 +44,9 @@ "Ticket": { "dataSource": "vn" }, + "TicketCollection": { + "dataSource": "vn" + }, "TicketDms": { "dataSource": "vn" }, diff --git a/modules/ticket/back/models/ticket-collection.json b/modules/ticket/back/models/ticket-collection.json new file mode 100644 index 000000000..e941ac2ce --- /dev/null +++ b/modules/ticket/back/models/ticket-collection.json @@ -0,0 +1,22 @@ +{ + "name": "TicketCollection", + "base": "VnModel", + "options": { + "mysql": { + "table": "ticketCollection" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + } + }, + "relations": { + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk" + } + } +} \ No newline at end of file