Merge branch 'dev' into 6005-backupLabeler
gitea/salix/pipeline/pr-dev Build started... Details

This commit is contained in:
Pablo Natek 2024-04-09 13:03:40 +00:00
commit 4a8adf4155
25 changed files with 600 additions and 447 deletions

View File

@ -29,6 +29,7 @@ module.exports = Self => {
}); });
Self.getSales = async(ctx, collectionOrTicketFk, print, source, options) => { Self.getSales = async(ctx, collectionOrTicketFk, print, source, options) => {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const myOptions = {userId}; const myOptions = {userId};
const $t = ctx.req.__; const $t = ctx.req.__;

View File

@ -19,12 +19,12 @@ module.exports = Self => {
} }
}); });
Self.getUrl = async(appName = 'salix') => { Self.getUrl = async(appName = 'salix') => {
const {url} = await Self.app.models.Url.findOne({ const url = await Self.app.models.Url.findOne({
where: { where: {
appName, appName,
environment: process.env.NODE_ENV || 'development' environment: process.env.NODE_ENV || 'development'
} }
}); });
return url; return url?.url;
}; };
}; };

View File

@ -1880,7 +1880,7 @@ INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRa
INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`) INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`)
VALUES VALUES
(1, 18, 'update', 'Claim', '{"hasToPickUp":false}', '{"hasToPickUp":true}', 1, NULL), (1, 18, 'update', 'Claim', '{"pickup":null}', '{"pickup":"agency"}', 1, NULL),
(1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL), (1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL),
(1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL), (1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL),
(1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL); (1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL);
@ -2916,7 +2916,8 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES VALUES
('lilium', 'development', 'http://localhost:9000/#/'), ('lilium', 'development', 'http://localhost:9000/#/'),
('hedera', 'development', 'http://localhost:9090/'), ('hedera', 'development', 'http://localhost:9090/'),
('salix', 'development', 'http://localhost:5000/#!/'); ('salix', 'development', 'http://localhost:5000/#!/'),
('docuware', 'development', 'http://docuware');
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
VALUES VALUES

View File

@ -21,7 +21,6 @@ BEGIN
SELECT barcodeToItem(vBarcode) INTO vItemFk; SELECT barcodeToItem(vBarcode) INTO vItemFk;
SET vPacking = COALESCE(vPacking, GREATEST(vn.itemPacking(vBarcode,vWarehouseFk), 1)); SET vPacking = COALESCE(vPacking, GREATEST(vn.itemPacking(vBarcode,vWarehouseFk), 1));
SET vQuantity = vQuantity * vPacking; SET vQuantity = vQuantity * vPacking;
IF (SELECT COUNT(*) FROM shelving WHERE code = vShelvingFk COLLATE utf8_unicode_ci) = 0 THEN IF (SELECT COUNT(*) FROM shelving WHERE code = vShelvingFk COLLATE utf8_unicode_ci) = 0 THEN

View File

@ -0,0 +1,20 @@
CREATE OR REPLACE TEMPORARY TABLE tmp.claimsWithHasToPickUp
SELECT id
FROM vn.claim
WHERE hasToPickUp;
ALTER TABLE vn.claim CHANGE hasToPickUp pickup ENUM('agency', 'delivery') DEFAULT NULL;
UPDATE vn.claim c
JOIN tmp.claimsWithHasToPickUp tmp ON tmp.id = c.id
SET c.pickup = 'delivery';
-- Solved bug empty value
UPDATE vn.claim
SET pickup = NULL
WHERE pickup = '';
DROP TEMPORARY TABLE tmp.claimsWithHasToPickUp;
INSERT INTO salix.ACL (model,property,accessType,principalId)
VALUES ('Application','getEnumValues','*','employee');

View File

@ -762,7 +762,6 @@ export default {
claimBasicData: { claimBasicData: {
claimState: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]', claimState: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]',
packages: 'vn-input-number[ng-model="$ctrl.claim.packages"]', packages: 'vn-input-number[ng-model="$ctrl.claim.packages"]',
hasToPickUpCheckbox: 'vn-claim-basic-data vn-check[ng-model="$ctrl.claim.hasToPickUp"]',
saveButton: `button[type=submit]` saveButton: `button[type=submit]`
}, },
claimDetail: { claimDetail: {

View File

@ -36,7 +36,6 @@ describe('Claim edit basic data path', () => {
it('should check the "Pick up" checkbox', async() => { it('should check the "Pick up" checkbox', async() => {
await page.reloadSection('claim.card.basicData'); await page.reloadSection('claim.card.basicData');
await page.waitToClick(selectors.claimBasicData.hasToPickUpCheckbox);
await page.waitToClick(selectors.claimBasicData.saveButton); await page.waitToClick(selectors.claimBasicData.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
@ -51,12 +50,6 @@ describe('Claim edit basic data path', () => {
expect(result).toEqual('Resuelto'); expect(result).toEqual('Resuelto');
}); });
it('should confirm the "is paid with mana" and "Pick up" checkbox are checked', async() => {
const hasToPickUpCheckbox = await page.checkboxState(selectors.claimBasicData.hasToPickUpCheckbox);
expect(hasToPickUpCheckbox).toBe('checked');
});
it('should confirm the claim packages was edited', async() => { it('should confirm the claim packages was edited', async() => {
const result = await page const result = await page
.waitToGetProperty(selectors.claimBasicData.packages, 'value'); .waitToGetProperty(selectors.claimBasicData.packages, 'value');

View File

@ -0,0 +1,56 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('getEnumValues', {
description: 'Return enum values of column',
accessType: 'EXECUTE',
accepts: [
{
arg: 'schema',
type: 'string',
description: 'The schema of db',
required: true,
},
{
arg: 'table',
type: 'string',
description: 'The table of schema',
required: true,
},
{
arg: 'column',
type: 'string',
description: 'The column of table',
required: true,
},
],
returns: {
type: 'any',
root: true
},
http: {
path: `/get-enum-values`,
verb: 'GET'
}
});
Self.getEnumValues = async(schema, table, column) => {
const stmt = new ParameterizedSQL(`
SELECT COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = ?
AND TABLE_NAME = ?
AND COLUMN_NAME = ?
AND DATA_TYPE = 'enum';`,
[schema, table, column]);
const conn = Self.dataSource.connector;
const [result] = await conn.executeStmt(stmt);
if (!result) throw new UserError(`No results found`);
const regex = /'([^']*)'/g;
return result.COLUMN_TYPE.match(regex).map(match => match.slice(1, -1));
};
};

View File

@ -0,0 +1,35 @@
const models = require('vn-loopback/server/server').models;
describe('Application getEnumValues()', () => {
let tx;
beforeEach(async() => {
tx = await models.Application.beginTransaction({});
const options = {transaction: tx};
await models.Application.rawSql(`
CREATE TABLE tableWithEnum (
direction enum('in', 'out', 'middle'),
PRIMARY KEY (direction)
) ENGINE=InnoDB;
`, null, options);
});
it('should return three if is ok', async() => {
try {
const options = {transaction: tx};
const response = await models.Application.getEnumValues(
'vn',
'tableWithEnum',
'direction',
options
);
expect(response.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -5,4 +5,5 @@ module.exports = function(Self) {
require('../methods/application/execute')(Self); require('../methods/application/execute')(Self);
require('../methods/application/executeProc')(Self); require('../methods/application/executeProc')(Self);
require('../methods/application/executeFunc')(Self); require('../methods/application/executeFunc')(Self);
require('../methods/application/getEnumValues')(Self);
}; };

View File

@ -68,7 +68,7 @@
"Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}", "Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}",
"Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked, with the pickup type *{{claimPickup}}*",
"Claim state has changed to": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *{{newState}}*", "Claim state has changed to": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *{{newState}}*",
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member", "Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
@ -89,6 +89,8 @@
"landed": "Landed", "landed": "Landed",
"addressFk": "Address", "addressFk": "Address",
"companyFk": "Company", "companyFk": "Company",
"agency": "Agency",
"delivery": "Delivery",
"You need to fill sage information before you check verified data": "You need to fill sage information before you check verified data", "You need to fill sage information before you check verified data": "You need to fill sage information before you check verified data",
"The social name cannot be empty": "The social name cannot be empty", "The social name cannot be empty": "The social name cannot be empty",
"The nif cannot be empty": "The nif cannot be empty", "The nif cannot be empty": "The nif cannot be empty",

View File

@ -1,353 +1,356 @@
{ {
"Phone format is invalid": "El formato del teléfono no es correcto", "Phone format is invalid": "El formato del teléfono no es correcto",
"You are not allowed to change the credit": "No tienes privilegios para modificar el crédito", "You are not allowed to change the credit": "No tienes privilegios para modificar el crédito",
"Unable to mark the equivalence surcharge": "No se puede marcar el recargo de equivalencia", "Unable to mark the equivalence surcharge": "No se puede marcar el recargo de equivalencia",
"The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado", "The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado",
"Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado", "Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado",
"Can't be blank": "No puede estar en blanco", "Can't be blank": "No puede estar en blanco",
"Invalid TIN": "NIF/CIF inválido", "Invalid TIN": "NIF/CIF inválido",
"TIN must be unique": "El NIF/CIF debe ser único", "TIN must be unique": "El NIF/CIF debe ser único",
"A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web", "A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web",
"Is invalid": "Es inválido", "Is invalid": "Es inválido",
"Quantity cannot be zero": "La cantidad no puede ser cero", "Quantity cannot be zero": "La cantidad no puede ser cero",
"Enter an integer different to zero": "Introduce un entero distinto de cero", "Enter an integer different to zero": "Introduce un entero distinto de cero",
"Package cannot be blank": "El embalaje no puede estar en blanco", "Package cannot be blank": "El embalaje no puede estar en blanco",
"The company name must be unique": "La razón social debe ser única", "The company name must be unique": "La razón social debe ser única",
"Invalid email": "Correo electrónico inválido", "Invalid email": "Correo electrónico inválido",
"The IBAN does not have the correct format": "El IBAN no tiene el formato correcto", "The IBAN does not have the correct format": "El IBAN no tiene el formato correcto",
"That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN", "That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN",
"That payment method requires a BIC": "El método de pago seleccionado requiere un BIC", "That payment method requires a BIC": "El método de pago seleccionado requiere un BIC",
"State cannot be blank": "El estado no puede estar en blanco", "State cannot be blank": "El estado no puede estar en blanco",
"Worker cannot be blank": "El trabajador no puede estar en blanco", "Worker cannot be blank": "El trabajador no puede estar en blanco",
"Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado", "Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
"can't be blank": "El campo no puede estar vacío", "can't be blank": "El campo no puede estar vacío",
"Observation type must be unique": "El tipo de observación no puede repetirse", "Observation type must be unique": "El tipo de observación no puede repetirse",
"The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero", "The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
"The grade must be similar to the last one": "El grade debe ser similar al último", "The grade must be similar to the last one": "El grade debe ser similar al último",
"Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente", "Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente",
"Name cannot be blank": "El nombre no puede estar en blanco", "Name cannot be blank": "El nombre no puede estar en blanco",
"Phone cannot be blank": "El teléfono no puede estar en blanco", "Phone cannot be blank": "El teléfono no puede estar en blanco",
"Period cannot be blank": "El periodo no puede estar en blanco", "Period cannot be blank": "El periodo no puede estar en blanco",
"Choose a company": "Selecciona una empresa", "Choose a company": "Selecciona una empresa",
"Se debe rellenar el campo de texto": "Se debe rellenar el campo de texto", "Se debe rellenar el campo de texto": "Se debe rellenar el campo de texto",
"Description should have maximum of 45 characters": "La descripción debe tener maximo 45 caracteres", "Description should have maximum of 45 characters": "La descripción debe tener maximo 45 caracteres",
"Cannot be blank": "El campo no puede estar en blanco", "Cannot be blank": "El campo no puede estar en blanco",
"The grade must be an integer greater than or equal to zero": "El grade debe ser un entero mayor o igual a cero", "The grade must be an integer greater than or equal to zero": "El grade debe ser un entero mayor o igual a cero",
"Sample type cannot be blank": "El tipo de plantilla no puede quedar en blanco", "Sample type cannot be blank": "El tipo de plantilla no puede quedar en blanco",
"Description cannot be blank": "Se debe rellenar el campo de texto", "Description cannot be blank": "Se debe rellenar el campo de texto",
"The price of the item changed": "El precio del artículo cambió", "The price of the item changed": "El precio del artículo cambió",
"The value should not be greater than 100%": "El valor no debe de ser mayor de 100%", "The value should not be greater than 100%": "El valor no debe de ser mayor de 100%",
"The value should be a number": "El valor debe ser un numero", "The value should be a number": "El valor debe ser un numero",
"This order is not editable": "Esta orden no se puede modificar", "This order is not editable": "Esta orden no se puede modificar",
"You can't create an order for a frozen client": "No puedes crear una orden para un cliente congelado", "You can't create an order for a frozen client": "No puedes crear una orden para un cliente congelado",
"You can't create an order for a client that has a debt": "No puedes crear una orden para un cliente con deuda", "You can't create an order for a client that has a debt": "No puedes crear una orden para un cliente con deuda",
"is not a valid date": "No es una fecha valida", "is not a valid date": "No es una fecha valida",
"Barcode must be unique": "El código de barras debe ser único", "Barcode must be unique": "El código de barras debe ser único",
"The warehouse can't be repeated": "El almacén no puede repetirse", "The warehouse can't be repeated": "El almacén no puede repetirse",
"The tag or priority can't be repeated for an item": "El tag o prioridad no puede repetirse para un item", "The tag or priority can't be repeated for an item": "El tag o prioridad no puede repetirse para un item",
"The observation type can't be repeated": "El tipo de observación no puede repetirse", "The observation type can't be repeated": "El tipo de observación no puede repetirse",
"A claim with that sale already exists": "Ya existe una reclamación para esta línea", "A claim with that sale already exists": "Ya existe una reclamación para esta línea",
"You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo", "You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
"Warehouse cannot be blank": "El almacén no puede quedar en blanco", "Warehouse cannot be blank": "El almacén no puede quedar en blanco",
"Agency cannot be blank": "La agencia no puede quedar en blanco", "Agency cannot be blank": "La agencia no puede quedar en blanco",
"Not enough privileges to edit a client with verified data": "No tienes permisos para hacer cambios en un cliente con datos comprobados", "Not enough privileges to edit a client with verified data": "No tienes permisos para hacer cambios en un cliente con datos comprobados",
"This address doesn't exist": "Este consignatario no existe", "This address doesn't exist": "Este consignatario no existe",
"You must delete the claim id %d first": "Antes debes borrar la reclamación %d", "You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
"You don't have enough privileges": "No tienes suficientes permisos", "You don't have enough privileges": "No tienes suficientes permisos",
"Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF", "Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",
"You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos básicos de una orden con artículos", "You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos básicos de una orden con artículos",
"INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no está permitido el uso de la letra ñ", "INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no está permitido el uso de la letra ñ",
"You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado", "You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado",
"You can't create a ticket for an inactive client": "No puedes crear un ticket para un cliente inactivo", "You can't create a ticket for an inactive client": "No puedes crear un ticket para un cliente inactivo",
"Tag value cannot be blank": "El valor del tag no puede quedar en blanco", "Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
"ORDER_EMPTY": "Cesta vacía", "ORDER_EMPTY": "Cesta vacía",
"You don't have enough privileges to do that": "No tienes permisos para cambiar esto", "You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
"NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT", "NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT",
"Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido", "Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido",
"Street cannot be empty": "Dirección no puede estar en blanco", "Street cannot be empty": "Dirección no puede estar en blanco",
"City cannot be empty": "Ciudad no puede estar en blanco", "City cannot be empty": "Ciudad no puede estar en blanco",
"Code cannot be blank": "Código no puede estar en blanco", "Code cannot be blank": "Código no puede estar en blanco",
"You cannot remove this department": "No puedes eliminar este departamento", "You cannot remove this department": "No puedes eliminar este departamento",
"The extension must be unique": "La extensión debe ser unica", "The extension must be unique": "La extensión debe ser unica",
"The secret can't be blank": "La contraseña no puede estar en blanco", "The secret can't be blank": "La contraseña no puede estar en blanco",
"We weren't able to send this SMS": "No hemos podido enviar el SMS", "We weren't able to send this SMS": "No hemos podido enviar el SMS",
"This client can't be invoiced": "Este cliente no puede ser facturado", "This client can't be invoiced": "Este cliente no puede ser facturado",
"You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa", "You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa",
"This ticket can't be invoiced": "Este ticket no puede ser facturado", "This ticket can't be invoiced": "Este ticket no puede ser facturado",
"You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado", "You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado",
"This ticket can not be modified": "Este ticket no puede ser modificado", "This ticket can not be modified": "Este ticket no puede ser modificado",
"The introduced hour already exists": "Esta hora ya ha sido introducida", "The introduced hour already exists": "Esta hora ya ha sido introducida",
"INFINITE_LOOP": "Existe una dependencia entre dos Jefes", "INFINITE_LOOP": "Existe una dependencia entre dos Jefes",
"The sales of the receiver ticket can't be modified": "Las lineas del ticket al que envias no pueden ser modificadas", "The sales of the receiver ticket can't be modified": "Las lineas del ticket al que envias no pueden ser modificadas",
"NO_AGENCY_AVAILABLE": "No hay una zona de reparto disponible con estos parámetros", "NO_AGENCY_AVAILABLE": "No hay una zona de reparto disponible con estos parámetros",
"ERROR_PAST_SHIPMENT": "No puedes seleccionar una fecha de envío en pasado", "ERROR_PAST_SHIPMENT": "No puedes seleccionar una fecha de envío en pasado",
"The current ticket can't be modified": "El ticket actual no puede ser modificado", "The current ticket can't be modified": "El ticket actual no puede ser modificado",
"The current claim can't be modified": "La reclamación actual no puede ser modificada", "The current claim can't be modified": "La reclamación actual no puede ser modificada",
"The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas", "The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas",
"The sales do not exists": "La(s) línea(s) seleccionada(s) no existe(n)", "The sales do not exists": "La(s) línea(s) seleccionada(s) no existe(n)",
"Please select at least one sale": "Por favor selecciona al menos una linea", "Please select at least one sale": "Por favor selecciona al menos una linea",
"All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket", "All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket",
"NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada", "NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
"This item doesn't exists": "El artículo no existe", "This item doesn't exists": "El artículo no existe",
"NOT_ZONE_WITH_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada", "NOT_ZONE_WITH_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
"Extension format is invalid": "El formato de la extensión es inválido", "Extension format is invalid": "El formato de la extensión es inválido",
"Invalid parameters to create a new ticket": "Parámetros inválidos para crear un nuevo ticket", "Invalid parameters to create a new ticket": "Parámetros inválidos para crear un nuevo ticket",
"This item is not available": "Este artículo no está disponible", "This item is not available": "Este artículo no está disponible",
"This postcode already exists": "Este código postal ya existe", "This postcode already exists": "Este código postal ya existe",
"Concept cannot be blank": "El concepto no puede quedar en blanco", "Concept cannot be blank": "El concepto no puede quedar en blanco",
"File doesn't exists": "El archivo no existe", "File doesn't exists": "El archivo no existe",
"You don't have privileges to change the zone": "No tienes permisos para cambiar la zona o para esos parámetros hay más de una opción de envío, hable con las agencias", "You don't have privileges to change the zone": "No tienes permisos para cambiar la zona o para esos parámetros hay más de una opción de envío, hable con las agencias",
"This ticket is already on weekly tickets": "Este ticket ya está en tickets programados", "This ticket is already on weekly tickets": "Este ticket ya está en tickets programados",
"Ticket id cannot be blank": "El id de ticket no puede quedar en blanco", "Ticket id cannot be blank": "El id de ticket no puede quedar en blanco",
"Weekday cannot be blank": "El día de la semana no puede quedar en blanco", "Weekday cannot be blank": "El día de la semana no puede quedar en blanco",
"You can't delete a confirmed order": "No puedes borrar un pedido confirmado", "You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
"The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto", "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto",
"Invalid quantity": "Cantidad invalida", "Invalid quantity": "Cantidad invalida",
"This postal code is not valid": "Este código postal no es válido", "This postal code is not valid": "Este código postal no es válido",
"is invalid": "es inválido", "is invalid": "es inválido",
"The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto", "The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto",
"The department name can't be repeated": "El nombre del departamento no puede repetirse", "The department name can't be repeated": "El nombre del departamento no puede repetirse",
"This phone already exists": "Este teléfono ya existe", "This phone already exists": "Este teléfono ya existe",
"You cannot move a parent to its own sons": "No puedes mover un elemento padre a uno de sus hijos", "You cannot move a parent to its own sons": "No puedes mover un elemento padre a uno de sus hijos",
"You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado", "You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
"You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada", "You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
"You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero", "You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
"You should specify a date": "Debes especificar una fecha", "You should specify a date": "Debes especificar una fecha",
"You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fin", "You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fin",
"Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fin", "Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fin",
"You should mark at least one week day": "Debes marcar al menos un día de la semana", "You should mark at least one week day": "Debes marcar al menos un día de la semana",
"Swift / BIC can't be empty": "Swift / BIC no puede estar vacío", "Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
"Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios", "Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
"Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios", "Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios",
"Deleted sales from ticket": "He eliminado las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{deletions}}}", "Deleted sales from ticket": "He eliminado las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{deletions}}}",
"Added sale to ticket": "He añadido la siguiente linea al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}", "Added sale to ticket": "He añadido la siguiente linea al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}",
"Changed sale discount": "He cambiado el descuento de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}", "Changed sale discount": "He cambiado el descuento de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
"Created claim": "He creado la reclamación [{{claimId}}]({{{claimUrl}}}) de las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}", "Created claim": "He creado la reclamación [{{claimId}}]({{{claimUrl}}}) de las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
"Changed sale price": "He cambiado el precio de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* del ticket [{{ticketId}}]({{{ticketUrl}}})", "Changed sale price": "He cambiado el precio de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* del ticket [{{ticketId}}]({{{ticketUrl}}})",
"Changed sale quantity": "He cambiado la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}* del ticket [{{ticketId}}]({{{ticketUrl}}})", "Changed sale quantity": "He cambiado la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}* del ticket [{{ticketId}}]({{{ticketUrl}}})",
"State": "Estado", "State": "Estado",
"regular": "normal", "regular": "normal",
"reserved": "reservado", "reserved": "reservado",
"Changed sale reserved state": "He cambiado el estado reservado de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}", "Changed sale reserved state": "He cambiado el estado reservado de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
"Bought units from buy request": "Se ha comprado {{quantity}} unidades de [{{itemId}} {{concept}}]({{{urlItem}}}) para el ticket id [{{ticketId}}]({{{url}}})", "Bought units from buy request": "Se ha comprado {{quantity}} unidades de [{{itemId}} {{concept}}]({{{urlItem}}}) para el ticket id [{{ticketId}}]({{{url}}})",
"Deny buy request": "Se ha rechazado la petición de compra para el ticket id [{{ticketId}}]({{{url}}}). Motivo: {{observation}}", "Deny buy request": "Se ha rechazado la petición de compra para el ticket id [{{ticketId}}]({{{url}}}). Motivo: {{observation}}",
"MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*", "MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*",
"Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}", "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*, con el tipo de recogida *{{claimPickup}}*",
"Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*", "Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*",
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
"Distance must be lesser than 4000": "La distancia debe ser inferior a 4000", "Distance must be lesser than 4000": "La distancia debe ser inferior a 4000",
"This ticket is deleted": "Este ticket está eliminado", "This ticket is deleted": "Este ticket está eliminado",
"Unable to clone this travel": "No ha sido posible clonar este travel", "Unable to clone this travel": "No ha sido posible clonar este travel",
"This thermograph id already exists": "La id del termógrafo ya existe", "This thermograph id already exists": "La id del termógrafo ya existe",
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante", "Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
"ORDER_ALREADY_CONFIRMED": "ORDEN YA CONFIRMADA", "ORDER_ALREADY_CONFIRMED": "ORDEN YA CONFIRMADA",
"Invalid password": "Invalid password", "Invalid password": "Invalid password",
"Password does not meet requirements": "La contraseña no cumple los requisitos", "Password does not meet requirements": "La contraseña no cumple los requisitos",
"Role already assigned": "Rol ya asignado", "Role already assigned": "Rol ya asignado",
"Invalid role name": "Nombre de rol no válido", "Invalid role name": "Nombre de rol no válido",
"Role name must be written in camelCase": "El nombre del rol debe escribirse en camelCase", "Role name must be written in camelCase": "El nombre del rol debe escribirse en camelCase",
"Email already exists": "El correo ya existe", "Email already exists": "El correo ya existe",
"User already exists": "El/La usuario/a ya existe", "User already exists": "El/La usuario/a ya existe",
"Absence change notification on the labour calendar": "Notificación de cambio de ausencia en el calendario laboral", "Absence change notification on the labour calendar": "Notificación de cambio de ausencia en el calendario laboral",
"Record of hours week": "Registro de horas semana {{week}} año {{year}} ", "Record of hours week": "Registro de horas semana {{week}} año {{year}} ",
"Created absence": "El empleado <strong>{{author}}</strong> ha añadido una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> para el día {{dated}}.", "Created absence": "El empleado <strong>{{author}}</strong> ha añadido una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> para el día {{dated}}.",
"Deleted absence": "El empleado <strong>{{author}}</strong> ha eliminado una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> del día {{dated}}.", "Deleted absence": "El empleado <strong>{{author}}</strong> ha eliminado una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> del día {{dated}}.",
"I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})", "I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})",
"I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})", "I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})",
"You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación", "You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación",
"Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}", "Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
"agencyModeFk": "Agencia", "agencyModeFk": "Agencia",
"clientFk": "Cliente", "clientFk": "Cliente",
"zoneFk": "Zona", "zoneFk": "Zona",
"warehouseFk": "Almacén", "warehouseFk": "Almacén",
"shipped": "F. envío", "shipped": "F. envío",
"landed": "F. entrega", "landed": "F. entrega",
"addressFk": "Consignatario", "addressFk": "Consignatario",
"companyFk": "Empresa", "companyFk": "Empresa",
"The social name cannot be empty": "La razón social no puede quedar en blanco", "agency": "Agencia",
"The nif cannot be empty": "El NIF no puede quedar en blanco", "delivery": "Reparto",
"You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados", "The social name cannot be empty": "La razón social no puede quedar en blanco",
"ASSIGN_ZONE_FIRST": "Asigna una zona primero", "The nif cannot be empty": "El NIF no puede quedar en blanco",
"Amount cannot be zero": "El importe no puede ser cero", "You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados",
"Company has to be official": "Empresa inválida", "ASSIGN_ZONE_FIRST": "Asigna una zona primero",
"You can not select this payment method without a registered bankery account": "No se puede utilizar este método de pago si no has registrado una cuenta bancaria", "Amount cannot be zero": "El importe no puede ser cero",
"Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas", "Company has to be official": "Empresa inválida",
"The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta", "You can not select this payment method without a registered bankery account": "No se puede utilizar este método de pago si no has registrado una cuenta bancaria",
"New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*", "Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas",
"New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}*", "The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
"Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío", "New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*",
"This BIC already exist.": "Este BIC ya existe.", "New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}*",
"That item doesn't exists": "Ese artículo no existe", "Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
"There's a new urgent ticket:": "Hay un nuevo ticket urgente:", "This BIC already exist.": "Este BIC ya existe.",
"Invalid account": "Cuenta inválida", "That item doesn't exists": "Ese artículo no existe",
"Compensation account is empty": "La cuenta para compensar está vacia", "There's a new urgent ticket:": "Hay un nuevo ticket urgente:",
"This genus already exist": "Este genus ya existe", "Invalid account": "Cuenta inválida",
"This specie already exist": "Esta especie ya existe", "Compensation account is empty": "La cuenta para compensar está vacia",
"Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})", "This genus already exist": "Este genus ya existe",
"None": "Ninguno", "This specie already exist": "Esta especie ya existe",
"The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada", "Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"Cannot add more than one '1/2 day vacation'": "No puedes añadir más de un 'Vacaciones 1/2 dia'", "None": "Ninguno",
"This document already exists on this ticket": "Este documento ya existe en el ticket", "The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada",
"Some of the selected tickets are not billable": "Algunos de los tickets seleccionados no son facturables", "Cannot add more than one '1/2 day vacation'": "No puedes añadir más de un 'Vacaciones 1/2 dia'",
"You can't invoice tickets from multiple clients": "No puedes facturar tickets de multiples clientes", "This document already exists on this ticket": "Este documento ya existe en el ticket",
"nickname": "nickname", "Some of the selected tickets are not billable": "Algunos de los tickets seleccionados no son facturables",
"INACTIVE_PROVIDER": "Proveedor inactivo", "You can't invoice tickets from multiple clients": "No puedes facturar tickets de multiples clientes",
"This client is not invoiceable": "Este cliente no es facturable", "nickname": "nickname",
"serial non editable": "Esta serie no permite asignar la referencia", "INACTIVE_PROVIDER": "Proveedor inactivo",
"Max shipped required": "La fecha límite es requerida", "This client is not invoiceable": "Este cliente no es facturable",
"Can't invoice to future": "No se puede facturar a futuro", "serial non editable": "Esta serie no permite asignar la referencia",
"Can't invoice to past": "No se puede facturar a pasado", "Max shipped required": "La fecha límite es requerida",
"This ticket is already invoiced": "Este ticket ya está facturado", "Can't invoice to future": "No se puede facturar a futuro",
"A ticket with an amount of zero can't be invoiced": "No se puede facturar un ticket con importe cero", "Can't invoice to past": "No se puede facturar a pasado",
"A ticket with a negative base can't be invoiced": "No se puede facturar un ticket con una base negativa", "This ticket is already invoiced": "Este ticket ya está facturado",
"Global invoicing failed": "[Facturación global] No se han podido facturar algunos clientes", "A ticket with an amount of zero can't be invoiced": "No se puede facturar un ticket con importe cero",
"Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes", "A ticket with a negative base can't be invoiced": "No se puede facturar un ticket con una base negativa",
"Can't verify data unless the client has a business type": "No se puede verificar datos de un cliente que no tiene tipo de negocio", "Global invoicing failed": "[Facturación global] No se han podido facturar algunos clientes",
"You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito", "Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes",
"You can't change the credit set to zero from a financialBoss": "No puedes cambiar el cŕedito establecido a cero por un jefe de finanzas", "Can't verify data unless the client has a business type": "No se puede verificar datos de un cliente que no tiene tipo de negocio",
"Amounts do not match": "Las cantidades no coinciden", "You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito",
"The PDF document does not exist": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'", "You can't change the credit set to zero from a financialBoss": "No puedes cambiar el cŕedito establecido a cero por un jefe de finanzas",
"The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos", "Amounts do not match": "Las cantidades no coinciden",
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días", "The PDF document does not exist": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
"The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día", "The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día", "You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
"You can not modify is pay method checked": "No se puede modificar el campo método de pago validado", "The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
"The account size must be exactly 10 characters": "El tamaño de la cuenta debe ser exactamente de 10 caracteres", "The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día",
"Can't transfer claimed sales": "No puedes transferir lineas reclamadas", "You can not modify is pay method checked": "No se puede modificar el campo método de pago validado",
"You don't have privileges to create refund": "No tienes permisos para crear un abono", "The account size must be exactly 10 characters": "El tamaño de la cuenta debe ser exactamente de 10 caracteres",
"The item is required": "El artículo es requerido", "Can't transfer claimed sales": "No puedes transferir lineas reclamadas",
"The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo", "You don't have privileges to create refund": "No tienes permisos para crear un abono",
"date in the future": "Fecha en el futuro", "The item is required": "El artículo es requerido",
"reference duplicated": "Referencia duplicada", "The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo",
"This ticket is already a refund": "Este ticket ya es un abono", "date in the future": "Fecha en el futuro",
"isWithoutNegatives": "Sin negativos", "reference duplicated": "Referencia duplicada",
"routeFk": "routeFk", "This ticket is already a refund": "Este ticket ya es un abono",
"Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador", "isWithoutNegatives": "Sin negativos",
"No hay un contrato en vigor": "No hay un contrato en vigor", "routeFk": "routeFk",
"No se permite fichar a futuro": "No se permite fichar a futuro", "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador",
"No está permitido trabajar": "No está permitido trabajar", "No hay un contrato en vigor": "No hay un contrato en vigor",
"Fichadas impares": "Fichadas impares", "No se permite fichar a futuro": "No se permite fichar a futuro",
"Descanso diario 12h.": "Descanso diario 12h.", "No está permitido trabajar": "No está permitido trabajar",
"Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.", "Fichadas impares": "Fichadas impares",
"Dirección incorrecta": "Dirección incorrecta", "Descanso diario 12h.": "Descanso diario 12h.",
"Modifiable user details only by an administrator": "Detalles de usuario modificables solo por un administrador", "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.",
"Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador", "Dirección incorrecta": "Dirección incorrecta",
"Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente", "Modifiable user details only by an administrator": "Detalles de usuario modificables solo por un administrador",
"This route does not exists": "Esta ruta no existe", "Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador",
"Claim pickup order sent": "Reclamación Orden de recogida enviada [{{claimId}}]({{{claimUrl}}}) al cliente *{{clientName}}*", "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente",
"You don't have grant privilege": "No tienes privilegios para dar privilegios", "This route does not exists": "Esta ruta no existe",
"You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario", "Claim pickup order sent": "Reclamación Orden de recogida enviada [{{claimId}}]({{{claimUrl}}}) al cliente *{{clientName}}*",
"Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) fusionado con [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})", "You don't have grant privilege": "No tienes privilegios para dar privilegios",
"Already has this status": "Ya tiene este estado", "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario",
"There aren't records for this week": "No existen registros para esta semana", "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) fusionado con [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
"Empty data source": "Origen de datos vacio", "Already has this status": "Ya tiene este estado",
"App locked": "Aplicación bloqueada por el usuario {{userId}}", "There aren't records for this week": "No existen registros para esta semana",
"Email verify": "Correo de verificación", "Empty data source": "Origen de datos vacio",
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment", "App locked": "Aplicación bloqueada por el usuario {{userId}}",
"Receipt's bank was not found": "No se encontró el banco del recibo", "Email verify": "Correo de verificación",
"This receipt was not compensated": "Este recibo no ha sido compensado", "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
"Client's email was not found": "No se encontró el email del cliente", "Receipt's bank was not found": "No se encontró el banco del recibo",
"Negative basis": "Base negativa", "This receipt was not compensated": "Este recibo no ha sido compensado",
"This worker code already exists": "Este codigo de trabajador ya existe", "Client's email was not found": "No se encontró el email del cliente",
"This personal mail already exists": "Este correo personal ya existe", "Negative basis": "Base negativa",
"This worker already exists": "Este trabajador ya existe", "This worker code already exists": "Este codigo de trabajador ya existe",
"App name does not exist": "El nombre de aplicación no es válido", "This personal mail already exists": "Este correo personal ya existe",
"Try again": "Vuelve a intentarlo", "This worker already exists": "Este trabajador ya existe",
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", "App name does not exist": "El nombre de aplicación no es válido",
"Failed to upload delivery note": "Error al subir albarán {{id}}", "Try again": "Vuelve a intentarlo",
"The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe", "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9",
"It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", "Failed to upload delivery note": "Error al subir albarán {{id}}",
"It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe",
"It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar",
"A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo",
"There is no assigned email for this client": "No hay correo asignado para este cliente", "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
"Exists an invoice with a future date": "Existe una factura con fecha posterior", "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.",
"Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", "There is no assigned email for this client": "No hay correo asignado para este cliente",
"Warehouse inventory not set": "El almacén inventario no está establecido", "Exists an invoice with a future date": "Existe una factura con fecha posterior",
"This locker has already been assigned": "Esta taquilla ya ha sido asignada", "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite",
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %d", "Warehouse inventory not set": "El almacén inventario no está establecido",
"Not exist this branch": "La rama no existe", "This locker has already been assigned": "Esta taquilla ya ha sido asignada",
"This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado", "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %d",
"Collection does not exist": "La colección no existe", "Not exist this branch": "La rama no existe",
"Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo", "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado",
"Insert a date range": "Inserte un rango de fechas", "Collection does not exist": "La colección no existe",
"Added observation": "{{user}} añadió esta observacion: {{text}}", "Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo",
"Comment added to client": "Observación añadida al cliente {{clientFk}}", "Insert a date range": "Inserte un rango de fechas",
"Invalid auth code": "Código de verificación incorrecto", "Added observation": "{{user}} añadió esta observacion: {{text}}",
"Invalid or expired verification code": "Código de verificación incorrecto o expirado", "Comment added to client": "Observación añadida al cliente {{clientFk}}",
"Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen", "Invalid auth code": "Código de verificación incorrecto",
"company": "Compañía", "Invalid or expired verification code": "Código de verificación incorrecto o expirado",
"country": "País", "Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen",
"clientId": "Id cliente", "company": "Compañía",
"clientSocialName": "Cliente", "country": "País",
"amount": "Importe", "clientId": "Id cliente",
"taxableBase": "Base", "clientSocialName": "Cliente",
"ticketFk": "Id ticket", "amount": "Importe",
"isActive": "Activo", "taxableBase": "Base",
"hasToInvoice": "Facturar", "ticketFk": "Id ticket",
"isTaxDataChecked": "Datos comprobados", "isActive": "Activo",
"comercialId": "Id comercial", "hasToInvoice": "Facturar",
"comercialName": "Comercial", "isTaxDataChecked": "Datos comprobados",
"Pass expired": "La contraseña ha caducado, cambiela desde Salix", "comercialId": "Id comercial",
"Invalid NIF for VIES": "Invalid NIF for VIES", "comercialName": "Comercial",
"Ticket does not exist": "Este ticket no existe", "Pass expired": "La contraseña ha caducado, cambiela desde Salix",
"Ticket is already signed": "Este ticket ya ha sido firmado", "Invalid NIF for VIES": "Invalid NIF for VIES",
"Authentication failed": "Autenticación fallida", "Ticket does not exist": "Este ticket no existe",
"You can't use the same password": "No puedes usar la misma contraseña", "Ticket is already signed": "Este ticket ya ha sido firmado",
"You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono", "Authentication failed": "Autenticación fallida",
"Fecha fuera de rango": "Fecha fuera de rango", "You can't use the same password": "No puedes usar la misma contraseña",
"Error while generating PDF": "Error al generar PDF", "You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono",
"Error when sending mail to client": "Error al enviar el correo al cliente", "Fecha fuera de rango": "Fecha fuera de rango",
"Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico", "Error while generating PDF": "Error al generar PDF",
"The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Error when sending mail to client": "Error al enviar el correo al cliente",
"Valid priorities": "Prioridades válidas: %d", "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
"hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}", "The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
"hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}", "Valid priorities": "Prioridades válidas: %d",
"You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", "hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}",
"This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s", "hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}",
"The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado",
"You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", "This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s",
"This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias",
"You don't have enough privileges.": "No tienes suficientes permisos.", "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado",
"This ticket is locked": "Este ticket está bloqueado.", "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado",
"This ticket is not editable.": "Este ticket no es editable.", "You don't have enough privileges.": "No tienes suficientes permisos.",
"The ticket doesn't exist.": "No existe el ticket.", "This ticket is locked": "Este ticket está bloqueado.",
"Social name should be uppercase": "La razón social debe ir en mayúscula", "This ticket is not editable.": "Este ticket no es editable.",
"Street should be uppercase": "La dirección fiscal debe ir en mayúscula", "The ticket doesn't exist.": "No existe el ticket.",
"Ticket without Route": "Ticket sin ruta", "Social name should be uppercase": "La razón social debe ir en mayúscula",
"Select a different client": "Seleccione un cliente distinto", "Street should be uppercase": "La dirección fiscal debe ir en mayúscula",
"Fill all the fields": "Rellene todos los campos", "Ticket without Route": "Ticket sin ruta",
"The response is not a PDF": "La respuesta no es un PDF", "Select a different client": "Seleccione un cliente distinto",
"Booking completed": "Reserva completada", "Fill all the fields": "Rellene todos los campos",
"The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación", "The response is not a PDF": "La respuesta no es un PDF",
"The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada", "Booking completed": "Reserva completada",
"User disabled": "Usuario desactivado", "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima", "User disabled": "Usuario desactivado",
"Cannot past travels with entries": "No se pueden pasar envíos con entradas", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
"It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima",
"This claim has been updated": "La reclamación con Id: {{claimId}}, ha sido actualizada", "Cannot past travels with entries": "No se pueden pasar envíos con entradas",
"This user does not have an assigned tablet": "Este usuario no tiene tablet asignada", "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}",
"Field are invalid": "El campo '{{tag}}' no es válido", "This claim has been updated": "La reclamación con Id: {{claimId}}, ha sido actualizada",
"Incorrect pin": "Pin incorrecto.", "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada",
"You already have the mailAlias": "Ya tienes este alias de correo", "Field are invalid": "El campo '{{tag}}' no es válido",
"The alias cant be modified": "Este alias de correo no puede ser modificado", "Incorrect pin": "Pin incorrecto.",
"No tickets to invoice": "No hay tickets para facturar", "You already have the mailAlias": "Ya tienes este alias de correo",
"this warehouse has not dms": "El Almacén no acepta documentos", "The alias cant be modified": "Este alias de correo no puede ser modificado",
"This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado", "No tickets to invoice": "No hay tickets para facturar",
"Name should be uppercase": "El nombre debe ir en mayúscula", "this warehouse has not dms": "El Almacén no acepta documentos",
"Bank entity must be specified": "La entidad bancaria es obligatoria", "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado",
"An email is necessary": "Es necesario un email", "Name should be uppercase": "El nombre debe ir en mayúscula",
"You cannot update these fields": "No puedes actualizar estos campos", "Bank entity must be specified": "La entidad bancaria es obligatoria",
"CountryFK cannot be empty": "El país no puede estar vacío", "An email is necessary": "Es necesario un email",
"Cmr file does not exist": "El archivo del cmr no existe", "You cannot update these fields": "No puedes actualizar estos campos",
"You are not allowed to modify the alias": "No estás autorizado a modificar el alias", "CountryFK cannot be empty": "El país no puede estar vacío",
"The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas", "Cmr file does not exist": "El archivo del cmr no existe",
"The line could not be marked": "La linea no puede ser marcada", "You are not allowed to modify the alias": "No estás autorizado a modificar el alias",
"This password can only be changed by the user themselves": "Esta contraseña solo puede ser modificada por el propio usuario", "The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas",
"They're not your subordinate": "No es tu subordinado/a." "The line could not be marked": "La linea no puede ser marcada",
"This password can only be changed by the user themselves": "Esta contraseña solo puede ser modificada por el propio usuario",
"They're not your subordinate": "No es tu subordinado/a.",
"No results found": "No se han encontrado resultados"
} }

View File

@ -6,7 +6,6 @@ columns:
isChargedToMana: charged to mana isChargedToMana: charged to mana
created: created created: created
responsibility: responsibility responsibility: responsibility
hasToPickUp: has to pickUp
ticketFk: ticket ticketFk: ticket
claimStateFk: claim state claimStateFk: claim state
workerFk: worker workerFk: worker

View File

@ -6,7 +6,6 @@ columns:
isChargedToMana: cargado al maná isChargedToMana: cargado al maná
created: creado created: creado
responsibility: responsabilidad responsibility: responsabilidad
hasToPickUp: es recogida
ticketFk: ticket ticketFk: ticket
claimStateFk: estado reclamación claimStateFk: estado reclamación
workerFk: trabajador workerFk: trabajador

View File

@ -11,7 +11,7 @@ describe('claim log()', () => {
model: 'Claim', model: 'Claim',
action: 'update', action: 'update',
changes: [ changes: [
{property: 'hasToPickUp', before: false, after: true} {property: 'pickup', before: null, after: 'agency'}
] ]
}; };

View File

@ -86,7 +86,7 @@ describe('Update Claim', () => {
args: { args: {
observation: 'valid observation', observation: 'valid observation',
claimStateFk: pendingState, claimStateFk: pendingState,
hasToPickUp: false pickup: null
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;
@ -124,7 +124,7 @@ describe('Update Claim', () => {
args: { args: {
observation: 'valid observation', observation: 'valid observation',
claimStateFk: canceledState, claimStateFk: canceledState,
hasToPickUp: false pickup: null
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;
@ -163,7 +163,7 @@ describe('Update Claim', () => {
claimStateFk: 3, claimStateFk: 3,
workerFk: 5, workerFk: 5,
observation: 'another valid observation', observation: 'another valid observation',
hasToPickUp: true pickup: 'agency'
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;

View File

@ -27,8 +27,8 @@ module.exports = Self => {
type: 'string' type: 'string'
}, },
{ {
arg: 'hasToPickUp', arg: 'pickup',
type: 'boolean' type: 'any'
}, },
{ {
arg: 'packages', arg: 'packages',
@ -72,9 +72,7 @@ module.exports = Self => {
// Get sales person from claim client // Get sales person from claim client
const salesPerson = claim.client().salesPersonUser(); const salesPerson = claim.client().salesPersonUser();
let changedHasToPickUp = false; const changedPickup = args.pickup != claim.pickup;
if (args.hasToPickUp)
changedHasToPickUp = true;
// Validate when claimState has been changed // Validate when claimState has been changed
if (args.claimStateFk) { if (args.claimStateFk) {
@ -82,15 +80,15 @@ module.exports = Self => {
const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions); const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions);
const canEditState = await models.ACL.checkAccessAcl(ctx, 'Claim', 'editState', 'WRITE'); const canEditState = await models.ACL.checkAccessAcl(ctx, 'Claim', 'editState', 'WRITE');
if (!canEditOldState || !canEditNewState || changedHasToPickUp && !canEditState) if (!canEditOldState || !canEditNewState || changedPickup && !canEditState)
throw new UserError(`You don't have enough privileges to change that field`); throw new UserError(`You don't have enough privileges to change that field`);
} }
delete args.ctx; delete args.ctx;
const updatedClaim = await claim.updateAttributes(args, myOptions); const updatedClaim = await claim.updateAttributes(args, myOptions);
// When hasToPickUp has been changed // When pickup has been changed
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) if (salesPerson && changedPickup && updatedClaim.pickup)
await notifyPickUp(ctx, salesPerson.id, claim); await notifyPickUp(ctx, salesPerson.id, claim);
// When claimState has been changed // When claimState has been changed
@ -132,7 +130,8 @@ module.exports = Self => {
const message = $t('Claim will be picked', { const message = $t('Claim will be picked', {
claimId: claim.id, claimId: claim.id,
clientName: claim.client().name, clientName: claim.client().name,
claimUrl: `${url}claim/${claim.id}/summary` claimUrl: `${url}claim/${claim.id}/summary`,
claimPickup: $t(claim.pickup)
}); });
await models.Chat.sendCheckingPresence(ctx, workerId, message); await models.Chat.sendCheckingPresence(ctx, workerId, message);
} }

View File

@ -31,8 +31,8 @@
"responsibility": { "responsibility": {
"type": "number" "type": "number"
}, },
"hasToPickUp": { "pickup": {
"type": "boolean" "type": "string"
}, },
"ticketFk": { "ticketFk": {
"type": "number" "type": "number"

View File

@ -85,7 +85,7 @@ describe('claim', () => {
it('should perform a patch query and show a success message', () => { it('should perform a patch query and show a success message', () => {
jest.spyOn(controller.vnApp, 'showSuccess'); jest.spyOn(controller.vnApp, 'showSuccess');
const data = {hasToPickUp: true}; const data = {pickup: 'agency'};
$httpBackend.expect('PATCH', `Claims/1/updateClaimAction`, data).respond({}); $httpBackend.expect('PATCH', `Claims/1/updateClaimAction`, data).respond({});
controller.save(data); controller.save(data);
$httpBackend.flush(); $httpBackend.flush();

View File

@ -49,13 +49,6 @@
label="Packages received" label="Packages received"
ng-model="$ctrl.claim.packages"> ng-model="$ctrl.claim.packages">
</vn-input-number> </vn-input-number>
<vn-check
class="vn-mr-md"
label="Pick up"
ng-model="$ctrl.claim.hasToPickUp"
vn-acl="claimManager"
title="{{'When checked will notify to the salesPerson' | translate}}">
</vn-check>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>
<vn-button-bar> <vn-button-bar>

View File

@ -49,13 +49,6 @@
label="Attended by" label="Attended by"
value="{{$ctrl.summary.claim.worker.user.nickname}}"> value="{{$ctrl.summary.claim.worker.user.nickname}}">
</vn-label-value> </vn-label-value>
<vn-check
class="vn-mr-md"
label="Pick up"
ng-model="$ctrl.summary.claim.hasToPickUp"
title="{{'When checked will notify to the salesPerson' | translate}}"
disabled="true">
</vn-check>
</vn-auto> </vn-auto>
<vn-auto> <vn-auto>
<h4 ng-show="$ctrl.isSalesPerson && $ctrl.summary.observations.length"> <h4 ng-show="$ctrl.isSalesPerson && $ctrl.summary.observations.length">

View File

@ -1,4 +1,4 @@
const {models} = require('vn-loopback/server/server'); const { models } = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
// #6276 // #6276
@ -8,11 +8,11 @@ describe('ItemShelving upsertItem()', () => {
let options; let options;
let tx; let tx;
beforeEach(async() => { beforeEach(async () => {
ctx = { ctx = {
req: { req: {
accessToken: {userId: 9}, accessToken: { userId: 9 },
headers: {origin: 'http://localhost'} headers: { origin: 'http://localhost' }
}, },
args: {} args: {}
}; };
@ -21,36 +21,37 @@ describe('ItemShelving upsertItem()', () => {
active: ctx.req active: ctx.req
}); });
options = {transaction: tx}; options = { transaction: tx };
tx = await models.ItemShelving.beginTransaction({}); tx = await models.ItemShelving.beginTransaction({});
options.transaction = tx; options.transaction = tx;
}); });
afterEach(async() => { afterEach(async () => {
await tx.rollback(); await tx.rollback();
}); });
xit('should add two new records', async() => { it('should add two new records', async () => {
const shelvingFk = 'ZPP'; const shelvingFk = 'ZPP';
const items = [1, 1, 1, 2]; const items = [1, 1, 1, 2];
await models.ItemShelving.upsertItem(ctx, shelvingFk, items, warehouseFk, options); await models.ItemShelving.upsertItem(ctx, shelvingFk, items, warehouseFk, options);
const itemShelvings = await models.ItemShelving.find({where: {shelvingFk}}, options); const itemShelvings = await models.ItemShelving.find({ where: { shelvingFk } }, options);
expect(itemShelvings.length).toEqual(2); expect(itemShelvings.length).toEqual(2);
}); });
xit('should update the visible items', async() => { it('should update the visible items', async () => {
const shelvingFk = 'GVC'; const shelvingFk = 'GVC';
const items = [2, 2]; const items = [2, 2];
const {visible: itemsBefore} = await models.ItemShelving.findOne({ const { visible: visibleItemsBefore } = await models.ItemShelving.findOne({
where: {shelvingFk, itemFk: items[0]} where: { shelvingFk, itemFk: items[0] }
}, options); }, options);
await models.ItemShelving.upsertItem(ctx, shelvingFk, items, warehouseFk, options); await models.ItemShelving.upsertItem(ctx, shelvingFk, items, warehouseFk, options);
const {visible: itemsAfter} = await models.ItemShelving.findOne({
where: {shelvingFk, itemFk: items[0]} const { visible: visibleItemsAfter } = await models.ItemShelving.findOne({
where: { shelvingFk, itemFk: items[0] }
}, options); }, options);
expect(itemsAfter).toEqual(itemsBefore + 2); expect(visibleItemsAfter).toEqual(visibleItemsBefore + 2);
}); });
}); });

View File

@ -1,4 +1,5 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('filter', { Self.remoteMethodCtx('filter', {
@ -33,28 +34,31 @@ module.exports = Self => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const models = Self.app.models; const models = Self.app.models;
// Get ids alloweds
const account = await models.VnUser.findById(userId); const account = await models.VnUser.findById(userId);
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT d.id dmsFk, d.reference, d.description, d.file, d.created, d.hardCopyNumber, d.hasFile `SELECT d.id, d.id dmsFk
FROM workerDocument wd FROM workerDocument wd
JOIN dms d ON d.id = wd.document JOIN dms d ON d.id = wd.document
JOIN dmsType dt ON dt.id = d.dmsTypeFk JOIN dmsType dt ON dt.id = d.dmsTypeFk
LEFT JOIN account.roleRole rr ON rr.inheritsFrom = dt.readRoleFk AND rr.role = ? LEFT JOIN account.roleRole rr ON rr.inheritsFrom = dt.readRoleFk AND rr.role = ?
`, [account.roleFk] `, [account.roleFk]
); );
const oldWhere = filter.where;
const yourOwnDms = {and: [{isReadableByWorker: true}, {worker: userId}]}; const yourOwnDms = {and: [{isReadableByWorker: true}, {worker: userId}]};
const where = {
or: [yourOwnDms, {
role: {
neq: null
}
}]
};
stmt.merge(conn.makeSuffix(mergeWhere(filter.where, where)));
filter.where = { // Get workerDms alloweds
and: [{ const dmsIds = await conn.executeStmt(stmt);
or: [yourOwnDms, { const allowedIds = dmsIds.map(dms => dms.id);
role: { const allowedFilter = mergeFilters(filter, {where: {dmsFk: {inq: allowedIds}, workerFk: id}});
neq: null let workerDms = await models.WorkerDms.find(allowedFilter);
}
}]
}, oldWhere]};
stmt.merge(conn.makeSuffix(filter));
const workerDms = await conn.executeStmt(stmt);
// Get docuware info // Get docuware info
const docuware = await models.Docuware.findOne({ const docuware = await models.Docuware.findOne({
@ -63,28 +67,43 @@ module.exports = Self => {
}); });
const docuwareDmsType = docuware.dmsTypeFk; const docuwareDmsType = docuware.dmsTypeFk;
let workerDocuware = []; let workerDocuware = [];
if (!docuwareDmsType || (docuwareDmsType && await models.DmsType.hasReadRole(ctx, docuwareDmsType))) { if (!filter.skip && (!docuwareDmsType || (docuwareDmsType && await models.DmsType.hasReadRole(ctx, docuwareDmsType)))) {
const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']});
const docuwareParse = { const docuwareParse = {
'Filename': 'dmsFk', 'Filename': 'dmsFk',
'Tipo Documento': 'description', 'Tipo Documento': 'description',
'Stored on': 'created', 'Stored on': 'created',
'Document ID': 'id' 'Document ID': 'id',
'URL': 'download',
'Stored by': 'name',
'Estado': 'state'
}; };
workerDocuware = workerDocuware =
await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? []; await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? [];
const url = (await Self.app.models.Url.getUrl('docuware')) + 'WebClient';
for (document of workerDocuware) { for (document of workerDocuware) {
const docuwareId = document.id;
const defaultData = { const defaultData = {
file: 'dw' + document.id + '.png', id: docuwareId,
isDocuware: true, workerFk: id,
hardCopyNumber: null, dmsFk: docuwareId,
hasFile: false, dms: {
reference: worker.fi, id: docuwareId,
dmsFk: 'DW' + document.id file: docuwareId + '.pdf',
isDocuware: true,
hasFile: false,
reference: worker.fi,
dmsFk: docuwareId,
url,
description: document.description + ' - ' + document.state,
download: document.download,
created: document.created,
dmsType: {name: 'Docuware'},
worker: {id: null, user: {name: document.name}},
}
}; };
Object.assign(document, defaultData);
document = Object.assign(document, defaultData);
} }
} }
return workerDms.concat(workerDocuware); return workerDms.concat(workerDocuware);

View File

@ -2,6 +2,7 @@
vn-id="model" vn-id="model"
url="WorkerDms/{{$ctrl.$params.id}}/filter" url="WorkerDms/{{$ctrl.$params.id}}/filter"
link="{worker: $ctrl.$params.id}" link="{worker: $ctrl.$params.id}"
filter="$ctrl.filter"
limit="20" limit="20"
data="$ctrl.workerDms" data="$ctrl.workerDms"
order="dmsFk DESC" order="dmsFk DESC"
@ -28,37 +29,37 @@
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="document in $ctrl.workerDms"> <vn-tr ng-repeat="document in $ctrl.workerDms">
<vn-td number shrink>{{::document.dmsFk}}</vn-td> <vn-td number shrink>{{::document.id}}</vn-td>
<vn-td shrink number> <vn-td shrink number>
<span class="chip" title="{{::document.hardCopyNumber}}" <span class="chip" title="{{::document.dms.hardCopyNumber}}"
ng-class="{'message': document.hardCopyNumber}"> ng-class="{'message': document.hardCopyNumber}">
{{::document.hardCopyNumber}} {{::document.dms.hardCopyNumber}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand>
<span title="{{::document.reference}}"> <span title="{{::document.dms.reference}}">
{{::document.reference}} {{::document.dms.reference}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand>
<span title="{{::document.description}}"> <span title="{{::document.dms.description}}">
{{::document.description}} {{::document.dms.description}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<vn-check <vn-check
ng-model="document.hasFile" ng-model="document.dms.hasFile"
disabled="true"> disabled="true">
</vn-check> </vn-check>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<span title="{{'Download file' | translate}}" class="link" <span title="{{'Download file' | translate}}" class="link"
ng-click="$ctrl.downloadFile(document.dmsFk, document.isDocuware)"> ng-click="$ctrl.downloadFile(document.dmsFk, document.dms.isDocuware)">
{{::document.file}} {{::document.dms.file}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink-datetime> <vn-td shrink-datetime>
{{::document.created | date:'dd/MM/yyyy HH:mm'}} {{::document.dms.created | date:'dd/MM/yyyy HH:mm'}}
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<vn-icon-button title="{{'Download file' | translate}}" <vn-icon-button title="{{'Download file' | translate}}"
@ -66,7 +67,7 @@
ng-click="$ctrl.downloadFile(document.dmsFk, document.isDocuware)"> ng-click="$ctrl.downloadFile(document.dmsFk, document.isDocuware)">
</vn-icon-button> </vn-icon-button>
</vn-td> </vn-td>
<vn-td expand ng-if="::!document.isDocuware"> <vn-td expand ng-if="::!document.dms.isDocuware">
<vn-icon-button ui-sref="worker.card.dms.edit({dmsId: {{::document.dmsFk}}})" <vn-icon-button ui-sref="worker.card.dms.edit({dmsId: {{::document.dmsFk}}})"
icon="edit" icon="edit"
title="{{'Edit file' | translate}}"> title="{{'Edit file' | translate}}">
@ -78,7 +79,7 @@
tabindex="-1"> tabindex="-1">
</vn-icon-button> </vn-icon-button>
</vn-td> </vn-td>
<vn-td expand ng-if="::document.isDocuware"> <vn-td expand ng-if="::document.dms.isDocuware">
<vn-icon-button <vn-icon-button
icon="open_in_new" icon="open_in_new"
ng-click="$ctrl.openDocuware()" ng-click="$ctrl.openDocuware()"

View File

@ -6,6 +6,45 @@ class Controller extends Component {
constructor($element, $, vnFile) { constructor($element, $, vnFile) {
super($element, $); super($element, $);
this.vnFile = vnFile; this.vnFile = vnFile;
this.filter = {
include: {
relation: 'dms',
scope: {
fields: [
'dmsTypeFk',
'reference',
'hardCopyNumber',
'workerFk',
'description',
'hasFile',
'file',
'created',
'companyFk',
'warehouseFk',
],
include: [
{
relation: 'dmsType',
scope: {
fields: ['name'],
},
},
{
relation: 'worker',
scope: {
fields: ['id'],
include: {
relation: 'user',
scope: {
fields: ['name'],
},
},
},
},
],
},
},
};
} }
deleteDms(index) { deleteDms(index) {