3491-ticket_volume #847

Merged
carlosjr merged 5 commits from 3491-ticket_volume into dev 2022-01-17 13:02:16 +00:00
8 changed files with 146 additions and 85 deletions

View File

@ -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 ;

View File

@ -799,25 +799,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
('VT', 'Sales'); ('VT', 'Sales');
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, 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 VALUES
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, '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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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); (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 the taxClass after insert of the items
UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2

View File

@ -9,10 +9,14 @@ module.exports = Self => {
description: 'ticket id', description: 'ticket id',
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: [{
type: ['Object'], arg: 'saleVolume',
root: true type: ['object']
}, },
{
arg: 'packingTypeVolume',
type: ['object']
}],
http: { http: {
path: `/:id/getVolume`, path: `/:id/getVolume`,
verb: 'GET' verb: 'GET'
@ -25,7 +29,21 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
return Self.rawSql(`SELECT * FROM vn.saleVolume const saleVolume = await Self.rawSql(`
SELECT saleFk, volume
FROM vn.saleVolume
WHERE ticketFk = ?`, [ticketFk], myOptions); 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];
}; };
}; };

View File

@ -8,9 +8,15 @@ describe('ticket getVolume()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
const ticketId = 1; 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(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -37,6 +37,7 @@ Observation type: Tipo de observación
Original: Original Original: Original
Package size: Bultos Package size: Bultos
Package type: Tipo de porte Package type: Tipo de porte
Packing type: Encajado
Phone: Teléfono Phone: Teléfono
PPU: Ud. PPU: Ud.
Price: Precio Price: Precio

View File

@ -6,20 +6,15 @@
data="$ctrl.sales" data="$ctrl.sales"
limit="20"> limit="20">
</vn-crud-model> </vn-crud-model>
<vn-crud-model auto-load="true"
url="tickets/{{$ctrl.$params.id}}/getVolume"
data="$ctrl.volumes">
</vn-crud-model>
<mg-ajax path="tickets/{{$ctrl.$params.id}}/getTotalVolume" options="mgEdit"></mg-ajax>
<vn-vertical> <vn-vertical>
<vn-card class="vn-pa-lg"> <vn-card class="vn-pa-lg">
<vn-horizontal> <vn-horizontal>
<div class="totalBox"> <div class="totalBox" ng-repeat="packingType in $ctrl.packingTypeVolume">
<vn-label-value label="Total" <vn-label-value label="Tipo"
value="{{::edit.model.totalVolume}}"> value="{{::packingType.description}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Cajas" <vn-label-value label="Volumen"
value="{{::edit.model.totalBoxes}}"> value="{{::packingType.volume}}">
</vn-label-value> </vn-label-value>
</div> </div>
</vn-horizontal> </vn-horizontal>
@ -29,6 +24,7 @@
<vn-tr> <vn-tr>
<vn-th field="itemFk" number>Item</vn-th> <vn-th field="itemFk" number>Item</vn-th>
<vn-th field="concept" default-order="ASC">Description</vn-th> <vn-th field="concept" default-order="ASC">Description</vn-th>
<vn-th field="itemPackingTypeFk" number>Packing type</vn-th>
<vn-th field="quantity" number>Quantity</vn-th> <vn-th field="quantity" number>Quantity</vn-th>
<vn-th number>m³ per quantity</vn-th> <vn-th number>m³ per quantity</vn-th>
</vn-tr> </vn-tr>
@ -55,6 +51,7 @@
tabindex="-1"> tabindex="-1">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.item.itemPackingTypeFk}}</vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td> <vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>
</vn-tr> </vn-tr>

View File

@ -23,24 +23,19 @@ class Controller extends Section {
if (value) this.applyVolumes(); if (value) this.applyVolumes();
} }
get volumes() {
return this._volumes;
}
set volumes(value) {
this._volumes = value;
if (value) this.applyVolumes();
}
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 => { const volumes = new Map();
this.volumes.forEach(volume => { for (const volume of saleVolume)
if (sale.id === volume.saleFk) volumes.set(volume.saleFk, volume);
sale.saleVolume = volume;
}); for (const sale of this.sales)
sale.saleVolume = volumes.get(sale.id);
this.packingTypeVolume = res.data.packingTypeVolume;
}); });
} }
} }

View File

@ -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()', () => { 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`, () => { 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'}]; 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`, () => { 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'}]; const expectedResultOne = response.saleVolume[0].volume;
controller.volumes = [{saleFk: 1, volume: 0.012}, {saleFk: 2, volume: 0.015}]; const expectedResultTwo = response.saleVolume[1].volume;
$httpBackend.expectGET(`Tickets/${ticket}/getVolume`).respond(response);
expect(controller.sales[0].saleVolume.volume).toEqual(0.012); controller.sales = [
expect(controller.sales[1].saleVolume.volume).toEqual(0.015); {id: 1, name: 'Sale one', ticketFk: ticket},
}); {id: 2, name: 'Sale two'}
}); ];
/*
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(); $httpBackend.flush();
expect($scope.model.data[0].volume.m3).toBe(0.008); expect(controller.sales[0].saleVolume.volume).toEqual(expectedResultOne);
expect($scope.model.data[1].volume.m3).toBe(0.003); 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);
});
}); });
*/
}); });
}); });