7658-devToTest_2428 #2663

Merged
alexm merged 251 commits from 7658-devToTest_2428 into test 2024-07-02 07:20:13 +00:00
63 changed files with 886 additions and 643 deletions
Showing only changes of commit d998b650da - Show all commits

View File

@ -3,14 +3,14 @@ const {models} = require('vn-loopback/server/server');
describe('Chat send()', () => { describe('Chat send()', () => {
it('should return true as response', async() => { it('should return true as response', async() => {
let ctx = {req: {accessToken: {userId: 1}}}; let ctx = {req: {accessToken: {userId: 1}}};
let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something'); let response = await models.Chat.send(ctx, '@salesperson', 'I changed something');
expect(response).toEqual(true); expect(response).toEqual(true);
}); });
it('should return false as response', async() => { it('should return false as response', async() => {
let ctx = {req: {accessToken: {userId: 18}}}; let ctx = {req: {accessToken: {userId: 18}}};
let response = await models.Chat.send(ctx, '@salesPerson', 'I changed something'); let response = await models.Chat.send(ctx, '@salesperson', 'I changed something');
expect(response).toEqual(false); expect(response).toEqual(false);
}); });

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 || 'dev' environment: process.env.NODE_ENV || 'dev'
} }
}); });
return url; return url?.url;
}; };
}; };

View File

@ -81,7 +81,7 @@ INSERT INTO `account`.`roleConfig`(`id`, `mysqlPassword`, `rolePrefix`, `userPre
CALL `account`.`role_sync`; CALL `account`.`role_sync`;
INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `role`,`active`,`email`, `lang`, `image`, `password`) INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `role`,`active`,`email`, `lang`, `image`, `password`)
SELECT id, name, CONCAT(name, 'Nick'), id, 1, CONCAT(name, '@mydomain.com'), 'en', '4fa3ada0-3ac4-11eb-9ab8-27f6fc3b85fd', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2' SELECT id, LOWER(name), CONCAT(name, 'Nick'), id, 1, CONCAT(name, '@mydomain.com'), 'en', '4fa3ada0-3ac4-11eb-9ab8-27f6fc3b85fd', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2'
FROM `account`.`role` FROM `account`.`role`
ORDER BY id; ORDER BY id;
@ -118,18 +118,18 @@ INSERT INTO `hedera`.`tpvConfig`(`id`, `currency`, `terminal`, `transactionType`
INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`) INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`)
VALUES VALUES
(1101, 'BruceWayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'BruceWayne@mydomain.com', 'es','1101'), (1101, 'brucewayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'BruceWayne@mydomain.com', 'es','1101'),
(1102, 'PetterParker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'PetterParker@mydomain.com', 'en','1102'), (1102, 'petterparker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'PetterParker@mydomain.com', 'en','1102'),
(1103, 'ClarkKent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'ClarkKent@mydomain.com', 'fr','1103'), (1103, 'clarkkent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'ClarkKent@mydomain.com', 'fr','1103'),
(1104, 'TonyStark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'TonyStark@mydomain.com', 'es','1104'), (1104, 'tonystark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'TonyStark@mydomain.com', 'es','1104'),
(1105, 'MaxEisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt','1105'), (1105, 'maxeisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt','1105'),
(1106, 'DavidCharlesHaller', 'David Charles Haller', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en','1106'), (1106, 'davidcharleshaller', 'David Charles Haller', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'DavidCharlesHaller@mydomain.com', 'en','1106'),
(1107, 'HankPym', 'Hank Pym', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'HankPym@mydomain.com', 'en','1107'), (1107, 'hankpym', 'Hank Pym', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'HankPym@mydomain.com', 'en','1107'),
(1108, 'CharlesXavier', 'Charles Xavier', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'CharlesXavier@mydomain.com', 'en','1108'), (1108, 'charlesxavier', 'Charles Xavier', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'CharlesXavier@mydomain.com', 'en','1108'),
(1109, 'BruceBanner', 'Bruce Banner', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'BruceBanner@mydomain.com', 'en','1109'), (1109, 'brucebanner', 'Bruce Banner', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'BruceBanner@mydomain.com', 'en','1109'),
(1110, 'JessicaJones', 'Jessica Jones', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'JessicaJones@mydomain.com', 'en','1110'), (1110, 'jessicajones', 'Jessica Jones', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 1, 1, 'JessicaJones@mydomain.com', 'en','1110'),
(1111, 'Missing', 'Missing', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 0, NULL, 'en','e7723f0b24ff05b32ed09d95196f2f29'), (1111, 'missing', 'Missing', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 0, NULL, 'en','e7723f0b24ff05b32ed09d95196f2f29'),
(1112, 'Trash', 'Trash', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 0, NULL, 'en','e7723f0b24ff05b32ed09d95196f2f29'); (1112, 'trash', 'Trash', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 0, NULL, 'en','e7723f0b24ff05b32ed09d95196f2f29');
UPDATE account.`user` UPDATE account.`user`
SET passExpired = DATE_SUB(util.VN_CURDATE(), INTERVAL 1 YEAR) SET passExpired = DATE_SUB(util.VN_CURDATE(), INTERVAL 1 YEAR)
@ -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);
@ -2913,7 +2913,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
@ -3735,3 +3736,18 @@ INSERT INTO vn.ticketLog (originFk,userFk,`action`,creationDate,changedModel,new
INSERT INTO `vn`.`supplierDms`(`supplierFk`, `dmsFk`, `editorFk`) INSERT INTO `vn`.`supplierDms`(`supplierFk`, `dmsFk`, `editorFk`)
VALUES VALUES
(1, 10, 9); (1, 10, 9);
INSERT INTO `vn`.`accountReconciliation` (supplierAccountFk,operationDated,valueDated,amount,concept,debitCredit,calculatedCode,created)
VALUES
(241,'2023-12-13 00:00:00.000','2023-12-07 00:00:00.000',19.36,'BEL 1','debit','2','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-07 00:00:00.000',30226.43,'BEL 2','debit','1','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',118.81,'RCBO','debit','10','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',150.03,'TJ','debit','12','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',150.03,'TJ','debit','12','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',2149.71,'RCBO.AMAZON','debit','122','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',3210.5,'RCBO.VOLVO','debit','121','2023-12-14 08:39:53.000'),
(241,'2023-12-13 00:00:00.000','2023-12-13 00:00:00.000',6513.7,'RCBO.ENERPLUS','debit','120','2023-12-14 08:39:53.000');
INSERT INTO `vn`.`accountReconciliationConfig`(currencyFk, warehouseFk)
VALUES
(1, 1);

View File

@ -7,7 +7,7 @@ BEGIN
* The user name must only contain lowercase letters or, starting with second * The user name must only contain lowercase letters or, starting with second
* character, numbers or underscores. * character, numbers or underscores.
*/ */
IF vUserName NOT REGEXP '^[a-z0-9_-]*$' THEN IF vUserName NOT REGEXP BINARY '^[a-z0-9_-]+$' THEN
SIGNAL SQLSTATE '45000' SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'INVALID_USER_NAME'; SET MESSAGE_TEXT = 'INVALID_USER_NAME';
END IF; END IF;

View File

@ -1,8 +1,19 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `bi`.`greuge_dif_porte_add`() CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `bi`.`greuge_dif_porte_add`()
BEGIN BEGIN
DECLARE datSTART DATETIME DEFAULT TIMESTAMPADD(DAY,-60,util.VN_CURDATE()); -- '2019-07-01'
DECLARE datEND DATETIME DEFAULT TIMESTAMPADD(DAY,-1,util.VN_CURDATE()); /**
* Calculates the greuge based on a specific date in the 'grievanceConfig' table
*/
DECLARE vDateStarted DATETIME;
DECLARE vDateEnded DATETIME DEFAULT (util.VN_CURDATE() - INTERVAL 1 DAY);
DECLARE vDaysAgoOffset INT;
SELECT daysAgoOffset INTO vDaysAgoOffset
FROM vn.greugeConfig;
SET vDateStarted = util.VN_CURDATE() - INTERVAL vDaysAgoOffset DAY;
DROP TEMPORARY TABLE IF EXISTS tmp.dp; DROP TEMPORARY TABLE IF EXISTS tmp.dp;
@ -10,53 +21,53 @@ BEGIN
CREATE TEMPORARY TABLE tmp.dp CREATE TEMPORARY TABLE tmp.dp
(PRIMARY KEY (ticketFk)) (PRIMARY KEY (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT t.id ticketFk, SELECT t.id ticketFk,
SUM((t.zonePrice - t.zoneBonus) * ebv.ratio) AS teorico, SUM((t.zonePrice - t.zoneBonus) * ebv.ratio) teorico,
00000.00 as practico, 00000.00 practico,
00000.00 as greuge, 00000.00 greuge,
t.clientFk, t.clientFk,
t.shipped t.shipped
FROM FROM vn.ticket t
vn.ticket t JOIN vn.client c ON c.id = t.clientFk
JOIN vn2008.Clientes cli ON cli.Id_cliente = t.clientFk LEFT JOIN vn.expedition e ON e.ticketFk = t.id
LEFT JOIN vn.expedition e ON e.ticketFk = t.id JOIN vn.expeditionBoxVol ebv ON ebv.boxFk = e.freightItemFk
JOIN vn.expeditionBoxVol ebv ON ebv.boxFk = e.freightItemFk JOIN vn.zone z ON t.zoneFk = z.id
JOIN vn.zone z ON t.zoneFk = z.id JOIN vn.company cp ON cp.id = t.companyFk
WHERE WHERE t.shipped BETWEEN vDateStarted AND vDateEnded
t.shipped between datSTART AND datEND AND c.isRelevant
AND cli.`real` AND cp.code IN ('VNL', 'VNH')
AND t.companyFk IN (442 , 567) AND NOT z.isVolumetric
AND z.isVolumetric = FALSE GROUP BY t.id;
GROUP BY t.id;
-- Agencias que cobran por volumen -- Agencias que cobran por volumen
INSERT INTO tmp.dp INSERT INTO tmp.dp
SELECT sv.ticketFk, SELECT sv.ticketFk,
SUM(IFNULL(sv.freight,0)) AS teorico, SUM(IFNULL(sv.freight,0)) teorico,
00000.00 as practico, 00000.00 practico,
00000.00 as greuge, 00000.00 greuge,
sv.clientFk, sv.clientFk,
sv.shipped sv.shipped
FROM vn.saleVolume sv FROM vn.saleVolume sv
JOIN vn.zone z ON z.id = sv.zoneFk JOIN vn.zone z ON z.id = sv.zoneFk
AND sv.shipped BETWEEN datSTART AND datEND AND sv.shipped BETWEEN vDateStarted AND vDateEnded
AND z.isVolumetric != FALSE AND z.isVolumetric != FALSE
GROUP BY sv.ticketFk; GROUP BY sv.ticketFk;
DROP TEMPORARY TABLE IF EXISTS tmp.dp_aux; DROP TEMPORARY TABLE IF EXISTS tmp.dp_aux;
CREATE TEMPORARY TABLE tmp.dp_aux CREATE TEMPORARY TABLE tmp.dp_aux
(PRIMARY KEY (ticketFk)) (PRIMARY KEY (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT dp.ticketFk, sum(Cantidad * Valor) as valor SELECT dp.ticketFk, SUM(s.quantity * sc.value) valor
FROM tmp.dp FROM tmp.dp
JOIN vn2008.Movimientos m ON m.Id_Ticket = dp.ticketFk JOIN vn.sale s ON s.ticketFk = dp.ticketFk
JOIN vn2008.Movimientos_componentes mc using(Id_Movimiento) JOIN vn.saleComponent sc ON sc.saleFk = s.id
WHERE mc.Id_Componente = 15 JOIN vn.component c ON c.id = sc.componentFk
GROUP BY dp.ticketFk; WHERE c.code = 'delivery'
GROUP BY dp.ticketFk;
UPDATE tmp.dp UPDATE tmp.dp
JOIN tmp.dp_aux USING(ticketFk) JOIN tmp.dp_aux USING(ticketFk)
SET practico = IFNULL(valor,0); SET practico = IFNULL(valor,0);
DROP TEMPORARY TABLE tmp.dp_aux; DROP TEMPORARY TABLE tmp.dp_aux;
@ -64,28 +75,29 @@ BEGIN
CREATE TEMPORARY TABLE tmp.dp_aux CREATE TEMPORARY TABLE tmp.dp_aux
(PRIMARY KEY (ticketFk)) (PRIMARY KEY (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT dp.ticketFk, sum(g.amount) Importe SELECT dp.ticketFk, SUM(g.amount) Importe
FROM tmp.dp FROM tmp.dp
JOIN vn.greuge g ON g.ticketFk = dp.ticketFk JOIN vn.greuge g ON g.ticketFk = dp.ticketFk
WHERE g.greugeTypeFk = 1 -- dif_porte JOIN vn.greugeType gt ON gt.id = g.greugeTypeFk
GROUP BY dp.ticketFk; WHERE gt.code = 'freightDifference' -- dif_porte
GROUP BY dp.ticketFk;
UPDATE tmp.dp UPDATE tmp.dp
JOIN tmp.dp_aux USING(ticketFk) JOIN tmp.dp_aux USING(ticketFk)
SET greuge = IFNULL(Importe,0); SET greuge = IFNULL(Importe,0);
INSERT INTO vn.greuge (clientFk,description,amount,shipped,greugeTypeFk,ticketFk) INSERT INTO vn.greuge (clientFk,description,amount,shipped,greugeTypeFk,ticketFk)
SELECT dp.clientFk SELECT dp.clientFk,
, concat('dif_porte ', dp.ticketFk) CONCAT('dif_porte ', dp.ticketFk),
, round(IFNULL(dp.teorico,0) - IFNULL(dp.practico,0) - IFNULL(dp.greuge,0),2) as Importe ROUND(IFNULL(dp.teorico,0) - IFNULL(dp.practico,0) - IFNULL(dp.greuge,0),2) Importe,
, date(dp.shipped) date(dp.shipped),
, 1 1,
,dp.ticketFk dp.ticketFk
FROM tmp.dp FROM tmp.dp
JOIN vn.client c ON c.id = dp.clientFk JOIN vn.client c ON c.id = dp.clientFk
WHERE ABS(IFNULL(dp.teorico,0) - IFNULL(dp.practico,0) - IFNULL(dp.greuge,0)) > 1 WHERE ABS(IFNULL(dp.teorico,0) - IFNULL(dp.practico,0) - IFNULL(dp.greuge,0)) > 1
AND c.isRelevant; AND c.isRelevant;
DROP TEMPORARY TABLE DROP TEMPORARY TABLE
tmp.dp, tmp.dp,
tmp.dp_aux; tmp.dp_aux;

View File

@ -4,7 +4,7 @@ DELIMITER $$
$$ $$
CREATE DEFINER=`root`@`localhost` PROCEDURE floranet.catalogue_get(vLanded DATE, vPostalCode VARCHAR(15)) CREATE DEFINER=`root`@`localhost` PROCEDURE floranet.catalogue_get(vLanded DATE, vPostalCode VARCHAR(15))
READS SQL DATA READS SQL DATA
BEGIN proc:BEGIN
/** /**
* Returns list, price and all the stuff regarding the floranet items * Returns list, price and all the stuff regarding the floranet items
* *
@ -12,10 +12,22 @@ BEGIN
* @param vPostalCode Delivery address postal code * @param vPostalCode Delivery address postal code
*/ */
DECLARE vLastCatalogueFk INT; DECLARE vLastCatalogueFk INT;
DECLARE vLockName VARCHAR(20);
DECLARE vLockTime INT;
START TRANSACTION; DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
DO RELEASE_LOCK(vLockName);
SELECT * FROM catalogue FOR UPDATE; RESIGNAL;
END;
SET vLockName = 'catalogue_get';
SET vLockTime = 15;
IF NOT GET_LOCK(vLockName, vLockTime) THEN
LEAVE proc;
END IF;
SELECT MAX(id) INTO vLastCatalogueFk SELECT MAX(id) INTO vLastCatalogueFk
FROM catalogue; FROM catalogue;
@ -46,7 +58,7 @@ BEGIN
FROM catalogue FROM catalogue
WHERE id > IFNULL(vLastCatalogueFk,0); WHERE id > IFNULL(vLastCatalogueFk,0);
COMMIT; DO RELEASE_LOCK(vLockName);
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -13,7 +13,8 @@ BEGIN
i.longName i.longName
FROM vn.item i FROM vn.item i
JOIN vn.itemType it ON it.id = i.typeFk JOIN vn.itemType it ON it.id = i.typeFk
WHERE it.code IN ('FNR','FNP'); WHERE it.code IN ('FNR','FNP')
LIMIT 3;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -0,0 +1,66 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`addAccountReconciliation`()
BEGIN
/**
* Updates duplicate records in the accountReconciliation table,
* by assigning them a new identifier and then inserts a new entry in the till table.
*/
UPDATE accountReconciliation ar
JOIN (
SELECT id,
calculatedCode,
CONCAT(
calculatedCode,
'(',
ROW_NUMBER() OVER (PARTITION BY calculatedCode ORDER BY id),
')'
) newId
FROM accountReconciliation ar
WHERE calculatedCode IN (
SELECT calculatedCode
FROM accountReconciliation
GROUP BY calculatedCode
HAVING COUNT(*) > 1
)
ORDER BY calculatedCode, id
) sub2 ON ar.id = sub2.id
SET ar.calculatedCode = sub2.newId;
INSERT INTO till(
dated,
isAccountable,
serie,
concept,
`in`,
`out`,
bankFk,
companyFk,
warehouseFk,
supplierAccountFk,
calculatedCode,
InForeignValue,
OutForeignValue,
workerFk
)
SELECT ar.operationDated,
TRUE,
'MB',
ar.concept,
IF(ar.debitCredit = 'credit' AND a.currencyFk = arc.currencyFk, ar.amount, NULL),
IF(ar.debitCredit = 'debit' AND a.currencyFk = arc.currencyFk, ar.amount, NULL),
a.id,
sa.supplierFk,
arc.warehouseFk,
ar.supplierAccountFk,
ar.calculatedCode,
IF(ar.debitCredit = 'credit' AND NOT a.currencyFk = arc.currencyFk, ar.amount, NULL),
IF(ar.debitCredit = 'debit' AND NOT a.currencyFk = arc.currencyFk, ar.amount, NULL),
account.myUser_getId()
FROM accountReconciliation ar
JOIN supplierAccount sa ON sa.id = ar.supplierAccountFk
JOIN accounting a ON a.id = sa.accountingFk
LEFT JOIN till t ON t.calculatedCode = ar.calculatedCode
JOIN accountReconciliationConfig arc
WHERE t.id IS NULL;
END$$
DELIMITER ;

View File

@ -0,0 +1,38 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`agencyVolume`()
BEGIN
/**
* Calculates and presents information on shipment and packaging volumes
* for agencies that are not owned for a specific period.
*/
DECLARE vStarted DATETIME DEFAULT util.VN_CURDATE();
DECLARE vEnded DATETIME DEFAULT util.dayEnd(util.VN_CURDATE());
SELECT ag.id agency_id,
CONCAT(RPAD(c.country, 16,' _') ,' ',ag.name) Agencia,
COUNT(*) expediciones,
SUM(t.packages) Bultos,
SUM(tpe.boxes) Faltan
FROM ticket t
JOIN warehouse w ON w.id = t.warehouseFk
JOIN country c ON w.countryFk = c.id
JOIN address a ON a.id = t.addressFk
JOIN agencyMode am ON am.id = t.agencyModeFk
JOIN agency ag ON ag.id = am.agencyFk
JOIN (
SELECT sv.ticketFk,
CEIL(1000 * SUM(sv.volume) / vc.standardFlowerBox) boxes
FROM ticket t
JOIN saleVolume sv ON sv.ticketFk = t.id
JOIN volumeConfig vc
WHERE t.shipped BETWEEN vStarted AND vEnded
AND (t.packages IS NULL OR NOT t.packages)
GROUP BY t.id
) tpe ON tpe.ticketFk = t.id
WHERE t.shipped BETWEEN vStarted AND vEnded
AND NOT ag.isOwn
GROUP BY ag.id
ORDER BY Agencia;
END$$
DELIMITER ;

View File

@ -19,7 +19,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

@ -1,33 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn2008`.`account_conciliacion_add`()
BEGIN
UPDATE account_conciliacion ac
JOIN
(
SELECT idaccount_conciliacion, @c:= if(@id = id_calculated, @c + 1, 1) contador,
@id:= id_calculated as id_calculated, concat(id_calculated,'(',@c,')') as new_id
FROM account_conciliacion
JOIN
(
select id_calculated, count(*) rep, @c:= 0, @id:= concat('-',id_calculated)
from account_conciliacion
group by id_calculated
having rep > 1
) sub using(id_calculated)
) sub2 using(idaccount_conciliacion)
SET ac.id_calculated = sub2.new_id;
INSERT INTO Cajas(Cajafecha, Partida, Serie, Concepto, Entrada,
Salida, Id_Banco,empresa_id, warehouse_id,
Proveedores_account_id, id_calculated, InForeignValue, OutForeignValue, Id_Trabajador)
SELECT Fechaoperacion, TRUE, 'MB', ac.Concepto, IF(DebeHaber = 2 AND currencyFk = 1, importe,null),
IF(DebeHaber = 1 AND currencyFk = 1, importe, null), a.id, sa.supplierFk, 1,
ac.Id_Proveedores_account, ac.id_calculated, IF(DebeHaber = 2 AND NOT currencyFk = 1, importe, null),
IF(DebeHaber = 1 AND NOT currencyFk = 1, importe, null), account.myUser_getId()
FROM account_conciliacion ac
JOIN vn.supplierAccount sa on sa.id = ac.Id_Proveedores_account
JOIN vn.accounting a ON a.id = sa.accountingFk
LEFT JOIN Cajas c on c.id_calculated = ac.id_calculated
WHERE c.Id_Caja IS NULL;
END$$
DELIMITER ;

View File

@ -1,44 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn2008`.`agencia_volume`()
BEGIN
DECLARE vStarted DATETIME DEFAULT TIMESTAMP(util.VN_CURDATE());
DECLARE vEnded DATETIME DEFAULT TIMESTAMP(util.VN_CURDATE(), '23:59:59');
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_PackagingEstimated;
CREATE TEMPORARY TABLE tmp.ticket_PackagingEstimated
(
ticketFk INT PRIMARY KEY
,boxes INT DEFAULT 0
);
INSERT INTO tmp.ticket_PackagingEstimated(ticketFk, boxes)
SELECT sv.ticketFk, CEIL(1000 * sum(sv.volume) / vc.standardFlowerBox)
FROM vn.ticket t
JOIN vn.saleVolume sv ON sv.ticketFk = t.id
JOIN vn.volumeConfig vc
WHERE t.shipped BETWEEN vStarted AND vEnded
AND IFNULL(t.packages,0) = 0
GROUP BY t.id;
SELECT * FROM
(
SELECT ag.id agency_id,
CONCAT(RPAD(c.country, 16,' _') ,' ',ag.name) Agencia,
count(*) expediciones,
sum(t.packages) Bultos,
sum(tpe.boxes) Faltan
FROM vn.ticket t
JOIN vn.warehouse w ON w.id = t.warehouseFk
JOIN vn.country c ON w.countryFk = c.id
JOIN vn.address a ON a.id = t.addressFk
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
JOIN vn.agency ag ON ag.id = am.agencyFk
JOIN tmp.ticket_PackagingEstimated tpe ON tpe.ticketFk = t.id
WHERE t.shipped BETWEEN vStarted AND vEnded
AND ag.isOwn = FALSE
GROUP BY ag.id
) sub
ORDER BY Agencia;
DROP TEMPORARY TABLE tmp.ticket_PackagingEstimated;
END$$
DELIMITER ;

View File

@ -1,15 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn2008`.`article`()
BEGIN
/**
* Crea la tabla temporal: article_inventory
*/
DROP TEMPORARY TABLE IF EXISTS article_inventory;
CREATE TEMPORARY TABLE article_inventory
(
`article_id` INT(11) NOT NULL PRIMARY KEY,
`future` DATETIME
)
ENGINE = MEMORY;
END$$
DELIMITER ;

View File

@ -23,7 +23,7 @@ AS SELECT `s`.`id` AS `Id_Proveedor`,
`s`.`isOfficial` AS `oficial`, `s`.`isOfficial` AS `oficial`,
`s`.`workerFk` AS `workerFk`, `s`.`workerFk` AS `workerFk`,
`s`.`payDay` AS `pay_day`, `s`.`payDay` AS `pay_day`,
`s`.`isSerious` AS `serious`, `s`.`isReal` AS `serious`,
`s`.`note` AS `notas`, `s`.`note` AS `notas`,
`s`.`taxTypeSageFk` AS `taxTypeSageFk`, `s`.`taxTypeSageFk` AS `taxTypeSageFk`,
`s`.`withholdingSageFk` AS `withholdingSageFk`, `s`.`withholdingSageFk` AS `withholdingSageFk`,

View File

@ -0,0 +1 @@
ALTER TABLE vn.supplier CHANGE COLUMN isSerious isReal tinyint(1) unsigned NOT NULL DEFAULT 0;

View File

@ -0,0 +1,9 @@
UPDATE account.user
SET name = LOWER(name),
name = REPLACE(name, ' ', ''),
name = REPLACE(name, '.', ''),
name = REPLACE(name, 'ñ', 'n'),
name = REPLACE(name, '*', ''),
name = REPLACE(name, 'ç', 'z'),
name = REPLACE(name, 'ã', 'a')
WHERE NOT active;

View File

@ -0,0 +1,8 @@
CREATE OR REPLACE TABLE `vn`.`accountReconciliationConfig` (
`id` INT AUTO_INCREMENT,
`currencyFk` TINYINT(3) unsigned,
`warehouseFk` SMALLINT(6) unsigned,
PRIMARY KEY (`id`),
CONSTRAINT `account_fk_currency` FOREIGN KEY (`currencyFk`) REFERENCES `currency` (`id`),
CONSTRAINT `account_fk_warehouse` FOREIGN KEY (`warehouseFk`) REFERENCES `warehouse` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;

View File

@ -0,0 +1,2 @@
INSERT INTO `vn`.`accountReconciliationConfig`(currencyFk, warehouseFk)
VALUES (1, 1);

View File

@ -0,0 +1,13 @@
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`agencyVolume`()
BEGIN
END;
REVOKE EXECUTE ON PROCEDURE `vn2008`.`agencia_volume` FROM `agency`;
GRANT EXECUTE ON PROCEDURE `vn`.`agencyVolume` TO `agency`;
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`addAccountReconciliation`()
BEGIN
END;
REVOKE EXECUTE ON PROCEDURE `vn2008`.`account_conciliacion_add` FROM `financial`;
GRANT EXECUTE ON PROCEDURE `vn`.`addAccountReconciliation` TO `financial`;

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`accountReconciliation` MODIFY debitCredit ENUM('debit', 'credit');

View File

@ -0,0 +1,4 @@
ALTER TABLE IF EXISTS `vn`.`greugeConfig`
ADD COLUMN IF NOT EXISTS `daysAgoOffset` int(11) NOT NULL;
UPDATE vn.greugeConfig SET daysAgoOffset=15;

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: {
@ -1259,7 +1258,7 @@ export default {
}, },
supplierBasicData: { supplierBasicData: {
alias: 'vn-supplier-basic-data vn-textfield[ng-model="$ctrl.supplier.nickname"]', alias: 'vn-supplier-basic-data vn-textfield[ng-model="$ctrl.supplier.nickname"]',
isSerious: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isSerious"]', isReal: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isReal"]',
isActive: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isActive"]', isActive: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isActive"]',
isPayMethodChecked: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isPayMethodChecked"]', isPayMethodChecked: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isPayMethodChecked"]',
notes: 'vn-supplier-basic-data vn-textarea[ng-model="$ctrl.supplier.note"]', notes: 'vn-supplier-basic-data vn-textarea[ng-model="$ctrl.supplier.note"]',

View File

@ -32,7 +32,7 @@ describe('Client create path', () => {
await page.autocompleteSearch(selectors.createClientView.salesPerson, 'salesPerson'); await page.autocompleteSearch(selectors.createClientView.salesPerson, 'salesPerson');
await page.autocompleteSearch(selectors.createClientView.businessType, 'florist'); await page.autocompleteSearch(selectors.createClientView.businessType, 'florist');
await page.write(selectors.createClientView.taxNumber, '74451390E'); await page.write(selectors.createClientView.taxNumber, '74451390E');
await page.write(selectors.createClientView.userName, 'CaptainMarvel'); await page.write(selectors.createClientView.userName, 'captainmarvel');
await page.write(selectors.createClientView.email, 'CarolDanvers@verdnatura.es'); await page.write(selectors.createClientView.email, 'CarolDanvers@verdnatura.es');
await page.waitToClick(selectors.createClientView.createButton); await page.waitToClick(selectors.createClientView.createButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();

View File

@ -29,7 +29,7 @@ describe('Client web access path', () => {
await page.click($.enableWebAccess); await page.click($.enableWebAccess);
await page.click($.saveButton); await page.click($.saveButton);
const enableMessage = await page.waitForSnackbar(); const enableMessage = await page.waitForSnackbar();
await page.overwrite($.userName, 'Legion'); await page.overwrite($.userName, 'legion');
await page.overwrite($.email, 'legion@marvel.com'); await page.overwrite($.email, 'legion@marvel.com');
await page.click($.saveButton); await page.click($.saveButton);
const modifyMessage = await page.waitForSnackbar(); const modifyMessage = await page.waitForSnackbar();
@ -47,7 +47,7 @@ describe('Client web access path', () => {
expect(modifyMessage.type).toBe('success'); expect(modifyMessage.type).toBe('success');
expect(hasAccess).toBe('unchecked'); expect(hasAccess).toBe('unchecked');
expect(userName).toEqual('Legion'); expect(userName).toEqual('legion');
expect(email).toEqual('legion@marvel.com'); expect(email).toEqual('legion@marvel.com');
// expect(logName).toEqual('Legion'); // expect(logName).toEqual('Legion');

View File

@ -34,6 +34,6 @@ describe('Client Add credit path', () => {
const result = await page.waitToGetProperty(selectors.clientCredit.firstCreditText, 'innerText'); const result = await page.waitToGetProperty(selectors.clientCredit.firstCreditText, 'innerText');
expect(result).toContain(999); expect(result).toContain(999);
expect(result).toContain('salesAssistant'); expect(result).toContain('salesassistant');
}); });
}); });

View File

@ -61,7 +61,7 @@ describe('Client summary path', () => {
it('should display web access details', async() => { it('should display web access details', async() => {
const result = await page.waitToGetProperty(selectors.clientSummary.userName, 'innerText'); const result = await page.waitToGetProperty(selectors.clientSummary.userName, 'innerText');
expect(result).toContain('PetterParker'); expect(result).toContain('petterparker');
}); });
it('should display business data', async() => { it('should display business data', async() => {

View File

@ -59,7 +59,7 @@ describe('Ticket Create new tracking state path', () => {
const result = await page const result = await page
.waitToGetProperty(selectors.createStateView.worker, 'value'); .waitToGetProperty(selectors.createStateView.worker, 'value');
expect(result).toEqual('salesPerson'); expect(result).toEqual('salesperson');
}); });
it(`should succesfully create a valid state`, async() => { it(`should succesfully create a valid state`, async() => {

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

@ -20,7 +20,7 @@ describe('Supplier basic data path', () => {
it('should edit the basic data', async() => { it('should edit the basic data', async() => {
await page.clearInput(selectors.supplierBasicData.alias); await page.clearInput(selectors.supplierBasicData.alias);
await page.write(selectors.supplierBasicData.alias, 'Plants Nick SL'); await page.write(selectors.supplierBasicData.alias, 'Plants Nick SL');
await page.waitToClick(selectors.supplierBasicData.isSerious); await page.waitToClick(selectors.supplierBasicData.isReal);
await page.waitToClick(selectors.supplierBasicData.isActive); await page.waitToClick(selectors.supplierBasicData.isActive);
await page.waitToClick(selectors.supplierBasicData.isPayMethodChecked); await page.waitToClick(selectors.supplierBasicData.isPayMethodChecked);
await page.write(selectors.supplierBasicData.notes, 'Some notes'); await page.write(selectors.supplierBasicData.notes, 'Some notes');
@ -41,8 +41,8 @@ describe('Supplier basic data path', () => {
expect(result).toEqual('Plants Nick SL'); expect(result).toEqual('Plants Nick SL');
}); });
it('should check the isSerious checkbox is now checked', async() => { it('should check the isReal checkbox is now checked', async() => {
const result = await page.checkboxState(selectors.supplierBasicData.isSerious); const result = await page.checkboxState(selectors.supplierBasicData.isReal);
expect(result).toBe('checked'); expect(result).toBe('checked');
}); });

View File

@ -21,7 +21,7 @@ describe('Account create and basic data path', () => {
}); });
it('should fill the form and then save it by clicking the create button', async() => { it('should fill the form and then save it by clicking the create button', async() => {
await page.write(selectors.accountIndex.newName, 'Remy'); await page.write(selectors.accountIndex.newName, 'remy');
await page.write(selectors.accountIndex.newNickname, 'Gambit'); await page.write(selectors.accountIndex.newNickname, 'Gambit');
await page.write(selectors.accountIndex.newEmail, 'RemyEtienneLeBeau@verdnatura.es'); await page.write(selectors.accountIndex.newEmail, 'RemyEtienneLeBeau@verdnatura.es');
await page.autocompleteSearch(selectors.accountIndex.newRole, 'Trainee'); await page.autocompleteSearch(selectors.accountIndex.newRole, 'Trainee');
@ -39,7 +39,7 @@ describe('Account create and basic data path', () => {
it('should check the name is as expected', async() => { it('should check the name is as expected', async() => {
const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value'); const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value');
expect(result).toEqual('Remy'); expect(result).toEqual('remy');
}); });
it('should check the nickname is as expected', async() => { it('should check the nickname is as expected', async() => {

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

@ -3,8 +3,8 @@ const LoopBackContext = require('loopback-context');
describe('Client Create', () => { describe('Client Create', () => {
const newAccount = { const newAccount = {
userName: 'Deadpool', userName: 'deadpool',
email: 'Deadpool@marvel.com', email: 'deadpool@marvel.com',
fi: '16195279J', fi: '16195279J',
name: 'Wade', name: 'Wade',
socialName: 'DEADPOOL MARVEL', socialName: 'DEADPOOL MARVEL',
@ -31,7 +31,7 @@ describe('Client Create', () => {
}); });
}); });
it(`should not find Deadpool as he's not created yet`, async() => { it(`should not find deadpool as he's not created yet`, async() => {
const tx = await models.Client.beginTransaction({}); const tx = await models.Client.beginTransaction({});
try { try {

View File

@ -31,8 +31,8 @@ describe('Client Model', () => {
await models.Client.notifyAssignment(instance, previousWorkerId, currentWorkerId); await models.Client.notifyAssignment(instance, previousWorkerId, currentWorkerId);
expect(chatModel.send).toHaveBeenCalledWith(ctx, '@DavidCharlesHaller', `Client assignment has changed`); expect(chatModel.send).toHaveBeenCalledWith(ctx, '@davidcharleshaller', `Client assignment has changed`);
expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', `Client assignment has changed`); expect(chatModel.send).toHaveBeenCalledWith(ctx, '@hankpym', `Client assignment has changed`);
}); });
it('should call to the Chat send() method for the previous worker', async() => { it('should call to the Chat send() method for the previous worker', async() => {
@ -40,7 +40,7 @@ describe('Client Model', () => {
await models.Client.notifyAssignment(instance, null, currentWorkerId); await models.Client.notifyAssignment(instance, null, currentWorkerId);
expect(chatModel.send).toHaveBeenCalledWith(ctx, '@HankPym', `Client assignment has changed`); expect(chatModel.send).toHaveBeenCalledWith(ctx, '@hankpym', `Client assignment has changed`);
}); });
it('should call to the Chat send() method for the current worker', async() => { it('should call to the Chat send() method for the current worker', async() => {
@ -48,7 +48,7 @@ describe('Client Model', () => {
await models.Client.notifyAssignment(instance, previousWorkerId, null); await models.Client.notifyAssignment(instance, previousWorkerId, null);
expect(chatModel.send).toHaveBeenCalledWith(ctx, '@DavidCharlesHaller', `Client assignment has changed`); expect(chatModel.send).toHaveBeenCalledWith(ctx, '@davidcharleshaller', `Client assignment has changed`);
}); });
}); });

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

@ -11,7 +11,7 @@ columns:
postcodeFk: postcode postcodeFk: postcode
isActive: active isActive: active
isOfficial: official isOfficial: official
isSerious: serious isReal: real
isTrucker: trucker isTrucker: trucker
note: note note: note
street: street street: street

View File

@ -11,7 +11,7 @@ columns:
postcodeFk: código postal postcodeFk: código postal
isActive: activo isActive: activo
isOfficial: oficial isOfficial: oficial
isSerious: serio isReal: real
isTrucker: camionero isTrucker: camionero
note: nota note: nota
street: calle street: calle

View File

@ -25,7 +25,7 @@ module.exports = Self => {
'id', 'id',
'name', 'name',
'nickname', 'nickname',
'isSerious', 'isReal',
'isActive', 'isActive',
'note', 'note',
'nif', 'nif',

View File

@ -48,7 +48,7 @@
"isOfficial": { "isOfficial": {
"type": "boolean" "type": "boolean"
}, },
"isSerious": { "isReal": {
"type": "boolean" "type": "boolean"
}, },
"isTrucker": { "isTrucker": {

View File

@ -26,7 +26,7 @@
<vn-horizontal> <vn-horizontal>
<vn-check <vn-check
label="Verified" label="Verified"
ng-model="$ctrl.supplier.isSerious"> ng-model="$ctrl.supplier.isReal">
</vn-check> </vn-check>
<vn-check <vn-check
label="Active" label="Active"

View File

@ -32,7 +32,7 @@
<vn-icon <vn-icon
vn-tooltip="Unverified supplier" vn-tooltip="Unverified supplier"
icon="icon-supplierfalse" icon="icon-supplierfalse"
ng-if="$ctrl.supplier.isSerious == false"> ng-if="$ctrl.supplier.isReal == false">
</vn-icon> </vn-icon>
</div> </div>
<div class="quicklinks"> <div class="quicklinks">

View File

@ -40,7 +40,7 @@ class Controller extends Descriptor {
'payDemFk', 'payDemFk',
'payDay', 'payDay',
'isActive', 'isActive',
'isSerious', 'isReal',
'isTrucker', 'isTrucker',
'account' 'account'
], ],

View File

@ -26,7 +26,7 @@ describe('Supplier Component vnSupplierDescriptor', () => {
'payDemFk', 'payDemFk',
'payDay', 'payDay',
'isActive', 'isActive',
'isSerious', 'isReal',
'isTrucker', 'isTrucker',
'account' 'account'
], ],

View File

@ -44,12 +44,12 @@
</vn-label-value> </vn-label-value>
<vn-check <vn-check
label="Verified" label="Verified"
ng-model="$ctrl.summary.isSerious" ng-model="$ctrl.summary.isReal"
disabled="true"> disabled="true">
</vn-check> </vn-check>
<vn-check <vn-check
label="Is active" label="Is active"
ng-model="$ctrl.summary.isActive" ng-model="$ctrl.summary.isActive"
disabled="true"> disabled="true">
</vn-check> </vn-check>
</vn-vertical> </vn-vertical>
@ -141,7 +141,7 @@
value="{{::$ctrl.summary.name}}"> value="{{::$ctrl.summary.name}}">
</vn-label-value> </vn-label-value>
<vn-label-value <vn-label-value
label="Tax number" label="Tax number"
value="{{::$ctrl.summary.nif}}"> value="{{::$ctrl.summary.nif}}">
</vn-label-value> </vn-label-value>
<vn-label-value <vn-label-value

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

@ -6,7 +6,7 @@ describe('Worker activeWithInheritedRole', () => {
allRolesCount = await app.models.VnRole.count(); allRolesCount = await app.models.VnRole.count();
}); });
it('should return the workers with an inherited role of salesPerson', async() => { it('should return the workers with an inherited role of salesperson', async() => {
const filter = {where: {role: 'salesPerson'}}; const filter = {where: {role: 'salesPerson'}};
const result = await app.models.Worker.activeWithInheritedRole(filter); const result = await app.models.Worker.activeWithInheritedRole(filter);

View File

@ -20,7 +20,7 @@ describe('Worker new', () => {
const employeeId = 1; const employeeId = 1;
const defaultWorker = { const defaultWorker = {
fi: '78457139E', fi: '78457139E',
name: 'DEFAULTERWORKER', name: 'defaulterworker',
firstName: 'DEFAULT', firstName: 'DEFAULT',
lastNames: 'WORKER', lastNames: 'WORKER',
email: 'defaultWorker@mydomain.com', email: 'defaultWorker@mydomain.com',

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