diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index e6250a8a2..3f021c910 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -185,7 +185,7 @@ let actions = { let element = selectorMatches[0]; if (selectorMatches.length > 1) - throw new Error(`multiple matches of ${elementSelector} found`); + throw new Error(`Multiple matches of ${elementSelector} found`); let isVisible = false; if (element) { diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f03e57962..c83db3b33 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -221,7 +221,7 @@ export default { moreMenuRegularizeButton: '.vn-drop-down.shown li[name="Regularize stock"]', regularizeQuantityInput: '.vn-dialog.shown tpl-body > div > vn-textfield input', regularizeWarehouseAutocomplete: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.warehouseFk"]', - editButton: 'vn-item-card vn-item-descriptor vn-float-button[icon="edit"]', + editButton: 'vn-item-descriptor vn-float-button[icon="edit"]', regularizeSaveButton: '.vn-dialog.shown tpl-buttons > button', inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]', navigateBackToIndex: 'vn-item-descriptor vn-icon[icon="chevron_left"]' diff --git a/e2e/paths/05-ticket-module/11_diary.spec.js b/e2e/paths/05-ticket-module/11_diary.spec.js index aeec780e7..c64c0ba7b 100644 --- a/e2e/paths/05-ticket-module/11_diary.spec.js +++ b/e2e/paths/05-ticket-module/11_diary.spec.js @@ -1,5 +1,4 @@ import selectors from '../../helpers/selectors.js'; -import config from '../../helpers/config.js'; import createNightmare from '../../helpers/nightmare'; describe('Ticket diary path', () => { @@ -31,12 +30,9 @@ describe('Ticket diary path', () => { }); it(`should navigate to the item diary from the 1st sale item id descriptor popover`, async() => { - const itemId = 2; const url = await nightmare .waitToClick(selectors.ticketSummary.firstSaleItemId) .waitToClick(selectors.ticketSummary.popoverDiaryButton) - .waitForLogin('employee') - .goto(`${config.url}#!/item/${itemId}/diary?warehouseFk=1&ticketFk=1`) .parsedUrl(); expect(url.hash).toContain('/diary'); diff --git a/front/salix/components/index.js b/front/salix/components/index.js index 5d51c7231..af8380498 100644 --- a/front/salix/components/index.js +++ b/front/salix/components/index.js @@ -9,6 +9,7 @@ import './main-menu/main-menu'; import './module-card'; import './module-main'; import './side-menu/side-menu'; +import './section'; import './summary'; import './topbar/topbar'; import './user-popover'; diff --git a/front/salix/components/section/index.js b/front/salix/components/section/index.js new file mode 100644 index 000000000..a0c7484b4 --- /dev/null +++ b/front/salix/components/section/index.js @@ -0,0 +1,14 @@ +import ngModule from '../../module'; +import Component from 'core/lib/component'; +import './style.scss'; + +export default class Section extends Component { + constructor($element, $) { + super($element, $); + this.element.classList.add('vn-section'); + } +} + +ngModule.vnComponent('vnSection', { + controller: Section +}); diff --git a/front/salix/components/section/style.scss b/front/salix/components/section/style.scss new file mode 100644 index 000000000..e69de29bb diff --git a/modules/item/front/diary/index.js b/modules/item/front/diary/index.js index e128369a2..6d9f80641 100644 --- a/modules/item/front/diary/index.js +++ b/modules/item/front/diary/index.js @@ -115,7 +115,7 @@ class Controller { balance.classList.add('message'); balance.title = this.$translate.instant('Visible quantity'); - let headerOffset = body.querySelector('header').getBoundingClientRect(); + let headerOffset = body.querySelector('vn-topbar').getBoundingClientRect(); let headerHeight = headerOffset.height; let offsetTop; diff --git a/modules/order/back/methods/order/specs/updateBasicData.spec.js b/modules/order/back/methods/order/specs/updateBasicData.spec.js index 9b92e69ca..5e83d69a0 100644 --- a/modules/order/back/methods/order/specs/updateBasicData.spec.js +++ b/modules/order/back/methods/order/specs/updateBasicData.spec.js @@ -5,7 +5,7 @@ describe('Order updateBasicData', () => { afterAll(async done => { let validparams = {note: null}; - await app.models.Order.updateBasicData(validparams, orderId); + await app.models.Order.updateBasicData(orderId, validparams); done(); }); @@ -16,7 +16,7 @@ describe('Order updateBasicData', () => { let params = []; let orderConfirmed = 1; - await app.models.Order.updateBasicData(params, orderConfirmed) + await app.models.Order.updateBasicData(orderConfirmed, params) .catch(e => { error = e; }); @@ -30,7 +30,7 @@ describe('Order updateBasicData', () => { let params = []; let orderWithRows = 16; - await app.models.Order.updateBasicData(params, orderWithRows) + await app.models.Order.updateBasicData(orderWithRows, params) .catch(e => { error = e; }); @@ -38,17 +38,15 @@ describe('Order updateBasicData', () => { expect(error.toString()).toContain(`You can't make changes on the basic data of an confirmed order or with rows`); }); - it('should return an error if the current user is administrative and the isTaxDataChecked value is true BUT the params aint valid', async() => { - let error; + it('should skip invalid params', async() => { + let success; let invalidparams = {invalid: 'param for update'}; - await app.models.Order.updateBasicData(invalidparams, orderId) - .catch(e => { - error = e; - }); + await app.models.Order.updateBasicData(orderId, invalidparams) + .then(() => success = true); - expect(error.toString()).toContain(`You don't have enough privileges to do that`); + expect(success).toBeTruthy(); }); it('should update the client fiscal data and return the count if changes made', async() => { @@ -58,7 +56,7 @@ describe('Order updateBasicData', () => { expect(order.note).toEqual(null); - let result = await app.models.Order.updateBasicData(validparams, orderId); + let result = await app.models.Order.updateBasicData(orderId, validparams); expect(result.note).toEqual('test note'); }); diff --git a/modules/order/back/methods/order/updateBasicData.js b/modules/order/back/methods/order/updateBasicData.js index 6a8148a21..8f4393c04 100644 --- a/modules/order/back/methods/order/updateBasicData.js +++ b/modules/order/back/methods/order/updateBasicData.js @@ -1,22 +1,25 @@ let UserError = require('vn-loopback/util/user-error'); +let pick = require('object.pick'); module.exports = Self => { Self.remoteMethod('updateBasicData', { description: 'Updates basic data of an order', accessType: 'WRITE', - accepts: [{ - arg: 'data', - type: 'Object', - required: true, - description: 'Params to update', - http: {source: 'body'} - }, { - arg: 'id', - type: 'string', - required: true, - description: 'Model id', - http: {source: 'path'} - }], + accepts: [ + { + arg: 'id', + type: 'string', + required: true, + description: 'Model id', + http: {source: 'path'} + }, { + arg: 'data', + type: 'Object', + required: true, + description: 'Params to update', + http: {source: 'body'} + } + ], returns: { arg: 'order', type: 'Object', @@ -28,25 +31,25 @@ module.exports = Self => { } }); - Self.updateBasicData = async(params, id) => { - let order = await Self.app.models.Order.findById(id); - let orderRows = await Self.app.models.OrderRow.find({where: {orderFk: id}}); + Self.updateBasicData = async(id, params) => { + let models = Self.app.models; + + let order = await models.Order.findById(id); + let orderRows = await models.OrderRow.find({where: {orderFk: id}}); if (order.isConfirmed || orderRows.length != 0) throw new UserError(`You can't make changes on the basic data of an confirmed order or with rows`); - let validUpdateParams = [ + let updateParams = pick(params, [ 'clientFk', 'addressFk', 'landed', 'agencyModeFk', 'note', - ]; + ]); + if (Object.keys(updateParams).length) + await order.updateAttributes(updateParams); - for (const key in params) { - if (validUpdateParams.indexOf(key) === -1) - throw new UserError(`You don't have enough privileges to do that`); - } - return await order.updateAttributes(params); + return await order; }; }; diff --git a/modules/order/front/basic-data/index.js b/modules/order/front/basic-data/index.js index e82d6a591..81aef8304 100644 --- a/modules/order/front/basic-data/index.js +++ b/modules/order/front/basic-data/index.js @@ -4,7 +4,7 @@ import './style.scss'; class Controller { constructor($scope) { let isDirty = false; - $scope.$watch('$ctrl.selection', newValue=>{ + $scope.$watch('$ctrl.selection', newValue => { if (newValue) { $scope.addressModel.where = {clientFk: newValue.id}; $scope.addressModel.refresh(); diff --git a/modules/order/front/line/index.html b/modules/order/front/line/index.html index dddeade46..72d019fe9 100644 --- a/modules/order/front/line/index.html +++ b/modules/order/front/line/index.html @@ -1,7 +1,3 @@ - -
@@ -28,7 +24,8 @@ Shipped Quantity Price - + Amount + @@ -59,11 +56,14 @@ {{::row.price | currency: 'EUR':2}} - + + {{::row.price * row.quantity | currency: 'EUR':2}} + + @@ -84,7 +84,7 @@ \ No newline at end of file diff --git a/modules/order/front/line/index.js b/modules/order/front/line/index.js index 14e29c5c5..149251c87 100644 --- a/modules/order/front/line/index.js +++ b/modules/order/front/line/index.js @@ -1,16 +1,8 @@ import ngModule from '../module'; +import Section from 'salix/components/section'; import './style.scss'; -class Controller { - constructor($scope, $state, $http, vnApp, $translate) { - this.$scope = $scope; - this.vnApp = vnApp; - this.$translate = $translate; - this.$state = $state; - this.$http = $http; - this.idsToRemove = []; - } - +class Controller extends Section { $onInit() { this.getRows(); } @@ -24,82 +16,56 @@ class Controller { return this._order; } + get subtotal() { + return this.order ? this.order.total - this.VAT : 0; + } + getRows() { let filter = { - where: {orderFk: this.$state.params.id}, - include: [{ - relation: 'item' - }, - {relation: 'warehouse'}] + where: {orderFk: this.$params.id}, + include: [ + {relation: 'item'}, + {relation: 'warehouse'} + ] }; - filter = encodeURIComponent(JSON.stringify(filter)); - let query = `OrderRows?filter=${filter}`; - - this.$http.get(query).then(res => { - this.rows = res.data; - }); + this.$http.get(`OrderRows`, {filter}) + .then(res => this.rows = res.data); } getVAT() { - let query = `Orders/${this.$state.params.id}/getVAT`; + this.$http.get(`Orders/${this.$params.id}/getVAT`) + .then(res => this.VAT = res.data); + } - this.$http.get(query).then(res => { - this.VAT = res.data; + deleteRow(index) { + let [row] = this.rows.splice(index, 1); + let params = { + rows: [row.id], + actualOrderId: this.$params.id + }; + return this.$http.post(`OrderRows/removes`, params).then(() => { + this.card.reload(); + this.vnApp.showSuccess(this.$t('Data saved!')); }); } - get subtotal() { - return this.order.total - this.VAT || 0; - } - - showDeleteRow(index) { - this.lineIdToRemove = index; - this.$scope.deleteRow.show(); - } - - deleteRow(response) { - if (response == 'accept') { - let [lineRemoved] = this.rows.splice(this.lineIdToRemove, 1); - this.idsToRemove.push(lineRemoved.id); - let params = { - rows: this.idsToRemove, - actualOrderId: this.$state.params.id - }; - let query = `OrderRows/removes`; - - this.$http.post(query, params).then(() => { - this.vnApp.showSuccess(this.$translate.instant('Data saved!')); - }); - this.$scope.watcher.updateOriginalData(); - this.getVAT(); - this.card.reload(); - } - this.lineIdToRemove = undefined; - } - - // Item Descriptor showDescriptor(event, itemFk) { - this.$scope.descriptor.itemFk = itemFk; - this.$scope.descriptor.parent = event.target; - this.$scope.descriptor.show(); - } - - onDescriptorLoad() { - this.$scope.popover.relocate(); + let descriptor = this.$.descriptor; + descriptor.itemFk = itemFk; + descriptor.parent = event.target; + descriptor.show(); } save() { - let query = `Orders/${this.order.id}/confirm`; - - this.$http.post(query).then(() => { - this.vnApp.showSuccess(this.$translate.instant('Order confirmed')); - this.$state.go(`ticket.index`, {q: JSON.stringify({clientFk: this.order.clientFk})}); + this.$http.post(`Orders/${this.$params.id}/confirm`).then(() => { + this.vnApp.showSuccess(this.$t('Order confirmed')); + this.$state.go(`ticket.index`, { + q: JSON.stringify({clientFk: this.order.clientFk}) + }); }); } } -Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate']; - ngModule.component('vnOrderLine', { template: require('./index.html'), controller: Controller, diff --git a/modules/order/front/line/index.spec.js b/modules/order/front/line/index.spec.js index c3a01bbe0..543ffeedc 100644 --- a/modules/order/front/line/index.spec.js +++ b/modules/order/front/line/index.spec.js @@ -1,5 +1,4 @@ import './index.js'; -import watcher from 'core/mocks/watcher'; describe('Order', () => { describe('Component vnOrderLine', () => { @@ -7,83 +6,60 @@ describe('Order', () => { let controller; let $httpBackend; + let rows = [ + { + quantity: 4, + price: 10.5 + }, { + quantity: 3, + price: 2.4 + } + ]; + beforeEach(ngModule('order')); beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_) => { $state = _$state_; - $state = {params: {id: 1}}; $httpBackend = _$httpBackend_; - controller = $componentController('vnOrderLine', {$state}); - controller.rows = [{id: 1}]; - controller.$scope.watcher = watcher; - controller.$scope.popover = {relocate: () => {}}; - controller.$scope.descriptor = {show: () => {}}; - controller.vnApp = {showSuccess: () => {}}; - controller.card = {reload: () => {}}; + + $state.params.id = 1; + $httpBackend.whenRoute('GET', `OrderRows`).respond(rows); + $httpBackend.whenRoute('GET', `Orders/:id/getVAT`).respond(200, 10.5); + + let $element = angular.element('
'); + controller = $componentController('vnOrderLine', {$element}); })); describe('getRows()', () => { it('should make a query to get the rows of a given order', () => { - let filter = { - where: {orderFk: controller.$state.params.id}, - include: [{ - relation: 'item' - }, - {relation: 'warehouse'}] - }; - - filter = encodeURIComponent(JSON.stringify(filter)); - $httpBackend.expectGET(`OrderRows?filter=${filter}`).respond({data: [{id: 1}]}); controller.getRows(); $httpBackend.flush(); + + expect(controller.rows).toBeDefined(); }); }); describe('getVAT()', () => { it('should make a query to get the VAT of a given order', () => { - $httpBackend.expectGET(`Orders/1/getVAT`).respond({data: {tax: 3}}); controller.getVAT(); $httpBackend.flush(); + + expect(controller.VAT).toBeDefined(); }); }); describe('deleteRow()', () => { it('should remove a row from rows and add save the data if the response is accept', () => { - expect(controller.rows.length).toBe(1); - spyOn(controller.vnApp, 'showSuccess'); - spyOn(controller, 'getVAT'); - spyOn(controller.card, 'reload'); - controller.deleteRow('accept'); - - $httpBackend.expectPOST(`OrderRows/removes`).respond(); + controller.getRows(); $httpBackend.flush(); - expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); + controller.card = {reload: jasmine.createSpy('reload')}; + $httpBackend.expectPOST(`OrderRows/removes`).respond(); + controller.deleteRow(0); + $httpBackend.flush(); + + expect(controller.rows.length).toBe(1); expect(controller.card.reload).toHaveBeenCalledWith(); - expect(controller.rows.length).toBe(0); - expect(controller.lineIdToRemove).toBe(undefined); - }); - }); - - describe('showDescriptor()', () => { - it('should set $scope.descriptor.itemFk, $scope.descriptor.parent and call $scope.descriptor.show()', () => { - let event = {target: 1}; - let itemFk = 1; - spyOn(controller.$scope.descriptor, 'show'); - controller.showDescriptor(event, itemFk); - - expect(controller.$scope.descriptor.itemFk).toBe(1); - expect(controller.$scope.descriptor.parent).toBe(1); - expect(controller.$scope.descriptor.show).toHaveBeenCalledWith(); - }); - }); - - describe('onDescriptorLoad()', () => { - it('should call $scope.popover.relocate()', () => { - spyOn(controller.$scope.popover, 'relocate'); - controller.onDescriptorLoad(); - - expect(controller.$scope.popover.relocate).toHaveBeenCalledWith(); }); }); });