diff --git a/db/changes/10410-january/00-saleVolume.sql b/db/changes/10410-january/00-saleVolume.sql new file mode 100644 index 000000000..e8a5e3433 --- /dev/null +++ b/db/changes/10410-january/00-saleVolume.sql @@ -0,0 +1,38 @@ +USE vn; +DELIMITER $$ +$$ +CREATE OR REPLACE +ALGORITHM = UNDEFINED VIEW `vn`.`saleVolume` AS +select + `s`.`ticketFk` AS `ticketFk`, + `s`.`id` AS `saleFk`, + round(`ic`.`cm3delivery` * `s`.`quantity` / 1000, 0) AS `litros`, + `t`.`routeFk` AS `routeFk`, + `t`.`shipped` AS `shipped`, + `t`.`landed` AS `landed`, + `s`.`quantity` * `ic`.`cm3delivery` / 1000000 AS `volume`, + `s`.`quantity` * `ic`.`grams` / 1000 AS `physicalWeight`, + `s`.`quantity` * `ic`.`cm3delivery` * greatest(`i`.`density`, 167) / 1000000 AS `weight`, + `s`.`quantity` * `ic`.`cm3delivery` / 1000000 AS `physicalVolume`, + `s`.`quantity` * `ic`.`cm3delivery` * ifnull(`t`.`zonePrice`, `z`.`price`) / (`vc`.`standardFlowerBox` * 1000) AS `freight`, + `t`.`zoneFk` AS `zoneFk`, + `t`.`clientFk` AS `clientFk`, + `s`.`isPicked` AS `isPicked`, + `s`.`quantity` * `s`.`price` * (100 - `s`.`discount`) / 100 AS `eurosValue`, + `i`.`itemPackingTypeFk` AS `itemPackingTypeFk` +from + (((((`sale` `s` +join `item` `i` on + (`i`.`id` = `s`.`itemFk`)) +join `ticket` `t` on + (`t`.`id` = `s`.`ticketFk`)) +join `zone` `z` on + (`z`.`id` = `t`.`zoneFk`)) +join `volumeConfig` `vc`) +join `itemCost` `ic` on + (`ic`.`itemFk` = `s`.`itemFk` + and `ic`.`warehouseFk` = `t`.`warehouseFk`)) +where + `s`.`quantity` > 0; +$$ +DELIMITER ; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5bfc76560..e33494836 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -799,25 +799,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`) ('VT', 'Sales'); INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, - `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`) + `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`) VALUES - (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL), - (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL), - (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL), - (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL), - (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL), - (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL), - (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL), - (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL), - (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL), - (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL), - (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL), - (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL), - (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL), - (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL), - (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL), - (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL), - (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL); + (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V'), + (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H'), + (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL), + (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL), + (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL), + (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL), + (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL), + (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL), + (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL), + (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL), + (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL), + (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL), + (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL, NULL), + (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL), + (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL), + (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL), + (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL); -- Update the taxClass after insert of the items UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 diff --git a/modules/ticket/back/methods/ticket/getVolume.js b/modules/ticket/back/methods/ticket/getVolume.js index 376c9ee4e..6029020ba 100644 --- a/modules/ticket/back/methods/ticket/getVolume.js +++ b/modules/ticket/back/methods/ticket/getVolume.js @@ -9,10 +9,14 @@ module.exports = Self => { description: 'ticket id', http: {source: 'path'} }], - returns: { - type: ['Object'], - root: true + returns: [{ + arg: 'saleVolume', + type: ['object'] }, + { + arg: 'packingTypeVolume', + type: ['object'] + }], http: { path: `/:id/getVolume`, verb: 'GET' @@ -25,7 +29,21 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - return Self.rawSql(`SELECT * FROM vn.saleVolume - WHERE ticketFk = ?`, [ticketFk], myOptions); + const saleVolume = await Self.rawSql(` + SELECT saleFk, volume + FROM vn.saleVolume + WHERE ticketFk = ?`, [ticketFk], myOptions); + + const packingTypeVolume = await Self.rawSql(` + SELECT s.itemPackingTypeFk code, + i.description, + SUM(s.volume) volume + FROM vn.saleVolume s + LEFT JOIN vn.itemPackingType i + ON i.code = s.itemPackingTypeFk + WHERE s.ticketFk = ? + GROUP BY s.itemPackingTypeFk`, [ticketFk], myOptions); + + return [saleVolume, packingTypeVolume]; }; }; diff --git a/modules/ticket/back/methods/ticket/specs/getVolume.spec.js b/modules/ticket/back/methods/ticket/specs/getVolume.spec.js index 35134e4d0..cba3948db 100644 --- a/modules/ticket/back/methods/ticket/specs/getVolume.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getVolume.spec.js @@ -8,9 +8,15 @@ describe('ticket getVolume()', () => { const options = {transaction: tx}; const ticketId = 1; - const result = await models.Ticket.getVolume(ticketId, options); + const expectedSaleVolume = 1.09; + const expectedPackingTypeVolume = 0.028; - expect(result[0].volume).toEqual(1.09); + const result = await models.Ticket.getVolume(ticketId, options); + const [saleVolume] = result[0]; + const [packingTypeVolume] = result[1]; + + expect(saleVolume.volume).toEqual(expectedSaleVolume); + expect(packingTypeVolume.volume).toEqual(expectedPackingTypeVolume); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/front/locale/es.yml b/modules/ticket/front/locale/es.yml index 6e502ed7d..752dd7b36 100644 --- a/modules/ticket/front/locale/es.yml +++ b/modules/ticket/front/locale/es.yml @@ -37,6 +37,7 @@ Observation type: Tipo de observación Original: Original Package size: Bultos Package type: Tipo de porte +Packing type: Encajado Phone: Teléfono PPU: Ud. Price: Precio diff --git a/modules/ticket/front/volume/index.html b/modules/ticket/front/volume/index.html index 70bd4f5fb..8f17a9475 100644 --- a/modules/ticket/front/volume/index.html +++ b/modules/ticket/front/volume/index.html @@ -6,22 +6,17 @@ data="$ctrl.sales" limit="20"> - - - -
- - - - -
+
+ + + + +
@@ -29,6 +24,7 @@ Item Description + Packing type Quantity m³ per quantity @@ -55,6 +51,7 @@ tabindex="-1"> + {{::sale.item.itemPackingTypeFk}} {{::sale.quantity}} {{::sale.saleVolume.volume | number:3}} diff --git a/modules/ticket/front/volume/index.js b/modules/ticket/front/volume/index.js index ead46024b..81491bca0 100644 --- a/modules/ticket/front/volume/index.js +++ b/modules/ticket/front/volume/index.js @@ -23,24 +23,19 @@ class Controller extends Section { if (value) this.applyVolumes(); } - get volumes() { - return this._volumes; - } - - set volumes(value) { - this._volumes = value; - - if (value) this.applyVolumes(); - } - applyVolumes() { - if (!this.sales || !this.volumes) return; + const ticket = this.sales[0].ticketFk; + this.$http.get(`Tickets/${ticket}/getVolume`).then(res => { + const saleVolume = res.data.saleVolume; - this.sales.forEach(sale => { - this.volumes.forEach(volume => { - if (sale.id === volume.saleFk) - sale.saleVolume = volume; - }); + const volumes = new Map(); + for (const volume of saleVolume) + volumes.set(volume.saleFk, volume); + + for (const sale of this.sales) + sale.saleVolume = volumes.get(sale.id); + + this.packingTypeVolume = res.data.packingTypeVolume; }); } } diff --git a/modules/ticket/front/volume/index.spec.js b/modules/ticket/front/volume/index.spec.js index 5f6f433fb..6ab968503 100644 --- a/modules/ticket/front/volume/index.spec.js +++ b/modules/ticket/front/volume/index.spec.js @@ -33,17 +33,20 @@ describe('ticket', () => { }); }); - describe('volumes() setter', () => { - it('should set volumes property on controller an then call applyVolumes() method', () => { - jest.spyOn(controller, 'applyVolumes'); - - controller.volumes = [{id: 1}]; - - expect(controller.applyVolumes).toHaveBeenCalledWith(); - }); - }); - describe('applyVolumes()', () => { + const ticket = 1; + const response = + { + saleVolume: [ + {saleFk: 1, volume: 0.012}, + {saleFk: 2, volume: 0.015} + ], + packingTypeVolume: [ + {code: 'V', volume: 1}, + {code: 'H', volume: 2} + ] + }; + it(`should not apply volumes to the sales if sales property is not defined on controller`, () => { controller.sales = [{id: 1, name: 'Sale one'}, {id: 2, name: 'Sale two'}]; @@ -58,29 +61,32 @@ describe('ticket', () => { }); it(`should apply volumes to the sales if sales and volumes properties are defined on controller`, () => { - controller.sales = [{id: 1, name: 'Sale one'}, {id: 2, name: 'Sale two'}]; - controller.volumes = [{saleFk: 1, volume: 0.012}, {saleFk: 2, volume: 0.015}]; + const expectedResultOne = response.saleVolume[0].volume; + const expectedResultTwo = response.saleVolume[1].volume; + $httpBackend.expectGET(`Tickets/${ticket}/getVolume`).respond(response); + controller.sales = [ + {id: 1, name: 'Sale one', ticketFk: ticket}, + {id: 2, name: 'Sale two'} + ]; + $httpBackend.flush(); - expect(controller.sales[0].saleVolume.volume).toEqual(0.012); - expect(controller.sales[1].saleVolume.volume).toEqual(0.015); + expect(controller.sales[0].saleVolume.volume).toEqual(expectedResultOne); + expect(controller.sales[1].saleVolume.volume).toEqual(expectedResultTwo); + }); + + it(`should apply packing volumes to the sales if sales and volumes properties are defined on controller`, () => { + const expectedResultOne = response.packingTypeVolume[0].code; + const expectedResultTwo = response.packingTypeVolume[1].code; + $httpBackend.expectGET(`Tickets/${ticket}/getVolume`).respond(response); + controller.sales = [ + {id: 1, name: 'Sale one', ticketFk: ticket}, + {id: 2, name: 'Sale two'} + ]; + $httpBackend.flush(); + + expect(controller.packingTypeVolume[0].code).toEqual(expectedResultOne); + expect(controller.packingTypeVolume[1].code).toEqual(expectedResultTwo); }); }); - - /* - it('should join the sale volumes to its respective sale', () => { - controller.ticket = {id: 1}; - let response = {volumes: [ - {saleFk: 1, m3: 0.008}, - {saleFk: 2, m3: 0.003} - ]}; - - $httpBackend.expectGET(`tickets/1/getVolume`).respond(response); - controller.onDataChange(); - $httpBackend.flush(); - - expect($scope.model.data[0].volume.m3).toBe(0.008); - expect($scope.model.data[1].volume.m3).toBe(0.003); - }); - */ }); });