diff --git a/client/core/src/components/snackbar/snackbar.js b/client/core/src/components/snackbar/snackbar.js index cf1418903..4106ffedd 100644 --- a/client/core/src/components/snackbar/snackbar.js +++ b/client/core/src/components/snackbar/snackbar.js @@ -66,7 +66,7 @@ export default class Controller extends Component { let shape = this.createShape(data); setTimeout(() => - this.hide(shape), data.timeout || 6000); + this.hide(shape), data.timeout || 3000); setTimeout(() => shape.classList.add('shown'), 30); diff --git a/client/core/src/components/snackbar/style.scss b/client/core/src/components/snackbar/style.scss index b8f863b79..5f14df76c 100644 --- a/client/core/src/components/snackbar/style.scss +++ b/client/core/src/components/snackbar/style.scss @@ -1,31 +1,32 @@ @import "colors"; vn-snackbar #shapes { - position: fixed; - bottom: 0; - right: 15px; - width: 20em; max-height: 20.625em; + margin-left: -12.5em; + position: fixed; z-index: 100; + width: 25em; + left: 50%; + bottom: 0 } vn-snackbar .shape { - box-sizing: border-box; background-color: rgba(1, 1, 1, 0.8); + box-shadow: 0 0 .4em rgba(1,1,1,.4); + transition: transform 300ms ease-in-out; + transform: translateY(20em); + box-sizing: border-box; + border-radius: .2em; + margin-bottom: 15px; color: white; padding: 1em; - border-radius: .2em; - box-shadow: 0 0 .4em rgba(1,1,1,.4); - margin-bottom: 15px; - transform: translateX(20em); - transition: transform 300ms ease-in-out; - + &.text { text-align: center } &.shown { - transform: translateX(0); + transform: translateY(0); } &.success { @@ -46,15 +47,15 @@ vn-snackbar .shape { } & > button { - cursor: pointer; - float: right; - text-transform: uppercase; - border: none; background-color: transparent; - font-weight: bold; - color: $main-01; - padding: .5em; - margin: -.5em; + text-transform: uppercase; margin-left: .5em; + font-weight: bold; + cursor: pointer; + color: $main-01; + float: right; + border: none; + padding: .5em; + margin: -.5em } } \ No newline at end of file diff --git a/client/order/routes.json b/client/order/routes.json index 090907c33..1a6b10c66 100644 --- a/client/order/routes.json +++ b/client/order/routes.json @@ -57,6 +57,18 @@ "icon": "icon-volume" } }, + { + "url": "/line", + "state": "order.card.line", + "component": "vn-order-line", + "description": "Lines", + "params": { + "order": "$ctrl.order" + }, + "menu": { + "icon": "icon-lines" + } + }, { "url": "/create", "state": "order.create", diff --git a/client/order/src/index.js b/client/order/src/index.js index 6ef6ed1ea..15adc056e 100644 --- a/client/order/src/index.js +++ b/client/order/src/index.js @@ -7,6 +7,8 @@ import './index/'; import './summary'; import './catalogue'; import './catalogue/product'; +import './line'; +//import './prices-popover'; import './volume'; import './create'; import './create/card'; diff --git a/client/order/src/line/index.html b/client/order/src/line/index.html new file mode 100644 index 000000000..d195cca78 --- /dev/null +++ b/client/order/src/line/index.html @@ -0,0 +1,82 @@ + + + + + + + + Sale + +
+ Subtotal + {{$ctrl.order.total - $ctrl.VAT | currency:'€':2}} +

+ VAT + {{$ctrl.VAT | currency:'€':2}} +

+ Total + {{$ctrl.order.total | currency:'€':2}} +
+
+ + + + Item + ID + Description + Warehouse + Shipped + Quantity + Price + + + + + + + + + + {{("000000"+row.itemFk).slice(-6)}} + + + {{row.warehouse.name}} + {{row.shipped | dashIfEmpty}} + {{row.quantity}} + + {{row.price | currency:'€':2}} + + + + + + + + + No results + + +
+
+ + + + +
+ + + \ No newline at end of file diff --git a/client/order/src/line/index.js b/client/order/src/line/index.js new file mode 100644 index 000000000..df83de62a --- /dev/null +++ b/client/order/src/line/index.js @@ -0,0 +1,95 @@ +import ngModule from '../module'; +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 = []; + } + + $onInit() { + this.getRows(); + this.getVAT(); + } + + getRows() { + let filter = { + where: {orderFk: this.$state.params.id}, + include: [{ + relation: 'item', + scope: { + include: { + relation: 'tags', + scope: { + fields: ['tagFk', 'value'], + include: { + relation: 'tag', + scope: { + fields: ['name'] + } + } + } + }, + fields: ['itemFk', 'name', 'image'] + } + }, + {relation: 'warehouse'}] + }; + filter = encodeURIComponent(JSON.stringify(filter)); + let query = `/order/api/OrderRows?filter=${filter}`; + + this.$http.get(query).then(res => { + this.rows = res.data; + }); + } + + getVAT() { + let query = `/order/api/Orders/${this.$state.params.id}/getTaxes`; + + this.$http.get(query).then(res => { + this.VAT = res.data.tax; + }); + } + + removeRow(index) { + let [lineRemoved] = this.rows.splice(index, 1); + this.idsToRemove.push(lineRemoved.id); + } + + // 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(); + } + + save() { + let params = { + rows: this.idsToRemove, + actualOrderId: this.$state.params.id + }; + let query = `/order/api/OrderRows/removes`; + + this.$http.post(query, params).then(() => { + this.vnApp.showSuccess(this.$translate.instant('Data saved!')); + }); + } +} + +Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate']; + +ngModule.component('vnOrderLine', { + template: require('./index.html'), + controller: Controller, + bindings: { + order: '<' + } +}); diff --git a/client/order/src/line/index.spec.js b/client/order/src/line/index.spec.js new file mode 100644 index 000000000..b57e57e0f --- /dev/null +++ b/client/order/src/line/index.spec.js @@ -0,0 +1,109 @@ +import './index.js'; + +describe('Order', () => { + describe('Component vnOrderLine', () => { + let $componentController; + let $state; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('order'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => { + $componentController = _$componentController_; + $state = _$state_; + $state = {params: {id: 1}}; + $httpBackend = _$httpBackend_; + $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); + controller = $componentController('vnOrderLine', {$state: $state}); + controller.rows = [{id: 1}]; + controller.$scope.popover = {relocate: () => {}}; + controller.$scope.descriptor = {show: () => {}}; + controller.vnApp = {showSuccess: () => {}}; + })); + + 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', + scope: { + include: { + relation: 'tags', + scope: { + fields: ['tagFk', 'value'], + include: { + relation: 'tag', + scope: { + fields: ['name'] + } + } + } + }, + fields: ['itemFk', 'name', 'image'] + } + }, + {relation: 'warehouse'}] + }; + + filter = encodeURIComponent(JSON.stringify(filter)); + $httpBackend.expectGET(`/order/api/OrderRows?filter=${filter}`).respond({data: [{id: 1}]}); + controller.getRows(); + $httpBackend.flush(); + }); + }); + + describe('getTaxes()', () => { + it('should make a query to get the taxes of a given order', () => { + $httpBackend.expectGET(`/order/api/Orders/1/getTaxes`).respond({data: {tax: 3}}); + controller.getVAT(); + $httpBackend.flush(); + }); + }); + + describe('removeRow()', () => { + it('should remove a row from rows and add his id to idsRemoved', () => { + controller.removeRow(0); + + expect(controller.rows.length).toBe(0); + expect(controller.idsToRemove[0]).toBe(1); + }); + }); + + 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(); + }); + }); + + describe('save()', () => { + it('should make a query to remove the selected rows and call vnApp.showSuccess', () => { + spyOn(controller.vnApp, 'showSuccess'); + $httpBackend.expectPOST(`/order/api/OrderRows/removes`).respond(); + controller.save(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); + }); + }); + }); +}); diff --git a/client/order/src/line/locale/es.yml b/client/order/src/line/locale/es.yml new file mode 100644 index 000000000..2e4bcfcb2 --- /dev/null +++ b/client/order/src/line/locale/es.yml @@ -0,0 +1 @@ +Remove item: Eliminar articulo \ No newline at end of file diff --git a/client/order/src/line/style.scss b/client/order/src/line/style.scss new file mode 100644 index 000000000..0487a360e --- /dev/null +++ b/client/order/src/line/style.scss @@ -0,0 +1,8 @@ +vn-order-line{ + vn-table { + img { + border-radius: 50%; + max-width: 50px; + } + } +} \ No newline at end of file diff --git a/client/order/src/volume/index.spec.js b/client/order/src/volume/index.spec.js new file mode 100644 index 000000000..e80e9b4c6 --- /dev/null +++ b/client/order/src/volume/index.spec.js @@ -0,0 +1,64 @@ +import './index'; + +describe('Order', () => { + describe('Component vnOrderVolume', () => { + let $componentController; + let controller; + let $httpBackend; + let $state; + let $scope; + + beforeEach(() => { + angular.mock.module('order'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => { + $componentController = _$componentController_; + $httpBackend = _$httpBackend_; + $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); + $scope = $rootScope.$new(); + $scope.model = {data: [{itemFk: 1}, {itemFk: 2}], accept: () => { + return { + then: () => {} + }; + }}; + $scope.descriptor = {show: () => {}}; + $scope.popover = {relocate: () => {}}; + $state = _$state_; + $state.params.id = 1; + controller = $componentController('vnOrderVolume', {$scope: $scope}, {$httpBackend: $httpBackend}, {$state: $state}); + })); + + it('should join the sale volumes to its respective sale', () => { + let response = {volumes: [{itemFk: 1, volume: 0.008}, {itemFk: 2, volume: 0.003}]}; + $httpBackend.whenGET(`/order/api/Orders/1/getVolumes`).respond(response); + $httpBackend.expectGET(`/order/api/Orders/1/getVolumes`); + controller.onDataChange(); + $httpBackend.flush(); + + expect(controller.$scope.model.data[0].volume).toBe(0.008); + expect(controller.$scope.model.data[1].volume).toBe(0.003); + }); + 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(); + }); + }); + }); +}); diff --git a/client/salix/src/styles/misc.scss b/client/salix/src/styles/misc.scss index f7aed13fc..7517ed95c 100644 --- a/client/salix/src/styles/misc.scss +++ b/client/salix/src/styles/misc.scss @@ -27,7 +27,7 @@ input[type=reset]::-moz-focus-inner .totalBox { border: 1px solid #CCC; - text-align: left; + text-align: right!important; justify-content: center; align-items: center; padding: 18px; diff --git a/client/ticket/src/sale/index.html b/client/ticket/src/sale/index.html index 8354443bb..ffe30b4ac 100644 --- a/client/ticket/src/sale/index.html +++ b/client/ticket/src/sale/index.html @@ -228,7 +228,7 @@ label="Price" model="$ctrl.editedPrice" type="text" - accept="$ctrl.updatePrice()"> + on-change="$ctrl.updatePrice()"> diff --git a/client/ticket/src/sale/index.js b/client/ticket/src/sale/index.js index 35dc6aeb5..587bb5d77 100644 --- a/client/ticket/src/sale/index.js +++ b/client/ticket/src/sale/index.js @@ -309,6 +309,9 @@ class Controller { this.$http.post(`/ticket/api/Sales/${id}/updateQuantity`, {quantity: parseInt(quantity)}).then(() => { this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.$scope.model.refresh(); + }).catch(e => { + this.vnApp.showError(e.data.error.message); + this.$scope.model.refresh(); }); } diff --git a/services/db/install/dump/fixtures.sql b/services/db/install/dump/fixtures.sql index 17142ee13..1521724c0 100644 --- a/services/db/install/dump/fixtures.sql +++ b/services/db/install/dump/fixtures.sql @@ -326,29 +326,29 @@ INSERT INTO `vn`.`invoiceOut`(`id`, `ref`, `serial`, `amount`, `issued`,`clientF ( 4, 'E4444444' , 'E', 290.30 , DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1), ( 5, 'E5555555' , 'E', 190.30 , DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 8, 1); - INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`) + INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`) VALUES - (1 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY) , DATE_ADD(CURDATE(), INTERVAL -15 DAY) , 101, 'Batman', 121, NULL), - (2 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -10 DAY) , DATE_ADD(CURDATE(), INTERVAL -10 DAY) , 101, 'Spider-Man', 121, NULL), - (3 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -5 DAY) , DATE_ADD(CURDATE(), INTERVAL -5 DAY) , 102, 'Super-Man', 122, NULL), - (4 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -4 DAY) , DATE_ADD(CURDATE(), INTERVAL -4 DAY) , 102, 'Iron-Man', 122, NULL), - (5 , 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -3 DAY) , DATE_ADD(CURDATE(), INTERVAL -3 DAY) , 103, 'Magneto', 123, NULL), - (6 , 3, 3, 4, DATE_ADD(CURDATE(), INTERVAL -2 DAY) , DATE_ADD(CURDATE(), INTERVAL -2 DAY) , 103, 'Legion', 123, NULL), - (7 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 DAY) , DATE_ADD(CURDATE(), INTERVAL -1 DAY) , 104, 'Ant-Man', 124, NULL), - (8 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 104, 'Professor X', 124, NULL), - (9 , 5, 5, 4, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 105, 'Hulk', 125, NULL), - (10, 6, 5, 5, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 105, 'Jessica Jones', 125, NULL), - (11, 7, 1, 1, CURDATE() , CURDATE() , 101, 'ticket 1', 121, NULL), - (12, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 101, 'ticket 2', 121, NULL), - (13, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +2 MONTH), DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 101, 'ticket 3', 121, NULL), - (14, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +3 MONTH), DATE_ADD(CURDATE(), INTERVAL +3 MONTH), 101, 'ticket 4', 121, NULL), - (15, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL +4 MONTH), DATE_ADD(CURDATE(), INTERVAL +4 MONTH), 101, 'ticket 5', 121, NULL), - (16, 3, 3, 4, CURDATE() , CURDATE() , 101, 'ticket 6', 121, NULL), - (17, 4, 4, 4, CURDATE() , CURDATE() , 106, 'ticket 7', 126, NULL), - (18, 4, 4, 4, CURDATE() , CURDATE() , 107, 'ticket 8', 127, NULL), - (19, 5, 5, 4, CURDATE() , CURDATE() , 108, 'ticket 9', 128, NULL), - (20, 5, 5, 4, CURDATE() , CURDATE() , 109, 'ticket 10', 119, NULL), - (21, 5, 5, 4, CURDATE() , CURDATE() , 110, 'ticket 11', 129, NULL); + (1 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY) , DATE_ADD(CURDATE(), INTERVAL -15 DAY) , 101, 'Batman', 121, NULL, 0), + (2 , 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -10 DAY) , DATE_ADD(CURDATE(), INTERVAL -10 DAY) , 101, 'Spider-Man', 121, NULL, 0), + (3 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -5 DAY) , DATE_ADD(CURDATE(), INTERVAL -5 DAY) , 102, 'Super-Man', 122, NULL, 0), + (4 , 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL -4 DAY) , DATE_ADD(CURDATE(), INTERVAL -4 DAY) , 102, 'Iron-Man', 122, NULL, 0), + (5 , 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -3 DAY) , DATE_ADD(CURDATE(), INTERVAL -3 DAY) , 103, 'Magneto', 123, NULL, 0), + (6 , 3, 3, 4, DATE_ADD(CURDATE(), INTERVAL -2 DAY) , DATE_ADD(CURDATE(), INTERVAL -2 DAY) , 103, 'Legion', 123, NULL, 0), + (7 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 DAY) , DATE_ADD(CURDATE(), INTERVAL -1 DAY) , 104, 'Ant-Man', 124, NULL, 0), + (8 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 104, 'Professor X', 124, NULL, 0), + (9 , 5, 5, 4, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 105, 'Hulk', 125, NULL, 0), + (10, 6, 5, 5, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 105, 'Jessica Jones', 125, NULL, 0), + (11, 7, 1, 1, CURDATE() , CURDATE() , 101, 'ticket 1', 121, NULL, 0), + (12, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 101, 'ticket 2', 121, NULL, 0), + (13, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +2 MONTH), DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 101, 'ticket 3', 121, NULL, 0), + (14, 2, 2, 2, DATE_ADD(CURDATE(), INTERVAL +3 MONTH), DATE_ADD(CURDATE(), INTERVAL +3 MONTH), 101, 'ticket 4', 121, NULL, 0), + (15, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL +4 MONTH), DATE_ADD(CURDATE(), INTERVAL +4 MONTH), 101, 'ticket 5', 121, NULL, 0), + (16, 3, 3, 4, CURDATE() , CURDATE() , 101, 'ticket 6', 121, NULL, 0), + (17, 4, 4, 4, CURDATE() , CURDATE() , 106, 'ticket 7', 126, NULL, 0), + (18, 4, 4, 4, CURDATE() , CURDATE() , 107, 'ticket 8', 127, NULL, 0), + (19, 5, 5, 4, CURDATE() , CURDATE() , 108, 'ticket 9', 128, NULL, 0), + (20, 5, 5, 4, CURDATE() , CURDATE() , 109, 'ticket 10', 119, NULL, 0), + (21, 5, 5, 4, CURDATE() , CURDATE() , 110, 'ticket 11', 129, NULL, 1); INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES @@ -358,27 +358,27 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`) VALUES - (1, 1, 3, 5, CURDATE()), - (2, 2, 15, 5, CURDATE()), - (3, 3, 16, 5, CURDATE()), - (4, 4, 13, 5, CURDATE()), - (5, 5, 15, 18, CURDATE()), - (6, 6, 16, 18, CURDATE()), - (7, 7, 13, 18, CURDATE()), - (8, 8, 15, 19, CURDATE()), - (9, 9, 16, 19, CURDATE()), + (1 , 1 , 3 , 5 , CURDATE()), + (2 , 2 , 15, 5 , CURDATE()), + (3 , 3 , 16, 5 , CURDATE()), + (4 , 4 , 13, 5 , CURDATE()), + (5 , 5 , 15, 18, CURDATE()), + (6 , 6 , 16, 18, CURDATE()), + (7 , 7 , 13, 18, CURDATE()), + (8 , 8 , 15, 19, CURDATE()), + (9 , 9 , 16, 19, CURDATE()), (10, 10, 13, 19, CURDATE()), - (11, 11, 3, 19, CURDATE()), - (12, 12, 3, 19, CURDATE()), - (13, 13, 3, 19, CURDATE()), - (14, 14, 3, 19, CURDATE()), - (15, 15, 3, 19, CURDATE()), - (16, 16, 1, 19, CURDATE()), - (17, 17, 1, 19, CURDATE()), - (18, 18, 1, 19, CURDATE()), + (11, 11, 3 , 19, CURDATE()), + (12, 12, 3 , 19, CURDATE()), + (13, 13, 3 , 19, CURDATE()), + (14, 14, 3 , 19, CURDATE()), + (15, 15, 3 , 19, CURDATE()), + (16, 16, 1 , 19, CURDATE()), + (17, 17, 1 , 19, CURDATE()), + (18, 18, 1 , 19, CURDATE()), (19, 19, 13, 19, CURDATE()), (20, 20, 15, 19, CURDATE()), - (21, 21, 16, 19, CURDATE()); + (21, 21, 3 , 19, CURDATE()); INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`) VALUES diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index e0a4fdd49..1653030b6 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -38,5 +38,6 @@ "You don't have enough privileges to change the state of this ticket": "No tienes permisos para cambiar el estado de este ticket", "The new quantity should be smaller than the old one": "La nueva cantidad debe de ser menor que la anterior", "The value should not be greater than 100%": "El valor no debe de ser mayor de 100%", - "The value should be a number": "El valor debe ser un numero" + "The value should be a number": "El valor debe ser un numero", + "This order is not editable": "Esta orden no se puede modificar" } \ No newline at end of file diff --git a/services/loopback/common/methods/ticket/specs/isEditable.spec.js b/services/loopback/common/methods/ticket/specs/isEditable.spec.js new file mode 100644 index 000000000..06e223c3c --- /dev/null +++ b/services/loopback/common/methods/ticket/specs/isEditable.spec.js @@ -0,0 +1,27 @@ +const app = require(`${servicesDir}/ticket/server/server`); + +describe('ticket isEditable()', () => { + it('should return false if the ticket given is not editable', async() => { + let result = await app.models.Ticket.isEditable(2); + + expect(result).toEqual(false); + }); + + it('should return false if the ticket given does not exists', async() => { + let result = await app.models.Ticket.isEditable(99999); + + expect(result).toEqual(false); + }); + + it('should return false if the ticket given isDeleted', async() => { + let result = await app.models.Ticket.isEditable(21); + + expect(result).toEqual(false); + }); + + it('should return true if the ticket given is editable', async() => { + let result = await app.models.Ticket.isEditable(1); + + expect(result).toEqual(true); + }); +}); diff --git a/services/order/common/locale/es.json b/services/order/common/locale/es.json new file mode 100644 index 000000000..5fa92d9e9 --- /dev/null +++ b/services/order/common/locale/es.json @@ -0,0 +1,3 @@ +{ + "This order is not editable": "Esta orden no se puede editar" +} diff --git a/services/order/common/methods/order-row/removes.js b/services/order/common/methods/order-row/removes.js new file mode 100644 index 000000000..b660d4be3 --- /dev/null +++ b/services/order/common/methods/order-row/removes.js @@ -0,0 +1,36 @@ +const UserError = require('vn-loopback/common/helpers').UserError; + +module.exports = Self => { + Self.remoteMethod('removes', { + description: 'Delete an Order Row', + accessType: '', + accepts: [{ + arg: 'params', + type: 'object', + required: true, + description: '[Row IDs], actualOrderId', + http: {source: 'body'} + }], + returns: { + type: 'string', + root: true + }, + http: { + path: `/removes`, + verb: 'post' + } + }); + + Self.removes = async params => { + if (!params.rows || !params.rows.length) + throw new Error('There is nothing delete'); + + await Self.app.models.Order.isEditable(params.actualOrderId); + + let promises = []; + for (let i = 0; i < params.rows.length; i++) { + promises.push(Self.app.models.OrderRow.destroyById(params.rows[i])); + } + return await Promise.all(promises); + }; +}; diff --git a/services/order/common/methods/order-row/specs/removes.spec.js b/services/order/common/methods/order-row/specs/removes.spec.js new file mode 100644 index 000000000..17d760eb3 --- /dev/null +++ b/services/order/common/methods/order-row/specs/removes.spec.js @@ -0,0 +1,25 @@ +const app = require(`../../../../server/server`); + +describe('order removes()', () => { + it('should throw an error if rows property is empty', async() => { + let error; + try { + await app.models.OrderRow.removes({rows: []}); + } catch (e) { + error = e; + } + + expect(error).toEqual(new Error('There is nothing delete')); + }); + + it('should throw an error if the row selected is not editable', async() => { + let error; + try { + await app.models.OrderRow.removes({rows: [2]}); + } catch (e) { + error = e; + } + + expect(error).toEqual(new Error('This order is not editable')); + }); +}); diff --git a/services/order/common/methods/order/getTaxes.js b/services/order/common/methods/order/getTaxes.js new file mode 100644 index 000000000..ff130c4ff --- /dev/null +++ b/services/order/common/methods/order/getTaxes.js @@ -0,0 +1,30 @@ +module.exports = Self => { + Self.remoteMethod('getTaxes', { + description: 'Gets the taxes of a given order', + accessType: 'READ', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'order id', + http: {source: 'path'} + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/:id/getTaxes`, + verb: 'GET' + } + }); + + Self.getTaxes = async orderFk => { + let query = `CALL hedera.orderGetTax(?); + SELECT * FROM tmp.orderTax;`; + let res = await Self.rawSql(query, [orderFk]); + let [taxes] = res[1]; + + return taxes; + }; +}; diff --git a/services/order/common/methods/order/isEditable.js b/services/order/common/methods/order/isEditable.js new file mode 100644 index 000000000..503d24418 --- /dev/null +++ b/services/order/common/methods/order/isEditable.js @@ -0,0 +1,30 @@ +const UserError = require('vn-loopback/common/helpers').UserError; + +module.exports = Self => { + Self.remoteMethod('isEditable', { + description: 'Check if an order is editable', + accessType: 'READ', + accepts: [{ + arg: 'orderId', + type: 'number', + required: true, + description: 'orderId', + http: {source: 'path'} + }], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/:orderId/isEditable`, + verb: 'get' + } + }); + + Self.isEditable = async orderId => { + let exists = await Self.app.models.Order.findOne({where: {id: orderId}, fields: ['isConfirmed']}); + + if (!exists || exists.isConfirmed === 1) + throw new UserError('This order is not editable'); + }; +}; diff --git a/services/order/common/methods/order/specs/getTaxes.spec.js b/services/order/common/methods/order/specs/getTaxes.spec.js new file mode 100644 index 000000000..a0efb862b --- /dev/null +++ b/services/order/common/methods/order/specs/getTaxes.spec.js @@ -0,0 +1,21 @@ +const app = require(`../../../../server/server`); + +describe('order getTaxes()', () => { + it('should call the getTaxes method and return undefined if its called with a string', async() => { + let result = await app.models.Order.getTaxes('pepinillos'); + + expect(result).toEqual(undefined); + }); + + it('should call the getTaxes method and return undefined if its called with unknown id', async() => { + let result = await app.models.Order.getTaxes(99999999999999999999999); + + expect(result).toEqual(undefined); + }); + + it('should call the getTaxes method and return the taxes if its called with a known id', async() => { + let result = await app.models.Order.getTaxes(1); + + expect(result.tax).toEqual(0.95); + }); +}); diff --git a/services/order/common/methods/order/specs/isEditable.spec.js b/services/order/common/methods/order/specs/isEditable.spec.js new file mode 100644 index 000000000..515ea29ed --- /dev/null +++ b/services/order/common/methods/order/specs/isEditable.spec.js @@ -0,0 +1,26 @@ +const app = require(`../../../../server/server`); +const UserError = require('vn-loopback/common/helpers').UserError; + +describe('order isEditable()', () => { + it('should throw an error if the order given is not editable', async() => { + let error; + try { + await app.models.Order.isEditable(2); + } catch (e) { + error = e; + } + + expect(error).toEqual(new UserError('This order is not editable')); + }); + + it('should throw an error if the order given does not exists', async() => { + let error; + try { + await app.models.Order.isEditable(99999); + } catch (e) { + error = e; + } + + expect(error).toEqual(new UserError('This order is not editable')); + }); +}); diff --git a/services/order/common/models/order-row.js b/services/order/common/models/order-row.js new file mode 100644 index 000000000..0c629669f --- /dev/null +++ b/services/order/common/models/order-row.js @@ -0,0 +1,4 @@ +module.exports = Self => { + //require('../methods/order-row/new')(Self); + require('../methods/order-row/removes')(Self); +}; diff --git a/services/order/common/models/order-row.json b/services/order/common/models/order-row.json index e28787a31..77c1d654d 100644 --- a/services/order/common/models/order-row.json +++ b/services/order/common/models/order-row.json @@ -50,6 +50,11 @@ "type": "belongsTo", "model": "Order", "foreignKey": "orderFk" + }, + "warehouse": { + "type": "belongsTo", + "model": "Warehouse", + "foreignKey": "warehouseFk" } } } diff --git a/services/order/common/models/order.js b/services/order/common/models/order.js index 00b0326d5..cb18ddb1c 100644 --- a/services/order/common/models/order.js +++ b/services/order/common/models/order.js @@ -2,6 +2,8 @@ module.exports = Self => { require('../methods/order/new')(Self); require('../methods/order/getTotalVolume')(Self); require('../methods/order/getVolumes')(Self); + require('../methods/order/getTaxes')(Self); + require('../methods/order/isEditable')(Self); require('../methods/order/getTotal')(Self); require('../methods/order/itemFilter')(Self); };