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');
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

View File

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

View File

@ -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) {

View File

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

View File

@ -6,22 +6,17 @@
data="$ctrl.sales"
limit="20">
</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-card class="vn-pa-lg">
<vn-horizontal>
<div class="totalBox">
<vn-label-value label="Total"
value="{{::edit.model.totalVolume}}">
</vn-label-value>
<vn-label-value label="Cajas"
value="{{::edit.model.totalBoxes}}">
</vn-label-value>
</div>
<div class="totalBox" ng-repeat="packingType in $ctrl.packingTypeVolume">
<vn-label-value label="Tipo"
value="{{::packingType.description}}">
</vn-label-value>
<vn-label-value label="Volumen"
value="{{::packingType.volume}}">
</vn-label-value>
</div>
</vn-horizontal>
<vn-vertical>
<vn-table model="model">
@ -29,6 +24,7 @@
<vn-tr>
<vn-th field="itemFk" number>Item</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 number>m³ per quantity</vn-th>
</vn-tr>
@ -55,6 +51,7 @@
tabindex="-1">
</vn-fetched-tags>
</vn-td>
<vn-td number>{{::sale.item.itemPackingTypeFk}}</vn-td>
<vn-td number>{{::sale.quantity}}</vn-td>
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>
</vn-tr>

View File

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

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()', () => {
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);
});
*/
});
});