Merge pull request '2615-waste_detail' (#595) from 2615-waste_detail into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #595 Reviewed-by: Carlos Jimenez Ruiz <carlosjr@verdnatura.es>
This commit is contained in:
commit
fba7d4b1c4
|
@ -1 +0,0 @@
|
||||||
Delete this
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
CREATE OR REPLACE DEFINER = root@`%` VIEW `vn`.`saleValue` AS
|
||||||
|
SELECT `wh`.`name` AS `warehouse`,
|
||||||
|
`c`.`name` AS `client`,
|
||||||
|
`c`.`typeFk` AS `clientTypeFk`,
|
||||||
|
`u`.`name` AS `buyer`,
|
||||||
|
`it`.`id` AS `itemTypeFk`,
|
||||||
|
`it`.`name` AS `family`,
|
||||||
|
`s`.`itemFk` AS `itemFk`,
|
||||||
|
`s`.`concept` AS `concept`,
|
||||||
|
`s`.`quantity` AS `quantity`,
|
||||||
|
`b`.`buyingValue` + `b`.`freightValue` + `b`.`comissionValue` + `b`.`packageValue` AS `cost`,
|
||||||
|
(`b`.`buyingValue` + `b`.`freightValue` + `b`.`comissionValue` + `b`.`packageValue`) * `s`.`quantity` AS `value`,
|
||||||
|
`tm`.`year` AS `year`,
|
||||||
|
`tm`.`week` AS `week`
|
||||||
|
FROM `vn`.`sale` `s`
|
||||||
|
JOIN `vn`.`item` `i` ON `i`.`id` = `s`.`itemFk`
|
||||||
|
JOIN `vn`.`itemType` `it` ON `it`.`id` = `i`.`typeFk`
|
||||||
|
JOIN `account`.`user` `u` ON `u`.`id` = `it`.`workerFk`
|
||||||
|
JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`
|
||||||
|
JOIN `vn`.`client` `c` ON `c`.`id` = `t`.`clientFk`
|
||||||
|
JOIN `vn`.`warehouse` `wh` ON `wh`.`id` = `t`.`warehouseFk`
|
||||||
|
JOIN `vn`.`time` `tm` ON `tm`.`dated` = CAST(`t`.`shipped` AS DATE)
|
||||||
|
JOIN `cache`.`last_buy` `lb` ON `lb`.`item_id` = `i`.`id` AND `lb`.`warehouse_id` = `wh`.`id`
|
||||||
|
JOIN `vn`.`buy` `b` ON `b`.`id` = `lb`.`buy_id`
|
||||||
|
WHERE `wh`.`isManaged` <> 0;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
drop procedure weekWaste;
|
||||||
|
|
||||||
|
create definer = root@`%` procedure weekWaste__()
|
||||||
|
BEGIN
|
||||||
|
DECLARE vWeek INT;
|
||||||
|
DECLARE vYear INT;
|
||||||
|
|
||||||
|
SELECT week, year
|
||||||
|
INTO vWeek, vYear
|
||||||
|
FROM vn.time
|
||||||
|
WHERE dated = DATE_ADD(CURDATE(), INTERVAL -1 WEEK);
|
||||||
|
|
||||||
|
SELECT *, 100 * dwindle / total AS percentage
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
sum(saleTotal) as total,
|
||||||
|
sum(saleWaste) as dwindle
|
||||||
|
FROM bs.waste
|
||||||
|
WHERE year = vYear and week = vWeek
|
||||||
|
GROUP BY buyer
|
||||||
|
) sub
|
||||||
|
ORDER BY percentage DESC;
|
||||||
|
END;
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
drop procedure weekWaste_byWorker;
|
||||||
|
|
||||||
|
create definer = root@`%` procedure weekWaste_byWorker__(IN vWorkerFk int)
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
DECLARE vWeek INT;
|
||||||
|
DECLARE vYear INT;
|
||||||
|
|
||||||
|
SELECT week, year
|
||||||
|
INTO vWeek, vYear
|
||||||
|
FROM vn.time
|
||||||
|
WHERE dated = TIMESTAMPADD(WEEK,-1,CURDATE());
|
||||||
|
|
||||||
|
SELECT *, 100 * mermas / total as porcentaje
|
||||||
|
FROM (
|
||||||
|
SELECT ws.family,
|
||||||
|
sum(ws.saleTotal) as total,
|
||||||
|
sum(ws.saleWaste) as mermas
|
||||||
|
FROM bs.waste ws
|
||||||
|
JOIN vn.worker w ON w.user = ws.buyer
|
||||||
|
WHERE year = vYear AND week = vWeek
|
||||||
|
AND w.id = vWorkerFk
|
||||||
|
GROUP BY family
|
||||||
|
|
||||||
|
) sub
|
||||||
|
ORDER BY porcentaje DESC;
|
||||||
|
END;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
drop procedure weekWaste_getDetail;
|
||||||
|
|
||||||
|
create definer = root@`%` procedure weekWaste_getDetail__()
|
||||||
|
BEGIN
|
||||||
|
DECLARE vLastWeek DATE;
|
||||||
|
DECLARE vWeek INT;
|
||||||
|
DECLARE vYear INT;
|
||||||
|
|
||||||
|
SET vLastWeek = TIMESTAMPADD(WEEK,-1,CURDATE());
|
||||||
|
SET vYear = YEAR(vLastWeek);
|
||||||
|
SET vWeek = WEEK(vLastWeek, 1);
|
||||||
|
|
||||||
|
SELECT *, 100 * dwindle / total AS percentage
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
ws.family,
|
||||||
|
sum(ws.saleTotal) AS total,
|
||||||
|
sum(ws.saleWaste) AS dwindle
|
||||||
|
FROM bs.waste ws
|
||||||
|
WHERE year = vYear AND week = vWeek
|
||||||
|
GROUP BY buyer, family
|
||||||
|
) sub
|
||||||
|
ORDER BY percentage DESC;
|
||||||
|
END;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
ALTER TABLE `bs`.`waste`
|
||||||
|
ADD itemFk INT NULL AFTER `family`;
|
||||||
|
|
||||||
|
ALTER TABLE `bs`.`waste`
|
||||||
|
ADD itemTypeFk SMALLINT(5) UNSIGNED NULL AFTER `itemFk`;
|
||||||
|
|
||||||
|
ALTER TABLE `bs`.`waste`
|
||||||
|
ADD CONSTRAINT waste_itemType_id
|
||||||
|
FOREIGN KEY (itemTypeFk) REFERENCES vn.itemType (id)
|
||||||
|
ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE `bs`.`waste`
|
||||||
|
ADD CONSTRAINT waste_item_id
|
||||||
|
FOREIGN KEY (itemFk) REFERENCES vn.item (id)
|
||||||
|
ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE `bs`.`waste` DROP PRIMARY KEY;
|
||||||
|
|
||||||
|
ALTER TABLE `bs`.`waste`
|
||||||
|
AD PRIMARY KEY (buyer, year, week, family, itemFk);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
UPDATE `bs`.nightTask t SET t.`procedure` = 'waste_addSales' WHERE t.id = 54;
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS `bs`.`waste_Add`;
|
||||||
|
|
||||||
|
CREATE
|
||||||
|
DEFINER = root@`%` PROCEDURE `bs`.`waste_addSales`()
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
DECLARE vWeek INT;
|
||||||
|
DECLARE vYear INT;
|
||||||
|
|
||||||
|
SELECT week, year
|
||||||
|
INTO vWeek, vYear
|
||||||
|
FROM vn.time
|
||||||
|
WHERE dated = CURDATE();
|
||||||
|
|
||||||
|
REPLACE bs.waste
|
||||||
|
SELECT *, 100 * mermas / total as porcentaje
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
year,
|
||||||
|
week,
|
||||||
|
family,
|
||||||
|
itemFk,
|
||||||
|
itemTypeFk,
|
||||||
|
floor(sum(value)) as total,
|
||||||
|
floor(sum(IF(clientTypeFk = 'loses', value, 0))) as mermas
|
||||||
|
FROM vn.saleValue
|
||||||
|
where year = vYear and week = vWeek
|
||||||
|
|
||||||
|
GROUP BY family, itemFk
|
||||||
|
|
||||||
|
) sub
|
||||||
|
ORDER BY mermas DESC;
|
||||||
|
|
||||||
|
END;
|
||||||
|
|
||||||
|
|
|
@ -1300,18 +1300,23 @@ INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRa
|
||||||
(103, 2000, 0.00, 0.00, 0.02, 1.00),
|
(103, 2000, 0.00, 0.00, 0.02, 1.00),
|
||||||
(104, 2500, 150.00, 0.02, 0.10, 1.00);
|
(104, 2500, 150.00, 0.02, 0.10, 1.00);
|
||||||
|
|
||||||
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `saleTotal`, `saleWaste`, `rate`)
|
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `itemFk`, `itemTypeFk`, `saleTotal`, `saleWaste`, `rate`)
|
||||||
VALUES
|
VALUES
|
||||||
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation', '1062', '51', '4.8'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation', 1, 1, '1062', '51', '4.8'),
|
||||||
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Colombia', '35074', '687', '2.0'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Colombia', 2, 1, '35074', '687', '2.0'),
|
||||||
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Mini', '1777', '13', '0.7'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Mini', 3, 1, '1777', '13', '0.7'),
|
||||||
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Short', '9182', '59', '0.6'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Carnation Short', 4, 1, '3182', '59', '0.6'),
|
||||||
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Containers', '-74', '0', '0.0'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Crisantemo', 5, 1, '1747', '13', '0.7'),
|
||||||
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Packagings', '-7', '0', '0.0'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Lilium Oriental', 6, 1, '7182', '59', '0.6'),
|
||||||
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Freight', '1100', '0', '0.0'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Alstroemeria', 7, 1, '1777', '13', '0.7'),
|
||||||
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Funeral Accessories', '848', '-187', '-22.1'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Cymbidium', 1, 1, '4181', '59', '0.6'),
|
||||||
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Miscellaneous Accessories', '186', '0', '0.0'),
|
('CharlesXavier', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Cymbidium', 2, 1, '7268', '59', '0.6'),
|
||||||
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Adhesives', '277', '0', '0.0');
|
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Containers', 2, 1, '-74', '0', '0.0'),
|
||||||
|
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Packagings', 3, 1, '-7', '0', '0.0'),
|
||||||
|
('DavidCharlesHaller', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Freight', 4, 1, '1100', '0', '0.0'),
|
||||||
|
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Funeral Accessories', 5, 1, '848', '-187', '-22.1'),
|
||||||
|
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Miscellaneous Accessories', 6, 1, '186', '0', '0.0'),
|
||||||
|
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Adhesives', 7, 1, '277', '0', '0.0');
|
||||||
|
|
||||||
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`producer`,`printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`)
|
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`producer`,`printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -77,9 +77,10 @@ class Controller extends Section {
|
||||||
if (sampleType.hasCompany)
|
if (sampleType.hasCompany)
|
||||||
params.companyId = this.clientSample.companyFk;
|
params.companyId = this.clientSample.companyFk;
|
||||||
|
|
||||||
if (isPreview) params.isPreview = true;
|
let query = `email/${sampleType.code}`;
|
||||||
|
if (isPreview)
|
||||||
|
query = `email/${sampleType.code}/preview`;
|
||||||
|
|
||||||
const query = `email/${sampleType.code}`;
|
|
||||||
this.$http.get(query, {params}).then(cb);
|
this.$http.get(query, {params}).then(cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getWasteByItem', {
|
||||||
|
description: 'Returns the details of losses by worker and item',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'buyer',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The buyer name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'family',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The item family name'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['Object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getWasteByItem`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getWasteByItem = async(buyer, family) => {
|
||||||
|
const wastes = await Self.rawSql(`
|
||||||
|
SELECT *, 100 * dwindle / total AS percentage
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
ws.family,
|
||||||
|
ws.itemFk,
|
||||||
|
sum(ws.saleTotal) AS total,
|
||||||
|
sum(ws.saleWaste) AS dwindle
|
||||||
|
FROM bs.waste ws
|
||||||
|
WHERE buyer = ? AND family = ?
|
||||||
|
AND year = YEAR(TIMESTAMPADD(WEEK,-1,CURDATE()))
|
||||||
|
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
|
||||||
|
GROUP BY buyer, itemFk
|
||||||
|
) sub
|
||||||
|
ORDER BY family, percentage DESC`, [buyer, family]);
|
||||||
|
|
||||||
|
const details = [];
|
||||||
|
|
||||||
|
for (let waste of wastes) {
|
||||||
|
const buyerName = waste.buyer;
|
||||||
|
|
||||||
|
let buyerDetail = details.find(waste => {
|
||||||
|
return waste.buyer == buyerName;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!buyerDetail) {
|
||||||
|
buyerDetail = {
|
||||||
|
buyer: buyerName,
|
||||||
|
family: waste.family,
|
||||||
|
lines: []
|
||||||
|
};
|
||||||
|
details.push(buyerDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
buyerDetail.lines.push(waste);
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('getWasteDetail', {
|
Self.remoteMethod('getWasteByWorker', {
|
||||||
description: 'Returns the details of losses by worker',
|
description: 'Returns the details of losses by worker',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [],
|
accepts: [],
|
||||||
|
@ -8,13 +8,25 @@ module.exports = Self => {
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
path: `/getWasteDetail`,
|
path: `/getWasteByWorker`,
|
||||||
verb: 'GET'
|
verb: 'GET'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getWasteDetail = async() => {
|
Self.getWasteByWorker = async() => {
|
||||||
const [wastes] = await Self.rawSql(`CALL bs.weekWaste_getDetail()`);
|
const wastes = await Self.rawSql(`
|
||||||
|
SELECT *, 100 * dwindle / total AS percentage
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
ws.family,
|
||||||
|
sum(ws.saleTotal) AS total,
|
||||||
|
sum(ws.saleWaste) AS dwindle
|
||||||
|
FROM bs.waste ws
|
||||||
|
WHERE year = YEAR(TIMESTAMPADD(WEEK,-1,CURDATE()))
|
||||||
|
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
|
||||||
|
GROUP BY buyer, family
|
||||||
|
) sub
|
||||||
|
ORDER BY percentage DESC`);
|
||||||
|
|
||||||
const details = [];
|
const details = [];
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Item getWasteByItem()', () => {
|
||||||
|
it('should check for the waste breakdown by worker and item', async() => {
|
||||||
|
const result = await app.models.Item.getWasteByItem('CharlesXavier', 'Cymbidium');
|
||||||
|
|
||||||
|
const length = result.length;
|
||||||
|
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
|
||||||
|
|
||||||
|
expect(anyResult.buyer).toEqual('CharlesXavier');
|
||||||
|
expect(anyResult.family).toEqual('Cymbidium');
|
||||||
|
expect(anyResult.lines.length).toBeGreaterThanOrEqual(2);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,8 +1,8 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('item getWasteDetail()', () => {
|
describe('Item getWasteByWorker()', () => {
|
||||||
it('should check for the waste breakdown for every worker', async() => {
|
it('should check for the waste breakdown for every worker', async() => {
|
||||||
const result = await app.models.Item.getWasteDetail();
|
const result = await app.models.Item.getWasteByWorker();
|
||||||
|
|
||||||
const length = result.length;
|
const length = result.length;
|
||||||
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
|
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
|
|
@ -11,7 +11,8 @@ module.exports = Self => {
|
||||||
require('../methods/item/regularize')(Self);
|
require('../methods/item/regularize')(Self);
|
||||||
require('../methods/item/getVisibleAvailable')(Self);
|
require('../methods/item/getVisibleAvailable')(Self);
|
||||||
require('../methods/item/new')(Self);
|
require('../methods/item/new')(Self);
|
||||||
require('../methods/item/getWasteDetail')(Self);
|
require('../methods/item/getWasteByWorker')(Self);
|
||||||
|
require('../methods/item/getWasteByItem')(Self);
|
||||||
require('../methods/item/createIntrastat')(Self);
|
require('../methods/item/createIntrastat')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
||||||
|
|
|
@ -20,7 +20,8 @@ import './niche';
|
||||||
import './botanical';
|
import './botanical';
|
||||||
import './barcode';
|
import './barcode';
|
||||||
import './summary';
|
import './summary';
|
||||||
import './waste';
|
import './waste/index/';
|
||||||
|
import './waste/detail';
|
||||||
import './fixed-price';
|
import './fixed-price';
|
||||||
import './fixed-price-search-panel';
|
import './fixed-price-search-panel';
|
||||||
|
|
||||||
|
|
|
@ -63,4 +63,5 @@ Diary: Histórico
|
||||||
Item diary: Registro de compra-venta
|
Item diary: Registro de compra-venta
|
||||||
Last entries: Últimas entradas
|
Last entries: Últimas entradas
|
||||||
Tags: Etiquetas
|
Tags: Etiquetas
|
||||||
Waste breakdown: Desglose de mermas
|
Waste breakdown: Desglose de mermas
|
||||||
|
Waste breakdown by item: Desglose de mermas por artículo
|
|
@ -8,7 +8,7 @@
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "item.index", "icon": "icon-item"},
|
{"state": "item.index", "icon": "icon-item"},
|
||||||
{"state": "item.request", "icon": "pan_tool"},
|
{"state": "item.request", "icon": "pan_tool"},
|
||||||
{"state": "item.waste", "icon": "icon-claims"},
|
{"state": "item.waste.index", "icon": "icon-claims"},
|
||||||
{"state": "item.fixedPrice", "icon": "contact_support"}
|
{"state": "item.fixedPrice", "icon": "contact_support"}
|
||||||
],
|
],
|
||||||
"card": [
|
"card": [
|
||||||
|
@ -155,12 +155,25 @@
|
||||||
"acl": ["employee"]
|
"acl": ["employee"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url" : "/waste",
|
"url": "/waste",
|
||||||
"state": "item.waste",
|
"state": "item.waste",
|
||||||
"component": "vn-item-waste",
|
"component": "ui-view",
|
||||||
|
"abstract": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url" : "/index",
|
||||||
|
"state": "item.waste.index",
|
||||||
|
"component": "vn-item-waste-index",
|
||||||
"description": "Waste breakdown",
|
"description": "Waste breakdown",
|
||||||
"acl": ["buyer"]
|
"acl": ["buyer"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url" : "/detail?buyer&family",
|
||||||
|
"state": "item.waste.detail",
|
||||||
|
"component": "vn-item-waste-detail",
|
||||||
|
"description": "Waste breakdown by item",
|
||||||
|
"acl": ["buyer"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url" : "/fixed-price?q",
|
"url" : "/fixed-price?q",
|
||||||
"state": "item.fixedPrice",
|
"state": "item.fixedPrice",
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<vn-crud-model auto-load="true"
|
||||||
|
vn-id="model"
|
||||||
|
url="Items/getWasteByItem"
|
||||||
|
params="$ctrl.$params"
|
||||||
|
data="details">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-data-viewer model="model">
|
||||||
|
<vn-card class="vn-w-md">
|
||||||
|
<section ng-repeat="detail in details" class="vn-pa-md">
|
||||||
|
<vn-horizontal class="header">
|
||||||
|
<h5>{{detail.family}} ({{detail.buyer}})</h5>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-table>
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th shrink>Item</vn-th>
|
||||||
|
<vn-th number>Percentage</vn-th>
|
||||||
|
<vn-th number>Dwindle</vn-th>
|
||||||
|
<vn-th number>Total</vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="waste in detail.lines">
|
||||||
|
<vn-td shrink>
|
||||||
|
<span
|
||||||
|
ng-click="descriptor.show($event, waste.itemFk)"
|
||||||
|
class="link">
|
||||||
|
{{::waste.itemFk}}
|
||||||
|
</span>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
|
||||||
|
<vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
|
||||||
|
<vn-td number>{{::waste.total | currency: 'EUR'}}</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
</vn-table>
|
||||||
|
</section>
|
||||||
|
</vn-card>
|
||||||
|
</vn-data-viewer>
|
||||||
|
<vn-item-descriptor-popover
|
||||||
|
vn-id="descriptor">
|
||||||
|
</vn-item-descriptor-popover>
|
|
@ -0,0 +1,7 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnItemWasteDetail', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Section
|
||||||
|
});
|
|
@ -1,13 +1,14 @@
|
||||||
<vn-crud-model auto-load="true"
|
<vn-crud-model auto-load="true"
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="Items/getWasteDetail"
|
url="Items/getWasteByWorker"
|
||||||
data="details">
|
data="details">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
|
||||||
<vn-data-viewer model="model">
|
<vn-data-viewer model="model">
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<section ng-repeat="detail in details" class="vn-pa-md">
|
<section ng-repeat="detail in details" class="vn-pa-md">
|
||||||
<vn-horizontal class="header">
|
<vn-horizontal class="header">
|
||||||
<h5><span translate>{{detail.buyer}}</span></h5>
|
<h5><span><span translate>{{detail.buyer}}</span></h5>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-table>
|
<vn-table>
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
|
@ -19,7 +20,8 @@
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="waste in detail.lines">
|
<a ng-repeat="waste in detail.lines" class="clickable vn-tr"
|
||||||
|
ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})" >
|
||||||
<vn-td class="waste-family">{{::waste.family}}</vn-td>
|
<vn-td class="waste-family">{{::waste.family}}</vn-td>
|
||||||
<vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
|
<vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
|
||||||
<vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
|
<vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
|
|
@ -1,8 +1,8 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
ngModule.vnComponent('vnItemWaste', {
|
ngModule.vnComponent('vnItemWasteIndex', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Section
|
controller: Section
|
||||||
});
|
});
|
|
@ -0,0 +1,26 @@
|
||||||
|
@import "variables";
|
||||||
|
|
||||||
|
vn-item-waste-index,
|
||||||
|
vn-item-waste-detail {
|
||||||
|
.header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 7px;
|
||||||
|
padding-bottom: 7px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
font-weight: lighter;
|
||||||
|
background-color: #fde6ca;
|
||||||
|
border-bottom: 1px solid #f7931e;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
vn-table vn-th.waste-family,
|
||||||
|
vn-table vn-td.waste-family {
|
||||||
|
max-width: 64px;
|
||||||
|
width: 64px
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ const imageSrc = {
|
||||||
getEmailSrc(image) {
|
getEmailSrc(image) {
|
||||||
let src = `cid:${image}`;
|
let src = `cid:${image}`;
|
||||||
|
|
||||||
if (this.isPreview === 'true')
|
if (this.isPreview)
|
||||||
src = `/api/${this.$options.name}/assets/images/${image}`;
|
src = `/api/${this.$options.name}/assets/images/${image}`;
|
||||||
|
|
||||||
return src;
|
return src;
|
||||||
|
|
|
@ -6,17 +6,26 @@ module.exports = app => {
|
||||||
const reportName = req.params.name;
|
const reportName = req.params.name;
|
||||||
const email = new Email(reportName, req.args);
|
const email = new Email(reportName, req.args);
|
||||||
|
|
||||||
if (req.args.isPreview === 'true') {
|
await email.send();
|
||||||
const rendered = await email.render();
|
|
||||||
|
|
||||||
res.send(rendered);
|
res.status(200).json({
|
||||||
} else {
|
message: 'Sent'
|
||||||
await email.send();
|
});
|
||||||
|
} catch (e) {
|
||||||
|
next(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
res.status(200).json({
|
app.get(`/api/email/:name/preview`, async(req, res, next) => {
|
||||||
message: 'Sent'
|
try {
|
||||||
});
|
const reportName = req.params.name;
|
||||||
}
|
const args = req.args;
|
||||||
|
args.isPreview = true;
|
||||||
|
|
||||||
|
const email = new Email(reportName, args);
|
||||||
|
const rendered = await email.render();
|
||||||
|
|
||||||
|
res.send(rendered);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
next(e);
|
next(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const Component = require(`${appPath}/core/component`);
|
const Component = require(`${appPath}/core/component`);
|
||||||
const db = require(`${appPath}/core/database`);
|
|
||||||
const emailHeader = new Component('email-header');
|
const emailHeader = new Component('email-header');
|
||||||
const emailFooter = new Component('email-footer');
|
const emailFooter = new Component('email-footer');
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchWastes() {
|
fetchWastes() {
|
||||||
return db.findOne(`CALL bs.weekWaste()`);
|
return this.rawSqlFromDef('wasteWeekly');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
SELECT *, 100 * dwindle / total AS percentage
|
||||||
|
FROM (
|
||||||
|
SELECT buyer,
|
||||||
|
sum(saleTotal) as total,
|
||||||
|
sum(saleWaste) as dwindle
|
||||||
|
FROM bs.waste w
|
||||||
|
JOIN vn.time t ON w.year = t.year AND w.week = t.week
|
||||||
|
WHERE t.dated = DATE_ADD(CURDATE(), INTERVAL -1 WEEK)
|
||||||
|
GROUP BY buyer
|
||||||
|
) sub
|
||||||
|
ORDER BY percentage DESC;
|
Loading…
Reference in New Issue