Merge branch '2008-item_buyer_waste_detail' of verdnatura/salix into dev
gitea/salix/dev This commit looks good Details

This commit is contained in:
Bernat Exposito 2020-01-16 13:42:12 +00:00 committed by Gitea
commit e1aefc795b
21 changed files with 4675 additions and 18 deletions

View File

@ -1135,6 +1135,19 @@ INSERT INTO `bi`.`claims_ratio`(`id_Cliente`, `Consumo`, `Reclamaciones`, `Ratio
(103, 2000, 0.00, 0.00, 0.02, 1.00),
(104, 2500, 150.00, 0.02, 0.10, 1.00);
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `saleTotal`, `saleWaste`, `rate`)
VALUES
('CharlesXavier', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Carnation', '1062', '51', '4.8'),
('CharlesXavier', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Carnation Colombia', '35074', '687', '2.0'),
('CharlesXavier', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Carnation Mini', '1777', '13', '0.7'),
('CharlesXavier', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Carnation Short', '9182', '59', '0.6'),
('DavidCharlesHaller', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Containers', '-74', '0', '0.0'),
('DavidCharlesHaller', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Packagings', '-7', '0', '0.0'),
('DavidCharlesHaller', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Freight', '1100', '0', '0.0'),
('HankPym', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Funeral Accessories', '848', '-187', '-22.1'),
('HankPym', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Miscellaneous Accessories', '186', '0', '0.0'),
('HankPym', YEAR(CURDATE()), WEEK(CURDATE(), 1), 'Adhesives', '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`,`minPrice`,`producer`,`printedStickers`,`isChecked`,`isIgnored`, `created`)
VALUES
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
SCHEMAS=(
account
bi
bs
cache
edi
hedera

View File

@ -29,7 +29,7 @@ describe('Ticket List sale path', () => {
const value = await nightmare
.waitToGetProperty(selectors.ticketSales.firstSaleDiscount, 'innerText');
expect(value).toContain('0 %');
expect(value).toContain('0.00%');
});
it('should confirm the first sale contains the total import', async() => {

View File

@ -173,10 +173,10 @@ xdescribe('Ticket Edit sale path', () => {
it('should confirm the discount have been updated', async() => {
const result = await nightmare
.waitForTextInElement(`${selectors.ticketSales.firstSaleDiscount} > span`, '50 %')
.waitForTextInElement(`${selectors.ticketSales.firstSaleDiscount} > span`, '50.00%')
.waitToGetProperty(`${selectors.ticketSales.firstSaleDiscount} > span`, 'innerText');
expect(result).toContain('50 %');
expect(result).toContain('50.00%');
});
it('should confirm the total import for that item have been updated', async() => {

View File

@ -1,15 +1,22 @@
import ngModule from '../module';
/**
* Formats a number multiplying by 100 and adding character %.
*
* @return {String} The formated number
*/
export default function percentage() {
return function(input) {
export default function percentage($translate) {
function percentage(input, fractionSize = 2) {
if (input == null || input === '')
return null;
return `${input} %`;
};
return new Intl.NumberFormat($translate.use(), {
style: 'percent',
minimumFractionDigits: fractionSize,
maximumFractionDigits: fractionSize
}).format(parseFloat(input));
}
percentage.$stateful = true;
return percentage;
}
percentage.$inject = ['$translate'];
ngModule.filter('percentage', percentage);

View File

@ -0,0 +1,52 @@
module.exports = Self => {
Self.remoteMethod('getWasteDetail', {
description: 'Returns the ',
accessType: 'READ',
accepts: [],
returns: {
type: ['Object'],
root: true
},
http: {
path: `/getWasteDetail`,
verb: 'GET'
}
});
Self.getWasteDetail = async() => {
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(CURDATE()) AND week = WEEK(CURDATE(), 1)
GROUP BY buyer, family
) sub
ORDER BY percentage DESC;`);
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,
lines: []
};
details.push(buyerDetail);
}
buyerDetail.lines.push(waste);
}
return details;
};
};

View File

@ -0,0 +1,23 @@
const app = require('vn-loopback/server/server');
describe('item getWasteDetail()', () => {
it('should check for the waste breakdown for every worker', async() => {
let result = await app.models.Item.getWasteDetail();
const firstBuyer = result[0].buyer;
const firstBuyerLines = result[0].lines;
const secondBuyer = result[1].buyer;
const secondBuyerLines = result[1].lines;
const thirdBuyer = result[2].buyer;
const thirdBuyerLines = result[2].lines;
expect(result.length).toEqual(3);
expect(firstBuyer).toEqual('CharlesXavier');
expect(firstBuyerLines.length).toEqual(4);
expect(secondBuyer).toEqual('DavidCharlesHaller');
expect(secondBuyerLines.length).toEqual(3);
expect(thirdBuyer).toEqual('HankPym');
expect(thirdBuyerLines.length).toEqual(3);
});
});

View File

@ -11,6 +11,7 @@ module.exports = Self => {
require('../methods/item/regularize')(Self);
require('../methods/item/getVisibleAvailable')(Self);
require('../methods/item/new')(Self);
require('../methods/item/getWasteDetail')(Self);
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});

View File

@ -20,4 +20,5 @@ import './niche';
import './botanical';
import './barcode';
import './summary';
import './waste';

View File

@ -60,4 +60,5 @@ Barcodes: Códigos de barras
Diary: Histórico
Item diary: Registro de compra-venta
Last entries: Últimas entradas
Tags: Etiquetas
Tags: Etiquetas
Waste breakdown: Desglose de mermas

View File

@ -7,7 +7,8 @@
"menus": {
"main": [
{"state": "item.index", "icon": "icon-item"},
{"state": "item.request", "icon": "pan_tool"}
{"state": "item.request", "icon": "pan_tool"},
{"state": "item.waste", "icon": "icon-claims"}
],
"card": [
{"state": "item.card.basicData", "icon": "settings"},
@ -137,6 +138,12 @@
"item": "$ctrl.item"
},
"acl": ["employee"]
}, {
"url" : "/waste",
"state": "item.waste",
"component": "vn-item-waste",
"description": "Waste breakdown",
"acl": ["buyer"]
}
]
}

View File

@ -0,0 +1,32 @@
<vn-crud-model auto-load="true"
vn-id="model"
url="Items/getWasteDetail"
data="details">
</vn-crud-model>
<vn-data-viewer model="model">
<vn-card>
<section ng-repeat="detail in details" class="vn-pa-md">
<vn-horizontal class="header">
<h5><span translate>{{detail.buyer}}</span></h5>
</vn-horizontal>
<vn-table>
<vn-thead>
<vn-tr>
<vn-th>Family</vn-th>
<vn-th shrink>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>{{::waste.family}}</vn-td>
<vn-td shrink>{{::(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>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
import Component from 'core/lib/component';
import './style.scss';
ngModule.component('vnItemWaste', {
template: require('./index.html'),
controller: Component
});

View File

@ -0,0 +1,3 @@
Family: Familia
Percentage: Porcentaje
Dwindle: Mermas

View File

@ -0,0 +1,19 @@
@import "variables";
vn-item-waste {
.header {
margin-bottom: 16px;
text-transform: uppercase;
font-size: 15pt;
line-height: 1;
padding: 7px;
padding-bottom: 7px;
padding-bottom: 4px;
font-weight: lighter;
background-color: #fde6ca;
border-bottom: 0.1em solid #f7931e;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

View File

@ -29,6 +29,6 @@ module.exports = Self => {
if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`);
return Self.rawSql('CALL vn.ticketCalculateSale(?)', [id]);
return Self.rawSql('CALL vn.sale_calculateComponent(?, null)', [id]);
};
};

View File

@ -4,5 +4,6 @@ module.exports = new Stylesheet([
`${appPath}/common/css/spacing.css`,
`${appPath}/common/css/misc.css`,
`${appPath}/common/css/layout.css`,
`${appPath}/common/css/email.css`])
`${appPath}/common/css/email.css`,
`${__dirname}/style.css`])
.mergeStyles();

View File

@ -0,0 +1,5 @@
.external-link {
border: 2px dashed #8dba25;
border-radius: 3px;
text-align: center
}

View File

@ -49,8 +49,15 @@
</tr>
</tbody>
</table>
<p v-html="$t('wasteDetailLink')"></p>
<div class="external-link vn-pa-sm vn-m-md">
<a href="https://salix.verdnatura.es/#!/item/waste" target="_blank">
https://salix.verdnatura.es/#!/item/waste
</a>
</div>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">

View File

@ -5,4 +5,5 @@ description: A continuación se muestra la merma semanal a fecha de <strong>{0}<
buyer: Comprador
percentage: Porcentaje
weakening: Mermas
total: Total
total: Total
wasteDetailLink: 'Para ver el desglose de mermas haz clic en el siguiente enlace:'