From a3d63825d9a4a2d043c06ab89f655f72488f06bd Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Mon, 10 Sep 2018 13:00:01 +0200 Subject: [PATCH 01/34] indentation fix --- client/client/src/address/create/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/client/src/address/create/index.html b/client/client/src/address/create/index.html index c2d8845b8..d68ca658a 100644 --- a/client/client/src/address/create/index.html +++ b/client/client/src/address/create/index.html @@ -19,7 +19,8 @@ - - Date: Mon, 10 Sep 2018 13:38:14 +0200 Subject: [PATCH 02/34] #604 e2e ticket.sale excludid as its in progress --- e2e/paths/ticket-module/07_edit_sale.spec.js | 657 +++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 e2e/paths/ticket-module/07_edit_sale.spec.js diff --git a/e2e/paths/ticket-module/07_edit_sale.spec.js b/e2e/paths/ticket-module/07_edit_sale.spec.js new file mode 100644 index 000000000..a80069045 --- /dev/null +++ b/e2e/paths/ticket-module/07_edit_sale.spec.js @@ -0,0 +1,657 @@ +import selectors from '../../helpers/selectors.js'; +import createNightmare from '../../helpers/helpers'; + +// #603 in progress +xdescribe('Ticket Edit sale path', () => { + const nightmare = createNightmare(); + + beforeAll(() => { + return nightmare + .waitForLogin('salesPerson'); + }); + + it('should click on the Tickets button of the top bar menu', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); + }); + }); + + it('should search for a specific ticket', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the search result to access to the ticket Sale`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + describe('Before tests begings', () => { + it(`should check the quantity in the 1st line which we will be using in the further tests`, () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInputValue(selectors.ticketSales.firstSaleQuantity) + .then(value => { + expect(value).toEqual('5'); + }); + }); + + it(`should check the Price in the 1st line which we will be using in the further tests`, () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSalePrice) + .then(value => { + expect(value).toEqual('€9.60'); + }); + }); + + it(`should check the Discount in the 1st line which we will be using in the further tests`, () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleDiscount) + .then(value => { + expect(value).toEqual('0 %'); + }); + }); + + it(`should check the Import in the 1st line which we will be using in the further tests`, () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleImport) + .then(value => { + expect(value).toEqual('€48.00'); + }); + }); + + it(`should count the ticket lines to verify there are 4 for further testing`, () => { + return nightmare + .countElement(selectors.ticketSales.saleLine) + .then(result => { + expect(result).toEqual(4); + }); + }); + }); + + it(`should check the zoomed image isnt present`, () => { + return nightmare + .countElement(selectors.ticketSales.firstSaleZoomedImage) + .then(result => { + expect(result).toEqual(0); + }); + }); + + it(`should click on the thumbnail image of the 1st sale and see the zoomed image`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleThumbnailImage) + .countElement(selectors.ticketSales.firstSaleZoomedImage) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the zoomed image to close it`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleZoomedImage) + .countElement(selectors.ticketSales.firstSaleZoomedImage) + .then(result => { + expect(result).toEqual(0); + }); + }); + + it(`should confirm the item descriptor insnt visible yet`, () => { + return nightmare + .isVisible(selectors.ticketSales.saleDescriptorPopover) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`should click on the first sale ID making the item descriptor visible`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleID) + .isVisible(selectors.ticketSales.saleDescriptorPopover) + .then(result => { + expect(result).toBeTruthy(); + }); + }); + + it(`should click on the descriptor image of the 1st sale and see the zoomed image`, () => { + return nightmare + .waitToClick('vn-item-descriptor img') + .countElement(selectors.ticketSales.firstSaleZoomedImage) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the zoomed image to close it`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleZoomedImage) + .countElement(selectors.ticketSales.firstSaleZoomedImage) + .then(result => { + expect(result).toEqual(0); + }); + }); + + it(`should click on the summary icon of the item-descriptor to access to the item summary`, () => { + return nightmare + .waitToClick(selectors.ticketSales.saleDescriptorPopoverSummaryButton) + .waitForURL('/summary') + .url() + .then(url => { + expect(url).toContain('/summary'); + }); + }); + + it('should return to ticket sales section', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + it('should try to add a higher quantity value and then receive an error', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleQuantityClearInput) + .type(selectors.ticketSales.firstSaleQuantity, '9\u000d') + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual('The new quantity should be smaller than the old one'); + }); + }); + + it('should remove 1 from quantity', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleQuantityClearInput) + .type(selectors.ticketSales.firstSaleQuantity, '4\u000d') + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual('Data saved!'); + }); + }); + + it('should update the price', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSalePrice) + .wait(selectors.ticketSales.firstSalePriceInput) + .type(selectors.ticketSales.firstSalePriceInput, 5) + .type('body', '\u000d') // simulates enter + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual('Data saved!'); + }); + }); + + it('should confirm the price have been updated', () => { + return nightmare + .getInnerText(selectors.ticketSales.firstSalePrice) + .then(result => { + expect(result).toContain('€5.00'); + }); + }); + + it('should confirm the total price for that item have been updated', () => { + return nightmare + .getInnerText(selectors.ticketSales.firstSaleImport) + .then(result => { + expect(result).toContain('€20.00'); + }); + }); + + it('should update the discount', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleDiscount) + .wait('vn-textfield[label="Discount"] > div[class="container selected"]') // a function selects the text after it's loaded + .type(selectors.ticketSales.firstSaleDiscountInput, 50) + .type('body', '\u000d') // simulates enter + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual('Data saved!'); + }); + }); + + it('should confirm the discount have been updated', () => { + return nightmare + .waitForTextInElement(selectors.ticketSales.firstSaleDiscount, '50 %') + .getInnerText(selectors.ticketSales.firstSaleDiscount) + .then(result => { + expect(result).toContain('50 %'); + }); + }); + + it('should confirm the total import for that item have been updated', () => { + return nightmare + .waitForTextInElement(selectors.ticketSales.firstSaleImport, '€10.00') + .getInnerText(selectors.ticketSales.firstSaleImport) + .then(result => { + expect(result).toContain('€10.00'); + }); + }); + + it('should select the third sale and delete it', () => { + return nightmare + .waitToClick(selectors.ticketSales.thirdSaleCheckbox) + .waitToClick(selectors.ticketSales.deleteSaleButton) + .waitToClick(selectors.ticketSales.acceptDeleteButton) + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual('Data saved!'); + }); + }); + + it(`should confirm the third sale was deleted`, () => { + return nightmare + .countElement(selectors.ticketSales.saleLine) + .then(result => { + expect(result).toEqual(3); + }); + }); + + it('should select the third sale and attempt to send it to a frozen client ticket', () => { + return nightmare + .waitToClick(selectors.ticketSales.thirdSaleCheckbox) + .waitToClick(selectors.ticketSales.transferSaleButton) + .wait(selectors.ticketSales.moveToTicketInput) + .type(selectors.ticketSales.moveToTicketInput, 2) + .waitToClick(selectors.ticketSales.moveToTicketButton) + .waitForLastSnackbar() + .then(result => { + expect(result).toEqual(`The sales of that ticket can't be modified`); + }); + }); + + it('should transfer the sale to a valid ticket', () => { + return nightmare + .waitToClick(selectors.ticketSales.moveToTicketInputClearButton) + .type(selectors.ticketSales.moveToTicketInput, 12) + .waitToClick(selectors.ticketSales.moveToTicketButton) + .waitForURL('ticket/12/sale') + .url() + .then(result => { + expect(result).toContain(`ticket/12/sale`); + }); + }); + + it('should confirm the transfered line is the correct one', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleText) + .then(result => { + expect(result).toContain(`Mark I`); + }); + }); + + it('should go back to the original ticket sales section', () => { + return nightmare + .waitToClick(selectors.itemsIndex.goBackToModuleIndexButton) + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + it(`should confirm the original ticket has only two lines now`, () => { + return nightmare + .wait(selectors.ticketSales.saleLine) + .countElement(selectors.ticketSales.saleLine) + .then(result => { + expect(result).toEqual(2); + }); + }); + + it('should go back to the receiver ticket sales section', () => { + return nightmare + .waitToClick(selectors.itemsIndex.goBackToModuleIndexButton) + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:12') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + it('should transfer the sale back to the original ticket', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleCheckbox) + .waitToClick(selectors.ticketSales.transferSaleButton) + .wait(selectors.ticketSales.moveToTicketInput) + .type(selectors.ticketSales.moveToTicketInput, 16) + .waitToClick(selectors.ticketSales.moveToTicketButton) + .waitForURL('ticket/16/sale') + .url() + .then(result => { + expect(result).toContain(`ticket/16/sale`); + }); + }); + + it('should confirm the original ticket received the line', () => { + return nightmare + .wait(selectors.ticketSales.saleLine) + .countElement(selectors.ticketSales.saleLine) + .then(result => { + expect(result).toEqual(3); + }); + }); + + it('should select the second and third sale and tranfer them to a new ticket then get to the ticket index', () => { + return nightmare + .waitToClick(selectors.ticketSales.secondSaleCheckbox) + .waitToClick(selectors.ticketSales.thirdSaleCheckbox) + .waitToClick(selectors.ticketSales.transferSaleButton) + .waitToClick(selectors.ticketSales.moveToNewTicketButton) + .waitForLogin('salesPerson') + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); + }); + }); + + it('should search for a specific created ticket', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:22') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the search result to access to the ticket Sale`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + it('should confirm the new ticket received both lines', () => { + return nightmare + .countElement(selectors.ticketSales.saleLine) + .then(result => { + expect(result).toEqual(2); + }); + }); + + it('should check the first sale reserved icon isnt visible', () => { + return nightmare + .isVisible(selectors.ticketSales.firstSaleReservedIcon) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it('should mark the first sale as reserved', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleCheckbox) + .waitToClick(selectors.ticketSales.moreMenuButton) + .waitToClick(selectors.ticketSales.moreMenuReseveOption) + .waitForClassNotPresent(selectors.ticketSales.firstSaleReservedIcon, 'ng-hide') + .isVisible(selectors.ticketSales.firstSaleReservedIcon) + .then(result => { + expect(result).toBeTruthy(); + }); + }); + + it('should unmark the first sale as reserved', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleCheckbox) + .waitToClick(selectors.ticketSales.moreMenuButton) + .waitToClick(selectors.ticketSales.moreMenuUnmarkResevedOption) + .waitForClassPresent(selectors.ticketSales.firstSaleReservedIcon, 'ng-hide') + .isVisible(selectors.ticketSales.firstSaleReservedIcon) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it('should update all sales discount', () => { + return nightmare + .waitToClick(selectors.ticketSales.selectAllSalesCheckbox) + .waitToClick(selectors.ticketSales.moreMenuButton) + .waitToClick(selectors.ticketSales.moreMenuUpdateDiscount) + .wait(selectors.ticketSales.moreMenuUpdateDiscountInput) + .type(selectors.ticketSales.moreMenuUpdateDiscountInput, 100) + .type('body', '\u000d') // simulates enter + .waitForTextInElement(selectors.ticketSales.totalImport, '€0.00') + .getInnerText(selectors.ticketSales.totalImport) + .then(result => { + expect(result).toEqual('€0.00'); + }); + }); + + it('should log in as Production role and go to the ticket index', () => { + return nightmare + .waitToClick(selectors.globalItems.logOutButton) + .waitForLogin('production') + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); + }); + }); + + it('should now search for a specific ticket', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should now click on the search result to access to the ticket Tracking`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketTracking.trackingButton) + .waitForURL('/tracking/index') + .url() + .then(url => { + expect(url).toContain('/tracking/index'); + }); + }); + + it(`should click on the edit ticket tracking state button`, () => { + return nightmare + .waitToClick(selectors.ticketTracking.createStateButton) + .waitForURL('/tracking/edit') + .url() + .then(url => { + expect(url).toContain('/tracking/edit'); + }); + }); + + it(`should set the state of the ticket to preparation`, () => { + return nightmare + .waitToClick(selectors.ticketTracking.stateSelect) + .wait(selectors.ticketTracking.stateSelectInput) + .type(selectors.ticketTracking.stateSelectInput, 'Preparación') + .waitToClick(selectors.ticketTracking.stateSelectFirstResult) + .waitForTextInInput(selectors.ticketTracking.stateSelectInput, 'Preparación') + .click(selectors.ticketTracking.saveButton) + .waitForURL('/tracking/index') + .url() + .then(url => { + expect(url).toContain('/tracking/index'); + }); + }); + + it(`should click on the ticket Sale menu button`, () => { + return nightmare + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + + describe('when state is preparation and loged as Production', () => { + it(`should not be able to edit the sale price`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSalePrice) + .exists(selectors.ticketSales.firstSalePriceInput) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`should not be able to edit the sale discount`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleDiscount) + .exists(selectors.ticketSales.firstSaleDiscountInput) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`should not be able to edit the sale state`, () => { + return nightmare + .waitToClick(selectors.ticketSales.stateMenuButton) + .exists(selectors.ticketSales.stateMenuOptions) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it('should log in as salesPerson role and go to the ticket index', () => { + return nightmare + .waitToClick(selectors.globalItems.logOutButton) + .waitForLogin('salesPerson') + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); + }); + }); + + it('should again search for a specific ticket', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should again click on the search result to access to the ticket Sales`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + }); + + describe('when state is preparation and loged as salesPerson', () => { + it(`shouldnt be able to edit the sale price`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSalePrice) + .exists(selectors.ticketSales.firstSalePriceInput) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`shouldnt be able to edit the sale discount`, () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleDiscount) + .exists(selectors.ticketSales.firstSaleDiscountInput) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`shouldnt be able to edit the sale state`, () => { + return nightmare + .waitToClick(selectors.ticketSales.stateMenuButton) + .exists(selectors.ticketSales.stateMenuOptions) + .then(result => { + expect(result).toBeFalsy(); + }); + }); + + it(`should be able to delete the ticket`, () => { + // return nightmare + // .waitToClick(selectors.ticketSales.moreMenuButton) + // .waitToClick(selectors.ticketSales.moreMenuDeleteOption) + // .exists(selectors.ticketSales.stateMenuOptions) + // .then(result => { + // expect(result).toBeFalsy(); + // }); + }); + }); +}); From 0102c4f673522ad764b8ea924301f93297788b02 Mon Sep 17 00:00:00 2001 From: gerard Date: Tue, 11 Sep 2018 09:38:37 +0200 Subject: [PATCH 03/34] =?UTF-8?q?Tarea=20#601=20boton=20+=20abrir=20el=20c?= =?UTF-8?q?uadro=20de=20dialogo=20de=20a=C3=B1adir=20cantidad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/order/common/methods/order/catalogFilter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/order/common/methods/order/catalogFilter.js b/services/order/common/methods/order/catalogFilter.js index 1666f8ef2..5065f85c4 100644 --- a/services/order/common/methods/order/catalogFilter.js +++ b/services/order/common/methods/order/catalogFilter.js @@ -86,6 +86,8 @@ module.exports = Self => { tcp.itemFk, tcp.grouping, tcp.price, + tcp.rate, + tcp.warehouseFk, w.name AS warehouse FROM tmp.ticketComponentPrice tcp JOIN vn.warehouse w ON w.id = tcp.warehouseFk` From c2543cae39022bde2026722545f9f7a305000b57 Mon Sep 17 00:00:00 2001 From: Bernat Date: Tue, 11 Sep 2018 10:53:57 +0200 Subject: [PATCH 04/34] add new selectors --- e2e/helpers/selectors.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 9568ddbaa..0d88574aa 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -319,10 +319,17 @@ export default { firstSaleDiscount: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(8)', firstSaleDiscountInput: 'vn-ticket-sale:nth-child(1) vn-ticket-sale-edit-discount > div > vn-textfield > div > div > div.infix > input.ng-not-empty', firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(9)', - totalImport: 'vn-ticket-sale vn-tfoot > vn-tr > vn-td:nth-child(9) > section > p:nth-child(3) > strong', - secondSaleText: `vn-table div > vn-tbody > vn-tr:nth-child(2)`, - selectAllSalesCheckbox: `vn-ticket-sale vn-thead vn-check label`, + firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(2)', + firstSaleColour: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(5) section:nth-child(5)`, + firstSaleLength: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(5) section:nth-child(3)`, firstSaleCheckbox: `vn-ticket-sale vn-tr:nth-child(1) vn-check[field="sale.checked"] label`, + secondSaleColour: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(5) section:nth-child(5)`, + secondSalePrice: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(7)`, + secondSaleDiscount: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(8)`, + secondSaleImport: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(9)`, + secondSaleText: `vn-table div > vn-tbody > vn-tr:nth-child(2)`, + totalImport: 'vn-ticket-sale vn-tfoot > vn-tr > vn-td:nth-child(9) > section > p:nth-child(3) > strong', + selectAllSalesCheckbox: `vn-ticket-sale vn-thead vn-check label`, secondSaleCheckbox: `vn-ticket-sale vn-tr:nth-child(2) vn-check[field="sale.checked"] label`, thirdSaleCheckbox: `vn-ticket-sale vn-tr:nth-child(3) vn-check[field="sale.checked"] label`, deleteSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="delete"]', @@ -339,8 +346,7 @@ export default { moreMenuReseveOption: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(3)', moreMenuUnmarkResevedOption: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(4)', moreMenuUpdateDiscount: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(5)', - moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog.shown vn-ticket-sale-edit-discount input', - firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(2)' + moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog.shown vn-ticket-sale-edit-discount input' }, ticketTracking: { trackingButton: `vn-left-menu a[ui-sref="ticket.card.tracking.index"]`, From c9ec4aee7ea27b45aac72cc3a935811bf88d9adb Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 11 Sep 2018 12:49:31 +0200 Subject: [PATCH 05/34] =?UTF-8?q?#612=20a=C3=B1adir=20reclamacion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ticket/src/sale/index.html | 4 +- client/ticket/src/sale/index.js | 21 ++++++-- client/ticket/src/sale/index.spec.js | 25 +++++++-- client/ticket/src/sale/locale/es.yml | 3 +- .../common/methods/claim/createFromSales.js | 50 +++++++++++++++++ .../claim/specs/createFromSales.spec.js | 54 +++++++++++++++++++ services/claim/common/models/claim.js | 1 + services/claim/common/models/claim.json | 9 ++-- services/loopback/common/locale/es.json | 3 +- 9 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 services/claim/common/methods/claim/createFromSales.js create mode 100644 services/claim/common/methods/claim/specs/createFromSales.spec.js diff --git a/client/ticket/src/sale/index.html b/client/ticket/src/sale/index.html index b3c756766..62e753ae1 100644 --- a/client/ticket/src/sale/index.html +++ b/client/ticket/src/sale/index.html @@ -47,7 +47,7 @@ - + @@ -64,7 +64,7 @@ - + diff --git a/client/ticket/src/sale/index.js b/client/ticket/src/sale/index.js index e5f602a96..74b1d2f7c 100644 --- a/client/ticket/src/sale/index.js +++ b/client/ticket/src/sale/index.js @@ -16,7 +16,8 @@ class Controller { {callback: this.showDeleteTicketDialog, name: "Delete ticket", always: true}, {callback: this.markAsReserved, name: 'Mark as reserved'}, {callback: this.unmarkAsReserved, name: 'Unmark as reserved'}, - {callback: this.showEditDialog, name: 'Update discount'} + {callback: this.showEditDialog, name: 'Update discount'}, + {callback: this.createClaim, name: 'Add claim'} ]; } @@ -78,7 +79,6 @@ class Controller { for (let i = 0; i < data.length; i++) if (data[i].checked) lines.push({id: data[i].id, instance: i}); - return lines; } @@ -177,7 +177,6 @@ class Controller { }); } - // In Progress linesToNewTicket() { let ticket = { oldTicketFk: this.ticket.id, @@ -197,6 +196,22 @@ class Controller { }); } + createClaim() { + let claim = { + ticketFk: this.ticket.id, + clientFk: this.ticket.clientFk, + ticketCreated: this.ticket.shipped, + workerFk: this.ticket.client.salesPersonFk + }; + let sales = this.getCheckedLines(); + for (let i = 0; i < sales.length; i++) + sales[i].quantity = this.sales[sales[i].instance].quantity; + this.$http.post(`claim/api/Claims/createFromSales`, {claim: claim, sales: sales}).then(res => { + let url = this.$state.href("claim.card.basicData", {id: res.data.id}, {absolute: true}); + window.open(url, '_blank'); + }); + } + goToTicket(ticketID) { this.$state.go("ticket.card.sale", {id: ticketID}); } diff --git a/client/ticket/src/sale/index.spec.js b/client/ticket/src/sale/index.spec.js index 9a5056891..a8f140506 100644 --- a/client/ticket/src/sale/index.spec.js +++ b/client/ticket/src/sale/index.spec.js @@ -33,14 +33,28 @@ describe('Ticket', () => { quantity: 20, price: 5.5, discount: 0, - checked: true + checked: false } ]}; $scope.addTurn = {show: () => {}}; controller = $componentController('vnTicketSale', {$scope: $scope}, {$state: $state}); - controller.ticket = {id: 1}; + controller.ticket = {id: 1, clientFk: 1, shipped: 1, client: {salesPersonFk: 1}}; + spyOn(window, 'open'); })); + describe('createClaim()', () => { + it('should perfrom a query and call windows open', () => { + controller.sales = controller.$scope.model.data; + let res = {id: 1}; + $httpBackend.expectPOST(`claim/api/Claims/createFromSales`).respond(res); + controller.createClaim(); + $httpBackend.flush(); + let urlMock = null; + + expect(window.open).toHaveBeenCalledWith(urlMock, '_blank'); + }); + }); + describe('getSales()', () => { it('should make a query and call getTaxes()', () => { let data = [ @@ -56,7 +70,7 @@ describe('Ticket', () => { quantity: 20, price: 5.5, discount: 0, - checked: true + checked: false } ]; @@ -113,9 +127,10 @@ describe('Ticket', () => { describe('getCheckedLines()', () => { it('should make an array of the instances with the property checked true()', () => { - controller.sales = [{id: 1, checked: true}, {id: 2, checked: false}, {id: 3, checked: true}]; + let expectedResult = [{id: 1, instance: 0}]; + controller.sales = controller.$scope.model.data; - expect(controller.getCheckedLines()).toEqual([{id: 1, instance: 0}, {id: 3, instance: 2}]); + expect(controller.getCheckedLines()).toEqual(expectedResult); }); }); diff --git a/client/ticket/src/sale/locale/es.yml b/client/ticket/src/sale/locale/es.yml index bbaf8d031..f52716b8c 100644 --- a/client/ticket/src/sale/locale/es.yml +++ b/client/ticket/src/sale/locale/es.yml @@ -22,4 +22,5 @@ Wednesday: Miércoles Thursday: Jueves Friday: Viernes Saturday: Sábado -Sunday: Domingo \ No newline at end of file +Sunday: Domingo +Add claim: Crear reclamación \ No newline at end of file diff --git a/services/claim/common/methods/claim/createFromSales.js b/services/claim/common/methods/claim/createFromSales.js new file mode 100644 index 000000000..97d4edea7 --- /dev/null +++ b/services/claim/common/methods/claim/createFromSales.js @@ -0,0 +1,50 @@ +module.exports = Self => { + Self.remoteMethod('createFromSales', { + description: 'Create a claim', + accessType: '', + accepts: [{ + arg: 'claim', + type: 'object', + required: true, + description: ' newTicketFk, clientFk, ticketCreated', + http: {source: 'body'} + }, { + arg: 'sales', + type: 'object', + required: true, + description: '[sales IDs]', + http: {source: 'body'} + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/createFromSales`, + verb: 'post' + } + }); + + Self.createFromSales = async params => { + let model = Self.app.models; + let transaction = await Self.beginTransaction({}); + try { + let newClaim = await Self.create(params.claim, {transaction}); + let promises = []; + for (let i = 0; i < params.sales.length; i++) { + promises.push(model.ClaimBeginning.create( + {saleFk: params.sales[i].id, + claimFk: newClaim.id, + quantity: params.sales[i].quantity}, + {transaction})); + } + await Promise.all(promises); + await transaction.commit(); + + return newClaim; + } catch (e) { + transaction.rollback(); + throw e; + } + }; +}; diff --git a/services/claim/common/methods/claim/specs/createFromSales.spec.js b/services/claim/common/methods/claim/specs/createFromSales.spec.js new file mode 100644 index 000000000..7c364c619 --- /dev/null +++ b/services/claim/common/methods/claim/specs/createFromSales.spec.js @@ -0,0 +1,54 @@ +const app = require(`${servicesDir}/claim/server/server`); + +fdescribe('Claim Create', () => { + let newDate = new Date(); + let createdClaimFk; + + afterAll(async() => { + console.log('asdf', createdClaimFk); + await app.models.Claim.destroyById(createdClaimFk); + }); + + let newClaim = { + ticketFk: 2, + clientFk: 101, + ticketCreated: newDate, + workerFk: 18 + }; + + let newSale = [{ + id: 2, + instance: 0, + quantity: 10 + }]; + + let params = {claim: newClaim, sales: newSale}; + + it('should create a new claim', async() => { + let claim = await app.models.Claim.createFromSales(params); + + expect(claim.ticketFk).toEqual(newClaim.ticketFk); + expect(claim.clientFk).toEqual(newClaim.clientFk); + expect(claim.ticketCreated).toEqual(newClaim.ticketCreated); + expect(claim.workerFk).toEqual(newClaim.workerFk); + + let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}); + + expect(claimBeginning.saleFk).toEqual(newSale[0].id); + expect(claimBeginning.quantity).toEqual(newSale[0].quantity); + + createdClaimFk = claim.id; + }); + + it('should not be able to create a claim if exists that sale', async() => { + let error; + + await app.models.Claim.createFromSales(params) + + .catch(e => { + error = e; + }); + + expect(error.toString()).toContain(`A claim with that sale already exists`); + }); +}); diff --git a/services/claim/common/models/claim.js b/services/claim/common/models/claim.js index dd01547ea..73a6da1d7 100644 --- a/services/claim/common/models/claim.js +++ b/services/claim/common/models/claim.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/claim/getSummary')(Self); + require('../methods/claim/createFromSales')(Self); }; diff --git a/services/claim/common/models/claim.json b/services/claim/common/models/claim.json index 7ca5d15b2..3380e6ec4 100644 --- a/services/claim/common/models/claim.json +++ b/services/claim/common/models/claim.json @@ -21,16 +21,13 @@ "required": true }, "isChargedToMana": { - "type": "boolean", - "required": true + "type": "boolean" }, "created": { - "type": "date", - "required": true + "type": "date" }, "responsibility": { - "type": "Number", - "required": true + "type": "Number" } }, "relations": { diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index 57ddd4465..f13c016c2 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -46,5 +46,6 @@ "Barcode must be unique": "El código de barras debe ser único", "The warehouse can't be repeated": "El almacén no puede repetirse", "The tag can't be repeated": "El tag no puede repetirse", - "The observation type can't be repeated": "El tipo de observación no puede repetirse" + "The observation type can't be repeated": "El tipo de observación no puede repetirse", + "A claim with that sale already exists": "Ya existe una reclamación para esta línea" } \ No newline at end of file From f105ffa2d66aac7afe4ab71f9e39de82ae3289b3 Mon Sep 17 00:00:00 2001 From: gerard Date: Tue, 11 Sep 2018 13:48:05 +0200 Subject: [PATCH 06/34] watchers reduced --- client/item/src/diary/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/item/src/diary/index.html b/client/item/src/diary/index.html index 63b811b26..cdc389b55 100644 --- a/client/item/src/diary/index.html +++ b/client/item/src/diary/index.html @@ -34,11 +34,11 @@ - {{::sale.date | date:'dd/MM/yyyy HH:mm' }} - {{::sale.origin | dashIfEmpty}} @@ -46,9 +46,9 @@ {{::sale.stateName | dashIfEmpty}} {{::sale.reference | dashIfEmpty}} - - {{sale.name | dashIfEmpty}} + {{::sale.name | dashIfEmpty}} {{::sale.in | dashIfEmpty}} From 6169486bb0ecb1bf290181781fb6864de31ce4bf Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 11 Sep 2018 13:56:40 +0200 Subject: [PATCH 07/34] fix test createFromSales --- .../claim/common/methods/claim/specs/createFromSales.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/claim/common/methods/claim/specs/createFromSales.spec.js b/services/claim/common/methods/claim/specs/createFromSales.spec.js index 7c364c619..4076059ec 100644 --- a/services/claim/common/methods/claim/specs/createFromSales.spec.js +++ b/services/claim/common/methods/claim/specs/createFromSales.spec.js @@ -1,6 +1,6 @@ const app = require(`${servicesDir}/claim/server/server`); -fdescribe('Claim Create', () => { +describe('Claim Create', () => { let newDate = new Date(); let createdClaimFk; @@ -17,7 +17,7 @@ fdescribe('Claim Create', () => { }; let newSale = [{ - id: 2, + id: 3, instance: 0, quantity: 10 }]; From 367604654c1a46773b09c31178f1844c319333d9 Mon Sep 17 00:00:00 2001 From: Bernat Date: Tue, 11 Sep 2018 15:09:15 +0200 Subject: [PATCH 08/34] update fixtures and fix test --- e2e/paths/ticket-module/03_list_sale.spec.js | 168 ++++++++++++------ .../06_edit_basic_data_steps.spec.js | 2 +- .../db/install/changes/1.1.0/ticketGetTax.sql | 70 ++++++++ services/db/install/dump/fixtures.sql | 36 ++-- .../methods/client/specs/getDebt.spec.js | 2 +- .../methods/client/specs/summary.spec.js | 2 +- .../sale/specs/priceDifference.spec.js | 6 +- .../loopback/common/methods/ticket/getVAT.js | 2 +- .../methods/ticket/specs/getTaxes.spec.js | 2 +- .../methods/ticket/specs/getTotal.spec.js | 2 +- .../ticket/specs/getTotalVolume.spec.js | 2 +- .../methods/ticket/specs/getVAT.spec.js | 2 +- .../methods/ticket/specs/summary.spec.js | 7 +- 13 files changed, 214 insertions(+), 89 deletions(-) create mode 100644 services/db/install/changes/1.1.0/ticketGetTax.sql diff --git a/e2e/paths/ticket-module/03_list_sale.spec.js b/e2e/paths/ticket-module/03_list_sale.spec.js index b76e9cc5a..3391be521 100644 --- a/e2e/paths/ticket-module/03_list_sale.spec.js +++ b/e2e/paths/ticket-module/03_list_sale.spec.js @@ -1,74 +1,128 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/helpers'; -describe('Ticket', () => { - describe('List sale path', () => { - const nightmare = createNightmare(); +describe('Ticket List sale path', () => { + const nightmare = createNightmare(); - beforeAll(() => { - return nightmare - .waitForLogin('developer'); + beforeAll(() => { + return nightmare + .waitForLogin('developer'); + }); + + it('should click on the Tickets button of the top bar menu', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); }); + }); - it('should click on the Tickets button of the top bar menu', () => { - return nightmare - .waitToClick(selectors.globalItems.applicationsMenuButton) - .wait(selectors.globalItems.applicationsMenuVisible) - .waitToClick(selectors.globalItems.ticketsButton) - .wait(selectors.ticketsIndex.createTicketButton) - .parsedUrl() - .then(url => { - expect(url.hash).toEqual('#!/ticket/index'); - }); + it('should search for the ticket 1', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:1') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); }); + }); - it('should search for the ticket 1', () => { - return nightmare - .wait(selectors.ticketsIndex.searchResult) - .type(selectors.ticketsIndex.searchTicketInput, 'id:1') - .click(selectors.ticketsIndex.searchButton) - .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) - .countElement(selectors.ticketsIndex.searchResult) - .then(result => { - expect(result).toEqual(1); - }); + it(`should click on the search result to access to the ticket's sale`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('sale') + .url() + .then(url => { + expect(url).toContain('sale'); }); + }); - it(`should click on the search result to access to the ticket's sale`, () => { - return nightmare - .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') - .waitToClick(selectors.ticketsIndex.searchResult) - .waitToClick(selectors.ticketSales.saleButton) - .waitForURL('sale') - .url() - .then(url => { - expect(url).toContain('sale'); - }); + it('should confirm the first ticket sale contains the colour', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleColour) + .then(value => { + expect(value).toContain('Yellow'); }); + }); - it('should confirm the first ticket sale is the expected one', () => { - return nightmare - .wait(selectors.ticketSales.firstSaleText) - .getInnerText(selectors.ticketSales.firstSaleText) - .then(value => { - expect(value).toContain('Yellow'); - expect(value).toContain('5'); - expect(value).toContain('€9.60'); - expect(value).toContain('0 %'); - expect(value).toContain('€48.00'); - }); + it('should confirm the first ticket sale contains the lenght', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleText) + .then(value => { + expect(value).toContain('5'); }); + }); - it('should confirm the second ticket sale is the expected one', () => { - return nightmare - .wait(selectors.ticketSales.secondSaleText) - .getInnerText(selectors.ticketSales.secondSaleText) - .then(value => { - expect(value).toContain('Red'); - expect(value).toContain('€4.21'); - expect(value).toContain('0 %'); - expect(value).toContain('€42.10'); - }); + it('should confirm the first ticket sale contains the price', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSalePrice) + .then(value => { + expect(value).toContain('€11.42'); + }); + }); + + it('should confirm the first ticket sale contains the discount', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleDiscount) + .then(value => { + expect(value).toContain('0 %'); + }); + }); + + it('should confirm the first ticket sale contains the total import', () => { + return nightmare + .wait(selectors.ticketSales.firstSaleText) + .getInnerText(selectors.ticketSales.firstSaleImport) + .then(value => { + expect(value).toContain('57.10'); + }); + }); + + it('should confirm the second ticket sale contains the colour', () => { + return nightmare + .wait(selectors.ticketSales.secondSaleText) + .getInnerText(selectors.ticketSales.secondSaleColour) + .then(value => { + expect(value).toContain('Red'); + }); + }); + + it('should confirm the second ticket sale contains the price', () => { + return nightmare + .wait(selectors.ticketSales.secondSaleText) + .getInnerText(selectors.ticketSales.secondSalePrice) + .then(value => { + expect(value).toContain('€1.30'); + }); + }); + + it('should confirm the second ticket sale contains the discount', () => { + return nightmare + .wait(selectors.ticketSales.secondSaleText) + .getInnerText(selectors.ticketSales.secondSaleDiscount) + .then(value => { + expect(value).toContain('0 %'); + }); + }); + + it('should confirm the second ticket sale contains the total import', () => { + return nightmare + .wait(selectors.ticketSales.secondSaleText) + .getInnerText(selectors.ticketSales.secondSaleImport) + .then(value => { + expect(value).toContain('13.00'); }); }); }); diff --git a/e2e/paths/ticket-module/06_edit_basic_data_steps.spec.js b/e2e/paths/ticket-module/06_edit_basic_data_steps.spec.js index beeb1d749..4c1140d5e 100644 --- a/e2e/paths/ticket-module/06_edit_basic_data_steps.spec.js +++ b/e2e/paths/ticket-module/06_edit_basic_data_steps.spec.js @@ -120,7 +120,7 @@ describe('Ticket', () => { return nightmare .getInnerText(selectors.ticketBasicData.stepTwoTotalPriceDif) .then(result => { - expect(result).toContain('-€206.60'); + expect(result).toContain('-€20.65'); }); }); diff --git a/services/db/install/changes/1.1.0/ticketGetTax.sql b/services/db/install/changes/1.1.0/ticketGetTax.sql new file mode 100644 index 000000000..cd52b10f0 --- /dev/null +++ b/services/db/install/changes/1.1.0/ticketGetTax.sql @@ -0,0 +1,70 @@ +USE `vn`; +DROP procedure IF EXISTS `ticketGetTax`; + +DELIMITER $$ +USE `vn`$$ +CREATE DEFINER=`root`@`%` PROCEDURE `ticketGetTax`() + READS SQL DATA +BEGIN +/** + * Calcula la base imponible, el IVA y el recargo de equivalencia para + * un conjunto de tickets. + * + * @table tmp.ticket(ticketFk) Identificadores de los tickets a calcular + * @return tmp.ticketTax Impuesto desglosado para cada ticket + * @return tmp.ticketAmount + */ + DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany; + CREATE TEMPORARY TABLE tmp.addressCompany + (INDEX (addressFk, companyFk)) + ENGINE = MEMORY + SELECT DISTINCT t.addressFk, t.companyFk + FROM tmp.ticket tmpTicket + JOIN ticket t ON t.id = tmpTicket.ticketFk; + + + CALL addressTaxArea (); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketTax; + CREATE TEMPORARY TABLE tmp.ticketTax + (INDEX (ticketFk)) + ENGINE = MEMORY + SELECT tmpTicket.ticketFk, + bp.pgcFk, + ROUND(SUM(s.quantity * s.price * (100 - s.discount)/100 + ),2) AS taxableBase, + ROUND(SUM(s.quantity * s.price * (100 - s.discount)/100 + ) * pgc.rate / 100,2) AS tax, + tc.code + FROM tmp.ticket tmpTicket + JOIN sale s ON s.ticketFk = tmpTicket.ticketFk + JOIN item i ON i.id = s.itemFk + JOIN ticket t ON t.id = tmpTicket.ticketFk + JOIN supplier su ON su.id = t.companyFk + JOIN tmp.addressTaxArea ata + ON ata.addressFk = t.addressFk AND ata.companyFk = t.companyFk + JOIN itemTaxCountry itc + ON itc.itemFk = i.id AND itc.countryFk = su.countryFk + JOIN bookingPlanner bp + ON bp.countryFk = su.countryFk + AND bp.taxAreaFk = ata.areaFk + AND bp.taxClassFk = itc.taxClassFk + JOIN pgc ON pgc.code = bp.pgcFk + JOIN taxClass tc ON tc.id = bp.taxClassFk + GROUP BY tmpTicket.ticketFk, pgc.code + HAVING taxableBase != 0; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticketAmount; + CREATE TEMPORARY TABLE tmp.ticketAmount + (INDEX (ticketFk)) + ENGINE = MEMORY + SELECT ticketFk, taxableBase, SUM(tax) tax + FROM tmp.ticketTax + GROUP BY ticketFk, code; + + DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany; + DROP TEMPORARY TABLE IF EXISTS tmp.addressTaxArea; +END$$ + +DELIMITER ; + diff --git a/services/db/install/dump/fixtures.sql b/services/db/install/dump/fixtures.sql index a53f7b82c..7e8a25d09 100644 --- a/services/db/install/dump/fixtures.sql +++ b/services/db/install/dump/fixtures.sql @@ -517,18 +517,18 @@ INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `price`, `discount`, `reserved`, `isPicked`, `created`) VALUES - ( 1, 1, 1 , 'Gem of Time', 5 , 9.60, 0, 0, 0, CURDATE()), - ( 2, 2, 1 , 'Gem of Mind', 10 , 4.21, 0, 0, 0, CURDATE()), - ( 3, 1, 1 , 'Gem of Time', 2 , 9.60, 0, 0, 0, CURDATE()), - ( 4, 4, 1 , 'Mark I' , 20 , 7.06, 0, 0, 0, CURDATE()), - ( 5, 1, 2 , 'Gem of Time', 10 , 9.60, 0, 0, 0, CURDATE()), - ( 6, 1, 3 , 'Gem of Time', 15 , 9.60, 0, 0, 0, CURDATE()), - ( 7, 2, 11, 'Gem of Mind', 15 , 4.21, 0, 0, 0, CURDATE()), - ( 8, 4, 11, 'Mark I' , 10 , 7.06, 0, 0, 0, CURDATE()), - ( 9, 1, 16, 'Gem of Time', 5 , 9.60, 0, 0, 0, CURDATE()), - ( 10, 2, 16, 'Gem of Mind', 10 , 4.21, 0, 0, 0, CURDATE()), - ( 11, 1, 16, 'Gem of Time', 2 , 9.60, 0, 0, 0, CURDATE()), - ( 12, 4, 16, 'Mark I' , 20 , 7.06, 0, 0, 0, CURDATE()); + ( 1, 1, 1 , 'Gem of Time', 5 , 11.42, 0, 0, 0, CURDATE()), + ( 2, 2, 1 , 'Gem of Mind', 10 , 1.30, 0, 0, 0, CURDATE()), + ( 3, 1, 1 , 'Gem of Time', 2 , 11.42, 0, 0, 0, CURDATE()), + ( 4, 4, 1 , 'Mark I' , 20 , 3.26, 0, 0, 0, CURDATE()), + ( 5, 1, 2 , 'Gem of Time', 10 , 11.42, 0, 0, 0, CURDATE()), + ( 6, 1, 3 , 'Gem of Time', 15 , 11.42, 0, 0, 0, CURDATE()), + ( 7, 2, 11, 'Gem of Mind', 15 , 1.30, 0, 0, 0, CURDATE()), + ( 8, 4, 11, 'Mark I' , 10 , 3.26, 0, 0, 0, CURDATE()), + ( 9, 1, 16, 'Gem of Time', 5 , 11.42, 0, 0, 0, CURDATE()), + ( 10, 2, 16, 'Gem of Mind', 10 , 1.30, 0, 0, 0, CURDATE()), + ( 11, 1, 16, 'Gem of Time', 2 , 11.42, 0, 0, 0, CURDATE()), + ( 12, 4, 16, 'Mark I' , 20 , 3.26, 0, 0, 0, CURDATE()); INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) VALUES @@ -785,12 +785,12 @@ INSERT INTO `bi`.`claims_ratio`(`id_Cliente`, `Consumo`, `Reclamaciones`, `Ratio INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`minPrice`,`producer`,`printedStickers`,`isChecked`,`isIgnored`, `created`) VALUES - (1, 1, 1, 2.5, 5000 , 1, 1, 0.350, 0.050, 0.000, 1, 1, 0, NULL, 1.50, 1.25, 1.30, 2.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)), - (2, 2, 1, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 1, 1, 0, NULL, 2.50, 1.00, 2.50, 2.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), - (3, 3, 1, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 1, 1, 0, NULL, 2.50, 1.00, 2.50, 2.00, NULL, 0, 1, 0, CURDATE()), - (4, 2, 2, 5 , 450 , 1, 1, 0.500, 0.100, 0.000, 1, 1, 0, NULL, 2, 1.00, 1.30, 2.00, NULL, 0, 1, 0, CURDATE()), - (5, 3, 3, 10 , 500 , 1, 1, 1.000, 0.050, 0.000, 1, 1, 0, NULL, 2.50, 1.00, 2.50, 2.00, NULL, 0, 1, 0, CURDATE()), - (6, 4, 4, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 1, 1, 0, NULL, 2.50, 1.00, 2.50, 2.00, NULL, 0, 1, 0, CURDATE()); + (1, 1, 1, 2.5, 5000 , 1, 1, 0.350, 0.050, 0.000, 10, 10, 1, NULL, 0.00, 1.30, 1.25, 1.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)), + (2, 2, 1, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 5, 5, 1, NULL, 0.00, 2.50, 2.00, 0.50, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), + (3, 3, 1, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 1, 1, 0, NULL, 0.00, 2.50, 2.00, 0.50, NULL, 0, 1, 0, CURDATE()), + (4, 2, 2, 5 , 450 , 1, 1, 0.500, 0.100, 0.000, 10, 10, 0, NULL, 0.00, 1.30, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()), + (5, 3, 3, 10 , 500 , 1, 1, 1.000, 0.050, 0.000, 10, 10, 0, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()), + (6, 4, 4, 20 , 100 , 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()); INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`) VALUES diff --git a/services/loopback/common/methods/client/specs/getDebt.spec.js b/services/loopback/common/methods/client/specs/getDebt.spec.js index 66e026e3d..e406f16e6 100644 --- a/services/loopback/common/methods/client/specs/getDebt.spec.js +++ b/services/loopback/common/methods/client/specs/getDebt.spec.js @@ -4,7 +4,7 @@ describe('client getDebt()', () => { it('should return the client debt', async() => { let result = await app.models.Client.getDebt(101); - expect(result.debt).toEqual(1342.66); + expect(result.debt).toEqual(1048.76); }); }); diff --git a/services/loopback/common/methods/client/specs/summary.spec.js b/services/loopback/common/methods/client/specs/summary.spec.js index fcdb6fa38..4e3c7cec7 100644 --- a/services/loopback/common/methods/client/specs/summary.spec.js +++ b/services/loopback/common/methods/client/specs/summary.spec.js @@ -17,7 +17,7 @@ describe('client summary()', () => { it('should return a summary object containing debt', async() => { let result = await app.models.Client.summary(101); - expect(result.debt.debt).toEqual(1342.66); + expect(result.debt.debt).toEqual(1048.76); }); it('should return a summary object containing averageInvoiced', async() => { diff --git a/services/loopback/common/methods/sale/specs/priceDifference.spec.js b/services/loopback/common/methods/sale/specs/priceDifference.spec.js index 0205cf098..dc562ee57 100644 --- a/services/loopback/common/methods/sale/specs/priceDifference.spec.js +++ b/services/loopback/common/methods/sale/specs/priceDifference.spec.js @@ -10,8 +10,8 @@ describe('sale priceDifference()', () => { }; let result = await app.models.Sale.priceDifference(1, data); - expect(result.totalUnitPrice).toEqual(30.469999999999995); - expect(result.totalNewPrice).toEqual(26.12); - expect(result.totalDifference).toEqual(63.8); + expect(result.totalUnitPrice).toEqual(27.4); + expect(result.totalNewPrice).toEqual(22.33); + expect(result.totalDifference).toEqual(22.54); }); }); diff --git a/services/loopback/common/methods/ticket/getVAT.js b/services/loopback/common/methods/ticket/getVAT.js index 509a0d13c..087697b0c 100644 --- a/services/loopback/common/methods/ticket/getVAT.js +++ b/services/loopback/common/methods/ticket/getVAT.js @@ -27,6 +27,6 @@ module.exports = Self => { totalTax += tax.tax; }); - return totalTax; + return Math.round(totalTax * 100) / 100; }; }; diff --git a/services/loopback/common/methods/ticket/specs/getTaxes.spec.js b/services/loopback/common/methods/ticket/specs/getTaxes.spec.js index d9637ab85..feab81459 100644 --- a/services/loopback/common/methods/ticket/specs/getTaxes.spec.js +++ b/services/loopback/common/methods/ticket/specs/getTaxes.spec.js @@ -4,6 +4,6 @@ describe('ticket getTaxes()', () => { it('should return the tax of a given ticket', async() => { let result = await app.models.Ticket.getTaxes(1); - expect(result[0].tax).toEqual(10.93); + expect(result[0].tax).toEqual(9.29); }); }); diff --git a/services/loopback/common/methods/ticket/specs/getTotal.spec.js b/services/loopback/common/methods/ticket/specs/getTotal.spec.js index 1d211fbba..b80ff3d97 100644 --- a/services/loopback/common/methods/ticket/specs/getTotal.spec.js +++ b/services/loopback/common/methods/ticket/specs/getTotal.spec.js @@ -4,7 +4,7 @@ describe('ticket getTotal()', () => { it('should return the total of a ticket', async() => { let result = await app.models.Ticket.getTotal(1); - expect(result).toEqual(291.08); + expect(result).toEqual(181.12); }); it(`should return zero if the ticket doesn't have lines`, async() => { diff --git a/services/loopback/common/methods/ticket/specs/getTotalVolume.spec.js b/services/loopback/common/methods/ticket/specs/getTotalVolume.spec.js index c6ed836ec..df566f1c4 100644 --- a/services/loopback/common/methods/ticket/specs/getTotalVolume.spec.js +++ b/services/loopback/common/methods/ticket/specs/getTotalVolume.spec.js @@ -4,7 +4,7 @@ describe('ticket getTotalVolume()', () => { it('should return the total volume of a ticket', async() => { let ticketFk = 1; - let expectedResult = 0.276; + let expectedResult = 0.078; let result = await app.models.Ticket.getTotalVolume(ticketFk); diff --git a/services/loopback/common/methods/ticket/specs/getVAT.spec.js b/services/loopback/common/methods/ticket/specs/getVAT.spec.js index 300744502..629452376 100644 --- a/services/loopback/common/methods/ticket/specs/getVAT.spec.js +++ b/services/loopback/common/methods/ticket/specs/getVAT.spec.js @@ -4,7 +4,7 @@ describe('ticket getVAT()', () => { it('should call the getVAT method and return the response', async() => { await app.models.Ticket.getVAT(1) .then(response => { - expect(response).toEqual(40.58); + expect(response).toEqual(22.98); }); }); diff --git a/services/loopback/common/methods/ticket/specs/summary.spec.js b/services/loopback/common/methods/ticket/specs/summary.spec.js index 96e0153be..9abb0fecd 100644 --- a/services/loopback/common/methods/ticket/specs/summary.spec.js +++ b/services/loopback/common/methods/ticket/specs/summary.spec.js @@ -17,18 +17,19 @@ describe('ticket summary()', () => { it('should return a summary object containing subTotal for 1 ticket', async() => { let result = await app.models.Ticket.summary(1); - expect(result.subTotal).toEqual(250.5); + expect(result.subTotal).toEqual(158.14); }); it('should return a summary object containing VAT for 1 ticket', async() => { let result = await app.models.Ticket.summary(1); - expect(result.VAT).toEqual(40.58); + expect(Math.round(result.VAT * 100) / 100).toEqual(22.98); }); it('should return a summary object containing total for 1 ticket', async() => { let result = await app.models.Ticket.summary(1); - let expectedTotal = result.subTotal + result.VAT; + let total = result.subTotal + result.VAT; + let expectedTotal = Math.round(total * 100) / 100; expect(result.total).toEqual(expectedTotal); }); From ed3c775c0430e0b3ad6e0f5c2fa2e7dbf483489d Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 08:24:19 +0200 Subject: [PATCH 09/34] #608 order-create now redirects correctly yo the catalog --- client/order/src/create/card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/order/src/create/card.js b/client/order/src/create/card.js index 7bf9ad4a8..ba605ae73 100644 --- a/client/order/src/create/card.js +++ b/client/order/src/create/card.js @@ -74,7 +74,7 @@ class Controller { }; this.$http.post(`order/api/Orders/new`, params).then(res => { this.vnApp.showSuccess(this.translate.instant('Data saved!')); - this.$state.go("order.card.catalogue", {id: res.data}); + this.$state.go("order.card.catalog", {id: res.data}); }).catch(e => { this.vnApp.showError(this.translate.instant(e.data.error.message)); }); From c2f8f236fb13cc6c7e4452cf9910c96dee1974c0 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 10:08:19 +0200 Subject: [PATCH 10/34] =?UTF-8?q?=20#647=20Si=20se=20hace=20control=20clic?= =?UTF-8?q?k=20en=20ticket.index=20abrir=20una=20nueva=20pesta=C3=B1a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/core/src/components/table/style.scss | 10 ++++------ client/ticket/src/index/index.html | 7 ++++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/client/core/src/components/table/style.scss b/client/core/src/components/table/style.scss index f5e6bf25e..3ada4feec 100644 --- a/client/core/src/components/table/style.scss +++ b/client/core/src/components/table/style.scss @@ -56,7 +56,7 @@ vn-table { display: table-footer-group } - vn-tr { + vn-tr, a.vn-tr { display: table-row } @@ -67,10 +67,8 @@ vn-table { padding: 10px } - vn-thead, - vn-tbody, - vn-tfoot { - vn-tr { + vn-thead, vn-tbody, vn-tfoot { + vn-tr, a.vn-tr { display: table-row; vn-th { @@ -101,7 +99,7 @@ vn-table { vn-thead, vn-tbody, vn-empty-rows { border-bottom: 3px solid $lines; } - vn-tbody > vn-tr { + vn-tbody > vn-tr, vn-tbody > a.vn-tr { border-bottom: 1px solid $lines; transition: background-color 200ms ease-in-out; diff --git a/client/ticket/src/index/index.html b/client/ticket/src/index/index.html index 467b0f3eb..f6a6b3440 100644 --- a/client/ticket/src/index/index.html +++ b/client/ticket/src/index/index.html @@ -37,8 +37,9 @@ - - + From b03b86059dcc6fdf28ac04c07d7fc930312b8ebf Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 11:00:51 +0200 Subject: [PATCH 11/34] #647 selectors for e2e update --- e2e/helpers/selectors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0d88574aa..29014b96a 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -274,7 +274,7 @@ export default { }, ticketsIndex: { createTicketButton: `vn-ticket-index ${components.vnFloatButton}`, - searchResult: `vn-ticket-index vn-card > div > vn-table > div > vn-tbody > vn-tr`, + searchResult: `vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr`, searchTicketInput: `vn-ticket-index ${components.vnTextfield}`, searchButton: `vn-ticket-index vn-searchbar vn-icon-button[icon="search"]` }, From e03241fcc63afa1e36bfc695857b597558718d58 Mon Sep 17 00:00:00 2001 From: gerard Date: Wed, 12 Sep 2018 11:06:28 +0200 Subject: [PATCH 12/34] Tarea #480 /icon-menu/icon-menu.js Front unit test --- .../components/icon-menu/icon-menu.spec.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 client/core/src/components/icon-menu/icon-menu.spec.js diff --git a/client/core/src/components/icon-menu/icon-menu.spec.js b/client/core/src/components/icon-menu/icon-menu.spec.js new file mode 100644 index 000000000..7db2a3e8c --- /dev/null +++ b/client/core/src/components/icon-menu/icon-menu.spec.js @@ -0,0 +1,53 @@ +import './icon-menu.js'; + +describe('Component vnIconMenu', () => { + let $componentController; + let controller; + let $element; + + beforeEach(() => { + angular.mock.module('ticket'); + }); + + beforeEach(angular.mock.inject(_$componentController_ => { + $componentController = _$componentController_; + $element = angular.element(`
`); + controller = $componentController('vnIconMenu', {$element: $element, $transclude: null}); + })); + + describe('getFields()', () => { + it(`should return an array with the fields selectables`, () => { + let fields = controller.getFields(); + + expect(fields).toEqual(['id', 'name']); + }); + }); + + describe('onClick(event)', () => { + it(`should call preventDefault, onOpen and showDropdown`, () => { + let event = {preventDefault: () => {}}; + controller.onOpen = () => {}; + spyOn(event, 'preventDefault'); + spyOn(controller, 'showDropDown'); + spyOn(controller, 'onOpen'); + + controller.onClick(event); + + expect(event.preventDefault).toHaveBeenCalledWith(); + expect(controller.showDropDown).toHaveBeenCalledWith(); + expect(controller.onOpen).toHaveBeenCalledWith(); + }); + }); + + describe('onDropDownSelect(value)', () => { + it(`should set field to a given value and call onChange`, () => { + controller.onChange = () => {}; + spyOn(controller, 'onChange'); + + controller.onDropDownSelect('mariano'); + + expect(controller.field).toBe('mariano'); + expect(controller.onChange).toHaveBeenCalledWith({value: 'mariano'}); + }); + }); +}); From 49b96c5cc355f090ce0b78bc5ba1ee8f3ea4edc5 Mon Sep 17 00:00:00 2001 From: gerard Date: Wed, 12 Sep 2018 11:08:48 +0200 Subject: [PATCH 13/34] test fixed --- client/order/src/create/card.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/order/src/create/card.spec.js b/client/order/src/create/card.spec.js index bace0bab3..42ca110b1 100644 --- a/client/order/src/create/card.spec.js +++ b/client/order/src/create/card.spec.js @@ -88,7 +88,7 @@ describe('Order', () => { $httpBackend.flush(); expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); - expect(controller.$state.go).toHaveBeenCalledWith("order.card.catalogue", {id: 1}); + expect(controller.$state.go).toHaveBeenCalledWith("order.card.catalog", {id: 1}); }); }); }); From fe6eb7dfd78a1fb177a5b25831c969b489f7297e Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:19:53 +0200 Subject: [PATCH 14/34] fixtures update for #604 create claim part of the path --- services/db/install/changes/1.1.0/03-acl.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 services/db/install/changes/1.1.0/03-acl.sql diff --git a/services/db/install/changes/1.1.0/03-acl.sql b/services/db/install/changes/1.1.0/03-acl.sql new file mode 100644 index 000000000..ca763b5f3 --- /dev/null +++ b/services/db/install/changes/1.1.0/03-acl.sql @@ -0,0 +1,7 @@ +UPDATE `salix`.`ACL` SET `model`='ClaimEnd' WHERE `id`='96'; +UPDATE `salix`.`ACL` SET `model`='ClaimEnd' WHERE `id`='97'; +UPDATE `salix`.`ACL` SET `model`='ClaimBeginning', `accessType`='*' WHERE `id`='98'; +UPDATE `salix`.`ACL` SET `model`='ClaimDevelopment' WHERE `id`='99'; +UPDATE `salix`.`ACL` SET `model`='ClaimDevelopment' WHERE `id`='100'; +INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (101, 'Claim', '*', '*', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (102, 'Claim', 'createFromSales', '*', 'ALLOW', 'ROLE', 'employee'); \ No newline at end of file From 58da484fe2f85677e818d18f3e2ecc3248569a93 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:20:39 +0200 Subject: [PATCH 15/34] minor refactor --- .../claim-module/01_edit_basic_data.spec.js | 168 +++++++++--------- 1 file changed, 83 insertions(+), 85 deletions(-) diff --git a/e2e/paths/claim-module/01_edit_basic_data.spec.js b/e2e/paths/claim-module/01_edit_basic_data.spec.js index 574b20c32..13ef6dd68 100644 --- a/e2e/paths/claim-module/01_edit_basic_data.spec.js +++ b/e2e/paths/claim-module/01_edit_basic_data.spec.js @@ -1,106 +1,104 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/helpers.js'; -describe('Claim', () => { - describe('Edit basic data path', () => { - const nightmare = createNightmare(); +describe('Claim edit basic data path', () => { + const nightmare = createNightmare(); - beforeAll(() => { - return nightmare - .waitForLogin('developer'); + beforeAll(() => { + return nightmare + .waitForLogin('salesAssistant'); + }); + + it('should click on the Claims button of the top bar menu', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.claimsButton) + .wait(selectors.claimsIndex.searchClaimInput) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/claim/index'); }); + }); - it('should click on the Claims button of the top bar menu', () => { - return nightmare - .waitToClick(selectors.globalItems.applicationsMenuButton) - .wait(selectors.globalItems.applicationsMenuVisible) - .waitToClick(selectors.globalItems.claimsButton) - .wait(selectors.claimsIndex.searchClaimInput) - .parsedUrl() - .then(url => { - expect(url.hash).toEqual('#!/claim/index'); - }); + it('should search for the claim with id 1', () => { + return nightmare + .wait(selectors.claimsIndex.searchResult) + .type(selectors.claimsIndex.searchClaimInput, '1') + .click(selectors.claimsIndex.searchButton) + .waitForNumberOfElements(selectors.claimsIndex.searchResult, 1) + .countElement(selectors.claimsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); }); + }); - it('should search for the claim with id 1', () => { - return nightmare - .wait(selectors.claimsIndex.searchResult) - .type(selectors.claimsIndex.searchClaimInput, '1') - .click(selectors.claimsIndex.searchButton) - .waitForNumberOfElements(selectors.claimsIndex.searchResult, 1) - .countElement(selectors.claimsIndex.searchResult) - .then(result => { - expect(result).toEqual(1); - }); + it(`should click on the search result to access to the claim Basic Data`, () => { + return nightmare + .waitToClick(selectors.claimsIndex.searchResult) + .waitToClick(selectors.claimBasicData.basicDataButton) + .waitForURL('basic-data') + .url() + .then(url => { + expect(url).toContain('basic-data'); }); + }); - it(`should click on the search result to access to the ticket Basic Data`, () => { - return nightmare - .waitToClick(selectors.claimsIndex.searchResult) - .waitToClick(selectors.claimBasicData.basicDataButton) - .waitForURL('basic-data') - .url() - .then(url => { - expect(url).toContain('basic-data'); - }); + it(`should edit claim state, is paid with mana and observation fields`, () => { + return nightmare + .waitToClick(selectors.claimBasicData.claimStateSelect) + .waitToClick(selectors.claimBasicData.claimStateSelectThirdOption) + .waitToClick(selectors.claimBasicData.isPaidWithManaCheckbox) + .clearInput(selectors.claimBasicData.observationInput) + .type(selectors.claimBasicData.observationInput, 'edited observation') + .click(selectors.claimBasicData.saveButton) + .waitForSnackbar() + .then(result => { + expect(result).toEqual(jasmine.arrayContaining(['Data saved!'])); }); + }); - it(`should edit claim state, is paid with mana and observation fields`, () => { - return nightmare - .waitToClick(selectors.claimBasicData.claimStateSelect) - .waitToClick(selectors.claimBasicData.claimStateSelectThirdOption) - .waitToClick(selectors.claimBasicData.isPaidWithManaCheckbox) - .clearInput(selectors.claimBasicData.observationInput) - .type(selectors.claimBasicData.observationInput, 'edited observation') - .click(selectors.claimBasicData.saveButton) - .waitForSnackbar() - .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Data saved!'])); - }); + it('should confirm the claim state was edited', () => { + return nightmare + .click(selectors.claimDetails.detailsButton) + .wait(selectors.claimDetails.addItemButton) + .click(selectors.claimBasicData.basicDataButton) + .wait(selectors.claimBasicData.claimStateSelect) + .getInputValue(selectors.claimBasicData.claimStateSelect) + .then(result => { + expect(result).toEqual('Gestionado'); }); + }); - it('should confirm the claim state was edited', () => { - return nightmare - .click(selectors.claimDetails.detailsButton) - .wait(selectors.claimDetails.addItemButton) - .click(selectors.claimBasicData.basicDataButton) - .wait(selectors.claimBasicData.claimStateSelect) - .getInputValue(selectors.claimBasicData.claimStateSelect) - .then(result => { - expect(result).toEqual('Gestionado'); - }); + it('should confirm the Is paid with mana checkbox is checked', () => { + return nightmare + .evaluate(selector => { + return document.querySelector(selector).checked; + }, selectors.claimBasicData.isPaidWithManaCheckbox) + .then(value => { + expect(value).toBeTruthy(); }); + }); - it('should confirm the Is paid with mana checkbox is checked', () => { - return nightmare - .evaluate(selector => { - return document.querySelector(selector).checked; - }, selectors.claimBasicData.isPaidWithManaCheckbox) - .then(value => { - expect(value).toBeTruthy(); - }); + it('should confirm the claim observation was edited', () => { + return nightmare + .getInputValue(selectors.claimBasicData.observationInput) + .then(result => { + expect(result).toEqual('edited observation'); }); + }); - it('should confirm the claim observation was edited', () => { - return nightmare - .getInputValue(selectors.claimBasicData.observationInput) - .then(result => { - expect(result).toEqual('edited observation'); - }); - }); - - it(`should edit the claim to leave it untainted`, () => { - return nightmare - .waitToClick(selectors.claimBasicData.claimStateSelect) - .waitToClick(selectors.claimBasicData.claimStateSelectFourthOption) - .waitToClick(selectors.claimBasicData.isPaidWithManaCheckbox) - .clearInput(selectors.claimBasicData.observationInput) - .type(selectors.claimBasicData.observationInput, 'Observation one') - .click(selectors.claimBasicData.saveButton) - .waitForSnackbar() - .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Data saved!'])); - }); + it(`should edit the claim to leave it untainted`, () => { + return nightmare + .waitToClick(selectors.claimBasicData.claimStateSelect) + .waitToClick(selectors.claimBasicData.claimStateSelectFourthOption) + .waitToClick(selectors.claimBasicData.isPaidWithManaCheckbox) + .clearInput(selectors.claimBasicData.observationInput) + .type(selectors.claimBasicData.observationInput, 'Observation one') + .click(selectors.claimBasicData.saveButton) + .waitForSnackbar() + .then(result => { + expect(result).toEqual(jasmine.arrayContaining(['Data saved!'])); }); }); }); From 88a4ed7fb39d50ffee67536ec9c65ff7ee1b4b94 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:21:20 +0200 Subject: [PATCH 16/34] #604 acl for claims --- client/claim/routes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/claim/routes.json b/client/claim/routes.json index 5af69e52f..326780329 100644 --- a/client/claim/routes.json +++ b/client/claim/routes.json @@ -16,7 +16,7 @@ "state": "claim.index", "component": "vn-claim-index", "description": "List", - "acl": ["salesAssistant"] + "acl": ["salesAssistant", "salesPerson"] }, { "url": "/:id", From f98fc703aa329d3ee62261c559fc9dc6cb7796f5 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:38:08 +0200 Subject: [PATCH 17/34] #604 e2e de la seccion ticket.sale + selectors --- e2e/helpers/selectors.js | 7 +- e2e/paths/ticket-module/07_edit_sale.spec.js | 140 +++++++++++++++++-- 2 files changed, 133 insertions(+), 14 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 29014b96a..6566bd181 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -275,6 +275,7 @@ export default { ticketsIndex: { createTicketButton: `vn-ticket-index ${components.vnFloatButton}`, searchResult: `vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr`, + searchResultDate: `vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)`, searchTicketInput: `vn-ticket-index ${components.vnTextfield}`, searchButton: `vn-ticket-index vn-searchbar vn-icon-button[icon="search"]` }, @@ -338,7 +339,8 @@ export default { moveToTicketInputClearButton: 'vn-popover.shown i[title="Clear"]', moveToTicketButton: 'vn-ticket-sale vn-popover.transfer vn-icon[icon="arrow_forward_ios"]', moveToNewTicketButton: 'vn-ticket-sale vn-popover.transfer vn-button[label="New ticket"]', - acceptDeleteButton: `vn-ticket-sale > vn-confirm[vn-id="delete-lines"] button[response=ACCEPT]`, + acceptDeleteLineButton: `vn-ticket-sale > vn-confirm[vn-id="delete-lines"] button[response=ACCEPT]`, + acceptDeleteTicketButton: `vn-ticket-sale > vn-confirm[vn-id="deleteConfirmation"] button[response=ACCEPT]`, stateMenuButton: 'vn-ticket-sale vn-tool-bar > vn-icon-menu[label="State"] button', stateMenuOptions: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(1)', moreMenuButton: 'vn-ticket-sale vn-tool-bar > vn-icon-menu[label="More"] button', @@ -346,7 +348,8 @@ export default { moreMenuReseveOption: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(3)', moreMenuUnmarkResevedOption: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(4)', moreMenuUpdateDiscount: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(5)', - moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog.shown vn-ticket-sale-edit-discount input' + moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog.shown vn-ticket-sale-edit-discount input', + moreMenuCreateClaim: 'vn-ticket-sale vn-drop-down > vn-popover ul > li:nth-child(6)' }, ticketTracking: { trackingButton: `vn-left-menu a[ui-sref="ticket.card.tracking.index"]`, diff --git a/e2e/paths/ticket-module/07_edit_sale.spec.js b/e2e/paths/ticket-module/07_edit_sale.spec.js index a80069045..5105dc734 100644 --- a/e2e/paths/ticket-module/07_edit_sale.spec.js +++ b/e2e/paths/ticket-module/07_edit_sale.spec.js @@ -1,8 +1,8 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/helpers'; -// #603 in progress -xdescribe('Ticket Edit sale path', () => { +// #604 in progress +fdescribe('Ticket Edit sale path', () => { const nightmare = createNightmare(); beforeAll(() => { @@ -61,7 +61,7 @@ xdescribe('Ticket Edit sale path', () => { .wait(selectors.ticketSales.firstSaleText) .getInnerText(selectors.ticketSales.firstSalePrice) .then(value => { - expect(value).toEqual('€9.60'); + expect(value).toEqual('€11.42'); }); }); @@ -79,7 +79,7 @@ xdescribe('Ticket Edit sale path', () => { .wait(selectors.ticketSales.firstSaleText) .getInnerText(selectors.ticketSales.firstSaleImport) .then(value => { - expect(value).toEqual('€48.00'); + expect(value).toEqual('€57.10'); }); }); @@ -261,11 +261,87 @@ xdescribe('Ticket Edit sale path', () => { }); }); + it('should select the third sale and create a claim of it', () => { + return nightmare + .waitToClick(selectors.ticketSales.firstSaleCheckbox) + .waitToClick(selectors.ticketSales.moreMenuButton) + .waitToClick(selectors.ticketSales.moreMenuCreateClaim) + .waitForLogin('Developer') + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.claimsButton) + .wait(selectors.claimsIndex.searchResult) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/claim/index'); + }); + }); + + it('should click on the Claims button of the top bar menu', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.claimsButton) + .wait(selectors.claimsIndex.searchClaimInput) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/claim/index'); + }); + }); + + it('should search for the claim with id 4', () => { + return nightmare + .wait(selectors.claimsIndex.searchResult) + .type(selectors.claimsIndex.searchClaimInput, 4) + .click(selectors.claimsIndex.searchButton) + .waitForNumberOfElements(selectors.claimsIndex.searchResult, 1) + .countElement(selectors.claimsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it('should click the Tickets button of the top bar menu', () => { + return nightmare + .waitToClick(selectors.globalItems.applicationsMenuButton) + .wait(selectors.globalItems.applicationsMenuVisible) + .waitToClick(selectors.globalItems.ticketsButton) + .wait(selectors.ticketsIndex.createTicketButton) + .parsedUrl() + .then(url => { + expect(url.hash).toEqual('#!/ticket/index'); + }); + }); + + it('should search the ticket', () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:16') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should click on the result to access to the ticket Sale`, () => { + return nightmare + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + it('should select the third sale and delete it', () => { return nightmare .waitToClick(selectors.ticketSales.thirdSaleCheckbox) .waitToClick(selectors.ticketSales.deleteSaleButton) - .waitToClick(selectors.ticketSales.acceptDeleteButton) + .waitToClick(selectors.ticketSales.acceptDeleteLineButton) .waitForLastSnackbar() .then(result => { expect(result).toEqual('Data saved!'); @@ -644,14 +720,54 @@ xdescribe('Ticket Edit sale path', () => { }); }); + it('should go to another ticket sales section', () => { + return nightmare + .waitToClick(selectors.itemsIndex.goBackToModuleIndexButton) + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:17') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 26') + .waitToClick(selectors.ticketsIndex.searchResult) + .waitToClick(selectors.ticketSales.saleButton) + .waitForURL('/sale') + .url() + .then(url => { + expect(url).toContain('/sale'); + }); + }); + it(`should be able to delete the ticket`, () => { - // return nightmare - // .waitToClick(selectors.ticketSales.moreMenuButton) - // .waitToClick(selectors.ticketSales.moreMenuDeleteOption) - // .exists(selectors.ticketSales.stateMenuOptions) - // .then(result => { - // expect(result).toBeFalsy(); - // }); + return nightmare + .waitToClick(selectors.ticketSales.moreMenuButton) + .waitToClick(selectors.ticketSales.moreMenuDeleteOption) + .waitToClick(selectors.ticketSales.acceptDeleteTicketButton) + .waitForURL('/ticket/index') + .url() + .then(url => { + expect(url).toContain('/ticket/index'); + }); + }); + + it(`should search for the deleted ticket`, () => { + return nightmare + .wait(selectors.ticketsIndex.searchResult) + .type(selectors.ticketsIndex.searchTicketInput, 'id:17') + .click(selectors.ticketsIndex.searchButton) + .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1) + .countElement(selectors.ticketsIndex.searchResult) + .then(result => { + expect(result).toEqual(1); + }); + }); + + it(`should search for the deleted ticket`, () => { + return nightmare + .wait(selectors.ticketsIndex.searchResultDate) + .getInnerText(selectors.ticketsIndex.searchResultDate) + .then(result => { + expect(result).toContain(2000); + }); }); }); }); From 516552c59fc35b3f2195bc588a8b4dba70cfb868 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:40:52 +0200 Subject: [PATCH 18/34] removed a console log --- .../claim/common/methods/claim/specs/createFromSales.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/claim/common/methods/claim/specs/createFromSales.spec.js b/services/claim/common/methods/claim/specs/createFromSales.spec.js index 4076059ec..8e770fd7f 100644 --- a/services/claim/common/methods/claim/specs/createFromSales.spec.js +++ b/services/claim/common/methods/claim/specs/createFromSales.spec.js @@ -5,7 +5,6 @@ describe('Claim Create', () => { let createdClaimFk; afterAll(async() => { - console.log('asdf', createdClaimFk); await app.models.Claim.destroyById(createdClaimFk); }); From b5301fcc94d8248748714e188bf3f3a20e69c805 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 15:45:44 +0200 Subject: [PATCH 19/34] removed fdescribe and comment --- e2e/paths/ticket-module/07_edit_sale.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e/paths/ticket-module/07_edit_sale.spec.js b/e2e/paths/ticket-module/07_edit_sale.spec.js index 5105dc734..0f7ac93cf 100644 --- a/e2e/paths/ticket-module/07_edit_sale.spec.js +++ b/e2e/paths/ticket-module/07_edit_sale.spec.js @@ -1,8 +1,7 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/helpers'; -// #604 in progress -fdescribe('Ticket Edit sale path', () => { +describe('Ticket Edit sale path', () => { const nightmare = createNightmare(); beforeAll(() => { From 6b6e7d96b8196d9965b43ea98aef5417c7e42e75 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 12 Sep 2018 16:25:12 +0200 Subject: [PATCH 20/34] #640 Ticket Create packages path is excluded --- e2e/helpers/selectors.js | 5 ++-- .../04_create_ticket_packages.spec.js | 29 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 6566bd181..571493ed4 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -276,6 +276,7 @@ export default { createTicketButton: `vn-ticket-index ${components.vnFloatButton}`, searchResult: `vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr`, searchResultDate: `vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)`, + searchResultAddress: `vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)`, searchTicketInput: `vn-ticket-index ${components.vnTextfield}`, searchButton: `vn-ticket-index vn-searchbar vn-icon-button[icon="search"]` }, @@ -297,9 +298,9 @@ export default { packagesButton: `vn-menu-item a[ui-sref="ticket.card.package.index"]`, firstPackageSelect: `vn-autocomplete[label="Package"] > div > div > input`, firstPackageSelectOptionThree: `vn-autocomplete[label="Package"] vn-drop-down ul > li:nth-child(3)`, - firstQuantityInput: `vn-textfield[label="Quantity"] > div > input`, + firstQuantityInput: `vn-textfield[label="Quantity"] input`, firstRemovePackageButton: `vn-icon[vn-tooltip="Remove package"]`, - addPackageButton: `vn-icon[vn-tooltip="Add package"]`, + addPackageButton: `vn-icon-button[vn-tooltip="Add package"]`, clearPackageSelectButton: `vn-autocomplete[label="Package"] > div > div > div > vn-icon > i`, savePackagesButton: `${components.vnSubmit}` }, diff --git a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js index c65bf7d4f..f9f36f424 100644 --- a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js +++ b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js @@ -1,8 +1,7 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/helpers'; -// #640 Ticket Create packages path is excluded -xdescribe('Ticket Create packages path', () => { +describe('Ticket Create packages path', () => { const nightmare = createNightmare(); beforeAll(() => { @@ -36,7 +35,7 @@ xdescribe('Ticket Create packages path', () => { it(`should click on the search result to access to the ticket packages`, () => { return nightmare - .waitForTextInElement(selectors.ticketsIndex.searchResult, 'Batman') + .waitForTextInElement(selectors.ticketsIndex.searchResultAddress, 'address 21') .waitToClick(selectors.ticketsIndex.searchResult) .waitToClick(selectors.ticketPackages.packagesButton) .waitForURL('package/index') @@ -53,9 +52,9 @@ xdescribe('Ticket Create packages path', () => { .waitToClick(selectors.ticketPackages.firstPackageSelect) .waitToClick(selectors.ticketPackages.firstPackageSelectOptionThree) .click(selectors.ticketPackages.savePackagesButton) - .waitForSnackbar() + .waitForLastSnackbar() .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Some fields are invalid'])); + expect(result).toEqual('Some fields are invalid'); }); }); @@ -63,32 +62,32 @@ xdescribe('Ticket Create packages path', () => { return nightmare .type(selectors.ticketPackages.firstQuantityInput, 'ninety 9') .click(selectors.ticketPackages.savePackagesButton) - .waitForSnackbar() + .waitForLastSnackbar() .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Some fields are invalid'])); + expect(result).toEqual('Some fields are invalid'); }); }); it(`should attempt create a new package but receive an error if quantity is 0`, () => { return nightmare .clearInput(selectors.ticketPackages.firstQuantityInput) - .type(selectors.ticketPackages.firstQuantityInput, '0') + .type(selectors.ticketPackages.firstQuantityInput, 0) .click(selectors.ticketPackages.savePackagesButton) - .waitForSnackbar() + .waitForLastSnackbar() .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Some fields are invalid'])); + expect(result).toEqual('Some fields are invalid'); }); }); it(`should attempt create a new package but receive an error if package is blank`, () => { return nightmare .clearInput(selectors.ticketPackages.firstQuantityInput) - .type(selectors.ticketPackages.firstQuantityInput, '99') + .type(selectors.ticketPackages.firstQuantityInput, 99) .click(selectors.ticketPackages.clearPackageSelectButton) .click(selectors.ticketPackages.savePackagesButton) - .waitForSnackbar() + .waitForLastSnackbar() .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Package cannot be blank'])); + expect(result).toEqual('The package cannot be blank'); }); }); @@ -98,9 +97,9 @@ xdescribe('Ticket Create packages path', () => { .waitToClick(selectors.ticketPackages.firstPackageSelectOptionThree) .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'Iron Patriot') .click(selectors.ticketPackages.savePackagesButton) - .waitForSnackbar() + .waitForLastSnackbar() .then(result => { - expect(result).toEqual(jasmine.arrayContaining(['Data saved!'])); + expect(result).toEqual('Data saved!'); }); }); From 7e309e5f62f95900c0066ddeb61fa0957aaa24ac Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 10:05:39 +0200 Subject: [PATCH 21/34] Bug #650 En la seccion claim detail no aparecen las sales reclamables --- client/claim/src/detail/index.html | 2 +- client/claim/src/locale/es.yml | 1 + services/claim/common/models/claim.json | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/claim/src/detail/index.html b/client/claim/src/detail/index.html index 6137d76a9..2a9258cc9 100644 --- a/client/claim/src/detail/index.html +++ b/client/claim/src/detail/index.html @@ -80,7 +80,7 @@ -

Claimable sales from ticket

{{$ctrl.claim.ticketFk}}

+

Claimable sales from ticket {{$ctrl.claim.ticketFk}}

diff --git a/client/claim/src/locale/es.yml b/client/claim/src/locale/es.yml index 49df860e8..63c96d9c6 100644 --- a/client/claim/src/locale/es.yml +++ b/client/claim/src/locale/es.yml @@ -3,6 +3,7 @@ Client Id: Id cliente Observation: Observación Responsible: Responsable Claim Id: Id reclamación +Created: Creado #sections Claims: Reclamaciones diff --git a/services/claim/common/models/claim.json b/services/claim/common/models/claim.json index 3380e6ec4..ab6a4ab05 100644 --- a/services/claim/common/models/claim.json +++ b/services/claim/common/models/claim.json @@ -28,6 +28,9 @@ }, "responsibility": { "type": "Number" + }, + "ticketFk": { + "type": "Number" } }, "relations": { From 8234780252b70b96f2e9a05b1d0fa470e773e409 Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 11:06:48 +0200 Subject: [PATCH 22/34] updated fonts --- client/core/src/styles/fontello-codes.css | 7 +++++-- client/core/src/styles/fontello.woff2 | Bin 12592 -> 13064 bytes 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/core/src/styles/fontello-codes.css b/client/core/src/styles/fontello-codes.css index 83e2c4d92..4e5a1712a 100644 --- a/client/core/src/styles/fontello-codes.css +++ b/client/core/src/styles/fontello-codes.css @@ -3,7 +3,7 @@ .icon-volume:before { content: '\e801'; } /* '' */ .icon-barcode:before { content: '\e802'; } /* '' */ .icon-bucket:before { content: '\e803'; } /* '' */ -.icon-accessory:before { content: '\e804'; } /* '' */ +.icon-accesory:before { content: '\e804'; } /* '' */ .icon-dfiscales:before { content: '\e805'; } /* '' */ .icon-doc:before { content: '\e806'; } /* '' */ .icon-eye:before { content: '\e807'; } /* '' */ @@ -13,6 +13,8 @@ .icon-disabled:before { content: '\e80b'; } /* '' */ .icon-invoices:before { content: '\e80c'; } /* '' */ .icon-frozen-1:before { content: '\e80d'; } /* '' */ +.icon-actions:before { content: '\e80e'; } /* '' */ +.icon-details:before { content: '\e80f'; } /* '' */ .icon-noweb:before { content: '\e812'; } /* '' */ .icon-payment:before { content: '\e813'; } /* '' */ .icon-recovery:before { content: '\e815'; } /* '' */ @@ -33,8 +35,9 @@ .icon-solunion:before { content: '\e827'; } /* '' */ .icon-reserva:before { content: '\e828'; } /* '' */ .icon-entry:before { content: '\e829'; } /* '' */ +.icon-traceability:before { content: '\e82a'; } /* '' */ .icon-transaction:before { content: '\e82b'; } /* '' */ -.icon-greenery:before { content: '\e82c'; } /* '' */ +.icon-verde:before { content: '\e82c'; } /* '' */ .icon-regentry:before { content: '\e82d'; } /* '' */ .icon-plant:before { content: '\e82e'; } /* '' */ .icon-artificial:before { content: '\e82f'; } /* '' */ diff --git a/client/core/src/styles/fontello.woff2 b/client/core/src/styles/fontello.woff2 index b3994ffe3c4f110e68ff440b4f8dae029a086e77..1795dc4a7fa94f61bbfbeddd14d62be4d9781dcd 100644 GIT binary patch literal 13064 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 literal 12592 zcmV-0G0)C-Pew8T0RR9105LEC4*&oF09iNy05H}70RR9100000000000000000000 z0000SR0dW6hdKx#36^jX2nvCOX!AV_QUC!q0we>0AOs)|XLj9&*rRS6)OCZ)21Bh@;Qab&JDJ>6(AjypOso_AiE zNWo#)k_)+zhNlShLOv};@h9pj|1Gz9b@rvJ-F-FxEoBcL9N7Cx*MWN&f*`*5Sq2nE zd;bV&OsxNWKh@5;@aX?1$+8_LryV9IvYV7$S3?>F>;Xkq29S10TgKHaHjFz$4}iOB z4OCK^R2t$G*)5GFB$YCDbaL*FTN8JVjCtIe19xt0@5XX>?r*O_ouwqp0Ti1k4%tDv z`aaLN9n1w@J9k>T0g!tG&OPRm~|XXPR?Q@SK@;h!q_(%h1tu+SNGF4fem? zIX4#;MX=gu}N(elU--BhBbmzEWs*@oropjy=(OUs=|x9QVJC0q(C@KG>kxj zCje`;*4!0|k{$@CTRImQD$jk!Om#7(Hl38BU$#Gni7A^M;D2*k`m-#}(UKD`*-jCX z0uP}i4*@vW_!=m@-BWo8$Z%gC9xkW%>|bMpeu7ljw15I%c#MIMWf&p$e@j#PXQVrq zs#L{D26AB+z}x@}BeS!T-t6qPUAJAyWwj^2NOIegQdZ|KoqOe}ovxH7yKC>_R^*gg zSx^89fB~=|JIH`000q!mAJ4L8Hb_7>5pm25^YiF1HtR6A_A;0<6WR@o#V6kNHz0t5 zdy)e!S2uRjxu(xgvIhjwD6V>c%xfbxHgCHAJ%3I_ z1Q56)y6Luus(v2X)`r(t@AyCJamBlMe|}>Sj!`OS3)}O%(B*fSHN!p_r3=A3-s>Pi z5d5v(#3`16X(7PKXV;NcqRXJmyrCR-5B1{AJpKz$O4SH|IliC%JBK* zdEYbpbzC67^At`0Q&!=2suLqZ@QFBUI|6c!&Ju!QTv#Gt27Y!l`!t>kwR1P^-hB3= zV)94uF9vNHr{wf&DV{q==p)eY%^D@4^mV*vmIfJJ0F*P4em~lx3 z4kxGc(3u5qh+-P7Z?j*P`nn2_6(AJ!ph1ao9-EPN&x=tBhazoF6x6!Ms|j(-7Mf-N zRX$l)*wf+y>m&3UH4V!)I+?J;hJQG_%|}y7fD!qMwY;EC1W(`jV!t+Q$M^l~4@N(U z*Z%3-v0|k0@Ie_0Xji;vUDt+8j$IGLq(xn6C#c%Uor0S7yfChr_KxK@ph&$E&57LC zn>Y}`iZg3q%YhXHCXblfBfRYvfHiGN5*H&3a9W;YsX$flJiFr1v2k@-gfKe9{Y<}m zi)GN_j?3fH?`8b%$XpJV0tN7+ipc>(P#A%MH83#-3+rIx5;(XFF0O!wtD29cYDIe` zP=I_CQU@Z8AjTRb7()l^km3?_aT$8J0)1R<831)%f?-BvFQO@4Zuo67^0Y$PGH~b| zRw|GK7}~*VQ`3o>srJWeMncy#;{S}?F|P=>R|%8H94Y*A%LKTEqcjb#CGU)5q!(Ba zW&-sKL?55_o}QFRkcXBtpvHisMx6CW$a0QqtF~MuYbIGC*1kkRnc6|6qC}#y$;bH( zgHk%dPmH;%MBI3v0Ok6j$$>vQEr5QD{R-miKkp7yh92Q2{bOnmwXx-@7v_ARe z*~VEB$Fm-2K~z$F2NNqF=4LM5`UfI7RCppV5KH>)8b6|A*ksc=zUzF$&K zM`k>>yLrirh*3L0Qz*x@{*C`wLshaMj(&AH4)tmYC&a?>*L?x5JVW*co3ZvBK59i- zTYjM1ikKC%xTd0ZA&aP=p{Su7PO>sCk4vRp(M}CdiJ|7vs#BA4^;%Di$a=H{{P-P4 zL}-YDDfO?;jTcZwlvhbYt1e6L%98lc}X&f*J>3npNS~h z31*w8v?a5LbsGS|?V!Eq1?YO4d-ym&eH`e0AUd>f0POw;00tsJpl}!zgdpDr6)lo% z0SbCTNNY7QU7-Zgb?4d)I!_=-Po^lGo0;?pHNIZBgr7JKwf-hxNifd&HbnwWc|BxIW*lbGDGX zZM9rVn{z&V;;GbGD97(L>wJ|Z;IAyzvc%%RQJa`G6_}9!wNN;A5m+mILa`^ z1-G-xQnY$@KBG7wg*0h(93D_cGT%3WN}s8r`mS`$TZP6H95iR0w!*6+jI_2$>4sg!$N1fwMzoB4?^veaj~zCYvjCU5+V+I?sSBI3|QkN}eTYWor-} z2_mkfm(*wW2Q9v0CEPYv?osa#HHAjq#YV0x3P3v!Hd3W3sQ4kI?JvFX5u}rs_RZRM z-Lq0qRm}%94&r~&aXuUntNPLDMa96vfS98eWG`d?*Z5v&@K)ush56jvyog%Ho7SY6 zFQlVTFfW|y4k-P9E73Xo*pjs>v8JWZupuWeDb!c^aEoYlK&4OO5k9QDlo%V>(e z@_@{gN7ukD^3X?dkda;AYPfK?bcM9d+BcOa)jH@k%%vOW@nn{#qBZdIbL+(y``fGZ z%dcmRI0^`tzDVE;f%+0CU#y@nDD*|Bm`ck)zWNYT!7^NOr+Ck7fz6#ws9c3KY*7_L zRGn%Bg>5}*M$V@qMm8_bL|*bzDtYCmhmGSP?I!Q;A3ZQiH&a!{iDd1WiH;dEZB2pe zne?UA8fgU~oudt)8!nMgm8Txdr{$+KuuuZ5W&+8@-MJ>C{Ijgtyri}*R+@KLuiy#kxt)7G%HQ4mr%Ir407J~z}@vlL&D zr56a2OXnY#3sXj_6)!!%@z`y*^M&i1lje2(#bFfJF>JWVIN+1PAZ+mooiLJD z^-QGghFJhp6|bnb2bg*RM>H>~8Y^$*1xX91ayrK;hs;tEmMt_b=o6I~zl!h%r=m}1k#b?6$m1fp_p5cP4Y1tgkxCs@+-~tYqiAZq|>J<3WtTtk*7cKO{ zSG?V{GC(C3bq~DSEcn`W_K!=%{I>M`V`uN_q5bY`SOLK{8f$8+hpL^L*;Q_BYqB{o zMh6C9>$MQL%E(=8+9ITb>jBJ5Fxft6O4KM>8ARPk?K9WH~b1poKK+AixDv z)k&htWbgyA$>2l*usJu3^kpT=q!QrpMgR-)m_VaMaTP3d!un8nw6%gU5w*FIVk(M& zGzx;Zsc*Ro204jzVjb!%XIgw@$T0wHI*9wSFTA-+6=ijZnOb3brS15wkY>Z+HReNGB1**9dR zGM=|yM};5fd=#B+kwD;g0udmneh}uU$%rqT)ArTojTzN^$(}|3T}lc8KzR;f*R;*j&+ek<7d|v#Rm;fj^+NKW+7#1s z7q)+4;7oj(MxduKWG>gVEYOZ$!SlI18~!++jkC(Z*NN9o56ZIR|0Nkw(^_iNO{BT3O(o-Y?c7Oi#HCsp$W!8d?*Js4(OFS*W z+_NA&6!M?G_5Qi(X%w&v%~tjgG3)YSt_j7)O=VBHLVIiMgDu|tK`YBK;Q|!o-;CS& zJzwB!MoWY)Ca_Dv+_e;mD62xRG)X+CWRogUje#sa=cAsbP%Hum@e{fT=l;0jIUgT5 znsvUYpXI|m>q`1I94=}T94S=vyM&TIjg3mRRls)Ne#BP~#z+@<^QtG%sPhLn`&-}+KJoAPRjmTnwx``)G#e3fKO zncx$FQXEU?N#RkfQsdiFO<^`aXsm1L2qP7h&eI01d}h#5HYM*eD2Nyc2KiuHOqQL` z+ddB{^^NF3*}6^#&Zd$6rpwG?N-j$Bt096PdT^?e7WOBSgIH}olVzfqF22}O-AzP6 zuX@2nqtfgzKJJIFXzWp#7S!@hB^~{*A`hpY&YOmA>iqs{8--ah&QWQG;UTm0SiD=5 zEwu3cb6qbNDE_$$-=W>NJ=+o*AyHXt-Ws<5^akEL9BYe2emKQx2!t$@Rr;L*bnQblTT4bFvsorx<`jqgUe&(Wq``&Pu`A$mS++Q%sB#6sz3;0L49p;o&vN zfCKBCYfVVtDOkW3Ga+ZxSx)%2iCfGgcGWMyN4Y0%AT2koHF3h7980{VL~T-Glz5lDfscqyn#%s|Dy@=4evtYcvc zVIBvXju98l3(cIbhjeQYp45pWg&-b_h0!w$j(y%zv1A}h33Kb{z;A30&ins3>4IQpr?cF3ivvd@4+>>#AhR-4uQs7ye z(w@>mtx4jAEeqFgJzSP;z4W?ZVL>8ij-`z{xQ)u7ZX2X#oJ`K>`P5bn%6E0)eSO8B z_EeOF7KU^#<~fNtQjy0JAB`Qxishx!>tAMlxxUt!?v}~i(`4@bk&fX!GZ{@o#-Ti8 z-ZQhjy6x(!)jI9)aB;DfbR4E>})O-uBXuE_a?CyvZpG%=? zNXaONyDuXwIyN^dCOcLna`e~TUL=0HeNjO4>bEyXWKAzhj{P-ImV6Wo(Y2FX2CIoj zLSN&TH^zt~r8{HxK>R6i6f$^E%<`=CC=u(t1s7lo3{O=Ge^V0+VyqHtOaaO8Ml zS!EcV@2j8W|6fG|K|RN34W=NAVW6$&9^BJH9*o`=kvYz2{|-{4Qeed}MF=<&G|RMg zcgrCuod z(X4(VH>ydK&+)e%LF7CsKoQ}-3Y==Vv!qQlxfR5r<0$JoBJ&nb3)B#q485K-W3ae{=%OX1h(Gu)*SR!E*ZO74*0)Xr@U-FF z3%u02ZQ5TQ8y1%zuyp5zT3w+z(8NYa&dpHiiN9@R`+5U96K;Yk1NL10z(`JH?$Ms+ zZr>Cn4gBQ(zS?$;!I=n4i2*U0ijWeRsHz=$$DXx1!I!i>YH-6|7s-5lt$Fm4rsDr$ z+pPj6G;GcJZK5pvGi(0J(bPQdOH$aN`~JVzF5ts0}Qw zpcp!=)l#vv+FCoNJvN5mG8)qx#VI-^c|dA33Nu-nUIi^ues;KhxM8?sxVd#4@#(?d zp1qs*ZH_%j-;IpD!%Z#AfbUP#1AZ*C!GlpCEC7-t(HGp`DEDj5z7~0YeX*v3>@7k57e&IpYE3vj>XyqFGQQj1}Q~^*BqCL%c_)1mBFHR&50ruA<&&HQ`c?n0j zR(Q|8+~fr(W&I*D8=4_r5g&XXdN9z6s_By(eQ@M(O5pLTpu>ZQp*Y>^B5{cDO3k0= zaFnXP@HC(SJ7+oj4GEx~Q>YITPHP-y95}rH z{aH_3WL8#Gd1h2p_82K;9uR$Kd;OXcu9x|g!uSRUv554aAzaoyZFE=Dwd>8-uPqOF z^{~ayFWGbadpsqJ694_UCpliZsQa4JTSJNRW_uXD`saY6-u^z)#kA zF)Gu%>giB%`?`iYcEEjRz;c$9e5d+0IfZH+-onE# zCd?s15a%lV&fTu1X^`Jk=$_&r5bTw(&0oVFO-`)G(`{ri$HLy9wX?6ki(~co%c&%D zv4~eMGlH%%6<_GMxRo`IfGkSK=jek?nE`Ue`Ly-O$bA^RmZ~NAEZj}7tmuSD0PC3? z0Cpgh^N<}i`I`OS@6!nq#02%8Ds~jG6#0&L5%1&GvDtnY^~(1jvc3xDUyhwXCVTz% zM!iCgz~q^3U#MT_zNVr2IQh25bLiBRnuVEZ^VW06mh@%pE{wIatM9#58hIc{@YsD$ zTZn>uKqDqcd3np0caDwpCLp)qOIev<90K6W4pom+0n`(a=Z%r7$l1*}taH)7 zGm_Okdob#Mh&v8ry50b0JrB*zCs`P%hE?K%PxRkvM|26x`BKnBk@)xstkqMd2=3R` z;@X?Ffqxk#56&E}2cTbRt0lw&^Et*3F`1^CdsnSG#CR8YIDFhC?UA($(&+uqKHY!I zJF)2u8$*NjaZIHm|Kk7o{zJC+jNuSqQu6E}1!p0$p*;tf1SynxW606jWXx_3elyn{ z!?NH0mf9XsAhZb6Qiay=vsR&5ATSH9JTrKu`=Ai`9aetQZg$%lZkKV#^ealiSlf^&!U4ok<~vkWhW7@o&<)+%CF| z6fZEynxbVQV=7+|7ndhQ0q3Xk9%(rFF*I6a4lh0E9lKZeG(u6K<%KC7U7854NpQM6 zO{vr=%WUVuILXS0iM6{pgi65wh&8ruW<2j?tx5DGE>MUYUiOUDBR@Je&0j4(JZNKm zuVe+LA!@^*D{jUn8caJziC*{(h+?O-?G3#GE=7 z3@s33kvKO`wfl-<2$(v1P1VH&-~I_%ll6yIC(rAByzG` zYH~YOGLD+Op*A4hdnJ*Pi<}^7AU8-S+|7e)rn_Y&5{XMzHY2^}g6D!QUuY4erV1>= zIbTgqI&3(KLyA zYm&c(?q-`}s|!<0!CW)*a`q+g3+S>%-ZVwMUl%s{VNgnSq!te2R1dA`U>sn%mN{@b zsgj!%mV#eCfn>xOs7ET7v5+7R5V~{h$lo?v5~Tq6Aq6v#Lt+FopR#9`$wo>gE_vBZ z>)eZ;i`D|1Yfm z9gMwkO6zlt_e29t^R-12Lu<$IR(R+7%&PpjGdLYP+m*Y$$G=~eIPIdy zt7z{#g^`$|2fUri(tRjhN%d>beE<2_HM@wBC>^t@L=>9wPQGEs9hQQ(+AT}voA|o_ zUG=+bmbX?OeX+kNzIk9*h@OD2QU3U-p=RT<2Tm?9snYPHA~H9Z&zSzFA*L^owuVhYkD)((C#830K{Eo@=UWZNm;aKN(9(=hSa?Qub+m0RgF zi=AC!#NMz?cxr(ULd*FYuAUg_JlnsfCx}*VLVnJfA4%sL0TqYkcl8a8L9fv|^M?mJ z3!bR8$unycfM^oLuMBk85O$E6DR{zjaf9oF$%_|}gX{I!$ynb-%p=$jQ(dXG%XUNp z0NDOhg}wq?0Bo0ODcA~NyF}|AHypplbF%;)2JHp-Xt(V?^kICVenr8DyKcL~sAms> zwt!P~YgW|^*JQ=o!Rcvmeb?V$Vg>K2el#>L`+OU;$;b z!9!>~FF#2%-l0S62JEY4Syp+iQJR)*(Lw-=C5AG^B>kbyQyLU$%2;BASd=jtV8&S6 z)*-dFD`pk4a<$;bto7$!?+O?t`wOqshh5W@@Vm~Ms?yVOzgolzWhqNV+VcHN#m!m@ zCJtiO%+b}!%~xCrM=EKcxOvE%BHB_w86Zj(arvP{<*MxpK*j2?vQq53mWuoDIxC$9 zb0s8wHw=Yd#K_vxTwNvGWP-&GR|hFd=SWO5M=YA1;LIXYN0_Vf>zGwrb+%@}d|#tW zbvm^vIa%}vhpKaJCY{f<2@2rA$^f_EBMd60qe2rR9G1*thB?S6SmY+G_@1Icn%pjK z&Js;s&8N8NJm|ziKrJw~QYfvhVg}EB;l=B*;1H+h<8d-}9Uh6OmeEf?`@&LD6JYI5 zZF7o2rG=b6m3ERi@IBWu8_{K8QYvx^>JdIdq+KD#8dvWRrR0?NDygx(R0fuyaCImH z2j7D3TyyQ~IQ=GpqjOPc%2t~k2XinM-MZ0}C3aE~=?;A4ECO)d)o+w+SA4pt%DNYe zNR`!~D2>?JYZeBrs-);K->+#F2vuxuiS}Kr_D@?Fyyn5Y?)yH&fSv zK)h+=*evFxM4eWnRw)$;wb*S$xKP03G6Sh>8XFHlBh~1JJ=wEJy6ZTpWhFRBhFk{3 z47qu?Th%`$ml>c25D^()aTo{%37-H&gO-N>7yyQ$gWr2#(0?H4f#5Gbdh4beOacOW zUIW5W5i#&=n*@e2B0zAymB_cL%Ak=#nZe8%Ip!HDmYB+vwlt+}rZk<>bS44VvC^@L z4_dESZ$ht9dSODSCDe(B)l2mWvCq=RatQ}~4R<^i95;{arf>gIRCGpZUkI{_9BXAy zz-_l|r>%>{M=AKXA8vW&wk~!-pI$xAI31LafbZtjR_f5EQJt}-hSohuiU&(^RtUae zObiAKpjccg3V(YSs5F1NYRT>E=$-F(`gCmdM_oeg?mQ&=<6p7BL>%;shUfqNK3~1% z>@W@(t#i2{apE>rX`#A#wJD}il<8wP#t!Qp4AMSho>Sb$-QhIUR z?|hH6jpm_@_@KEFa*vZ;t?))R#Rl21S;oumKekX~Whx_y$gQw|BNt24l(m)MHitB& zxp+MWfTe|amdwnF7>s0XGc6iu+%fM00Lb7Y40RI~neKK6X8H^)WOSbQCEv63Uz39g z^oFI&yYSxdMuGx3Xq`?~!05p{2Z&vWzIX|Q-Dn^f0EmF=2=WjpKma}mi22L`hy~CM z6qWsc3omVFR4raNV90@aN+%x-oed5`&Vf-N875u3xw;c}4H?QbzGU|Vb1n9z9HD;y zE4&H5h9L%vW17UkCdk8|J0(Bdi~a4zH6QFAIpk~ez4rW=9={IWoQ;tKfU)(`JTH^8^YKn7n{)7PCImNYKiYw*r#%_ zg&H-O<~g=p^JE*I;PHm;c9%Qd<`(zE#)Fq=PKYo;f z6KoI^UWK)NYek%cxv5i3X7(%=NEk;}0!fj^H?-3+9(u8erQS%GP{kd=NQtn&Ao5FU zn&Qt58{?5ALPTN}Q&#u=OaIJKl!J!E-rH2AxU2H?W#tvJ=9!~N5|`vtE8WCxf(5ZK zA%rbdMAuN2yAhQOa#56a19RpXniBL48=%(jQOIJdBPH+q?{BlSbTy%2YR0e=OhqYU zYRyA({u^&~>D=2ZRu8s$_No=j*Vj~*mmasz@}FhQvQ55`mC20_>1)e_`xjPHA~;|I zSTSu7)EOpSqYg50Fp3_x34)v?k5Kg??(GUGg&`r-uo_kf_uF2~)l9aGhDq3gZDZ6T zy3%dCfiIl#3o<@Rr0@<(`Z|$q;D>hZ8?nsXX1MwcjXEPT&S2oo&XB^)!6a#hWSNnX zd%Fkq`nGws-SgWPw=Zt=)V9uRt*M^1F*wlHs+3-wiVD@PBTXB?pqaJV5~aj~Sks0d#!j6B6FR*b zn9ys~z=V=(U_$QJPEW9I+qHHYfDLMD>evU}Ww?97x;!85UN*LE(}YnY3nhw{cFImq zPQN2mu6HprJyYV;XPWu!Q69W#ewfG6FE3q~9~su)baggAYkAhxSXG(3&M!t6y)??= ztQ)g#D)ik;MQlk)+bxLRlaylwcP41bHfTs3xJ^}ZcMUq}pal=Mf%_JWL?TA^!9LL= zN(g0*Qo=f+gq!3dFV*_{)ISJKiCN|-8xH!tZW@KYZ6;RIq10*|AUG2F=fx@GT>rK3 z-sLuf`HO}PFdM9iId;q3%rnt{Sm#%uoPd>|1+)+Nx#%C<1(gK!z(sF^L;Cnr%r`z!f7D z;TmL13=FHoBAKa#@d}s(ql)YltB0w-9yawKLQPYm^BDk)FMGP08lPTgTysytkv^^Y z&ZXiSfIw(6!u>!V7^$zNcc@W^rB=Pj;}S)k6bqMC4;1$66_kVylgQDeE-2WO=(`!> zYHg<03*OgTQi&TnwR1h%E~4DoHaBarQf(T5ExK&GW7wy#pBgQqcQ`00RmupGe|bmR=A2$XpM7TA^j`$W)e4AJKTY$$%&GQC%ZqgcE8|%|)we>n5d8 zYZ$fBupCkQyircK*-9Sg8N|)4>dM0XYB`@}?;pI^@bm!ZY*FAT!6$Y15-n6nZKM$V&ME>=)`Q_~`Eoy2-dC3XHikS@?WL9lVI6iV$ zFPVhTz1{6-19SMyjYikgRry-Z93uC^#_P}+}mql%$A4#;y-cq%Ei93 zr?;i6R<2m8t(1IW2><~Q_*C`pP1p0#za_N(9suyYm-m;)u`B=n{4NU8MJq`4Ko;#P z>CoTDz(+ctH)5yQkV~(>WX>b6RG)DwkEBJk1HpOgo(bIDTql~)_kgCZDB=4ckx+ty zh<;F!up3#;;h>|z>0m&@eS-x{q}B%WMpE6)^7sYQK#=HZ2?{!RUr^Dr6Ou)TkM&h3cK}(L=Xs{qk+7IBwvC^S3#=C^Bqc+dX6W%x8r-3O#<>W4nJ?{5MBD% zAr)}xY0so9u-J`CQ{4LN9!yABUhGEBTo#cUR5*Iko{CUubOuHyW)?PVS=nKiJh)^Un8hDh}Y6H8p3uIyf>MU70!K)u}$?#>#+Yb9QQ#Z)17#?7+g%fXM=1qcj9u zOnU01ow-@&%v)1S1HIPa_8KM2dE7MYo@}-wC!5P%#BNhgH(wdQN!Tv+_gk6MjF(63 zq-RddSw1ZA4vo*!m(5#KPZn!D)hBg}wLEUJ+Q+0sd3-RvMXc|`RyGfPx0vHq@9WJ! zfmZW?6q1KtmMug0t)kmMEazN5lcmzvhqgn23t#9xYTwDXJT^g_73Sl2K&=+2ICC@Q zM-e8!M+dpENB@*>07MP}-V+LE#q#GdzV3E4@yO$$hO795sfc93dbcQ;XkE3n> SXoc;WFL3*Wy!n$LECUGU0X4P& From e6bc71ee337689dc72d96e4cd5bd4b123c119cd9 Mon Sep 17 00:00:00 2001 From: Bernat Date: Thu, 13 Sep 2018 11:08:31 +0200 Subject: [PATCH 23/34] update fixtures table packaging --- .../changes/1.1.0/{ticketGetTax.sql => 01-ticketGetTax.sql} | 0 services/db/install/dump/fixtures.sql | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename services/db/install/changes/1.1.0/{ticketGetTax.sql => 01-ticketGetTax.sql} (100%) diff --git a/services/db/install/changes/1.1.0/ticketGetTax.sql b/services/db/install/changes/1.1.0/01-ticketGetTax.sql similarity index 100% rename from services/db/install/changes/1.1.0/ticketGetTax.sql rename to services/db/install/changes/1.1.0/01-ticketGetTax.sql diff --git a/services/db/install/dump/fixtures.sql b/services/db/install/dump/fixtures.sql index 7e8a25d09..956e29971 100644 --- a/services/db/install/dump/fixtures.sql +++ b/services/db/install/dump/fixtures.sql @@ -507,13 +507,13 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack VALUES (1, 0.00, 10, 10, 0, 0, CURDATE(), 1, 1.50), (2, 100.00, 20, 20, 0, 0, CURDATE(), 2, 1.00), - ('a', 50.00, 30, 30, 0, 1, CURDATE(), 3, 0.00); + (3, 50.00, 30, 30, 0, 1, CURDATE(), 71, 0.00); INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`) VALUES ( 1, 1, 1, 2, CURDATE(), NULL), ( 2, 2, 2, 1, CURDATE(), NULL), - ( 3, 3, 'a', 4, CURDATE(), NULL); + ( 3, 3, 3, 4, CURDATE(), NULL); INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `price`, `discount`, `reserved`, `isPicked`, `created`) VALUES From 094a6eda68ae5e903f1aa32b72ca182ea0b4b86a Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 11:27:38 +0200 Subject: [PATCH 24/34] Bug #644 Crear componente Input Number --- client/core/src/components/index.js | 1 + .../src/components/input-number/index.html | 42 +++++ .../core/src/components/input-number/index.js | 104 ++++++++++++ .../src/components/input-number/index.spec.js | 160 ++++++++++++++++++ .../src/components/input-number/style.scss | 21 +++ .../src/components/textfield/textfield.js | 4 +- 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 client/core/src/components/input-number/index.html create mode 100644 client/core/src/components/input-number/index.js create mode 100644 client/core/src/components/input-number/index.spec.js create mode 100644 client/core/src/components/input-number/style.scss diff --git a/client/core/src/components/index.js b/client/core/src/components/index.js index dbba202d0..6ca4fd0e5 100644 --- a/client/core/src/components/index.js +++ b/client/core/src/components/index.js @@ -40,3 +40,4 @@ import './table'; import './th'; import './input-range'; import './chip'; +import './input-number'; diff --git a/client/core/src/components/input-number/index.html b/client/core/src/components/input-number/index.html new file mode 100644 index 000000000..1eb20fda3 --- /dev/null +++ b/client/core/src/components/input-number/index.html @@ -0,0 +1,42 @@ +
+
+
+ + +
+
+ + +
+
+
+
+ + + + info_outline + +
+
+
+
diff --git a/client/core/src/components/input-number/index.js b/client/core/src/components/input-number/index.js new file mode 100644 index 000000000..e344abd88 --- /dev/null +++ b/client/core/src/components/input-number/index.js @@ -0,0 +1,104 @@ +import ngModule from '../../module'; +import Textfield from '../textfield/textfield'; +import './style.scss'; + +export default class InputNumber extends Textfield { + + constructor($element, $scope, $attrs, vnTemplate, $transclude) { + super($element, $scope, $attrs, vnTemplate, $transclude); + + this.input.addEventListener('change', () => { + this.validateValue(); + }); + } + + get value() { + return this._value; + } + + set value(value) { + this._value = value; + this.hasValue = this._value !== null; + + if (this.hasValue) this.element.classList.add('not-empty'); + else this.element.classList.remove('not-empty'); + + this.element.querySelector('.infix').classList.remove('invalid', 'validated'); + } + + get max() { + return this.input.max; + } + + set max(value) { + if (value) + this.input.max = value; + } + + get min() { + return this.input.min; + } + + set min(value) { + if (!value) value = 0; + this.input.min = value; + } + + get step() { + return parseInt(this.input.step); + } + + set step(value) { + this.input.step = value; + } + + validateValue() { + if ((this.validate() !== undefined && !this.validate()) || + (this.max && this.value > this.max) || + (this.min && this.value < this.min) || + (this.step && this.value % this.step != 0)) { + this.$element[0].querySelector('.infix').classList.add('invalid', 'validated'); + } + + if (this.onChange) + this.onChange(); + } + + add() { + if (this.step && this.value % this.step != 0) { + this.value += (this.step - this.value % this.step); + } else { + this.value += this.step; + } + + this.validateValue(); + } + + remove() { + if (this.step && this.value % this.step != 0) { + this.value -= (this.step + this.value % this.step); + } else { + this.value -= this.step; + } + this.validateValue(); + } +} + +InputNumber.$inject = ['$element', '$scope', '$attrs', 'vnTemplate', '$transclude']; + +ngModule.component('vnInputNumber', { + template: require('./index.html'), + controller: InputNumber, + bindings: { + label: '@?', + disabled: ' { + let $componentController; + let $scope; + let $attrs; + let $timeout; + let $element; + let controller; + + beforeEach(() => { + angular.mock.module('claim'); + }); + + beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => { + $componentController = _$componentController_; + $scope = $rootScope.$new(); + $attrs = {}; + $timeout = _$timeout_; + $element = angular.element('
'); + controller = $componentController('vnInputNumber', {$element, $scope, $attrs, $timeout, $transclude: () => {}}); + })); + + describe('value() setter', () => { + it(`should set _value to a given value, add the class not-empty and remove invalid and validated`, () => { + controller.value = 'pepino'; + let classes = controller.element.classList.toString(); + + expect(classes).toContain('not-empty'); + expect(controller._value).toEqual('pepino'); + + classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).not.toContain('invalid validated'); + }); + + it(`should set _value to a given value and not add the class not-empty if the given value is null`, () => { + controller.value = null; + let classes = controller.element.classList.toString(); + + expect(classes).not.toContain('not-empty'); + expect(controller._value).toEqual(null); + }); + }); + + describe('max() setter', () => { + it(`should set input.max to a given value`, () => { + controller.max = 10; + + expect(controller.input.max).toEqual('10'); + }); + }); + + describe('min() setter', () => { + it(`should set input.min if theres a given value`, () => { + controller.min = 1; + + expect(controller.input.min).toEqual('1'); + }); + + it(`should set input.min to 0 if theres not a given value`, () => { + controller.min = null; + + expect(controller.input.min).toEqual('0'); + }); + }); + + describe('step() setter/getter', () => { + it(`should set input.step to a given value`, () => { + controller.step = 50; + + expect(controller.input.step).toEqual('50'); + }); + + it(`should return a number`, () => { + controller.step = 50; + + expect(controller.step).toEqual(50); + expect(typeof controller.step).toEqual('number'); + }); + }); + + describe('validateValue()', () => { + it(`should add the classes invalid and validated if the value is less than min`, () => { + controller.validate = () => {}; + controller.min = 0; + controller.value = -7; + let classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).not.toContain('invalid validated'); + expect(controller.value).toEqual(-7); + + controller.validateValue(); + classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).toContain('infix invalid validated'); + }); + + it(`should add the classes invalid and validated if the value is greater than max`, () => { + controller.validate = () => {}; + controller.max = 10; + controller.value = 15; + let classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).not.toContain('invalid validated'); + expect(controller.value).toEqual(15); + + controller.validateValue(); + classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).toContain('infix invalid validated'); + }); + + it(`should add the classes invalid and validated if the value is not a valid step`, () => { + controller.validate = () => {}; + controller.step = 5; + controller.value = 7; + let classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).not.toContain('invalid validated'); + expect(controller.value).toEqual(7); + + controller.validateValue(); + classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).toContain('infix invalid validated'); + }); + + it(`should add the classes invalid and validated if the function validate returns false`, () => { + controller.validate = () => { + return false; + }; + controller.step = 5; + controller.value = 7; + let classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).not.toContain('invalid validated'); + expect(controller.value).toEqual(7); + + controller.validateValue(); + classes = controller.element.querySelector('.infix').classList.toString(); + + expect(classes).toContain('infix invalid validated'); + }); + }); + + describe('add()', () => { + it(`should set value to the next possible step and call validateValue`, () => { + spyOn(controller, 'validateValue'); + + controller.step = 50; + controller.value = -1; + + controller.remove(); + + expect(controller.value).toEqual(-50); + expect(controller.validateValue).toHaveBeenCalledWith(); + }); + }); +}); diff --git a/client/core/src/components/input-number/style.scss b/client/core/src/components/input-number/style.scss new file mode 100644 index 000000000..2b7749d26 --- /dev/null +++ b/client/core/src/components/input-number/style.scss @@ -0,0 +1,21 @@ +@import 'colors'; +@import '../textfield/style.scss'; + +vn-input-number { + @extend vn-textfield; + input { + text-align: center!important; + } + vn-icon[icon=add], + vn-icon[icon=remove]{ + &:not(:hover){ + color: $secondary-font-color; + } + i { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + } + } +} \ No newline at end of file diff --git a/client/core/src/components/textfield/textfield.js b/client/core/src/components/textfield/textfield.js index 64b91faa0..3817ab0d5 100644 --- a/client/core/src/components/textfield/textfield.js +++ b/client/core/src/components/textfield/textfield.js @@ -81,6 +81,7 @@ export default class Textfield extends Input { clear() { this.saveOldValue(); this.value = null; + if (this.onClear) this.onClear(); this.input.focus(); } } @@ -102,6 +103,7 @@ ngModule.component('vnTextfield', { rule: '@?', type: '@?', vnTabIndex: '@?', - onChange: '&' + onChange: '&', + onClear: '&' } }); From 7638881c541a0de6f886d4649a5cb64c897a322d Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Thu, 13 Sep 2018 11:29:21 +0200 Subject: [PATCH 25/34] corrected description --- e2e/paths/item-module/06_create_item_botanical.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/item-module/06_create_item_botanical.spec.js b/e2e/paths/item-module/06_create_item_botanical.spec.js index c06376365..1bc3dfa39 100644 --- a/e2e/paths/item-module/06_create_item_botanical.spec.js +++ b/e2e/paths/item-module/06_create_item_botanical.spec.js @@ -20,7 +20,7 @@ describe('Item', () => { }); }); - it('should search for the item Gem of Time', () => { + it('should search for the item Mjolnir', () => { return nightmare .wait(selectors.itemsIndex.searchResult) .type(selectors.itemsIndex.searchItemInput, 'Mjolnir') From b2b2c71117e6871e5c7185a15fd30ded5d399424 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Thu, 13 Sep 2018 11:29:53 +0200 Subject: [PATCH 26/34] #640 Ticket Create packages path is excluded --- e2e/paths/ticket-module/04_create_ticket_packages.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js index f9f36f424..0966f8e7e 100644 --- a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js +++ b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js @@ -95,7 +95,7 @@ describe('Ticket Create packages path', () => { return nightmare .waitToClick(selectors.ticketPackages.firstPackageSelect) .waitToClick(selectors.ticketPackages.firstPackageSelectOptionThree) - .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'Iron Patriot') + .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'ShippingCost') .click(selectors.ticketPackages.savePackagesButton) .waitForLastSnackbar() .then(result => { @@ -108,10 +108,10 @@ describe('Ticket Create packages path', () => { .click(selectors.ticketSales.saleButton) .wait(selectors.ticketSales.firstPackageSelect) .click(selectors.ticketPackages.packagesButton) - .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'Iron Patriot') + .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'ShippingCost') .getInputValue(selectors.ticketPackages.firstPackageSelect) .then(result => { - expect(result).toEqual('Iron Patriot'); + expect(result).toEqual('ShippingCost'); }); }); From 24f89156e4f208fa7003ce17f261f7a503e660f3 Mon Sep 17 00:00:00 2001 From: Bernat Date: Thu, 13 Sep 2018 12:32:33 +0200 Subject: [PATCH 27/34] update fixtures, fix test and selectors --- e2e/helpers/selectors.js | 6 ++-- .../02_edit_item_basic_data.spec.js | 2 +- .../08_item_create_and_clone.spec.js | 2 +- .../04_create_ticket_packages.spec.js | 10 +++--- services/db/install/dump/fixtures.sql | 34 ++++++++++--------- .../packaging/specs/listPackaging.spec.js | 2 +- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 571493ed4..1e238b2c0 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -167,7 +167,7 @@ export default { itemCreateView: { name: `${components.vnTextfield}[name="name"]`, typeSelect: `vn-autocomplete[field="$ctrl.item.typeFk"] input`, - typeSelectOptionOne: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`, + typeSelectOptionThree: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(3)`, intrastatSelect: `vn-autocomplete[field="$ctrl.item.intrastatFk"] input`, intrastatSelectOptionOne: `vn-autocomplete[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(2)`, originSelect: `vn-autocomplete[field="$ctrl.item.originFk"] input`, @@ -180,7 +180,7 @@ export default { goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]', basicDataButton: `vn-menu-item a[ui-sref="item.card.data"]`, typeSelect: `vn-autocomplete[field="$ctrl.item.typeFk"] input`, - typeSelectOptionTwo: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`, + typeSelectOptionThree: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(3)`, intrastatSelect: `vn-autocomplete[field="$ctrl.item.intrastatFk"] input`, intrastatSelectOptionOne: `vn-autocomplete[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(1)`, nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`, @@ -297,7 +297,7 @@ export default { ticketPackages: { packagesButton: `vn-menu-item a[ui-sref="ticket.card.package.index"]`, firstPackageSelect: `vn-autocomplete[label="Package"] > div > div > input`, - firstPackageSelectOptionThree: `vn-autocomplete[label="Package"] vn-drop-down ul > li:nth-child(3)`, + firstPackageSelectOptionTwo: `vn-autocomplete[label="Package"] vn-drop-down ul > li:nth-child(2)`, firstQuantityInput: `vn-textfield[label="Quantity"] input`, firstRemovePackageButton: `vn-icon[vn-tooltip="Remove package"]`, addPackageButton: `vn-icon-button[vn-tooltip="Add package"]`, diff --git a/e2e/paths/item-module/02_edit_item_basic_data.spec.js b/e2e/paths/item-module/02_edit_item_basic_data.spec.js index 3a1bde0b1..f0361aa9c 100644 --- a/e2e/paths/item-module/02_edit_item_basic_data.spec.js +++ b/e2e/paths/item-module/02_edit_item_basic_data.spec.js @@ -49,7 +49,7 @@ describe('Item', () => { .clearInput(selectors.itemBasicData.nameInput) .type(selectors.itemBasicData.nameInput, 'Rose of Purity') .waitToClick(selectors.itemBasicData.typeSelect) - .waitToClick(selectors.itemBasicData.typeSelectOptionTwo) + .waitToClick(selectors.itemBasicData.typeSelectOptionThree) .waitToClick(selectors.itemBasicData.intrastatSelect) .waitToClick(selectors.itemBasicData.intrastatSelectOptionOne) .clearInput(selectors.itemBasicData.relevancyInput) diff --git a/e2e/paths/item-module/08_item_create_and_clone.spec.js b/e2e/paths/item-module/08_item_create_and_clone.spec.js index 706977ac9..b74e65a18 100644 --- a/e2e/paths/item-module/08_item_create_and_clone.spec.js +++ b/e2e/paths/item-module/08_item_create_and_clone.spec.js @@ -65,7 +65,7 @@ describe('Item', () => { return nightmare .type(selectors.itemCreateView.name, 'Infinity Gauntlet') .waitToClick(selectors.itemCreateView.typeSelect) - .waitToClick(selectors.itemCreateView.typeSelectOptionOne) + .waitToClick(selectors.itemCreateView.typeSelectOptionThree) .waitToClick(selectors.itemCreateView.intrastatSelect) .waitToClick(selectors.itemCreateView.intrastatSelectOptionOne) .waitToClick(selectors.itemCreateView.originSelect) diff --git a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js index 0966f8e7e..916d7bf48 100644 --- a/e2e/paths/ticket-module/04_create_ticket_packages.spec.js +++ b/e2e/paths/ticket-module/04_create_ticket_packages.spec.js @@ -50,7 +50,7 @@ describe('Ticket Create packages path', () => { .waitToClick(selectors.ticketPackages.firstRemovePackageButton) .waitToClick(selectors.ticketPackages.addPackageButton) .waitToClick(selectors.ticketPackages.firstPackageSelect) - .waitToClick(selectors.ticketPackages.firstPackageSelectOptionThree) + .waitToClick(selectors.ticketPackages.firstPackageSelectOptionTwo) .click(selectors.ticketPackages.savePackagesButton) .waitForLastSnackbar() .then(result => { @@ -94,8 +94,8 @@ describe('Ticket Create packages path', () => { it(`should create a new package with correct data`, () => { return nightmare .waitToClick(selectors.ticketPackages.firstPackageSelect) - .waitToClick(selectors.ticketPackages.firstPackageSelectOptionThree) - .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'ShippingCost') + .waitToClick(selectors.ticketPackages.firstPackageSelectOptionTwo) + .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'Legendary Box') .click(selectors.ticketPackages.savePackagesButton) .waitForLastSnackbar() .then(result => { @@ -108,10 +108,10 @@ describe('Ticket Create packages path', () => { .click(selectors.ticketSales.saleButton) .wait(selectors.ticketSales.firstPackageSelect) .click(selectors.ticketPackages.packagesButton) - .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'ShippingCost') + .waitForTextInInput(selectors.ticketPackages.firstPackageSelect, 'Legendary Box') .getInputValue(selectors.ticketPackages.firstPackageSelect) .then(result => { - expect(result).toEqual('ShippingCost'); + expect(result).toEqual('Legendary Box'); }); }); diff --git a/services/db/install/dump/fixtures.sql b/services/db/install/dump/fixtures.sql index 956e29971..4cc87d81d 100644 --- a/services/db/install/dump/fixtures.sql +++ b/services/db/install/dump/fixtures.sql @@ -441,10 +441,11 @@ INSERT INTO `vn`.`itemCategory`(`id`, `name`, `display`, `color`, `icon`) INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk`, `isPackaging`) VALUES - (1, 'CRI', 'Crisantemo' , 2, 31, 5, 0), - (2, 'ITG', 'Anthurium' , 1, 31, 5, 0), - (3, 'WPN', 'Paniculata' , 2, 31, 5, 0), - (4, 'PRT', 'Delivery ports', 3, 31, 5, 1); + (1, 'CRI', 'Crisantemo', 2, 31, 5, 0), + (2, 'ITG', 'Anthurium', 1, 31, 5, 0), + (3, 'WPN', 'Paniculata', 2, 31, 5, 0), + (4, 'PRT', 'Delivery ports', 3, NULL, 5, 1), + (5, 'CON', 'Container', 3, NULL, 5, 1); INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`) VALUES @@ -487,12 +488,14 @@ INSERT INTO `vn`.`intrastat`(`id`, `description`, `taxClassFk`, `taxCodeFk`) INSERT INTO `vn`.`item`(`id`, `name`,`typeFk`,`size`,`inkFk`,`category`,`stems`,`originFk`,`description`,`producerFk`,`intrastatFk`,`isOnOffer`,`expenceFk`,`isBargain`,`comment`,`relevancy`,`image`,`taxClassFk`,`longName`,`subName`,`tag5`,`value5`,`tag6`,`value6`,`tag7`,`value7`,`tag8`,`value8`) VALUES - (1 , 'Gem of Time', 2, 70, 'AMA', 'EXT', 1 , 1, 'One of the infinity gems' , 1 , 06021010, 0, 2000000000, 0, NULL, 0, 66540, 1, 'Gem of Time' , NULL, 'Medida', '70', 'Color', 'Amarillo' , 'Categoria', 'EXT', 'Tallos', '1'), - (2 , 'Gem of Mind', 2, 70, 'AZL', 'EXT', 1 , 2, 'One of the infinity gems' , 1 , 06021010, 0, 2000000000, 0, NULL, 0, 65540, 1, 'Gem of Mind' , NULL, 'Medida', '70', 'Color', 'Azul' , 'Categoria', 'EXT', 'Tallos', '1'), - (3 , 'Iron Patriot', 1, 60, 'AMR', 'EXT', 1 , 3, 'Rhodeys armor' , 1 , 05080000, 0, 4751000000, 0, NULL, 0, 61692, 1, 'Iron Patriot', NULL, 'Medida', '60', 'Color', 'Rosa/Amarillo', 'Categoria', 'EXT', 'Tallos', '1'), - (4 , 'Mark I', 1, 60, 'AMR', 'EXT', 1 , 1, 'Iron Mans first armor' , 1 , 05080000, 1, 4751000000, 0, NULL, 0, 66090, 2, 'Mark I' , NULL, 'Medida', '60', 'Color', 'Rosa/Amarillo', 'Categoria', 'EXT', 'Tallos', '1'), - (5 , 'Mjolnir', 3, 30, 'AZL', 'EXT', 1 , 2, 'Thors hammer!' , 2 , 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, 'Mjolnir' , NULL, 'Medida', '30', 'Color', 'Azul' , 'Categoria', 'EXT', 'Tallos', '1'), - (71, 'ShippingCost', 4, NULL, NULL, NULL, NULL, 1, NULL , NULL, 06021010, 1, 4751000000, 0, NULL, 0, NULL, 2, 'ShippingCost', NULL, NULL , NULL, NULL , NULL , NULL, NULL , NULL , NULL); + (1 , 'Gem of Time', 2, 70, 'AMA', 'EXT', 1 , 1, 'One of the infinity gems', 1, 06021010, 0, 2000000000, 0, NULL, 0, 66540, 1, 'Gem of Time', NULL, 'Medida', '70', 'Color', 'Amarillo' , 'Categoria', 'EXT', 'Tallos', '1'), + (2 , 'Gem of Mind', 2, 70, 'AZL', 'EXT', 1 , 2, 'One of the infinity gems', 1, 06021010, 0, 2000000000, 0, NULL, 0, 65540, 1, 'Gem of Mind', NULL, 'Medida', '70', 'Color', 'Azul' , 'Categoria', 'EXT', 'Tallos', '1'), + (3 , 'Iron Patriot', 1, 60, 'AMR', 'EXT', 1 , 3, 'Rhodeys armor', 1, 05080000, 0, 4751000000, 0, NULL, 0, 61692, 1, 'Iron Patriot', NULL, 'Medida', '60', 'Color', 'Rosa/Amarillo', 'Categoria', 'EXT', 'Tallos', '1'), + (4 , 'Mark I', 1, 60, 'AMR', 'EXT', 1 , 1, 'Iron Mans first armor', 1, 05080000, 1, 4751000000, 0, NULL, 0, 66090, 2, 'Mark I', NULL, 'Medida', '60', 'Color', 'Rosa/Amarillo', 'Categoria', 'EXT', 'Tallos', '1'), + (5 , 'Mjolnir', 3, 30, 'GRE', 'EXT', 1 , 2, 'Thors hammer!', 2, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, 'Mjolnir', NULL, 'Medida', '30', 'Color', 'Azul' , 'Categoria', 'EXT', 'Tallos', '1'), + (6 , 'Broken Box', 5, 30, 'GRE', 'EXT', 1 , 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, 'Legendary Box', NULL, 'Medida', '30', 'Color', 'Gris' , NULL, NULL, NULL, NULL), + (7 , 'Legendary Box', 5, 90, 'AZL', 'EXT', 1 , 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, 'Broken Box', NULL, 'Medida', '90', 'Color', 'Gris' , NULL, NULL, NULL, NULL), + (71, 'ShippingCost', 4, NULL, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, NULL, 2, 'ShippingCost', NULL, NULL , NULL, NULL , NULL , NULL, NULL, NULL, NULL); INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`) VALUES @@ -505,15 +508,14 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `create INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`) VALUES - (1, 0.00, 10, 10, 0, 0, CURDATE(), 1, 1.50), - (2, 100.00, 20, 20, 0, 0, CURDATE(), 2, 1.00), - (3, 50.00, 30, 30, 0, 1, CURDATE(), 71, 0.00); + (1, 0.00, 10, 10, 0, 0, CURDATE(), 6, 1.50), + (2, 100.00, 20, 20, 0, 0, CURDATE(), 7, 1.00); INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`) VALUES - ( 1, 1, 1, 2, CURDATE(), NULL), - ( 2, 2, 2, 1, CURDATE(), NULL), - ( 3, 3, 3, 4, CURDATE(), NULL); + ( 1, 1, 2, 2, CURDATE(), NULL), + ( 2, 2, 2, 1, CURDATE(), NULL), + ( 3, 3, 2, 4, CURDATE(), NULL); INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `price`, `discount`, `reserved`, `isPicked`, `created`) VALUES diff --git a/services/ticket/common/methods/packaging/specs/listPackaging.spec.js b/services/ticket/common/methods/packaging/specs/listPackaging.spec.js index 3b503d833..36530e36e 100644 --- a/services/ticket/common/methods/packaging/specs/listPackaging.spec.js +++ b/services/ticket/common/methods/packaging/specs/listPackaging.spec.js @@ -6,7 +6,7 @@ describe('ticket listPackaging()', () => { let response = await app.models.Packaging.listPackaging(filter); expect(response[0].name).toBeDefined(); - expect(response[0].name).toEqual('Gem of Time'); + expect(response[0].name).toEqual('Broken Box'); }); }); From fe80a6b8c842c0d6a666c794ca4eedf9bb37235c Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 12:36:52 +0200 Subject: [PATCH 28/34] Bug #651 Al borrar un ticket no se cambia su estado a eliminado --- services/loopback/common/methods/ticket/deleted.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/services/loopback/common/methods/ticket/deleted.js b/services/loopback/common/methods/ticket/deleted.js index 36bffaf95..2636963a8 100644 --- a/services/loopback/common/methods/ticket/deleted.js +++ b/services/loopback/common/methods/ticket/deleted.js @@ -1,5 +1,5 @@ module.exports = Self => { - Self.remoteMethod('deleted', { + Self.remoteMethodCtx('deleted', { description: 'Sets the isDeleted value of a ticket to 1', accessType: '', accepts: [{ @@ -19,7 +19,15 @@ module.exports = Self => { } }); - Self.deleted = async params => { - return await Self.app.models.Ticket.update({id: params.id}, {isDeleted: '1'}); + Self.deleted = async(ctx, params) => { + await Self.app.models.Ticket.update({id: params.id}, {isDeleted: '1'}); + + if (ctx.req.accessToken) { + let token = ctx.req.accessToken; + let currentUserId = token && token.userId; + let worker = await Self.app.models.Worker.findOne({where: {userFk: currentUserId}}); + params.workerFk = worker.id; + } + return await Self.app.models.TicketTracking.create({ticketFk: params.id, stateFk: 17, workerFk: params.workerFk}); }; }; From a2506a787e201ce14b968f54fe0b058aac07a0d9 Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 12:39:56 +0200 Subject: [PATCH 29/34] updated description --- services/loopback/common/methods/sale/moveToTicket.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/loopback/common/methods/sale/moveToTicket.js b/services/loopback/common/methods/sale/moveToTicket.js index 9f6a47d70..254ad859e 100644 --- a/services/loopback/common/methods/sale/moveToTicket.js +++ b/services/loopback/common/methods/sale/moveToTicket.js @@ -2,7 +2,7 @@ let UserError = require('../../helpers').UserError; module.exports = Self => { Self.remoteMethod('moveToTicket', { - description: 'Change the state of a ticket', + description: 'Moves a line to a given ticket', accessType: '', accepts: [{ arg: 'params', From 1e3b3b0ffaa247a990fbe297a0297e308eb60eea Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 12:46:32 +0200 Subject: [PATCH 30/34] Tarea #644 Crear componente Input Number --- client/salix/src/styles/misc.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/salix/src/styles/misc.scss b/client/salix/src/styles/misc.scss index bb722f87b..7e3619cf1 100644 --- a/client/salix/src/styles/misc.scss +++ b/client/salix/src/styles/misc.scss @@ -17,6 +17,12 @@ input[type=reset]::-moz-focus-inner { border: none; } +.unselectable { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} .link{ text-decoration: underline; cursor: pointer; From a6b63d4113e22108b5726722a8c94f59b8870201 Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 14:01:26 +0200 Subject: [PATCH 31/34] Bug #652 El componente textarea muestra mal el label --- client/core/src/components/textarea/style.scss | 18 ++++++++++++++++++ .../core/src/components/textarea/textarea.html | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/client/core/src/components/textarea/style.scss b/client/core/src/components/textarea/style.scss index 91b29b3cf..52f579e24 100644 --- a/client/core/src/components/textarea/style.scss +++ b/client/core/src/components/textarea/style.scss @@ -1,6 +1,24 @@ +@import 'colors'; + vn-textarea { & > .mdl-textfield { width: initial; display: block; } + label { + position: absolute; + bottom: 0; + pointer-events: none; + color: $secondary-font-color; + transition-duration: .2s; + transition-timing-function: cubic-bezier(.4,0,.2,1); + } + & textarea.ng-not-empty+label.placeholder{ + top: 5px; + color: $main-01; + padding: 0; + font-size: 12px; + visibility: visible!important; + content: normal!important; + } } \ No newline at end of file diff --git a/client/core/src/components/textarea/textarea.html b/client/core/src/components/textarea/textarea.html index b60aef926..9bd419e55 100644 --- a/client/core/src/components/textarea/textarea.html +++ b/client/core/src/components/textarea/textarea.html @@ -5,5 +5,5 @@ ng-disabled="$ctrl.disabled" ng-model="$ctrl.model"> - +
\ No newline at end of file From 7211277b25dbadaf40015851afb25aac2f681f9f Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Thu, 13 Sep 2018 14:29:59 +0200 Subject: [PATCH 32/34] amends on spec file --- .../methods/ticket/specs/deleted.spec.js | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/services/loopback/common/methods/ticket/specs/deleted.spec.js b/services/loopback/common/methods/ticket/specs/deleted.spec.js index 7b1e8e2dc..fda330111 100644 --- a/services/loopback/common/methods/ticket/specs/deleted.spec.js +++ b/services/loopback/common/methods/ticket/specs/deleted.spec.js @@ -1,15 +1,21 @@ const app = require(`${servicesDir}/ticket/server/server`); describe('ticket deleted()', () => { - it('should call the getShipped method', async() => { - let oldTicket = await app.models.Ticket.findOne({where: {id: 1}}); + let ticket; + afterAll(async() => { + ticket.isDeleted = 0; + await app.models.Ticket.upsert(ticket); + }); + + it('YOU should work this out', async() => { + ticket = await app.models.Ticket.findOne({where: {id: 1}}); + + expect(ticket.isDeleted).toEqual(false); - expect(oldTicket.isDeleted).toEqual(false); await app.models.Ticket.deleted({id: 1}); - let ticket = await app.models.Ticket.findOne({where: {id: 1}, fields: ['isDeleted']}); - expect(ticket.isDeleted).toEqual(true); - oldTicket.isDeleted = 0; - await app.models.Ticket.upsert(oldTicket); + let deletedTicket = await app.models.Ticket.findOne({where: {id: 1}, fields: ['isDeleted']}); + + expect(deletedTicket.isDeleted).toEqual(true); }); }); From 447044faf92f98994463fd780c0d6a832dc6212c Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Thu, 13 Sep 2018 14:33:09 +0200 Subject: [PATCH 33/34] task updated #651 Al borrar un ticket no se cambia su estado a eliminado --- services/loopback/common/methods/ticket/specs/deleted.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/loopback/common/methods/ticket/specs/deleted.spec.js b/services/loopback/common/methods/ticket/specs/deleted.spec.js index fda330111..5ca217537 100644 --- a/services/loopback/common/methods/ticket/specs/deleted.spec.js +++ b/services/loopback/common/methods/ticket/specs/deleted.spec.js @@ -1,6 +1,7 @@ const app = require(`${servicesDir}/ticket/server/server`); -describe('ticket deleted()', () => { +// #651 Al borrar un ticket no se cambia su estado a eliminado +xdescribe('ticket deleted()', () => { let ticket; afterAll(async() => { ticket.isDeleted = 0; From d39365b63bda05ece52e7415572b507f7deba8c7 Mon Sep 17 00:00:00 2001 From: gerard Date: Thu, 13 Sep 2018 15:13:42 +0200 Subject: [PATCH 34/34] Bug #651 Al borrar un ticket no se cambia su estado a eliminado test --- .../common/methods/ticket/specs/deleted.spec.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/services/loopback/common/methods/ticket/specs/deleted.spec.js b/services/loopback/common/methods/ticket/specs/deleted.spec.js index 5ca217537..84c7b784c 100644 --- a/services/loopback/common/methods/ticket/specs/deleted.spec.js +++ b/services/loopback/common/methods/ticket/specs/deleted.spec.js @@ -1,22 +1,25 @@ const app = require(`${servicesDir}/ticket/server/server`); -// #651 Al borrar un ticket no se cambia su estado a eliminado -xdescribe('ticket deleted()', () => { +describe('ticket deleted()', () => { let ticket; + afterAll(async() => { - ticket.isDeleted = 0; await app.models.Ticket.upsert(ticket); + await app.models.TicketTracking.create({ticketFk: ticket.id, stateFk: 3}); }); - it('YOU should work this out', async() => { + it('should change the state of a ticket to deleted, and set the property isDeleted true', async() => { ticket = await app.models.Ticket.findOne({where: {id: 1}}); expect(ticket.isDeleted).toEqual(false); - - await app.models.Ticket.deleted({id: 1}); + ctx = {req: {accessToken: {userId: 9}}}; + params = {id: 1}; + await app.models.Ticket.deleted(ctx, params); let deletedTicket = await app.models.Ticket.findOne({where: {id: 1}, fields: ['isDeleted']}); + let changedState = await app.models.TicketState.findOne({where: {id: 1}}); expect(deletedTicket.isDeleted).toEqual(true); + expect(changedState.stateFk).toEqual(17); }); });