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/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/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/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/models/order.js b/services/order/common/models/order.js index 4ab2891d9..cb18ddb1c 100644 --- a/services/order/common/models/order.js +++ b/services/order/common/models/order.js @@ -2,7 +2,7 @@ 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/getTaxes')(Self); require('../methods/order/isEditable')(Self); require('../methods/order/getTotal')(Self); require('../methods/order/itemFilter')(Self);