fixes #4945 Dejar de buscar por tag 'Nombre temporal' #1258

Merged
alexandre merged 9 commits from 4945-dejar-buscar-tag-nombreTemporal into dev 2023-01-23 06:04:41 +00:00
36 changed files with 462 additions and 3631 deletions
Showing only changes of commit 200a256016 - Show all commits

View File

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Artículo](Datos Básicos) Añadido campo Unidades/Caja
### Changed
- [Reclamaciones](Descriptor) Cambiado el campo Agencia por Zona
- [Tickets](Líneas preparadas) Actualizada sección para que sea más visual
### Fixed

View File

@ -0,0 +1,49 @@
const {Report} = require('vn-print');
module.exports = Self => {
Self.remoteMethodCtx('previousLabel', {
description: 'Returns the previa label pdf',
accessType: 'READ',
accepts: [
{
arg: 'id',
type: 'number',
required: true,
description: 'The item id',
http: {source: 'path'}
}],
returns: [
{
arg: 'body',
type: 'file',
root: true
}, {
arg: 'Content-Type',
type: 'String',
http: {target: 'header'}
}, {
arg: 'Content-Disposition',
type: 'String',
http: {target: 'header'}
}
],
http: {
path: '/:id/previousLabel',
verb: 'GET'
}
});
Self.previousLabel = async(ctx, id) => {
const args = Object.assign({}, ctx.args);
const params = {lang: ctx.req.getLocale()};
delete args.ctx;
for (const param in args)
params[param] = args[param];
const report = new Report('previa-label', params);
const stream = await report.toPdfStream();
return [stream, 'application/pdf', `filename="previa-${id}.pdf"`];
};
};

View File

@ -3,4 +3,5 @@ module.exports = Self => {
require('../methods/collection/newCollection')(Self);
require('../methods/collection/getSectors')(Self);
require('../methods/collection/setSaleQuantity')(Self);
require('../methods/collection/previousLabel')(Self);
};

View File

@ -0,0 +1,3 @@
UPDATE `vn`.`collection`
SET sectorFk=1
WHERE id=1;

View File

@ -0,0 +1,3 @@
ALTER TABLE `vn`.`itemPackingType` ADD isActive BOOLEAN NOT NULL;
UPDATE `vn`.`itemPackingType` SET isActive = 0 WHERE code IN ('P', 'F');
UPDATE `vn`.`itemPackingType` SET isActive = 1 WHERE code IN ('V', 'H');

View File

@ -0,0 +1,23 @@
DROP FUNCTION IF EXISTS `vn`.`priceFixed_getRate2`;
DELIMITER $$
$$
CREATE FUNCTION `vn`.`priceFixed_getRate2`(vFixedPriceFk INT, vRate3 DOUBLE)
RETURNS DOUBLE
BEGIN
DECLARE vWarehouse INT;
DECLARE vRate2 DOUBLE;
SELECT round(vRate3 * (1 + ((r.rate2 - r.rate3)/100)), 2) INTO vRate2
FROM vn.rate r
JOIN vn.priceFixed p ON p.id = vFixedPriceFk
WHERE r.dated <= p.started
AND r.warehouseFk = p.warehouseFk
ORDER BY r.dated DESC
LIMIT 1;
RETURN vRate2;
END$$
DELIMITER ;

View File

@ -1215,7 +1215,7 @@ INSERT INTO `vn`.`tag`(`id`, `code`, `name`, `isFree`, `isQuantitatif`, `sourceT
(7, NULL, 'Ancho de la base', 1, 1, NULL, 'mm',NULL, NULL),
(23, 'stems', 'Tallos', 1, 1, NULL, NULL, NULL, 'stems'),
(27, NULL, 'Longitud(cm)', 1, 1, NULL, 'cm', NULL, NULL),
(36, NULL, 'Proveedor', 1, 0, NULL, NULL, NULL, NULL),
(36, 'producer', 'Proveedor', 1, 0, NULL, NULL, NULL, 'producer'),
(56, NULL, 'Genero', 1, 0, NULL, NULL, NULL, NULL),
(58, NULL, 'Variedad', 1, 0, NULL, NULL, NULL, NULL),
(67, 'category', 'Categoria', 1, 0, NULL, NULL, NULL, NULL),

View File

@ -80203,3 +80203,4 @@ USE `vncontrol`;
-- Dump completed on 2022-11-21 7:57:28

View File

@ -417,8 +417,8 @@ export default {
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]',
fourthWarehouse: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.warehouseFk"]',
fourthPPU: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)',
fourthPPP: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)',
fourthGroupingPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)',
fourthPackingPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)',
fourthHasMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-check[ng-model="price.hasMinPrice"]',
fourthMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-input-number[ng-model="price.minPrice"]',
fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]',

View File

@ -24,8 +24,8 @@ describe('Item fixed prices path', () => {
it('should fill the fixed price data', async() => {
const now = new Date();
await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one');
await page.write(selectors.itemFixedPrice.fourthPPU, '1');
await page.write(selectors.itemFixedPrice.fourthPPP, '1');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthGroupingPrice, '1');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPackingPrice, '1');
await page.write(selectors.itemFixedPrice.fourthMinPrice, '1');
await page.pickDate(selectors.itemFixedPrice.fourthStarted, now);
await page.pickDate(selectors.itemFixedPrice.fourthEnded, now);

View File

@ -19,9 +19,9 @@ class Controller extends ModuleCard {
}, {
relation: 'ticket',
scope: {
fields: ['agencyModeFk'],
fields: ['zoneFk'],
include: {
relation: 'agencyMode'
relation: 'zone'
}
}
}, {

View File

@ -27,16 +27,16 @@
<slot-body>
<div class="attributes">
<vn-label-value
label="State"
label="State"
value="{{$ctrl.claim.claimState.description}}">
</vn-label-value>
<vn-label-value
label="Created"
label="Created"
value="{{$ctrl.claim.created | date: 'dd/MM/yyyy HH:mm'}}">
</vn-label-value>
<vn-label-value
label="Salesperson">
<span
<span
ng-click="workerDescriptor.show($event, $ctrl.claim.client.salesPersonFk)"
class="link">
{{$ctrl.claim.client.salesPersonUser.name}}
@ -44,19 +44,23 @@
</vn-label-value>
<vn-label-value
label="Attended by">
<span
<span
ng-click="workerDescriptor.show($event, $ctrl.claim.worker.userFk)"
class="link">
{{$ctrl.claim.worker.user.name}}
</span>
</vn-label-value>
<vn-label-value
label="Agency"
value="{{$ctrl.claim.ticket.agencyMode.name}}">
label="Zone">
<span
ng-click="zoneDescriptor.show($event, $ctrl.claim.ticket.zoneFk)"
class="link">
{{$ctrl.claim.ticket.zoneFk}}
</span>
</vn-label-value>
<vn-label-value
label="Ticket">
<span
<span
ng-click="ticketDescriptor.show($event, $ctrl.claim.ticketFk)"
class="link">
{{$ctrl.claim.ticketFk}}
@ -94,12 +98,15 @@
question="Delete claim"
message="Are you sure you want to delete this claim?">
</vn-confirm>
<vn-worker-descriptor-popover
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>
<vn-ticket-descriptor-popover
<vn-ticket-descriptor-popover
vn-id="ticketDescriptor">
</vn-ticket-descriptor-popover>
<vn-popup vn-id="summary">
<vn-claim-summary claim="$ctrl.claim"></vn-claim-summary>
</vn-popup>
</vn-popup>
<vn-zone-descriptor-popover
vn-id="zoneDescriptor">
</vn-zone-descriptor-popover>

View File

@ -0,0 +1,39 @@
module.exports = Self => {
Self.remoteMethod('getRate2', {
description: 'Return the rate2',
accessType: 'READ',
accepts: [
{
arg: 'fixedPriceId',
type: 'integer',
description: 'The fixedPrice Id',
required: true
},
{
arg: 'rate3',
type: 'number',
description: `The price rate 3`,
required: true
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/getRate2`,
verb: 'GET'
}
});
Self.getRate2 = async(fixedPriceId, rate3, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const [result] = await Self.rawSql(`SELECT vn.priceFixed_getRate2(?, ?) as rate2`,
[fixedPriceId, rate3], myOptions);
return result;
};
};

View File

@ -0,0 +1,39 @@
const models = require('vn-loopback/server/server').models;
describe('getRate2()', () => {
it(`should return new rate2 if exists rate`, async() => {
const tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const fixedPriceId = 1;
const rate3 = 2;
const result = await models.FixedPrice.getRate2(fixedPriceId, rate3, options);
expect(result.rate2).toEqual(1.9);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it(`should return null if not exists rate`, async() => {
const tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const fixedPriceId = 13;
const rate3 = 2;
const result = await models.FixedPrice.getRate2(fixedPriceId, rate3, options);
expect(result.rate2).toEqual(null);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,4 +1,5 @@
module.exports = Self => {
require('../methods/fixed-price/filter')(Self);
require('../methods/fixed-price/upsertFixedPrice')(Self);
require('../methods/fixed-price/getRate2')(Self);
};

View File

@ -13,6 +13,9 @@
},
"description": {
"type": "string"
},
"isActive":{
"type": "boolean"
}
},
"acls": [
@ -23,4 +26,4 @@
"permission": "ALLOW"
}
]
}
}

View File

@ -41,14 +41,12 @@
<span translate>Warehouse</span>
</th>
<th
field="rate2"
vn-tooltip="Price By Unit">
<span translate>P.P.U.</span>
field="rate2">
<span translate>Grouping price</span>
</th>
<th
field="rate3"
vn-tooltip="Price By Package">
<span translate>P.P.P.</span>
field="rate3">
<span translate>Packing price</span>
</th>
<th field="minPrice">
<span translate>Min price</span>
@ -72,7 +70,7 @@
show-field="name"
value-field="id"
search-function="$ctrl.itemSearchFunc($search)"
on-change="$ctrl.upsertPrice(price)"
on-change="$ctrl.upsertPrice(price, true)"
order="id DESC"
tabindex="1">
<tpl-item>
@ -112,18 +110,32 @@
</vn-autocomplete>
</td>
<td shrink-field>
<vn-input-number
ng-model="price.rate2"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
<vn-td-editable number>
<text>{{price.rate2 | currency: 'EUR':2}}</text>
<field>
<vn-input-number
class="dense"
vn-focus
ng-model="price.rate2"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
</field>
</vn-td-editable>
</td>
<td shrink-field>
<vn-input-number
ng-model="price.rate3"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
<vn-td-editable number>
<text>{{price.rate3 | currency: 'EUR':2}}</text>
<field>
<vn-input-number
class="dense"
vn-focus
ng-model="price.rate3"
on-change="$ctrl.upsertPrice(price); $ctrl.recalculateRate2(price)"
step="0.01"s>
</vn-input-number>
</field>
</vn-td-editable>
</td>
<td shrink-field-expand class="minPrice">
<vn-check

View File

@ -62,7 +62,10 @@ export default class Controller extends Section {
});
}
upsertPrice(price) {
upsertPrice(price, resetMinPrice) {
if (resetMinPrice)
delete price['minPrice'];
price.hasMinPrice = price.minPrice ? true : false;
let requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3'];
@ -110,6 +113,24 @@ export default class Controller extends Section {
return {[param]: value};
}
}
recalculateRate2(price) {
if (!price.id || !price.rate3) return;
const query = 'FixedPrices/getRate2';
const params = {
fixedPriceId: price.id,
rate3: price.rate3
};
this.$http.get(query, {params})
.then(res => {
const rate2 = res.data.rate2;
if (rate2) {
price.rate2 = rate2;
this.upsertPrice(price);
}
});
}
}
ngModule.vnComponent('vnFixedPrice', {

View File

@ -85,5 +85,25 @@ describe('fixed price', () => {
expect(controller.$.model.remove).toHaveBeenCalled();
});
});
describe('recalculateRate2()', () => {
it(`should rate2 recalculate`, () => {
jest.spyOn(controller.vnApp, 'showSuccess');
const price = {
id: 1,
itemFk: 1,
rate2: 2,
rate3: 2
};
const response = {rate2: 1};
controller.recalculateRate2(price);
const query = `FixedPrices/getRate2?fixedPriceId=${price.id}&rate3=${price.rate3}`;
$httpBackend.expectGET(query).respond(response);
$httpBackend.flush();
expect(price.rate2).toEqual(response.rate2);
});
});
});
});

View File

@ -3,5 +3,3 @@ Search prices by item ID or code: Buscar por ID de artículo o código
Search fixed prices: Buscar precios fijados
Add fixed price: Añadir precio fijado
This row will be removed: Esta linea se eliminará
Price By Unit: Precio Por Unidad
Price By Package: Precio Por Paquete

View File

@ -25,7 +25,10 @@ class Controller extends SearchPanel {
getItemPackingTypes() {
let itemPackingTypes = [];
this.$http.get('ItemPackingTypes').then(res => {
const filter = {
where: {isActive: true}
};
this.$http.get('ItemPackingTypes', {filter}).then(res => {
for (let ipt of res.data) {
itemPackingTypes.push({
code: ipt.code,

View File

@ -39,6 +39,7 @@ export default class Controller extends Section {
field: 'ipt',
autocomplete: {
url: 'ItemPackingTypes',
where: `{isActive: true}`,
showField: 'description',
valueField: 'code'
}
@ -47,6 +48,7 @@ export default class Controller extends Section {
field: 'futureIpt',
autocomplete: {
url: 'ItemPackingTypes',
where: `{isActive: true}`,
showField: 'description',
valueField: 'code'
}

View File

@ -25,7 +25,10 @@ class Controller extends SearchPanel {
getItemPackingTypes() {
let itemPackingTypes = [];
this.$http.get('ItemPackingTypes').then(res => {
const filter = {
where: {isActive: true}
};
this.$http.get('ItemPackingTypes', {filter}).then(res => {
for (let ipt of res.data) {
itemPackingTypes.push({
description: this.$t(ipt.description),

View File

@ -134,7 +134,7 @@
{{::ticket.shipped | date: 'dd/MM/yyyy HH:mm'}}
</span>
</td>
<td>{{::ticket.ipt}}</td>
<td>{{::ticket.ipt | dashIfEmpty}}</td>
<td>
<span
class="chip {{$ctrl.stateColor(ticket.state)}}">
@ -155,7 +155,7 @@
{{::ticket.futureShipped | date: 'dd/MM/yyyy HH:mm'}}
</span>
</td>
<td>{{::ticket.futureIpt}}</td>
<td>{{::ticket.futureIpt | dashIfEmpty}}</td>
<td>
<span
class="chip {{$ctrl.stateColor(ticket.futureState)}}">

View File

@ -34,6 +34,7 @@ export default class Controller extends Section {
field: 'ipt',
autocomplete: {
url: 'ItemPackingTypes',
where: `{isActive: true}`,
showField: 'description',
valueField: 'code'
}
@ -42,6 +43,7 @@ export default class Controller extends Section {
field: 'futureIpt',
autocomplete: {
url: 'ItemPackingTypes',
where: `{isActive: true}`,
showField: 'description',
valueField: 'code'
}

3588
print/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,12 @@ SELECT
i.name,
i.stems,
i.size,
b.packing
b.packing,
p.name as 'producer'
FROM vn.item i
JOIN cache.last_buy clb ON clb.item_id = i.id
JOIN vn.buy b ON b.id = clb.buy_id
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.producer p ON p.id = i.producerFk
WHERE i.id = ? AND clb.warehouse_id = ?

View File

@ -0,0 +1,12 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/report.css`,
`${__dirname}/style.css`])
.mergeStyles();

View File

@ -0,0 +1,85 @@
* {
box-sizing: border-box;
padding-right: 1%;
}
.label {
font-size: 1.2em;
font-family: Arial, Helvetica, sans-serif;
}
.barcode {
float: left;
width: 40%;
}
.barcode h1 {
text-align: center;
font-size: 1.8em;
margin: 0 0 10px 0
}
.barcode .image {
text-align: center
}
.barcode .image img {
width: 170px
}
.data {
float: left;
width: 60%;
}
.data .header {
background-color: #000;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-bottom: 25px;
text-align: right;
font-size: 1.2em;
padding: 0.2em;
color: #FFF
}
.data .sector,
.data .producer {
text-transform: uppercase;
text-align: right;
font-size: 1.5em;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data .sector-sm {
text-transform: uppercase;
text-align: right;
font-size: 1.2em;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data .producer {
text-justify: inter-character;
}
.data .details {
border-top: 4px solid #000;
padding-top: 2px;
}
.data .details .package {
padding-right: 5px;
float: left;
width: 50%;
}
.package .packing,
.package .dated,
.package .labelNumber {
text-align: right
}
.package .packing {
font-size: 1.8em;
font-weight: 400
}
.data .details .size {
background-color: #000;
text-align: center;
font-size: 3em;
padding: 0.2em 0;
float: left;
width: 50%;
color: #FFF
}

View File

@ -0,0 +1,2 @@
previous: PREVIOUS
report: Report

View File

@ -0,0 +1,2 @@
previous: PREVIA
report: Ticket

View File

@ -0,0 +1,11 @@
{
"width": "10.4cm",
"height": "4.8cm",
"margin": {
"top": "0cm",
"right": "0cm",
"bottom": "0cm",
"left": "0cm"
},
"printBackground": true
}

View File

@ -0,0 +1,26 @@
<DOCTYPE html>
<body>
<div class="label">
<div class="barcode">
<h1>{{previa.saleGroupFk}}</h1>
<div class="image">
<img v-bind:src="barcode" />
</div>
</div>
<div class="data">
<div class="header">{{ $t('previous') }}</div>
<div v-if="sector.description.length > 16" class="sector-sm">
{{sector.description}}
</div>
<div v-else class="sector">{{sector.description}}</div>
<div class="producer">{{ $t('report') }}#{{previa.ticketFk}}</div>
<div class="details">
<div class="package">
<div class="packing">{{previa.itemPackingTypeFk}}</div>
<div class="dated">{{previa.shippingHour}}:{{previa.shippingMinute}}</div>
</div>
<div class="size">{{previa.items}}</div>
</div>
</div>
</div>
</body>

View File

@ -0,0 +1,42 @@
const Component = require(`vn-print/core/component`);
const reportBody = new Component('report-body');
const qrcode = require('qrcode');
const UserError = require('vn-loopback/util/user-error');
module.exports = {
name: 'previa-label',
async serverPrefetch() {
this.previa = await this.fetchPrevia(this.id);
this.sector = await this.fetchSector(this.id);
this.barcode = await this.getBarcodeBase64(this.id);
if (this.previa)
this.previa = this.previa[0];
if (!this.sector)
throw new UserError('Something went wrong - no sector found');
},
methods: {
fetchPrevia(id) {
return this.findOneFromDef('previa', [id]);
},
getBarcodeBase64(id) {
const data = String(id);
return qrcode.toDataURL(data, {margin: 0});
},
fetchSector(id) {
return this.findOneFromDef('sector', [id]);
}
},
components: {
'report-body': reportBody.build()
},
props: {
id: {
type: Number,
required: true,
description: 'The saleGroupFk id'
},
}
};

View File

@ -0,0 +1 @@
CALL vn.previousSticker_get(?)

View File

@ -0,0 +1,4 @@
SELECT s.description
FROM vn.saleGroup sg
JOIN vn.sector s ON sg.sectorFk = s.id
WHERE sg.id = ?