Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2145_e2e_linux_fix
This commit is contained in:
commit
1ee0acf310
|
@ -10,8 +10,7 @@ module.exports = Self => {
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: 'The document id',
|
description: 'The document id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
arg: 'warehouseId',
|
arg: 'warehouseId',
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
description: 'The warehouse id'
|
description: 'The warehouse id'
|
||||||
|
@ -44,9 +43,9 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.updateFile = async(ctx, id, warehouseId, companyId,
|
Self.updateFile = async(ctx, id, options) => {
|
||||||
dmsTypeId, reference, description, hasFileAttached, options) => {
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const args = ctx.args;
|
||||||
|
|
||||||
let tx;
|
let tx;
|
||||||
let myOptions = {};
|
let myOptions = {};
|
||||||
|
@ -60,20 +59,20 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dmsTypeId);
|
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId);
|
||||||
if (!hasWriteRole)
|
if (!hasWriteRole)
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
const dms = await Self.findById(id, null, myOptions);
|
const dms = await Self.findById(id, null, myOptions);
|
||||||
await dms.updateAttributes({
|
await dms.updateAttributes({
|
||||||
dmsTypeFk: dmsTypeId,
|
dmsTypeFk: args.dmsTypeId,
|
||||||
companyFk: companyId,
|
companyFk: args.companyId,
|
||||||
warehouseFk: warehouseId,
|
warehouseFk: args.warehouseId,
|
||||||
reference: reference,
|
reference: args.reference,
|
||||||
description: description
|
description: args.description
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
if (hasFileAttached)
|
if (args.hasFileAttached)
|
||||||
await uploadNewFile(ctx, dms, myOptions);
|
await uploadNewFile(ctx, dms, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
|
@ -35,6 +35,13 @@
|
||||||
"foreignKey": "zoneFk"
|
"foreignKey": "zoneFk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"scopes": {
|
||||||
|
"location": {
|
||||||
|
"include": {
|
||||||
|
"relation": "country"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
{
|
{
|
||||||
"accessType": "READ",
|
"accessType": "READ",
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES ('EntryLog', '*', 'READ', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -0,0 +1,182 @@
|
||||||
|
|
||||||
|
DROP procedure IF EXISTS `vn`.`workerTimeControl_check`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`workerTimeControl_check`(vUserFk INT, vTabletFk VARCHAR(100), vTimed DATETIME)
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifica si el empleado puede fichar en el momento actual, si puede fichar llama a vn.workerTimeControlAdd
|
||||||
|
* @param vUserFk Identificador del trabajador
|
||||||
|
* @return Retorna si encuentra un problema 'odd','maxTimeWork','breakDay','breakWeek' ;
|
||||||
|
* En caso de tener algun problema retorna el primero que encuentra
|
||||||
|
*/
|
||||||
|
DECLARE vLastIn DATETIME ;
|
||||||
|
DECLARE vLastOut DATETIME ;
|
||||||
|
DECLARE vDayWorkMax INT;
|
||||||
|
DECLARE vDayBreak INT;
|
||||||
|
DECLARE vWeekBreak INT ;
|
||||||
|
DECLARE vWeekMaxBreak INT;
|
||||||
|
DECLARE vWeekScope INT;
|
||||||
|
DECLARE vWeekMaxScope INT;
|
||||||
|
DECLARE vDayStayMax INT;
|
||||||
|
DECLARE vAskInOut INT;
|
||||||
|
DECLARE vTimedWorked INT;
|
||||||
|
DECLARE vCalendarStateType VARCHAR(20) DEFAULT NULL;
|
||||||
|
DECLARE vDepartmentFk INT;
|
||||||
|
DECLARE vTo VARCHAR(50) DEFAULT NULL;
|
||||||
|
DECLARE vUserName VARCHAR(50) DEFAULT NULL;
|
||||||
|
DECLARE vBody VARCHAR(255) DEFAULT NULL;
|
||||||
|
|
||||||
|
IF (vTimed IS NULL) THEN
|
||||||
|
SET vTimed = NOW();
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT dayBreak, weekBreak, weekScope, dayWorkMax, dayStayMax, weekMaxBreak, weekMaxScope, askInOut
|
||||||
|
INTO vDayBreak, vWeekBreak, vWeekScope, vDayWorkMax, vDayStayMax, vWeekMaxBreak, vWeekMaxScope, vAskInOut
|
||||||
|
FROM vn.workerTimeControlParams;
|
||||||
|
|
||||||
|
SELECT MAX(timed) INTO vLastIn
|
||||||
|
FROM vn.workerTimeControl
|
||||||
|
WHERE userFk = vUserFk AND
|
||||||
|
direction = 'in';
|
||||||
|
|
||||||
|
SELECT MAX(timed) INTO vLastOut
|
||||||
|
FROM vn.workerTimeControl
|
||||||
|
WHERE userFk = vUserFk AND
|
||||||
|
direction = 'out';
|
||||||
|
|
||||||
|
SELECT email INTO vTo
|
||||||
|
FROM vn.worker w
|
||||||
|
WHERE w.id = (SELECT bossFk FROM vn.worker WHERE id = vUserFk);
|
||||||
|
|
||||||
|
SELECT CONCAT(firstName,' ',lastName) INTO vUserName
|
||||||
|
FROM vn.worker w
|
||||||
|
WHERE w.id = vUserFk;
|
||||||
|
|
||||||
|
-- VERIFICAR CONTRATO EN VIGOR
|
||||||
|
IF (SELECT COUNT(*)
|
||||||
|
FROM postgresql.business b
|
||||||
|
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
|
||||||
|
JOIN postgresql.person p ON p.person_id = pr.person_id
|
||||||
|
JOIN vn.worker w ON w.id = p.id_trabajador
|
||||||
|
WHERE w.userFk = vUserFk AND
|
||||||
|
b.date_start <= CURDATE() AND
|
||||||
|
IFNULL(b.date_end,CURDATE()) >= CURDATE()
|
||||||
|
) = 0 THEN
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No hay un contrato en vigor") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw("No hay un contrato en vigor");
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- VERIFICAR DEPARTAMENTO
|
||||||
|
IF vTabletFk IS NOT NULL THEN
|
||||||
|
IF ( SELECT COUNT(*)
|
||||||
|
FROM vn.tabletDepartment td
|
||||||
|
JOIN vn.workerTimeControlUserInfo wtcu ON wtcu.departmentFk = td.departmentFk
|
||||||
|
WHERE td.tabletFk = vTabletFk AND wtcu.userFk = vUserFk
|
||||||
|
) = 0 THEN
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No perteneces a este departamento.") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw("No perteneces a este departamento.");
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT IFNULL(dayBreak, vDayBreak) INTO vDayBreak
|
||||||
|
FROM postgresql.business b
|
||||||
|
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
|
||||||
|
JOIN postgresql.person p ON p.person_id = pr.person_id
|
||||||
|
JOIN postgresql. business_labour bl ON b.business_id = bl.business_id
|
||||||
|
JOIN postgresql.professional_category pc ON bl.professional_category_id = pc.professional_category_id
|
||||||
|
WHERE p.id_trabajador = vUserFk AND
|
||||||
|
b.date_start <= DATE(vTimed) AND
|
||||||
|
IFNULL(b.date_end, DATE(vTimed)) >= DATE(vTimed);
|
||||||
|
-- VERIFICAR DESCANSO DIARIO
|
||||||
|
-- 12 / 9 horas dependiendo del valor de vDayBreak
|
||||||
|
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vDayBreak THEN
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vDayBreak/3600,0) ," h") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw(CONCAT("Descansos ", FORMAT(vDayBreak/3600,0) ," h"));
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- VERIFICAR FICHADAS IMPARES DEL ÚLTIMO DÃÂÂA QUE SE FICHÓ
|
||||||
|
IF (SELECT MOD(COUNT(*),2) -- <>0
|
||||||
|
FROM vn.workerTimeControl
|
||||||
|
WHERE userFk = vUserFk AND
|
||||||
|
timed >= vLastIn
|
||||||
|
) THEN
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Dias con fichadas impares") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw("Dias con fichadas impares");
|
||||||
|
END IF;
|
||||||
|
-- VERIFICAR VACACIONES
|
||||||
|
SELECT cs.type INTO vCalendarStateType
|
||||||
|
FROM postgresql.calendar_employee ce
|
||||||
|
JOIN postgresql.business b USING(business_id)
|
||||||
|
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
|
||||||
|
JOIN postgresql.person p ON p.person_id = pr.person_id
|
||||||
|
JOIN postgresql.calendar_state cs USING(calendar_state_id)
|
||||||
|
JOIN vn.worker w ON w.id = p.id_trabajador
|
||||||
|
WHERE ce.date = CURDATE() AND
|
||||||
|
cs.isAllowedToWork = FALSE AND
|
||||||
|
w.userFk = vUserFk
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF(LENGTH(vCalendarStateType)) THEN
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Vacaciones") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw(vCalendarStateType);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- VERIFICAR DESCANSO SEMANAL
|
||||||
|
SET @vHasBreakWeek:= FALSE;
|
||||||
|
SET @vLastTimed:= UNIX_TIMESTAMP((vTimed - INTERVAL vWeekScope SECOND));
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.trash;
|
||||||
|
CREATE TEMPORARY TABLE tmp.trash
|
||||||
|
SELECT IF(vWeekBreak-(UNIX_TIMESTAMP(timed)-@vLastTimed) <= 0, @vHasBreakWeek:=TRUE, TRUE) alias,
|
||||||
|
@vLastTimed:= UNIX_TIMESTAMP(timed)
|
||||||
|
FROM workerTimeControl
|
||||||
|
WHERE timed>= (vTimed - INTERVAL vWeekScope SECOND) AND
|
||||||
|
userFk= vUserFk AND
|
||||||
|
direction IN ('in','out')
|
||||||
|
ORDER BY timed ASC;
|
||||||
|
|
||||||
|
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vWeekBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÉS DE LA ÚLTIMA FICHADA
|
||||||
|
SET @vHasBreakWeek:= FALSE;
|
||||||
|
SET @vLastTimed:= UNIX_TIMESTAMP((vTimed - INTERVAL vWeekMaxScope SECOND));
|
||||||
|
DROP TEMPORARY TABLE tmp.trash;
|
||||||
|
CREATE TEMPORARY TABLE tmp.trash
|
||||||
|
SELECT IF(vWeekMaxBreak-(UNIX_TIMESTAMP(timed)-@vLastTimed) <= 0, @vHasBreakWeek:=TRUE, TRUE) alias,
|
||||||
|
@vLastTimed:= UNIX_TIMESTAMP(timed)
|
||||||
|
FROM workerTimeControl
|
||||||
|
WHERE timed>= (vTimed - INTERVAL vWeekMaxScope SECOND) AND
|
||||||
|
userFk= vUserFk AND
|
||||||
|
direction IN ('in','out')
|
||||||
|
ORDER BY timed ASC;
|
||||||
|
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vWeekMaxBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÉS DE LA ÚLTIMA FICHADA
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vWeekMaxBreak/3600,0) ," h") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.throw(CONCAT( "Descansos ", FORMAT(vWeekMaxBreak/3600,0) ," h"));
|
||||||
|
END IF;
|
||||||
|
-- ENVIAMOS CORREO AL BOSSFK
|
||||||
|
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vWeekBreak/3600,0) ," h") INTO vBody;
|
||||||
|
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
|
||||||
|
CALL util.warn(CONCAT( "Descansos ", FORMAT(vWeekBreak/3600,0) ," h"));
|
||||||
|
END IF;
|
||||||
|
DROP TEMPORARY TABLE tmp.trash;
|
||||||
|
|
||||||
|
-- Preguntar dirección de la fichada
|
||||||
|
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastIn) >= vAskInOut AND (SELECT MOD(COUNT(*),2)
|
||||||
|
FROM vn.workerTimeControl WHERE userFk = vUserFk AND timed >= vLastIn) THEN
|
||||||
|
CALL util.warn("AskInOut");
|
||||||
|
END IF ;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
|
@ -1,2 +0,0 @@
|
||||||
ALTER TABLE `vn`.`zoneEvent`
|
|
||||||
ADD COLUMN m3Max DECIMAL(10,2) UNSIGNED NULL DEFAULT NULL AFTER bonus;
|
|
File diff suppressed because one or more lines are too long
|
@ -39,8 +39,8 @@ INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`
|
||||||
FROM `account`.`role` WHERE id <> 20
|
FROM `account`.`role` WHERE id <> 20
|
||||||
ORDER BY id;
|
ORDER BY id;
|
||||||
|
|
||||||
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`)
|
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`, `email`)
|
||||||
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
|
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9, 'test@nightmare.es'
|
||||||
FROM `vn`.`user`;
|
FROM `vn`.`user`;
|
||||||
|
|
||||||
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
|
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
|
||||||
|
@ -68,13 +68,13 @@ INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,
|
||||||
(111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en'),
|
(111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en'),
|
||||||
(112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en');
|
(112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en');
|
||||||
|
|
||||||
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`)
|
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `email`)
|
||||||
VALUES
|
VALUES
|
||||||
(106, 'LGN', 'David Charles', 'Haller', 106, 19, 432978106),
|
(106, 'LGN', 'David Charles', 'Haller', 106, 19, 432978106, 'test@nightmare.es'),
|
||||||
(107, 'ANT', 'Hank' , 'Pym' , 107, 19, 432978107),
|
(107, 'ANT', 'Hank' , 'Pym' , 107, 19, 432978107, 'test@nightmare.es'),
|
||||||
(108, 'DCX', 'Charles' , 'Xavier', 108, 19, 432978108),
|
(108, 'DCX', 'Charles' , 'Xavier', 108, 19, 432978108, 'test@nightmare.es'),
|
||||||
(109, 'HLK', 'Bruce' , 'Banner', 109, 19, 432978109),
|
(109, 'HLK', 'Bruce' , 'Banner', 109, 19, 432978109, 'test@nightmare.es'),
|
||||||
(110, 'JJJ', 'Jessica' , 'Jones' , 110, 19, 432978110);
|
(110, 'JJJ', 'Jessica' , 'Jones' , 110, 19, 432978110, 'test@nightmare.es');
|
||||||
|
|
||||||
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`)
|
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -197,14 +197,16 @@ INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
|
||||||
(1, 'Valencia', 1),
|
(1, 'Valencia', 1),
|
||||||
(2, 'Silla', 1),
|
(2, 'Silla', 1),
|
||||||
(3, 'Algemesi', 1),
|
(3, 'Algemesi', 1),
|
||||||
(4, 'Alzira', 1);
|
(4, 'Alzira', 1),
|
||||||
|
(5, 'Quito', 5);
|
||||||
|
|
||||||
INSERT INTO `vn`.`postCode`(`code`, `townFk`, `geoFk`)
|
INSERT INTO `vn`.`postCode`(`code`, `townFk`, `geoFk`)
|
||||||
VALUES
|
VALUES
|
||||||
('46000', 1, 6),
|
('46000', 1, 6),
|
||||||
('46460', 2, 6),
|
('46460', 2, 6),
|
||||||
('46680', 3, 6),
|
('46680', 3, 6),
|
||||||
('46600', 4, 7);
|
('46600', 4, 7),
|
||||||
|
('EC170150', 5, 8);
|
||||||
|
|
||||||
INSERT INTO `vn`.`clientType`(`id`, `code`, `type`)
|
INSERT INTO `vn`.`clientType`(`id`, `code`, `type`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -554,30 +556,30 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
|
||||||
|
|
||||||
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`)
|
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
(1, 16, 5 , DATE_ADD(NOW(), INTERVAL -1 MONTH)),
|
||||||
(2, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
(2, 16, 5 , DATE_ADD(NOW(), INTERVAL -1 MONTH)),
|
||||||
(3, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
(3, 16, 5 , DATE_ADD(NOW(), INTERVAL -2 MONTH)),
|
||||||
(4, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
|
(4, 16, 5 , DATE_ADD(NOW(), INTERVAL -3 MONTH)),
|
||||||
(5, 16, 18, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
|
(5, 16, 18, DATE_ADD(NOW(), INTERVAL -4 MONTH)),
|
||||||
(6, 16, 18, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
(6, 16, 18, DATE_ADD(NOW(), INTERVAL -1 MONTH)),
|
||||||
(7, 10, 18, CURDATE()),
|
(7, 10, 18, NOW()),
|
||||||
(8, 5, 19, CURDATE()),
|
(8, 5, 19, NOW()),
|
||||||
(9, 5, 19, CURDATE()),
|
(9, 5, 19, NOW()),
|
||||||
(10, 5, 19, CURDATE()),
|
(10, 5, 19, NOW()),
|
||||||
(11, 3, 19, CURDATE()),
|
(11, 3, 19, NOW()),
|
||||||
(12, 3, 19, CURDATE()),
|
(12, 3, 19, NOW()),
|
||||||
(13, 3, 19, CURDATE()),
|
(13, 3, 19, NOW()),
|
||||||
(14, 3, 19, CURDATE()),
|
(14, 3, 19, NOW()),
|
||||||
(15, 3, 19, CURDATE()),
|
(15, 3, 19, NOW()),
|
||||||
(16, 3, 19, CURDATE()),
|
(16, 3, 19, NOW()),
|
||||||
(17, 3, 19, CURDATE()),
|
(17, 3, 19, NOW()),
|
||||||
(18, 3, 19, CURDATE()),
|
(18, 3, 19, NOW()),
|
||||||
(19, 17, 19, CURDATE()),
|
(19, 17, 19, NOW()),
|
||||||
(20, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
(20, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||||
(21, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
(21, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||||
(22, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
(22, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||||
(23, 16, 21, CURDATE()),
|
(23, 16, 21, NOW()),
|
||||||
(24, 16, 21, CURDATE());
|
(24, 16, 21, NOW());
|
||||||
|
|
||||||
INSERT INTO `vn`.`stowaway`(`id`, `shipFk`, `created`)
|
INSERT INTO `vn`.`stowaway`(`id`, `shipFk`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1580,6 +1582,13 @@ INSERT INTO `postgresql`.`business_labour`(`business_id`, `notes`, `department_i
|
||||||
SELECT b.business_id, NULL, 23, 1, 0, 1, 1, 1, 1
|
SELECT b.business_id, NULL, 23, 1, 0, 1, 1, 1, 1
|
||||||
FROM `postgresql`.`business` `b`;
|
FROM `postgresql`.`business` `b`;
|
||||||
|
|
||||||
|
UPDATE `postgresql`.`business_labour` bl
|
||||||
|
JOIN `postgresql`.`business` b ON b.business_id = bl.business_id
|
||||||
|
JOIN `postgresql`.`profile` pr ON pr.profile_id = b.client_id
|
||||||
|
JOIN `postgresql`.`person` p ON p.person_id = pr.person_id
|
||||||
|
SET bl.`professional_category_id` = 31
|
||||||
|
WHERE p.`Id_trabajador` = 110;
|
||||||
|
|
||||||
INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`)
|
INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 10, 600123321, 0),
|
(1, 10, 600123321, 0),
|
||||||
|
@ -1677,12 +1686,12 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
|
||||||
|
|
||||||
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
|
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
|
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
|
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
|
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
|
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
|
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
|
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
|
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
|
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
|
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
|
@ -1901,11 +1910,11 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `c
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Facturas Recibidas', 'recibidas', NULL, NULL, 'invoiceIn'),
|
(1, 'Facturas Recibidas', 'recibidas', NULL, NULL, 'invoiceIn'),
|
||||||
(2, 'Doc oficial', 'oficial', NULL, NULL, 'officialDoc'),
|
(2, 'Doc oficial', 'oficial', NULL, NULL, 'officialDoc'),
|
||||||
(3, 'Laboral', 'laboral', NULL, NULL, 'hhrrData'),
|
(3, 'Laboral', 'laboral', 37, 37, 'hhrrData'),
|
||||||
(4, 'Albaranes recibidos', 'entradas', NULL, NULL, 'deliveryNote'),
|
(4, 'Albaranes recibidos', 'entradas', NULL, NULL, 'deliveryNote'),
|
||||||
(5, 'Otros', 'otros', 1, 1, 'miscellaneous'),
|
(5, 'Otros', 'otros', 1, 1, 'miscellaneous'),
|
||||||
(6, 'Pruebas', 'pruebas', NULL, NULL, 'tests'),
|
(6, 'Pruebas', 'pruebas', NULL, NULL, 'tests'),
|
||||||
(7, 'IAE Clientes', 'IAE_Clientes', NULL, NULL, 'economicActivitiesTax'),
|
(7, 'IAE Clientes', 'IAE_Clientes', 1, 1, 'economicActivitiesTax'),
|
||||||
(8, 'Fiscal', 'fiscal', NULL, NULL, 'fiscal'),
|
(8, 'Fiscal', 'fiscal', NULL, NULL, 'fiscal'),
|
||||||
(9, 'Vehiculos', 'vehiculos', NULL, NULL, 'vehicles'),
|
(9, 'Vehiculos', 'vehiculos', NULL, NULL, 'vehicles'),
|
||||||
(10, 'Plantillas', 'plantillas', NULL, NULL, 'templates'),
|
(10, 'Plantillas', 'plantillas', NULL, NULL, 'templates'),
|
||||||
|
@ -1951,9 +1960,9 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`)
|
||||||
(2, 'Normal'),
|
(2, 'Normal'),
|
||||||
(3, 'Baja');
|
(3, 'Baja');
|
||||||
|
|
||||||
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`)
|
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 43200, 129600, 734400, 43200, 50400);
|
(1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000);
|
||||||
|
|
||||||
INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11');
|
INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11');
|
||||||
|
|
||||||
|
@ -1973,11 +1982,21 @@ INSERT INTO `vn`.`travelThermograph`(`thermographFk`, `created`, `warehouseFk`,
|
||||||
('138350-0', DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 'WARM', NULL, 5),
|
('138350-0', DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 'WARM', NULL, 5),
|
||||||
('138350-0', CURDATE(), 1, NULL, 'COOL', NULL, NULL);
|
('138350-0', CURDATE(), 1, NULL, 'COOL', NULL, NULL);
|
||||||
|
|
||||||
REPLACE INTO `vn`.`incoterms` (`code`, `name`)
|
REPLACE INTO `vn`.`incoterms`(`code`, `name`)
|
||||||
VALUES
|
VALUES
|
||||||
('FAS', 'Free Alongside Ship');
|
('FAS', 'Free Alongside Ship');
|
||||||
|
|
||||||
REPLACE INTO `vn`.`customsAgent` (`id`, `fiscalName`, `street`, `nif`, `phone`, `email`)
|
REPLACE INTO `vn`.`customsAgent`(`id`, `fiscalName`, `street`, `nif`, `phone`, `email`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Agent one', '1007 Mountain Drive, Gotham', 'N1111111111', '111111111', 'agentone@gotham.com'),
|
(1, 'Agent one', '1007 Mountain Drive, Gotham', 'N1111111111', '111111111', 'agentone@gotham.com'),
|
||||||
(2, 'Agent two', '1007 Mountain Drive, Gotham', 'N2222222222', '222222222', 'agenttwo@gotham.com');
|
(2, 'Agent two', '1007 Mountain Drive, Gotham', 'N2222222222', '222222222', 'agenttwo@gotham.com');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`tabletDepartment`(`tabletFk`, `departmentFk`)
|
||||||
|
VALUES
|
||||||
|
(1, 23),
|
||||||
|
(2, 1);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`tablet`(`uuid`, `name`, `place`, `macwifi`)
|
||||||
|
VALUES
|
||||||
|
('1', 'TEST', 'ON THE FIXTURES', '0'),
|
||||||
|
('2', 'DEV', 'OTHER TABLET', '0');
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,7 +43,6 @@ describe('ticket ticketCreateWithUser()', () => {
|
||||||
|
|
||||||
let ticketResult = result[ticketResultIndex][0];
|
let ticketResult = result[ticketResultIndex][0];
|
||||||
|
|
||||||
|
|
||||||
expect(ticketResult.id).toBeGreaterThan(21);
|
expect(ticketResult.id).toBeGreaterThan(21);
|
||||||
expect(ticketResult.clientFk).toEqual(params.clientFk);
|
expect(ticketResult.clientFk).toEqual(params.clientFk);
|
||||||
expect(ticketResult.warehouseFk).toEqual(params.warehouseFk);
|
expect(ticketResult.warehouseFk).toEqual(params.warehouseFk);
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
describe('timeBusiness_calculateByUser()', () => {
|
||||||
|
it('should return the expected hours for today', async() => {
|
||||||
|
let start = new Date();
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
let end = new Date();
|
||||||
|
end.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
workerID: 106,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
};
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.timeBusiness_calculateByUser(?, ?, ?)', [
|
||||||
|
params.workerID,
|
||||||
|
params.start,
|
||||||
|
params.end
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
let tableIndex = stmts.push('SELECT * FROM tmp.timeBusinessCalculate') - 1;
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Ticket.rawStmt(sql);
|
||||||
|
|
||||||
|
let [timeBusinessCalculateTable] = result[tableIndex];
|
||||||
|
|
||||||
|
expect(timeBusinessCalculateTable.timeBusinessSeconds).toEqual(28800);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,107 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
describe('timeControl_calculateByUser()', () => {
|
||||||
|
it(`should return today's worked hours`, async() => {
|
||||||
|
let start = new Date();
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
start.setDate(start.getDate() - 1);
|
||||||
|
|
||||||
|
let end = new Date();
|
||||||
|
end.setHours(0, 0, 0, 0);
|
||||||
|
end.setDate(end.getDate() + 1);
|
||||||
|
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmts.push(`
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS
|
||||||
|
tmp.timeControlCalculate,
|
||||||
|
tmp.timeBusinessCalculate
|
||||||
|
`);
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
workerID: 106,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
};
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
|
||||||
|
params.workerID,
|
||||||
|
params.start,
|
||||||
|
params.end
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Ticket.rawStmt(sql);
|
||||||
|
|
||||||
|
let [timeControlCalculateTable] = result[tableIndex];
|
||||||
|
|
||||||
|
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(29400);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return the worked hours between last sunday and monday`, async() => {
|
||||||
|
let lastSunday = new Date();
|
||||||
|
let daysSinceSunday = lastSunday.getDay();
|
||||||
|
if (daysSinceSunday === 0) // this means today is sunday but you need the previous sunday :)
|
||||||
|
daysSinceSunday = 7;
|
||||||
|
lastSunday.setHours(23, 0, 0, 0);
|
||||||
|
lastSunday.setDate(lastSunday.getDate() - daysSinceSunday);
|
||||||
|
|
||||||
|
let monday = new Date();
|
||||||
|
let daysSinceMonday = daysSinceSunday - 1; // aiming for monday (today could be monday)
|
||||||
|
monday.setHours(7, 0, 0, 0);
|
||||||
|
monday.setDate(monday.getDate() - daysSinceMonday);
|
||||||
|
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmts.push(`
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS
|
||||||
|
tmp.timeControlCalculate,
|
||||||
|
tmp.timeBusinessCalculate
|
||||||
|
`);
|
||||||
|
|
||||||
|
const workerID = 107;
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`
|
||||||
|
INSERT INTO vn.workerTimeControl(userFk, timed, manual, direction)
|
||||||
|
VALUES
|
||||||
|
(?, ?, 1, 'in'),
|
||||||
|
(?, ?, 1, 'out')
|
||||||
|
`, [
|
||||||
|
workerID,
|
||||||
|
lastSunday,
|
||||||
|
workerID,
|
||||||
|
monday
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
|
||||||
|
workerID,
|
||||||
|
lastSunday,
|
||||||
|
monday
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Ticket.rawStmt(sql);
|
||||||
|
|
||||||
|
let [timeControlCalculateTable] = result[tableIndex];
|
||||||
|
|
||||||
|
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(30000);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,587 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
describe('worker workerTimeControl_check()', () => {
|
||||||
|
it(`should throw an error if the worker can't sign on that tablet`, async() => {
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
const workerId = 110;
|
||||||
|
const tabletId = 2;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
try {
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err.sqlMessage).toEqual('No perteneces a este departamento.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check that the worker can sign on that tablet', async() => {
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
const workerId = 110;
|
||||||
|
const tabletId = 1;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
try {
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err).not.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker with a special category has not finished the 9h break', async() => {
|
||||||
|
// dayBreak to 9h in postgresql.professional_category
|
||||||
|
const workerId = 110;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let sql;
|
||||||
|
let error;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-17,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(SECOND,-32399,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.sqlMessage).toEqual('Descansos 9 h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check f the worker with a special category has finished the 9h break', async() => {
|
||||||
|
// dayBreak to 9h in postgresql.professional_category
|
||||||
|
const workerId = 110;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-17,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(SECOND,-32401,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err).not.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker has not finished the 12h break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let sql;
|
||||||
|
let error;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(SECOND,-43199,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.sqlMessage).toEqual('Descansos 12 h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker has finished the 12h break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(SECOND,-43201,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err).not.toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker has odd entry records', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in")`, [
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err.sqlMessage).toEqual('Dias con fichadas impares');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker try to sign on a holiday day', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO postgresql.calendar_employee(business_id,calendar_state_id,date)
|
||||||
|
VALUES
|
||||||
|
(?,1,CURDATE())`, [
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err.sqlMessage).toEqual('Holidays');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker try to sign with your contract ended', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`UPDATE postgresql.business SET date_end=DATE_ADD(CURDATE(), INTERVAL -1 DAY) WHERE business_id=?`, [
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err.sqlMessage).toEqual('No hay un contrato en vigor');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker has not finished the 36h weekly break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('SET @warn := NULL');
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
let warningMessageIndex = stmts.push('SELECT @warn AS warning') - 1;
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Worker.rawStmt(sql);
|
||||||
|
|
||||||
|
expect(result[warningMessageIndex][0].warning).toEqual('Descansos 36 h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if the worker has finished the 36h weekly break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('SET @warn := NULL');
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let warningMessageIndex = stmts.push('SELECT @warn AS warning') - 1;
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Worker.rawStmt(sql);
|
||||||
|
|
||||||
|
expect(result[warningMessageIndex][0].warning).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the worker has not finished the 72h biweekly break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-216,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-208,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-240,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-232,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-264,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-256,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-289,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-280,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
stmts.push('SELECT @warn AS warning') - 1;
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err.sqlMessage).toEqual('Descansos 72 h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if the worker has finished the 72h biweekly break', async() => {
|
||||||
|
const workerId = 109;
|
||||||
|
const tabletId = 1;
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
let err;
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
|
||||||
|
VALUES
|
||||||
|
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-216,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-208,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-240,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-232,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-264,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-256,NOW()),0,"out"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-288,NOW()),0,"in"),
|
||||||
|
(?,TIMESTAMPADD(HOUR,-280,NOW()),0,"out")`, [
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId,
|
||||||
|
workerId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
|
||||||
|
workerId,
|
||||||
|
tabletId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
stmts.push('SELECT @warn AS warning') - 1;
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.Worker.rawStmt(sql);
|
||||||
|
} catch (e) {
|
||||||
|
await app.models.Worker.rawSql('ROLLBACK');
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(err).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,6 +9,7 @@ export default {
|
||||||
invoiceOutButton: '.modules-menu > li[ui-sref="invoiceOut.index"]',
|
invoiceOutButton: '.modules-menu > li[ui-sref="invoiceOut.index"]',
|
||||||
claimsButton: '.modules-menu > li[ui-sref="claim.index"]',
|
claimsButton: '.modules-menu > li[ui-sref="claim.index"]',
|
||||||
returnToModuleIndexButton: 'a[ui-sref="order.index"]',
|
returnToModuleIndexButton: 'a[ui-sref="order.index"]',
|
||||||
|
homeButton: 'vn-topbar > div.side.start > a',
|
||||||
userMenuButton: '#user',
|
userMenuButton: '#user',
|
||||||
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
|
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
|
||||||
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
|
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
|
||||||
|
@ -43,8 +44,8 @@ export default {
|
||||||
taxNumber: 'vn-client-create vn-textfield[ng-model="$ctrl.client.fi"]',
|
taxNumber: 'vn-client-create vn-textfield[ng-model="$ctrl.client.fi"]',
|
||||||
socialName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.socialName"]',
|
socialName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.socialName"]',
|
||||||
street: 'vn-client-create vn-textfield[ng-model="$ctrl.client.street"]',
|
street: 'vn-client-create vn-textfield[ng-model="$ctrl.client.street"]',
|
||||||
postcode: 'vn-client-create vn-textfield[ng-model="$ctrl.client.postcode"]',
|
postcode: 'vn-client-create vn-datalist[ng-model="$ctrl.client.postcode"]',
|
||||||
city: 'vn-client-create vn-textfield[ng-model="$ctrl.client.city"]',
|
city: 'vn-client-create vn-datalist[ng-model="$ctrl.client.city"]',
|
||||||
province: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
province: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
||||||
country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
||||||
userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]',
|
userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]',
|
||||||
|
@ -75,8 +76,8 @@ export default {
|
||||||
equalizationTaxCheckbox: 'vn-client-fiscal-data vn-check[ng-model="$ctrl.client.isEqualizated"]',
|
equalizationTaxCheckbox: 'vn-client-fiscal-data vn-check[ng-model="$ctrl.client.isEqualizated"]',
|
||||||
acceptPropagationButton: '.vn-confirm.shown button[response=accept]',
|
acceptPropagationButton: '.vn-confirm.shown button[response=accept]',
|
||||||
address: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.street"]',
|
address: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.street"]',
|
||||||
postcode: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.postcode"]',
|
postcode: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.postcode"]',
|
||||||
city: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.city"]',
|
city: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.city"]',
|
||||||
province: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
province: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
||||||
country: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
country: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
||||||
activeCheckbox: 'vn-client-fiscal-data vn-check[label="Active"]',
|
activeCheckbox: 'vn-client-fiscal-data vn-check[label="Active"]',
|
||||||
|
@ -113,8 +114,8 @@ export default {
|
||||||
defaultCheckbox: 'vn-check[label="Default"]',
|
defaultCheckbox: 'vn-check[label="Default"]',
|
||||||
consignee: 'vn-textfield[ng-model="$ctrl.address.nickname"]',
|
consignee: 'vn-textfield[ng-model="$ctrl.address.nickname"]',
|
||||||
streetAddress: 'vn-textfield[ng-model="$ctrl.address.street"]',
|
streetAddress: 'vn-textfield[ng-model="$ctrl.address.street"]',
|
||||||
postcode: 'vn-textfield[ng-model="$ctrl.address.postalCode"]',
|
postcode: 'vn-datalist[ng-model="$ctrl.address.postalCode"]',
|
||||||
city: 'vn-textfield[ng-model="$ctrl.address.city"]',
|
city: 'vn-datalist[ng-model="$ctrl.address.city"]',
|
||||||
province: 'vn-autocomplete[ng-model="$ctrl.address.provinceId"]',
|
province: 'vn-autocomplete[ng-model="$ctrl.address.provinceId"]',
|
||||||
agency: 'vn-autocomplete[ng-model="$ctrl.address.agencyModeId"]',
|
agency: 'vn-autocomplete[ng-model="$ctrl.address.agencyModeId"]',
|
||||||
phone: 'vn-textfield[ng-model="$ctrl.address.phone"]',
|
phone: 'vn-textfield[ng-model="$ctrl.address.phone"]',
|
||||||
|
@ -192,7 +193,7 @@ export default {
|
||||||
},
|
},
|
||||||
dms: {
|
dms: {
|
||||||
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||||
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
|
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(7) > span',
|
||||||
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
|
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
|
||||||
acceptDeleteButton: '.vn-confirm.shown button[response="accept"]'
|
acceptDeleteButton: '.vn-confirm.shown button[response="accept"]'
|
||||||
},
|
},
|
||||||
|
@ -365,7 +366,7 @@ export default {
|
||||||
ticketsIndex: {
|
ticketsIndex: {
|
||||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
|
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
|
||||||
newTicketButton: 'vn-ticket-index > a',
|
newTicketButton: 'vn-ticket-index a',
|
||||||
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
||||||
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
|
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
|
||||||
|
@ -524,6 +525,7 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
ticketLog: {
|
ticketLog: {
|
||||||
|
firstTD: 'vn-ticket-log vn-table vn-td:nth-child(1)',
|
||||||
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
|
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
|
||||||
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
|
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
|
||||||
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
|
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
|
||||||
|
@ -630,6 +632,16 @@ export default {
|
||||||
createButton: 'button[type=submit]',
|
createButton: 'button[type=submit]',
|
||||||
cancelButton: 'vn-button[href="#!/client/index"]'
|
cancelButton: 'vn-button[href="#!/client/index"]'
|
||||||
},
|
},
|
||||||
|
orderSummary: {
|
||||||
|
header: 'vn-order-summary h5',
|
||||||
|
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
|
||||||
|
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
|
||||||
|
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) span',
|
||||||
|
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
|
||||||
|
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
|
||||||
|
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
|
||||||
|
sale: 'vn-order-summary vn-tbody > vn-tr',
|
||||||
|
},
|
||||||
orderCatalog: {
|
orderCatalog: {
|
||||||
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
|
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
|
||||||
type: 'vn-autocomplete[data="$ctrl.itemTypes"]',
|
type: 'vn-autocomplete[data="$ctrl.itemTypes"]',
|
||||||
|
@ -700,6 +712,17 @@ export default {
|
||||||
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',
|
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',
|
||||||
confirmButton: '.vn-confirm.shown button[response="accept"]'
|
confirmButton: '.vn-confirm.shown button[response="accept"]'
|
||||||
},
|
},
|
||||||
|
workerSummary: {
|
||||||
|
header: 'vn-worker-summary h5',
|
||||||
|
id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) > section > span',
|
||||||
|
email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span',
|
||||||
|
department: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span',
|
||||||
|
userId: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(2) > section > span',
|
||||||
|
userName: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) > section > span',
|
||||||
|
role: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(4) > section > span',
|
||||||
|
extension: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(5) > section > span',
|
||||||
|
|
||||||
|
},
|
||||||
workerBasicData: {
|
workerBasicData: {
|
||||||
name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]',
|
name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]',
|
||||||
surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]',
|
surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]',
|
||||||
|
@ -783,10 +806,25 @@ export default {
|
||||||
ticketOne: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(1)',
|
ticketOne: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(1)',
|
||||||
ticketTwo: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(2)'
|
ticketTwo: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(2)'
|
||||||
},
|
},
|
||||||
|
travelBasicDada: {
|
||||||
|
reference: 'vn-travel-basic-data vn-textfield[ng-model="$ctrl.travel.ref"]',
|
||||||
|
agency: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.agencyModeFk"]',
|
||||||
|
shippingDate: 'vn-travel-basic-data vn-date-picker[ng-model="$ctrl.travel.shipped"]',
|
||||||
|
deliveryDate: 'vn-travel-basic-data vn-date-picker[ng-model="$ctrl.travel.landed"]',
|
||||||
|
outputWarehouse: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.warehouseOutFk"]',
|
||||||
|
inputWarehouse: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.warehouseInFk"]',
|
||||||
|
delivered: 'vn-travel-basic-data vn-check[ng-model="$ctrl.travel.isDelivered"]',
|
||||||
|
received: 'vn-travel-basic-data vn-check[ng-model="$ctrl.travel.isReceived"]',
|
||||||
|
save: 'vn-travel-basic-data vn-submit[label="Save"]',
|
||||||
|
undoChanges: 'vn-travel-basic-data vn-button[label="Undo changes"]'
|
||||||
|
},
|
||||||
|
travelLog: {
|
||||||
|
firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(1) > div'
|
||||||
|
},
|
||||||
travelThermograph: {
|
travelThermograph: {
|
||||||
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
||||||
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
||||||
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="cloud_upload"]',
|
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="attach_file"]',
|
||||||
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
||||||
upload: 'vn-travel-thermograph-create button[type=submit]'
|
upload: 'vn-travel-thermograph-create button[type=submit]'
|
||||||
},
|
},
|
||||||
|
@ -806,5 +844,10 @@ export default {
|
||||||
header: 'vn-entry-summary > vn-card > h5',
|
header: 'vn-entry-summary > vn-card > h5',
|
||||||
reference: 'vn-entry-summary vn-label-value[label="Reference"]',
|
reference: 'vn-entry-summary vn-label-value[label="Reference"]',
|
||||||
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
|
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
|
||||||
|
},
|
||||||
|
entryDescriptor: {
|
||||||
|
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(3) span',
|
||||||
|
travelsQuicklink: 'vn-entry-descriptor vn-quick-links > a:nth-child(1)',
|
||||||
|
entriesQuicklink: 'vn-entry-descriptor vn-quick-links > a:nth-child(2)'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,7 +87,7 @@ describe('Client create path', async() => {
|
||||||
.waitToGetProperty(selectors.createClientView.country, 'value');
|
.waitToGetProperty(selectors.createClientView.country, 'value');
|
||||||
|
|
||||||
expect(clientCity).toEqual('Valencia');
|
expect(clientCity).toEqual('Valencia');
|
||||||
expect(clientProvince).toEqual('Province one');
|
expect(clientProvince).toContain('Province one');
|
||||||
expect(clientCountry).toEqual('España');
|
expect(clientCountry).toEqual('España');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -198,11 +198,10 @@ describe('Client Edit fiscalData path', () => {
|
||||||
expect(result).toEqual('Valencia');
|
expect(result).toEqual('Valencia');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it(`should confirm the province have been autocompleted`, async() => {
|
it(`should confirm the province have been autocompleted`, async() => {
|
||||||
const result = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value');
|
const result = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value');
|
||||||
|
|
||||||
expect(result).toEqual('Province one');
|
expect(result).toContain('Province one');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the country have been autocompleted', async() => {
|
it('should confirm the country have been autocompleted', async() => {
|
||||||
|
|
|
@ -25,9 +25,7 @@ describe('Client Add address path', () => {
|
||||||
|
|
||||||
it('should receive an error after clicking save button as consignee, street and town fields are empty', async() => {
|
it('should receive an error after clicking save button as consignee, street and town fields are empty', async() => {
|
||||||
await page.waitToClick(selectors.clientAddresses.defaultCheckbox);
|
await page.waitToClick(selectors.clientAddresses.defaultCheckbox);
|
||||||
await page.autocompleteSearch(selectors.clientAddresses.province, 'Province five');
|
await page.write(selectors.clientAddresses.postcode, 'EC170150');
|
||||||
await page.write(selectors.clientAddresses.city, 'Valencia');
|
|
||||||
await page.write(selectors.clientAddresses.postcode, '46000');
|
|
||||||
await page.autocompleteSearch(selectors.clientAddresses.agency, 'Entanglement');
|
await page.autocompleteSearch(selectors.clientAddresses.agency, 'Entanglement');
|
||||||
await page.write(selectors.clientAddresses.phone, '999887744');
|
await page.write(selectors.clientAddresses.phone, '999887744');
|
||||||
await page.write(selectors.clientAddresses.mobileInput, '999887744');
|
await page.write(selectors.clientAddresses.mobileInput, '999887744');
|
||||||
|
@ -37,6 +35,16 @@ describe('Client Add address path', () => {
|
||||||
expect(result).toEqual('Some fields are invalid');
|
expect(result).toEqual('Some fields are invalid');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should confirm that the city and province are propertly filled', async() => {
|
||||||
|
const city = await page
|
||||||
|
.waitToGetProperty(selectors.clientAddresses.city, 'value');
|
||||||
|
|
||||||
|
const province = await page
|
||||||
|
.waitToGetProperty(selectors.clientAddresses.province, 'value');
|
||||||
|
|
||||||
|
expect(city).toEqual('Quito');
|
||||||
|
expect(province).toContain('Province five');
|
||||||
|
});
|
||||||
|
|
||||||
it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => {
|
it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => {
|
||||||
await page.write(selectors.clientAddresses.consignee, 'Bruce Bunner');
|
await page.write(selectors.clientAddresses.consignee, 'Bruce Bunner');
|
||||||
|
|
|
@ -16,6 +16,12 @@ describe('Client Add notes path', () => {
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`should reach the notes index`, async() => {
|
||||||
|
let url = await page.expectURL('/note');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it(`should click on the add note button`, async() => {
|
it(`should click on the add note button`, async() => {
|
||||||
await page.waitToClick(selectors.clientNotes.addNoteFloatButton);
|
await page.waitToClick(selectors.clientNotes.addNoteFloatButton);
|
||||||
let url = await page.expectURL('/note/create');
|
let url = await page.expectURL('/note/create');
|
||||||
|
|
|
@ -35,7 +35,7 @@ describe('Client balance path', () => {
|
||||||
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
|
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
|
||||||
let result = await page.waitForLastSnackbar();
|
let result = await page.waitForLastSnackbar();
|
||||||
|
|
||||||
expect(result).toEqual('Data saved!');
|
expect(result).toContain('Data saved!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should click the new payment button', async() => {
|
it('should click the new payment button', async() => {
|
||||||
|
@ -63,7 +63,6 @@ describe('Client balance path', () => {
|
||||||
let firstBalanceLine = await page
|
let firstBalanceLine = await page
|
||||||
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
|
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
|
||||||
|
|
||||||
|
|
||||||
expect(company).toEqual('VNL');
|
expect(company).toEqual('VNL');
|
||||||
expect(firstBalanceLine).toContain('0.00');
|
expect(firstBalanceLine).toContain('0.00');
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Worker summary path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('employee', 'worker');
|
||||||
|
await page.accessToSearchResult('agencyNick');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reach the employee summary section', async() => {
|
||||||
|
const url = await page.expectURL('#!/worker/3/summary');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the name and userName on the header', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.header, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('agency agency');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the basic data id', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.id, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the basic data email', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.email, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('agency@verdnatura.es');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the basic data department', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.department, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('CAMARA');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the user data id', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.userId, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the user data name', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.userName, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('agency');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the user data role', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.role, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('agency');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the user data extension', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.workerSummary.extension, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('1101');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,65 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Ticket log path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
const ticketId = '5';
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to the target ticket notes section', async() => {
|
||||||
|
await page.loginAndModule('employee', 'ticket');
|
||||||
|
await page.accessToSearchResult(ticketId);
|
||||||
|
await page.accessToSection('ticket.card.observation');
|
||||||
|
let url = await page.expectURL('/observation');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a new note for the test', async() => {
|
||||||
|
await page.waitToClick(selectors.ticketNotes.addNoteButton);
|
||||||
|
await page.autocompleteSearch(selectors.ticketNotes.firstNoteType, 'observation one');
|
||||||
|
await page.write(selectors.ticketNotes.firstDescription, 'description');
|
||||||
|
await page.waitToClick(selectors.ticketNotes.submitNotesButton);
|
||||||
|
const result = await page.waitForLastSnackbar();
|
||||||
|
|
||||||
|
expect(result).toEqual('Data saved!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to the log section', async() => {
|
||||||
|
await page.accessToSection('ticket.card.log');
|
||||||
|
let url = await page.expectURL('/log');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the viewport width to 1920 to see the table full width', async() => {
|
||||||
|
await page.setViewport({
|
||||||
|
width: 1920,
|
||||||
|
height: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
|
||||||
|
|
||||||
|
expect(result.length).not.toBeGreaterThan('20');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the viewport width to 800 to see the table shrink and move data to the 1st column', async() => {
|
||||||
|
await page.setViewport({
|
||||||
|
width: 800,
|
||||||
|
height: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
|
||||||
|
|
||||||
|
expect(result.length).toBeGreaterThan('20');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,65 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Order summary path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('employee', 'order');
|
||||||
|
await page.accessToSearchResult('16');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reach the order summary section', async() => {
|
||||||
|
const url = await page.expectURL('#!/order/16/summary');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order id', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.id, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('16');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order alias', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.alias, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('address 26');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order consignee', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.consignee, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual('Many places - Silla (Province one)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order subtotal', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.subtotal, 'innerText');
|
||||||
|
|
||||||
|
expect(result.length).toBeGreaterThan(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order vat', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.vat, 'innerText');
|
||||||
|
|
||||||
|
expect(result.length).toBeGreaterThan(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order total', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.orderSummary.total, 'innerText');
|
||||||
|
|
||||||
|
expect(result.length).toBeGreaterThan(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the summary contains the order sales', async() => {
|
||||||
|
const result = await page.countElement(selectors.orderSummary.sale);
|
||||||
|
|
||||||
|
expect(result).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,102 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Travel basic data path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('buyer', 'travel');
|
||||||
|
await page.accessToSearchResult('3');
|
||||||
|
await page.accessToSection('travel.card.basicData');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reach the thermograph section', async() => {
|
||||||
|
const result = await page.expectURL('/basic-data');
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set a wrong delivery date then receive an error on submit', async() => {
|
||||||
|
await page.datePicker(selectors.travelBasicDada.deliveryDate, -1, null);
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.save);
|
||||||
|
const result = await page.waitForLastSnackbar();
|
||||||
|
|
||||||
|
expect(result).toEqual('Landing cannot be lesser than shipment');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should undo the changes', async() => {
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.undoChanges);
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.save);
|
||||||
|
const result = await page.waitForLastSnackbar();
|
||||||
|
|
||||||
|
expect(result).toEqual('No changes to save');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should now edit the whole form then save', async() => {
|
||||||
|
await page.clearInput(selectors.travelBasicDada.reference);
|
||||||
|
await page.write(selectors.travelBasicDada.reference, 'new reference!');
|
||||||
|
await page.waitFor(2000);
|
||||||
|
await page.autocompleteSearch(selectors.travelBasicDada.agency, 'Entanglement');
|
||||||
|
await page.autocompleteSearch(selectors.travelBasicDada.outputWarehouse, 'Warehouse Three');
|
||||||
|
await page.autocompleteSearch(selectors.travelBasicDada.inputWarehouse, 'Warehouse Four');
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.delivered);
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.received);
|
||||||
|
await page.waitToClick(selectors.travelBasicDada.save);
|
||||||
|
const result = await page.waitForLastSnackbar();
|
||||||
|
|
||||||
|
expect(result).toEqual('Data saved!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reload the section and check the reference was saved', async() => {
|
||||||
|
await page.reloadSection('travel.card.basicData');
|
||||||
|
const result = await page.waitToGetProperty(selectors.travelBasicDada.reference, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('new reference!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the agency was saved', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.travelBasicDada.agency, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Entanglement');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the output warehouse date was saved', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.travelBasicDada.outputWarehouse, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Warehouse Three');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the input warehouse date was saved', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.travelBasicDada.inputWarehouse, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Warehouse Four');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should check the delivered checkbox was saved even tho it doesn't make sense`, async() => {
|
||||||
|
await page.waitForClassPresent(selectors.travelBasicDada.delivered, 'checked');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should check the received checkbox was saved even tho it doesn't make sense`, async() => {
|
||||||
|
await page.waitForClassPresent(selectors.travelBasicDada.received, 'checked');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to the travel logs', async() => {
|
||||||
|
await page.accessToSection('travel.card.log');
|
||||||
|
const result = await page.expectURL('/log');
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the 1st log contains details from the changes made', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toContain('new reference!');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,61 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Entry descriptor path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('buyer', 'entry');
|
||||||
|
await page.accessToSearchResult('2');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reach the second entry summary section', async() => {
|
||||||
|
let url = await page.expectURL('#!/entry/2/summary');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show some entry information', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.entryDescriptor.agency, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toContain('inhouse pickup');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should click the travels button to be redirected to the travels index filtered by the current agency', async() => {
|
||||||
|
await page.waitToClick(selectors.entryDescriptor.travelsQuicklink);
|
||||||
|
const url = await page.expectURL('/travel/index');
|
||||||
|
const filter = await page.expectURL('agencyFk');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
expect(filter).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go back to the entry summary', async() => {
|
||||||
|
await page.waitToClick(selectors.globalItems.homeButton);
|
||||||
|
await page.selectModule('entry');
|
||||||
|
await page.accessToSearchResult('2');
|
||||||
|
let url = await page.expectURL('#!/entry/2/summary');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should click the entries button to be redirected to the entries index filtered by the current supplier', async() => {
|
||||||
|
await page.waitToClick(selectors.entryDescriptor.entriesQuicklink);
|
||||||
|
const url = await page.expectURL('/entry/index');
|
||||||
|
const supplierFilter = await page.expectURL('supplierFk');
|
||||||
|
const toFilter = await page.expectURL('to');
|
||||||
|
const fromFilter = await page.expectURL('from');
|
||||||
|
|
||||||
|
expect(url).toBe(true);
|
||||||
|
expect(supplierFilter).toBe(true);
|
||||||
|
expect(toFilter).toBe(true);
|
||||||
|
expect(fromFilter).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -50,6 +50,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.message {
|
||||||
|
color: white;
|
||||||
|
background-color: $color-bg-dark;
|
||||||
|
|
||||||
|
&:not(.disabled) {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: lighten($color-bg-dark, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
&.flat {
|
&.flat {
|
||||||
color: $color-button;
|
color: $color-button;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -75,6 +86,22 @@
|
||||||
& > button > span {
|
& > button > span {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.xs {
|
||||||
|
font-size: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sm {
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.md {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.lg {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: .7;
|
opacity: .7;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default class Datalist extends Textfield {
|
||||||
value = value == '' || value == null ? null : value;
|
value = value == '' || value == null ? null : value;
|
||||||
oldValue = oldValue == '' || oldValue == null ? null : oldValue;
|
oldValue = oldValue == '' || oldValue == null ? null : oldValue;
|
||||||
|
|
||||||
this.refreshSelection();
|
if (oldValue === undefined) this.refreshSelection();
|
||||||
|
|
||||||
if (!value || value === oldValue && this.modelData != null) return;
|
if (!value || value === oldValue && this.modelData != null) return;
|
||||||
|
|
||||||
|
@ -52,7 +52,14 @@ export default class Datalist extends Textfield {
|
||||||
|
|
||||||
validSelection(selection) {
|
validSelection(selection) {
|
||||||
return this.modelData && this.modelData.find(item => {
|
return this.modelData && this.modelData.find(item => {
|
||||||
return item[this.valueField] == selection;
|
let dataValue = item[this.valueField];
|
||||||
|
if (typeof(dataValue) === 'string')
|
||||||
|
dataValue = dataValue.toLowerCase();
|
||||||
|
|
||||||
|
if (typeof(selection) === 'string')
|
||||||
|
selection = selection.toLowerCase();
|
||||||
|
|
||||||
|
return dataValue == selection;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
ng-click="$ctrl.onClear($event)">
|
ng-click="$ctrl.onClear($event)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="cloud_upload"
|
icon="attach_file"
|
||||||
vn-tooltip="Select a file"
|
vn-tooltip="Select a file"
|
||||||
ng-click="$ctrl.openFileSelector()">
|
ng-click="$ctrl.openFileSelector()">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
describe('Directive http-click', () => {
|
||||||
|
let $scope;
|
||||||
|
let element;
|
||||||
|
let compile;
|
||||||
|
|
||||||
|
beforeEach(ngModule('vnCore'));
|
||||||
|
|
||||||
|
compile = (_element, _childElement) => {
|
||||||
|
inject(($compile, $rootScope) => {
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
element = angular.element(_element);
|
||||||
|
$compile(element)($scope);
|
||||||
|
$scope.$digest();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should call click function on the element, disable it and then enable it again', () => {
|
||||||
|
let html = `<input vn-http-click="myEvent()"/>`;
|
||||||
|
compile(html);
|
||||||
|
|
||||||
|
const myPromise = new Promise(resolve => resolve());
|
||||||
|
$scope.myEvent = () => {
|
||||||
|
return myPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
element[0].$ctrl = {disabled: false};
|
||||||
|
element[0].click();
|
||||||
|
|
||||||
|
expect(element[0].$ctrl.disabled).toEqual(true);
|
||||||
|
|
||||||
|
let finalValue;
|
||||||
|
myPromise.then(() => {
|
||||||
|
finalValue = 'called!';
|
||||||
|
|
||||||
|
expect(element[0].$ctrl.disabled).toEqual(false);
|
||||||
|
}).finally(() => {
|
||||||
|
expect(finalValue).toEqual('called!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call click function on the element and not disable it', () => {
|
||||||
|
let html = `<input vn-http-click="myEvent()"/>`;
|
||||||
|
compile(html);
|
||||||
|
|
||||||
|
const myPromise = new Promise(resolve => resolve());
|
||||||
|
$scope.myEvent = () => {
|
||||||
|
return myPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
element[0].$ctrl = {disabled: true};
|
||||||
|
element[0].click();
|
||||||
|
|
||||||
|
expect(element[0].$ctrl.disabled).toEqual(true);
|
||||||
|
|
||||||
|
let finalValue;
|
||||||
|
myPromise.then(() => {
|
||||||
|
finalValue = 'called!';
|
||||||
|
|
||||||
|
expect(element[0].$ctrl.disabled).toEqual(true);
|
||||||
|
}).finally(() => {
|
||||||
|
expect(finalValue).toEqual('called!');
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -108,7 +108,10 @@ function runFn(
|
||||||
$filter,
|
$filter,
|
||||||
$interpolate,
|
$interpolate,
|
||||||
$window,
|
$window,
|
||||||
vnApp) {
|
vnApp,
|
||||||
|
vnToken,
|
||||||
|
vnConfig,
|
||||||
|
aclService) {
|
||||||
Object.assign(Component.prototype, {
|
Object.assign(Component.prototype, {
|
||||||
$translate,
|
$translate,
|
||||||
$q,
|
$q,
|
||||||
|
@ -121,7 +124,10 @@ function runFn(
|
||||||
$filter,
|
$filter,
|
||||||
$interpolate,
|
$interpolate,
|
||||||
$window,
|
$window,
|
||||||
vnApp
|
vnApp,
|
||||||
|
vnToken,
|
||||||
|
vnConfig,
|
||||||
|
aclService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
runFn.$inject = [
|
runFn.$inject = [
|
||||||
|
@ -136,7 +142,10 @@ runFn.$inject = [
|
||||||
'$filter',
|
'$filter',
|
||||||
'$interpolate',
|
'$interpolate',
|
||||||
'$window',
|
'$window',
|
||||||
'vnApp'
|
'vnApp',
|
||||||
|
'vnToken',
|
||||||
|
'vnConfig',
|
||||||
|
'aclService'
|
||||||
];
|
];
|
||||||
|
|
||||||
ngModule.run(runFn);
|
ngModule.run(runFn);
|
||||||
|
|
|
@ -1,24 +1,8 @@
|
||||||
<a ng-if="$ctrl.links.btnOne"
|
<a ng-repeat="button in $ctrl.links"
|
||||||
vn-tooltip="{{::$ctrl.links.btnOne.tooltip}}"
|
vn-tooltip="{{::button.tooltip}}"
|
||||||
class="vn-button colored"
|
class="vn-button colored"
|
||||||
ui-sref="{{::$ctrl.links.btnOne.state}}">
|
ui-sref="{{::button.state}}">
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="{{::$ctrl.links.btnOne.icon}}">
|
icon="{{::button.icon}}">
|
||||||
</vn-icon>
|
|
||||||
</a>
|
|
||||||
<a ng-if="$ctrl.links.btnTwo"
|
|
||||||
vn-tooltip="{{::$ctrl.links.btnTwo.tooltip}}"
|
|
||||||
class="vn-button colored"
|
|
||||||
ui-sref="{{::$ctrl.links.btnTwo.state}}">
|
|
||||||
<vn-icon
|
|
||||||
icon="{{::$ctrl.links.btnTwo.icon}}">
|
|
||||||
</vn-icon>
|
|
||||||
</a>
|
|
||||||
<a ng-if="$ctrl.links.btnThree"
|
|
||||||
vn-tooltip="{{::$ctrl.links.btnThree.tooltip}}"
|
|
||||||
class="vn-button colored"
|
|
||||||
ui-sref="{{::$ctrl.links.btnThree.state}}">
|
|
||||||
<vn-icon
|
|
||||||
icon="{{::$ctrl.links.btnThree.icon}}">
|
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</a>
|
</a>
|
|
@ -64,5 +64,6 @@
|
||||||
"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}}})",
|
||||||
"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",
|
||||||
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}"
|
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}",
|
||||||
|
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment"
|
||||||
}
|
}
|
|
@ -127,5 +127,6 @@
|
||||||
"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}}})",
|
||||||
"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 1000": "La distancia debe ser inferior a 1000"
|
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
|
||||||
|
"This ticket is deleted": "Este ticket está eliminado"
|
||||||
}
|
}
|
|
@ -155,7 +155,6 @@ class Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onUpdateGreugeResponse(response) {
|
onUpdateGreugeResponse(response) {
|
||||||
if (response == 'accept') {
|
if (response == 'accept') {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
class Controller {
|
class Controller extends Component {
|
||||||
constructor($scope, $state, $http, $translate, vnApp, aclService, $httpParamSerializer) {
|
constructor($element, $scope, $httpParamSerializer) {
|
||||||
this.$scope = $scope;
|
super($element, $scope);
|
||||||
this.$state = $state;
|
|
||||||
this.$http = $http;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
this.aclService = aclService;
|
|
||||||
this.$httpParamSerializer = $httpParamSerializer;
|
this.$httpParamSerializer = $httpParamSerializer;
|
||||||
|
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{callback: this.showPickupOrder, name: 'Show Pickup order'},
|
{callback: this.showPickupOrder, name: 'Show Pickup order'},
|
||||||
{callback: this.confirmPickupOrder, name: 'Send Pickup order'},
|
{callback: this.confirmPickupOrder, name: 'Send Pickup order'},
|
||||||
|
@ -22,7 +19,7 @@ class Controller {
|
||||||
|
|
||||||
return !hasAclProperty || (hasAclProperty && this.aclService.hasAny([option.acl]));
|
return !hasAclProperty || (hasAclProperty && this.aclService.hasAny([option.acl]));
|
||||||
});
|
});
|
||||||
this.$scope.moreButton.data = options;
|
this.$.moreButton.data = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMoreChange(callback) {
|
onMoreChange(callback) {
|
||||||
|
@ -63,7 +60,8 @@ class Controller {
|
||||||
showPickupOrder() {
|
showPickupOrder() {
|
||||||
const params = {
|
const params = {
|
||||||
clientId: this.claim.clientFk,
|
clientId: this.claim.clientFk,
|
||||||
claimId: this.claim.id
|
claimId: this.claim.id,
|
||||||
|
authorization: this.vnToken.token
|
||||||
};
|
};
|
||||||
const serializedParams = this.$httpParamSerializer(params);
|
const serializedParams = this.$httpParamSerializer(params);
|
||||||
let url = `api/report/claim-pickup-order?${serializedParams}`;
|
let url = `api/report/claim-pickup-order?${serializedParams}`;
|
||||||
|
@ -71,7 +69,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmPickupOrder() {
|
confirmPickupOrder() {
|
||||||
this.$scope.confirmPickupOrder.show();
|
this.$.confirmPickupOrder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPickupOrder(response) {
|
sendPickupOrder(response) {
|
||||||
|
@ -81,16 +79,14 @@ class Controller {
|
||||||
clientId: this.claim.clientFk,
|
clientId: this.claim.clientFk,
|
||||||
claimId: this.claim.id
|
claimId: this.claim.id
|
||||||
};
|
};
|
||||||
const serializedParams = this.$httpParamSerializer(params);
|
this.$http.get(`email/claim-pickup-order`, {params}).then(
|
||||||
const url = `email/claim-pickup-order?${serializedParams}`;
|
|
||||||
this.$http.get(url).then(
|
|
||||||
() => this.vnApp.showMessage(this.$translate.instant('Notification sent!'))
|
() => this.vnApp.showMessage(this.$translate.instant('Notification sent!'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeleteClaim() {
|
confirmDeleteClaim() {
|
||||||
this.$scope.confirmDeleteClaim.show();
|
this.$.confirmDeleteClaim.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteClaim(response) {
|
deleteClaim(response) {
|
||||||
|
@ -103,7 +99,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$state', '$http', '$translate', 'vnApp', 'aclService', '$httpParamSerializer'];
|
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
|
||||||
|
|
||||||
ngModule.component('vnClaimDescriptor', {
|
ngModule.component('vnClaimDescriptor', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -3,14 +3,19 @@ import './index.js';
|
||||||
describe('Item Component vnClaimDescriptor', () => {
|
describe('Item Component vnClaimDescriptor', () => {
|
||||||
let $httpParamSerializer;
|
let $httpParamSerializer;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
|
let $element;
|
||||||
|
let $scope;
|
||||||
let controller;
|
let controller;
|
||||||
|
|
||||||
beforeEach(ngModule('claim'));
|
beforeEach(ngModule('claim'));
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
controller = $componentController('vnClaimDescriptor');
|
$scope = $rootScope.$new();
|
||||||
|
|
||||||
|
$element = angular.element('<vn-claim-descriptor></vn-claim-descriptor>');
|
||||||
|
controller = $componentController('vnClaimDescriptor', {$element, $scope});
|
||||||
controller.claim = {id: 2, clientFk: 101, client: {email: 'client@email'}};
|
controller.claim = {id: 2, clientFk: 101, client: {email: 'client@email'}};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -31,13 +36,13 @@ describe('Item Component vnClaimDescriptor', () => {
|
||||||
|
|
||||||
describe('confirmPickupOrder()', () => {
|
describe('confirmPickupOrder()', () => {
|
||||||
it('should call confirmPickupOrder.show()', () => {
|
it('should call confirmPickupOrder.show()', () => {
|
||||||
controller.$scope.confirmPickupOrder = {
|
controller.$.confirmPickupOrder = {
|
||||||
show: jasmine.createSpy('show')
|
show: jasmine.createSpy('show')
|
||||||
};
|
};
|
||||||
controller.claim = {id: 2};
|
controller.claim = {id: 2};
|
||||||
controller.confirmPickupOrder();
|
controller.confirmPickupOrder();
|
||||||
|
|
||||||
expect(controller.$scope.confirmPickupOrder.show).toHaveBeenCalledWith();
|
expect(controller.$.confirmPickupOrder.show).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -63,13 +68,13 @@ describe('Item Component vnClaimDescriptor', () => {
|
||||||
|
|
||||||
describe('confirmDeleteClaim()', () => {
|
describe('confirmDeleteClaim()', () => {
|
||||||
it('should call confirmDeleteClaim.show()', () => {
|
it('should call confirmDeleteClaim.show()', () => {
|
||||||
controller.$scope.confirmDeleteClaim = {
|
controller.$.confirmDeleteClaim = {
|
||||||
show: jasmine.createSpy('show')
|
show: jasmine.createSpy('show')
|
||||||
};
|
};
|
||||||
controller.claim = {id: 2};
|
controller.claim = {id: 2};
|
||||||
controller.confirmDeleteClaim();
|
controller.confirmDeleteClaim();
|
||||||
|
|
||||||
expect(controller.$scope.confirmDeleteClaim.show).toHaveBeenCalledWith();
|
expect(controller.$.confirmDeleteClaim.show).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,24 +10,17 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Client Id"]
|
||||||
|
ng-model="filter.clientFk">
|
||||||
|
</vn-textfield>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
label="Client"
|
label="Client"
|
||||||
ng-model="filter.client">
|
ng-model="filter.client">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Claim Id"
|
|
||||||
ng-model="filter.id">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Client Id"
|
|
||||||
ng-model="filter.clientFk">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe('Client activeWorkersWithRole', () => {
|
||||||
|
|
||||||
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
|
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
|
||||||
|
|
||||||
expect(result.length).toEqual(14);
|
expect(result.length).toEqual(15);
|
||||||
expect(isSalesPerson).toBeTruthy();
|
expect(isSalesPerson).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ describe('Client activeWorkersWithRole', () => {
|
||||||
|
|
||||||
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
|
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
|
||||||
|
|
||||||
expect(result.length).toEqual(11);
|
expect(result.length).toEqual(13);
|
||||||
expect(isBuyer).toBeTruthy();
|
expect(isBuyer).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,7 @@ describe('Client isValidClient', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call the isValidClient() method with an unexistant id and receive false', async() => {
|
it('should call the isValidClient() method with an unexistant id and receive false', async() => {
|
||||||
let id = 999999;
|
let id = 999;
|
||||||
let result = await app.models.Client.isValidClient(id);
|
let result = await app.models.Client.isValidClient(id);
|
||||||
|
|
||||||
expect(result).toBeFalsy();
|
expect(result).toBeFalsy();
|
||||||
|
|
|
@ -47,7 +47,6 @@ module.exports = Self => {
|
||||||
let xmlParsed;
|
let xmlParsed;
|
||||||
let status;
|
let status;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
status = {
|
status = {
|
||||||
|
|
|
@ -191,7 +191,6 @@ module.exports = Self => {
|
||||||
if (socialNameChanged && !isAlpha(changes.socialName))
|
if (socialNameChanged && !isAlpha(changes.socialName))
|
||||||
throw new UserError('The socialName has an invalid format');
|
throw new UserError('The socialName has an invalid format');
|
||||||
|
|
||||||
|
|
||||||
if (changes.salesPerson === null) {
|
if (changes.salesPerson === null) {
|
||||||
changes.credit = 0;
|
changes.credit = 0;
|
||||||
changes.discount = 0;
|
changes.discount = 0;
|
||||||
|
@ -238,7 +237,9 @@ module.exports = Self => {
|
||||||
const httpCtx = {req: loopBackContext.active};
|
const httpCtx = {req: loopBackContext.active};
|
||||||
const httpRequest = httpCtx.req.http.req;
|
const httpRequest = httpCtx.req.http.req;
|
||||||
const $t = httpRequest.__;
|
const $t = httpRequest.__;
|
||||||
const origin = httpRequest.headers.origin;
|
const headers = httpRequest.headers;
|
||||||
|
const origin = headers.origin;
|
||||||
|
const authorization = headers.authorization;
|
||||||
|
|
||||||
const salesPersonId = instance.salesPersonFk;
|
const salesPersonId = instance.salesPersonFk;
|
||||||
|
|
||||||
|
@ -254,12 +255,14 @@ module.exports = Self => {
|
||||||
|
|
||||||
// Send email to client
|
// Send email to client
|
||||||
if (!instance.email) return;
|
if (!instance.email) return;
|
||||||
const serializedParams = httpParamSerializer({
|
const params = {
|
||||||
|
authorization: authorization,
|
||||||
clientId: instance.id,
|
clientId: instance.id,
|
||||||
recipient: instance.email
|
recipient: instance.email
|
||||||
|
};
|
||||||
|
await request.get(`${origin}/api/email/payment-update`, {
|
||||||
|
qs: params
|
||||||
});
|
});
|
||||||
const query = `${origin}/api/email/payment-update?${serializedParams}`;
|
|
||||||
await request.get(query);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -39,61 +39,53 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-datalist vn-one
|
||||||
vn-one
|
|
||||||
vn-id="province"
|
|
||||||
ng-model="$ctrl.address.provinceId"
|
|
||||||
url="Provinces"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="City"
|
|
||||||
ng-model="$ctrl.address.city"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<!-- <vn-autocomplete vn-id="town" vn-one
|
|
||||||
label="City"
|
|
||||||
url="Towns"
|
|
||||||
fields="['id', 'name']"
|
|
||||||
where="{provinceFk: province.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="name"
|
|
||||||
ng-model="$ctrl.address.city">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
url="Postcodes/location"
|
|
||||||
fields="['code', 'townFk']"
|
|
||||||
ng-model="$ctrl.address.postalCode"
|
|
||||||
selection="$ctrl.postcodeSelection"
|
|
||||||
search-function="{code: $search}"
|
|
||||||
where="{townFk: town.selection.id}"
|
|
||||||
order="code, townFk"
|
|
||||||
show-field="code"
|
|
||||||
value-field="code"
|
|
||||||
label="Postcode">
|
|
||||||
<tpl-item>
|
|
||||||
{{code}}, {{town.name}} - {{town.province.name}}
|
|
||||||
({{town.province.country.country}})
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete> -->
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Postcode"
|
label="Postcode"
|
||||||
ng-model="$ctrl.address.postalCode"
|
ng-model="$ctrl.address.postalCode"
|
||||||
|
selection="$ctrl.postcode"
|
||||||
|
url="Postcodes/location"
|
||||||
|
fields="['code','townFk']"
|
||||||
|
order="code, townFk"
|
||||||
|
value-field="code"
|
||||||
|
show-field="code"
|
||||||
rule>
|
rule>
|
||||||
</vn-textfield>
|
<tpl-item>
|
||||||
<!--
|
{{code}} - {{town.name}} ({{town.province.name}},
|
||||||
|
{{town.province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
<append>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-auto
|
|
||||||
class="vn-my-md"
|
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
vn-tooltip="New postcode"
|
vn-tooltip="New postcode"
|
||||||
ng-click="postcode.open()">
|
ng-click="postcode.open()"
|
||||||
|
vn-acl="deliveryBoss"
|
||||||
|
vn-acl-action="remove">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
-->
|
</append>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-datalist vn-id="town" vn-one
|
||||||
|
label="City"
|
||||||
|
ng-model="$ctrl.address.city"
|
||||||
|
selection="$ctrl.town"
|
||||||
|
url="Towns/location"
|
||||||
|
fields="['id', 'name', 'provinceFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="name">
|
||||||
|
<tpl-item>
|
||||||
|
{{name}}, {{province.name}}
|
||||||
|
({{province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-autocomplete vn-id="province" vn-one
|
||||||
|
label="Province"
|
||||||
|
ng-model="$ctrl.address.provinceId"
|
||||||
|
url="Provinces/location"
|
||||||
|
fields="['id', 'name', 'countryFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
rule>
|
||||||
|
<tpl-item>{{name}} ({{country.country}})</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
|
|
|
@ -11,26 +11,6 @@ export default class Controller extends Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get postcodeSelection() {
|
|
||||||
return this._postcodeSelection;
|
|
||||||
}
|
|
||||||
|
|
||||||
set postcodeSelection(selection) {
|
|
||||||
this._postcodeSelection = selection;
|
|
||||||
|
|
||||||
if (!selection) return;
|
|
||||||
|
|
||||||
const town = selection.town;
|
|
||||||
const province = town.province;
|
|
||||||
|
|
||||||
this.address.city = town.name;
|
|
||||||
this.address.provinceFk = province.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponse(response) {
|
|
||||||
this.address.postalCode = response.code;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$.watcher.submit().then(res => {
|
this.$.watcher.submit().then(res => {
|
||||||
if (this.address.isDefaultAddress)
|
if (this.address.isDefaultAddress)
|
||||||
|
@ -51,6 +31,46 @@ export default class Controller extends Component {
|
||||||
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
||||||
.then(res => this.address.customsAgentFk = res.data.id);
|
.then(res => this.address.customsAgentFk = res.data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get town() {
|
||||||
|
return this._town;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Town auto complete
|
||||||
|
set town(selection) {
|
||||||
|
this._town = selection;
|
||||||
|
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const province = selection.province;
|
||||||
|
const postcodes = selection.postcodes;
|
||||||
|
|
||||||
|
this.address.provinceId = province.id;
|
||||||
|
|
||||||
|
if (postcodes.length === 1)
|
||||||
|
this.address.postalCode = postcodes[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get postcode() {
|
||||||
|
return this._postcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postcode auto complete
|
||||||
|
set postcode(selection) {
|
||||||
|
this._postcode = selection;
|
||||||
|
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const town = selection.town;
|
||||||
|
const province = town.province;
|
||||||
|
|
||||||
|
this.address.city = town.name;
|
||||||
|
this.address.provinceId = province.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponse(response) {
|
||||||
|
this.address.postalCode = response.code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
Controller.$inject = ['$element', '$scope'];
|
||||||
|
|
|
@ -53,9 +53,48 @@ describe('Client', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('postcodeSelection() setter', () => {
|
describe('town() setter', () => {
|
||||||
it(`should set the town, province and contry properties`, () => {
|
it(`should set provinceId property`, () => {
|
||||||
controller.postcodeSelection = {
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: []
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.address.provinceId).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should set provinceId property and fill the postalCode if there's just one`, () => {
|
||||||
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: [{code: '46001'}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.address.provinceId).toEqual(1);
|
||||||
|
expect(controller.address.postalCode).toEqual('46001');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('postcode() setter', () => {
|
||||||
|
it(`should set the town and province properties`, () => {
|
||||||
|
controller.postcode = {
|
||||||
townFk: 1,
|
townFk: 1,
|
||||||
code: 46001,
|
code: 46001,
|
||||||
town: {
|
town: {
|
||||||
|
@ -73,7 +112,7 @@ describe('Client', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(controller.address.city).toEqual('New York');
|
expect(controller.address.city).toEqual('New York');
|
||||||
expect(controller.address.provinceFk).toEqual(1);
|
expect(controller.address.provinceId).toEqual(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -56,58 +56,53 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-datalist vn-one
|
||||||
vn-one
|
|
||||||
vn-id="province"
|
|
||||||
ng-model="$ctrl.address.provinceFk"
|
|
||||||
url="Provinces"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="City"
|
|
||||||
ng-model="$ctrl.address.city"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<!--
|
|
||||||
<vn-autocomplete vn-id="town" vn-one
|
|
||||||
label="City"
|
|
||||||
url="Towns"
|
|
||||||
fields="['id', 'name']"
|
|
||||||
where="{provinceFk: province.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="name"
|
|
||||||
ng-model="$ctrl.address.city">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
url="Postcodes/location"
|
|
||||||
fields="['code', 'townFk']"
|
|
||||||
ng-model="$ctrl.address.postalCode"
|
|
||||||
where="{townFk: town.selection.id}"
|
|
||||||
search-function="{code: $search}"
|
|
||||||
order="code, townFk"
|
|
||||||
show-field="code"
|
|
||||||
value-field="code"
|
|
||||||
label="Postcode">
|
|
||||||
</vn-autocomplete>
|
|
||||||
-->
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Postcode"
|
label="Postcode"
|
||||||
ng-model="$ctrl.address.postalCode"
|
ng-model="$ctrl.address.postalCode"
|
||||||
|
selection="$ctrl.postcode"
|
||||||
|
url="Postcodes/location"
|
||||||
|
fields="['code','townFk']"
|
||||||
|
order="code, townFk"
|
||||||
|
value-field="code"
|
||||||
|
show-field="code"
|
||||||
rule>
|
rule>
|
||||||
</vn-textfield>
|
<tpl-item>
|
||||||
|
{{code}} - {{town.name}} ({{town.province.name}},
|
||||||
<!-- <vn-icon-button
|
{{town.province.country.country}})
|
||||||
vn-auto
|
</tpl-item>
|
||||||
class="vn-my-md"
|
<append>
|
||||||
|
<vn-icon-button
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
vn-tooltip="New postcode"
|
vn-tooltip="New postcode"
|
||||||
ng-click="postcode.open()">
|
ng-click="postcode.open()"
|
||||||
|
vn-acl="deliveryBoss"
|
||||||
|
vn-acl-action="remove">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
-->
|
</append>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-datalist vn-id="town" vn-one
|
||||||
|
label="City"
|
||||||
|
ng-model="$ctrl.address.city"
|
||||||
|
selection="$ctrl.town"
|
||||||
|
url="Towns/location"
|
||||||
|
fields="['id', 'name', 'provinceFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="name">
|
||||||
|
<tpl-item>
|
||||||
|
{{name}}, {{province.name}}
|
||||||
|
({{province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-autocomplete vn-id="province" vn-one
|
||||||
|
label="Province"
|
||||||
|
ng-model="$ctrl.address.provinceFk"
|
||||||
|
url="Provinces/location"
|
||||||
|
fields="['id', 'name', 'countryFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
rule>
|
||||||
|
<tpl-item>{{name}} ({{country.country}})</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
|
|
|
@ -15,10 +15,6 @@ export default class Controller extends Component {
|
||||||
this.$state.go('client.card.address.index');
|
this.$state.go('client.card.address.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
onResponse(response) {
|
|
||||||
this.address.postalCode = response.code;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$.watcher.submit()
|
this.$.watcher.submit()
|
||||||
.then(() => this.$.model.save(true))
|
.then(() => this.$.model.save(true))
|
||||||
|
@ -39,6 +35,48 @@ export default class Controller extends Component {
|
||||||
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
return this.$http.post(`CustomsAgents`, this.newCustomsAgent)
|
||||||
.then(res => this.address.customsAgentFk = res.data.id);
|
.then(res => this.address.customsAgentFk = res.data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get town() {
|
||||||
|
return this._town;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Town auto complete
|
||||||
|
set town(selection) {
|
||||||
|
const oldValue = this._town;
|
||||||
|
this._town = selection;
|
||||||
|
|
||||||
|
if (!oldValue) return;
|
||||||
|
|
||||||
|
const province = selection.province;
|
||||||
|
const postcodes = selection.postcodes;
|
||||||
|
|
||||||
|
this.address.provinceFk = province.id;
|
||||||
|
|
||||||
|
if (postcodes.length === 1)
|
||||||
|
this.address.postalCode = postcodes[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get postcode() {
|
||||||
|
return this._postcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postcode auto complete
|
||||||
|
set postcode(selection) {
|
||||||
|
const oldValue = this._postcode;
|
||||||
|
this._postcode = selection;
|
||||||
|
|
||||||
|
if (!oldValue) return;
|
||||||
|
|
||||||
|
const town = selection.town;
|
||||||
|
const province = town.province;
|
||||||
|
|
||||||
|
this.address.city = town.name;
|
||||||
|
this.address.provinceFk = province.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponse(response) {
|
||||||
|
this.address.postalCode = response.code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnClientAddressEdit', {
|
ngModule.component('vnClientAddressEdit', {
|
||||||
|
|
|
@ -49,76 +49,63 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-datalist vn-one
|
||||||
vn-id="country"
|
label="Postcode"
|
||||||
vn-one
|
ng-model="$ctrl.client.postcode"
|
||||||
|
selection="$ctrl.postcode"
|
||||||
|
url="Postcodes/location"
|
||||||
|
fields="['code','townFk']"
|
||||||
|
order="code, townFk"
|
||||||
|
value-field="code"
|
||||||
|
show-field="code"
|
||||||
|
rule>
|
||||||
|
<tpl-item>
|
||||||
|
{{code}} - {{town.name}} ({{town.province.name}},
|
||||||
|
{{town.province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
<append>
|
||||||
|
<vn-icon-button
|
||||||
|
icon="add_circle"
|
||||||
|
vn-tooltip="New postcode"
|
||||||
|
ng-click="postcode.open()"
|
||||||
|
vn-acl="deliveryBoss"
|
||||||
|
vn-acl-action="remove">
|
||||||
|
</vn-icon-button>
|
||||||
|
</append>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-datalist vn-id="town" vn-one
|
||||||
|
label="City"
|
||||||
|
ng-model="$ctrl.client.city"
|
||||||
|
selection="$ctrl.town"
|
||||||
|
url="Towns/location"
|
||||||
|
fields="['id', 'name', 'provinceFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="name">
|
||||||
|
<tpl-item>
|
||||||
|
{{name}}, {{province.name}}
|
||||||
|
({{province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
</vn-datalist>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-id="province" vn-one
|
||||||
|
label="Province"
|
||||||
|
ng-model="$ctrl.client.provinceFk"
|
||||||
|
selection="$ctrl.province"
|
||||||
|
url="Provinces/location"
|
||||||
|
fields="['id', 'name', 'countryFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
rule>
|
||||||
|
<tpl-item>{{name}} ({{country.country}})</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-id="country" vn-one
|
||||||
ng-model="$ctrl.client.countryFk"
|
ng-model="$ctrl.client.countryFk"
|
||||||
url="Countries"
|
url="Countries"
|
||||||
show-field="country"
|
show-field="country"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
label="Country">
|
label="Country">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete
|
|
||||||
vn-id="province"
|
|
||||||
vn-one
|
|
||||||
url="Provinces"
|
|
||||||
ng-model="$ctrl.client.provinceFk"
|
|
||||||
where="{countryFk: country.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="City"
|
|
||||||
ng-model="$ctrl.client.city"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<!--
|
|
||||||
<vn-autocomplete vn-id="town" vn-one
|
|
||||||
label="City"
|
|
||||||
url="Towns"
|
|
||||||
fields="['id', 'name']"
|
|
||||||
where="{provinceFk: province.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="name"
|
|
||||||
ng-model="$ctrl.client.city">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-auto
|
|
||||||
class="vn-my-md"
|
|
||||||
icon="add_circle"
|
|
||||||
vn-tooltip="New postcode"
|
|
||||||
ng-click="postcode.open()">
|
|
||||||
</vn-icon-button>
|
|
||||||
-->
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Postcode"
|
|
||||||
ng-model="$ctrl.client.postcode"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<!--
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="Postcodes/location"
|
|
||||||
fields="['code', 'townFk']"
|
|
||||||
ng-model="$ctrl.client.postcode"
|
|
||||||
selection="$ctrl.postcodeSelection"
|
|
||||||
search-function="{code: $search}"
|
|
||||||
where="{townFk: town.selection.id}"
|
|
||||||
order="code, townFk"
|
|
||||||
show-field="code"
|
|
||||||
value-field="code"
|
|
||||||
label="Postcode">
|
|
||||||
<tpl-item>
|
|
||||||
{{code}}, {{town.name}} - {{town.province.name}}
|
|
||||||
({{town.province.country.country}})
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
-->
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
|
|
|
@ -12,12 +12,55 @@ export default class Controller {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get postcodeSelection() {
|
onSubmit() {
|
||||||
return this._postcodeSelection;
|
return this.$.watcher.submit().then(
|
||||||
|
json => this.$state.go('client.card.basicData', {id: json.data.id})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
set postcodeSelection(selection) {
|
get province() {
|
||||||
this._postcodeSelection = selection;
|
return this._province;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Province auto complete
|
||||||
|
set province(selection) {
|
||||||
|
this._province = selection;
|
||||||
|
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const country = selection.country;
|
||||||
|
|
||||||
|
this.client.countryFk = country.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get town() {
|
||||||
|
return this._town;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Town auto complete
|
||||||
|
set town(selection) {
|
||||||
|
this._town = selection;
|
||||||
|
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const province = selection.province;
|
||||||
|
const country = province.country;
|
||||||
|
const postcodes = selection.postcodes;
|
||||||
|
|
||||||
|
this.client.provinceFk = province.id;
|
||||||
|
this.client.countryFk = country.id;
|
||||||
|
|
||||||
|
if (postcodes.length === 1)
|
||||||
|
this.client.postcode = postcodes[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get postcode() {
|
||||||
|
return this._postcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postcode auto complete
|
||||||
|
set postcode(selection) {
|
||||||
|
this._postcode = selection;
|
||||||
|
|
||||||
if (!selection) return;
|
if (!selection) return;
|
||||||
|
|
||||||
|
@ -33,13 +76,8 @@ export default class Controller {
|
||||||
onResponse(response) {
|
onResponse(response) {
|
||||||
this.client.postcode = response.code;
|
this.client.postcode = response.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
return this.$.watcher.submit().then(
|
|
||||||
json => this.$state.go('client.card.basicData', {id: json.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$state', '$http', '$translate', 'vnApp'];
|
Controller.$inject = ['$scope', '$state', '$http', '$translate', 'vnApp'];
|
||||||
|
|
||||||
ngModule.component('vnClientCreate', {
|
ngModule.component('vnClientCreate', {
|
||||||
|
|
|
@ -40,9 +40,63 @@ describe('Client', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('postcodeSelection() setter', () => {
|
describe('province() setter', () => {
|
||||||
it(`should set the town, province and contry properties`, () => {
|
it(`should set countryFk property`, () => {
|
||||||
controller.postcodeSelection = {
|
controller.province = {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.countryFk).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('town() setter', () => {
|
||||||
|
it(`should set provinceFk property`, () => {
|
||||||
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: []
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.provinceFk).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should set provinceFk property and fill the postalCode if there's just one`, () => {
|
||||||
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: [{code: '46001'}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.provinceFk).toEqual(1);
|
||||||
|
expect(controller.client.postcode).toEqual('46001');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('postcode() setter', () => {
|
||||||
|
it(`should set the town, provinceFk and contryFk properties`, () => {
|
||||||
|
controller.postcode = {
|
||||||
townFk: 1,
|
townFk: 1,
|
||||||
code: 46001,
|
code: 46001,
|
||||||
town: {
|
town: {
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Controller extends Component {
|
||||||
constructor($element, $, $httpParamSerializer) {
|
constructor($element, $, $httpParamSerializer) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.$httpParamSerializer = $httpParamSerializer;
|
this.$httpParamSerializer = $httpParamSerializer;
|
||||||
|
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{name: 'Simple ticket', callback: this.newTicket},
|
{name: 'Simple ticket', callback: this.newTicket},
|
||||||
{name: 'Send SMS', callback: this.showSMSDialog},
|
{name: 'Send SMS', callback: this.showSMSDialog},
|
||||||
|
@ -72,8 +73,13 @@ class Controller extends Component {
|
||||||
|
|
||||||
sendConsumerReport(response) {
|
sendConsumerReport(response) {
|
||||||
if (response === 'accept') {
|
if (response === 'accept') {
|
||||||
const data = {from: this.from, to: this.to, clientId: this.client.id};
|
const params = {
|
||||||
const serializedParams = this.$httpParamSerializer(data);
|
authorization: this.vnToken.token,
|
||||||
|
clientId: this.client.id,
|
||||||
|
from: this.from,
|
||||||
|
to: this.to,
|
||||||
|
};
|
||||||
|
const serializedParams = this.$httpParamSerializer(params);
|
||||||
const url = `api/report/campaign-metrics?${serializedParams}`;
|
const url = `api/report/campaign-metrics?${serializedParams}`;
|
||||||
window.open(url);
|
window.open(url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,16 @@
|
||||||
label="File"
|
label="File"
|
||||||
ng-model="$ctrl.dms.files"
|
ng-model="$ctrl.dms.files"
|
||||||
on-change="$ctrl.onFileChange($files)"
|
on-change="$ctrl.onFileChange($files)"
|
||||||
accept=".pdf, .png, .jpg, .jpeg, application/zip, application/rar, application/x-7z-compressed">
|
accept="{{$ctrl.allowedContentTypes}}"
|
||||||
|
required="true"
|
||||||
|
multiple="true">
|
||||||
|
<append>
|
||||||
|
<vn-icon vn-none
|
||||||
|
color-marginal
|
||||||
|
title="{{$ctrl.contentTypesInfo}}"
|
||||||
|
icon="info">
|
||||||
|
</vn-icon>
|
||||||
|
</append>
|
||||||
</vn-input-file>
|
</vn-input-file>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
|
|
|
@ -53,11 +53,6 @@
|
||||||
{{::document.dms.description}}
|
{{::document.dms.description}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>
|
|
||||||
<vn-check disabled="true"
|
|
||||||
ng-model="document.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<a target="_blank"
|
<a target="_blank"
|
||||||
title="{{'Download file' | translate}}"
|
title="{{'Download file' | translate}}"
|
||||||
|
|
|
@ -33,9 +33,57 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-datalist vn-one
|
||||||
vn-one
|
label="Postcode"
|
||||||
vn-id="country"
|
ng-model="$ctrl.client.postcode"
|
||||||
|
selection="$ctrl.postcode"
|
||||||
|
url="Postcodes/location"
|
||||||
|
fields="['code','townFk']"
|
||||||
|
order="code, townFk"
|
||||||
|
value-field="code"
|
||||||
|
show-field="code"
|
||||||
|
rule>
|
||||||
|
<tpl-item>
|
||||||
|
{{code}} - {{town.name}} ({{town.province.name}},
|
||||||
|
{{town.province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
<append>
|
||||||
|
<vn-icon-button
|
||||||
|
icon="add_circle"
|
||||||
|
vn-tooltip="New postcode"
|
||||||
|
ng-click="postcode.open()"
|
||||||
|
vn-acl="deliveryBoss"
|
||||||
|
vn-acl-action="remove">
|
||||||
|
</vn-icon-button>
|
||||||
|
</append>
|
||||||
|
</vn-datalist>
|
||||||
|
<vn-datalist vn-id="town" vn-one
|
||||||
|
label="City"
|
||||||
|
ng-model="$ctrl.client.city"
|
||||||
|
selection="$ctrl.town"
|
||||||
|
url="Towns/location"
|
||||||
|
fields="['id', 'name', 'provinceFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="name">
|
||||||
|
<tpl-item>
|
||||||
|
{{name}}, {{province.name}}
|
||||||
|
({{province.country.country}})
|
||||||
|
</tpl-item>
|
||||||
|
</vn-datalist>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-id="province" vn-one
|
||||||
|
label="Province"
|
||||||
|
ng-model="$ctrl.client.provinceFk"
|
||||||
|
selection="$ctrl.province"
|
||||||
|
url="Provinces/location"
|
||||||
|
fields="['id', 'name', 'countryFk']"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
rule>
|
||||||
|
<tpl-item>{{name}} ({{country.country}})</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-id="country" vn-one
|
||||||
ng-model="$ctrl.client.countryFk"
|
ng-model="$ctrl.client.countryFk"
|
||||||
url="Countries"
|
url="Countries"
|
||||||
show-field="country"
|
show-field="country"
|
||||||
|
@ -43,51 +91,6 @@
|
||||||
label="Country"
|
label="Country"
|
||||||
rule>
|
rule>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
vn-id="province"
|
|
||||||
ng-model="$ctrl.client.provinceFk"
|
|
||||||
url="Provinces"
|
|
||||||
where="{countryFk: country.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="City"
|
|
||||||
ng-model="$ctrl.client.city"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Postcode"
|
|
||||||
ng-model="$ctrl.client.postcode"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<!-- <vn-autocomplete vn-id="town" vn-one
|
|
||||||
label="City"
|
|
||||||
url="Towns"
|
|
||||||
fields="['id', 'name']"
|
|
||||||
where="{provinceFk: province.selection.id}"
|
|
||||||
show-field="name"
|
|
||||||
value-field="name"
|
|
||||||
ng-model="$ctrl.client.city">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-id="postcode" vn-one
|
|
||||||
url="Postcodes/location"
|
|
||||||
fields="['code', 'townFk']"
|
|
||||||
ng-model="$ctrl.client.postcode"
|
|
||||||
search-function="{code: $search}"
|
|
||||||
where="{townFk: town.selection.id}"
|
|
||||||
order="code, townFk"
|
|
||||||
show-field="code"
|
|
||||||
value-field="code"
|
|
||||||
label="Postcode">
|
|
||||||
</vn-autocomplete> -->
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check
|
<vn-check
|
||||||
|
@ -157,3 +160,8 @@
|
||||||
message="Found a client with this data"
|
message="Found a client with this data"
|
||||||
on-accept="$ctrl.onAcceptDuplication()">
|
on-accept="$ctrl.onAcceptDuplication()">
|
||||||
</vn-confirm>
|
</vn-confirm>
|
||||||
|
<!-- New postcode dialog -->
|
||||||
|
<vn-client-postcode
|
||||||
|
vn-id="postcode"
|
||||||
|
on-response="$ctrl.onResponse($response)">
|
||||||
|
</vn-client-postcode>
|
|
@ -5,16 +5,29 @@ export default class Controller extends Component {
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
const orgData = this.$.watcher.orgData;
|
const orgData = this.$.watcher.orgData;
|
||||||
delete this.client.despiteOfClient;
|
delete this.client.despiteOfClient;
|
||||||
if (!orgData.isTaxDataChecked && this.client.isTaxDataChecked)
|
|
||||||
|
const hasContactData = this.client.email || this.client.phone || this.client.mobile;
|
||||||
|
const hasChangedTaxData = !orgData.isTaxDataChecked && this.client.isTaxDataChecked;
|
||||||
|
if (hasChangedTaxData && hasContactData)
|
||||||
this.checkExistingClient();
|
this.checkExistingClient();
|
||||||
else this.save();
|
else this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExistingClient() {
|
checkExistingClient() {
|
||||||
|
const findParams = [];
|
||||||
|
if (this.client.email)
|
||||||
|
findParams.push({email: this.client.email});
|
||||||
|
|
||||||
|
if (this.client.phone)
|
||||||
|
findParams.push({phone: this.client.phone});
|
||||||
|
|
||||||
|
if (this.client.mobile)
|
||||||
|
findParams.push({mobile: this.client.mobile});
|
||||||
|
|
||||||
const filterObj = {
|
const filterObj = {
|
||||||
where: {
|
where: {
|
||||||
and: [
|
and: [
|
||||||
{or: [{email: this.client.email}, {phone: this.client.phone}]},
|
{or: findParams},
|
||||||
{id: {neq: this.client.id}}
|
{id: {neq: this.client.id}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -32,7 +45,8 @@ export default class Controller extends Component {
|
||||||
this.$.confirmDuplicatedClient.show();
|
this.$.confirmDuplicatedClient.show();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.status == 404)
|
if (error.status == 404)
|
||||||
this.save();
|
return this.save();
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +91,68 @@ export default class Controller extends Component {
|
||||||
|
|
||||||
this.$.$apply();
|
this.$.$apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get province() {
|
||||||
|
return this._province;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Province auto complete
|
||||||
|
set province(selection) {
|
||||||
|
const oldValue = this._province;
|
||||||
|
this._province = selection;
|
||||||
|
|
||||||
|
if (!selection || !oldValue) return;
|
||||||
|
|
||||||
|
const country = selection.country;
|
||||||
|
|
||||||
|
this.client.countryFk = country.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
get town() {
|
||||||
|
return this._town;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Town auto complete
|
||||||
|
set town(selection) {
|
||||||
|
const oldValue = this._town;
|
||||||
|
this._town = selection;
|
||||||
|
|
||||||
|
if (!selection || !oldValue) return;
|
||||||
|
|
||||||
|
const province = selection.province;
|
||||||
|
const country = province.country;
|
||||||
|
const postcodes = selection.postcodes;
|
||||||
|
|
||||||
|
this.client.provinceFk = province.id;
|
||||||
|
this.client.countryFk = country.id;
|
||||||
|
|
||||||
|
if (postcodes.length === 1)
|
||||||
|
this.client.postcode = postcodes[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get postcode() {
|
||||||
|
return this._postcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postcode auto complete
|
||||||
|
set postcode(selection) {
|
||||||
|
const oldValue = this._postcode;
|
||||||
|
this._postcode = selection;
|
||||||
|
|
||||||
|
if (!selection || !oldValue) return;
|
||||||
|
|
||||||
|
const town = selection.town;
|
||||||
|
const province = town.province;
|
||||||
|
const country = province.country;
|
||||||
|
|
||||||
|
this.client.city = town.name;
|
||||||
|
this.client.provinceFk = province.id;
|
||||||
|
this.client.countryFk = country.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponse(response) {
|
||||||
|
this.client.postcode = response.code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnClientFiscalData', {
|
ngModule.component('vnClientFiscalData', {
|
||||||
|
|
|
@ -25,6 +25,10 @@ describe('Client', () => {
|
||||||
isEqualizated: false,
|
isEqualizated: false,
|
||||||
isTaxDataChecked: false
|
isTaxDataChecked: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
controller.province = {};
|
||||||
|
controller.town = {};
|
||||||
|
controller.postcode = {};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
describe('onSubmit()', () => {
|
||||||
|
@ -49,9 +53,30 @@ describe('Client', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('checkExistingClient()', () => {
|
describe('checkExistingClient()', () => {
|
||||||
it('should show a save confirmation when a duplicated client is found and then set the despiteOfClient property', () => {
|
it(`should make a HTTP GET query filtering by email, phone and mobile`, () => {
|
||||||
|
controller.client.mobile = 222222222;
|
||||||
|
const filterObj = {
|
||||||
|
where: {
|
||||||
|
and: [
|
||||||
|
{or: [
|
||||||
|
{email: controller.client.email},
|
||||||
|
{phone: controller.client.phone},
|
||||||
|
{mobile: controller.client.mobile}
|
||||||
|
]},
|
||||||
|
{id: {neq: controller.client.id}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const filter = encodeURIComponent(JSON.stringify(filterObj));
|
||||||
|
$httpBackend.expect('GET', `Clients/findOne?filter=${filter}`).respond(404);
|
||||||
|
controller.checkExistingClient();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should show a save confirmation and then set the despiteOfClient property`, () => {
|
||||||
controller.$.confirmDuplicatedClient = {show: () => {}};
|
controller.$.confirmDuplicatedClient = {show: () => {}};
|
||||||
jest.spyOn(controller.$.confirmDuplicatedClient, 'show');
|
jest.spyOn(controller.$.confirmDuplicatedClient, 'show');
|
||||||
|
|
||||||
const filterObj = {
|
const filterObj = {
|
||||||
where: {
|
where: {
|
||||||
and: [
|
and: [
|
||||||
|
@ -107,5 +132,84 @@ describe('Client', () => {
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('province() setter', () => {
|
||||||
|
it(`should set countryFk property`, () => {
|
||||||
|
controller.province = {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.countryFk).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('town() setter', () => {
|
||||||
|
it(`should set provinceFk property`, () => {
|
||||||
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: []
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.provinceFk).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should set provinceFk property and fill the postalCode if there's just one`, () => {
|
||||||
|
controller.town = {
|
||||||
|
provinceFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
postcodes: [{code: '46001'}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.provinceFk).toEqual(1);
|
||||||
|
expect(controller.client.postcode).toEqual('46001');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('postcode() setter', () => {
|
||||||
|
it(`should set the town, provinceFk and contryFk properties`, () => {
|
||||||
|
controller.postcode = {
|
||||||
|
townFk: 1,
|
||||||
|
code: 46001,
|
||||||
|
town: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New York',
|
||||||
|
province: {
|
||||||
|
id: 1,
|
||||||
|
name: 'New york',
|
||||||
|
country: {
|
||||||
|
id: 2,
|
||||||
|
name: 'USA'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.client.city).toEqual('New York');
|
||||||
|
expect(controller.client.provinceFk).toEqual(1);
|
||||||
|
expect(controller.client.countryFk).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<vn-dialog class="edit"
|
<vn-dialog class="edit"
|
||||||
vn-id="postcodeDialog"
|
vn-id="postcodeDialog"
|
||||||
on-open="$ctrl.onOpen()"
|
on-open="$ctrl.onOpen()"
|
||||||
on-response="$ctrl.onResponse($response)">
|
on-accept="$ctrl.onAccept()">
|
||||||
<tpl-body>
|
<tpl-body>
|
||||||
<h5 class="vn-py-sm" translate>New postcode</h5>
|
<h5 class="vn-py-sm" translate>New postcode</h5>
|
||||||
<p translate>Please, ensure you put the correct data!</p>
|
<p translate>Please, ensure you put the correct data!</p>
|
||||||
|
|
|
@ -35,26 +35,21 @@ class Controller extends Component {
|
||||||
this.$.postcode.focus();
|
this.$.postcode.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
onResponse(response) {
|
onAccept() {
|
||||||
if (response == 'accept') {
|
|
||||||
try {
|
try {
|
||||||
if (!this.data.code)
|
if (!this.data.code)
|
||||||
throw new Error(`The postcode can't be empty`);
|
throw new Error(`The postcode can't be empty`);
|
||||||
if (!this.data.townFk)
|
if (!this.data.townFk)
|
||||||
throw new Error(`The town can't be empty`);
|
throw new Error(`The town can't be empty`);
|
||||||
|
|
||||||
this.$http.patch(`postcodes`, this.data).then(response => {
|
this.$http.patch(`postcodes`, this.data).then(res => {
|
||||||
if (response.data) {
|
|
||||||
this.vnApp.showMessage(this.$translate.instant('The postcode has been saved'));
|
this.vnApp.showMessage(this.$translate.instant('The postcode has been saved'));
|
||||||
|
this.emit('response', {$response: res.data});
|
||||||
this.emit('response', {response: response.data});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.vnApp.showError(this.$translate.instant(e.message));
|
this.vnApp.showError(this.$translate.instant(e.message));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ describe('Client', () => {
|
||||||
controller.client = {id: 101};
|
controller.client = {id: 101};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('onResponse()', () => {
|
describe('onAccept()', () => {
|
||||||
it('should perform a POST query and show a success snackbar', () => {
|
it('should perform a POST query and show a success snackbar', () => {
|
||||||
let params = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
|
let params = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
|
||||||
controller.data = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
|
controller.data = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
|
||||||
|
@ -24,7 +24,7 @@ describe('Client', () => {
|
||||||
$httpBackend.when('PATCH', `postcodes`, params).respond(200, params);
|
$httpBackend.when('PATCH', `postcodes`, params).respond(200, params);
|
||||||
$httpBackend.expect('PATCH', `postcodes`, params).respond(params);
|
$httpBackend.expect('PATCH', `postcodes`, params).respond(params);
|
||||||
|
|
||||||
controller.onResponse('accept');
|
controller.onAccept();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The postcode has been saved');
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The postcode has been saved');
|
||||||
|
|
|
@ -9,18 +9,6 @@
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Client id"
|
|
||||||
ng-model="filter.id">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Tax number"
|
|
||||||
ng-model="filter.fi">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one label="Name"
|
vn-one label="Name"
|
||||||
|
@ -39,6 +27,11 @@
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Tax number"
|
||||||
|
ng-model="filter.fi">
|
||||||
|
</vn-textfield>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
label="Social name"
|
label="Social name"
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
{
|
{
|
||||||
"Entry": {
|
"Entry": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"EntryLog": {
|
||||||
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "EntryLog",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "entryLog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"id": true,
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
|
"originFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"userFk": {
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"creationDate": {
|
||||||
|
"type": "Date"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "userFk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"order": ["creationDate DESC", "id DESC"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "Entry",
|
"name": "Entry",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
|
"log": {
|
||||||
|
"model":"EntryLog"
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "entry"
|
"table": "entry"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
constructor($element, $) {
|
||||||
|
super($element, $);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$element', '$scope'];
|
||||||
|
|
||||||
|
ngModule.component('vnEntryBuy', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
entry: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
Buy: Lineas de entrada
|
|
@ -2,10 +2,10 @@ import ngModule from '../module';
|
||||||
import Component from 'core/lib/component';
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
class Controller extends Component {
|
class Controller extends Component {
|
||||||
constructor($element, $, $httpParamSerializer, vnConfig) {
|
constructor($element, $, $httpParamSerializer) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.vnConfig = vnConfig;
|
|
||||||
this.$httpParamSerializer = $httpParamSerializer;
|
this.$httpParamSerializer = $httpParamSerializer;
|
||||||
|
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{name: 'Show entry report', callback: this.showEntryReport}
|
{name: 'Show entry report', callback: this.showEntryReport}
|
||||||
];
|
];
|
||||||
|
@ -59,6 +59,7 @@ class Controller extends Component {
|
||||||
|
|
||||||
showEntryReport() {
|
showEntryReport() {
|
||||||
const params = {
|
const params = {
|
||||||
|
authorization: this.vnToken.token,
|
||||||
clientId: this.vnConfig.storage.currentUserWorkerId,
|
clientId: this.vnConfig.storage.currentUserWorkerId,
|
||||||
entryId: this.entry.id
|
entryId: this.entry.id
|
||||||
};
|
};
|
||||||
|
@ -68,7 +69,7 @@ class Controller extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', '$httpParamSerializer', 'vnConfig'];
|
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
|
||||||
|
|
||||||
ngModule.component('vnEntryDescriptor', {
|
ngModule.component('vnEntryDescriptor', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -6,3 +6,5 @@ import './search-panel';
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
import './card';
|
import './card';
|
||||||
import './summary';
|
import './summary';
|
||||||
|
import './log';
|
||||||
|
import './buy';
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<vn-log url="EntryLogs" origin-id="$ctrl.$stateParams.id"></vn-log>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
class Controller {
|
||||||
|
constructor($scope, $stateParams) {
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.$stateParams = $stateParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$scope', '$stateParams'];
|
||||||
|
|
||||||
|
ngModule.component('vnEntryLog', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
Date: Fecha
|
|
@ -9,6 +9,8 @@
|
||||||
{"state": "entry.index", "icon": "icon-entry"}
|
{"state": "entry.index", "icon": "icon-entry"}
|
||||||
],
|
],
|
||||||
"card": [
|
"card": [
|
||||||
|
{"state": "entry.card.buy", "icon": "icon-lines"},
|
||||||
|
{"state": "entry.card.log", "icon": "history"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"routes": [
|
"routes": [
|
||||||
|
@ -36,6 +38,19 @@
|
||||||
"params": {
|
"params": {
|
||||||
"entry": "$ctrl.entry"
|
"entry": "$ctrl.entry"
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"url" : "/log",
|
||||||
|
"state": "entry.card.log",
|
||||||
|
"component": "vn-entry-log",
|
||||||
|
"description": "Log"
|
||||||
|
}, {
|
||||||
|
"url" : "/buy",
|
||||||
|
"state": "entry.card.buy",
|
||||||
|
"component": "vn-entry-buy",
|
||||||
|
"description": "Buy",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -10,11 +10,6 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Order id"
|
|
||||||
ng-model="filter.id">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
label="Client id"
|
label="Client id"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Order id: Id pedido
|
Order id: Id cesta
|
||||||
Client id: Id cliente
|
Client id: Id cliente
|
||||||
From landed: Desde f. entrega
|
From landed: Desde f. entrega
|
||||||
To landed: Hasta f. entrega
|
To landed: Hasta f. entrega
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
constructor($element, $scope, $httpParamSerializer) {
|
||||||
|
super($element, $scope);
|
||||||
|
|
||||||
class Controller {
|
|
||||||
constructor($, $http, vnApp, $translate, aclService, $httpParamSerializer) {
|
|
||||||
this.$http = $http;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.$ = $;
|
|
||||||
this.aclService = aclService;
|
|
||||||
this.$httpParamSerializer = $httpParamSerializer;
|
this.$httpParamSerializer = $httpParamSerializer;
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{callback: this.showRouteReport, name: 'Show route report'},
|
{callback: this.showRouteReport, name: 'Show route report'},
|
||||||
|
@ -39,6 +37,7 @@ class Controller {
|
||||||
showRouteReport() {
|
showRouteReport() {
|
||||||
const user = this.route.worker.user;
|
const user = this.route.worker.user;
|
||||||
const params = {
|
const params = {
|
||||||
|
authorization: this.vnToken.token,
|
||||||
clientId: user.id,
|
clientId: user.id,
|
||||||
routeId: this.route.id
|
routeId: this.route.id
|
||||||
};
|
};
|
||||||
|
@ -54,9 +53,7 @@ class Controller {
|
||||||
clientId: user.id,
|
clientId: user.id,
|
||||||
routeId: this.route.id
|
routeId: this.route.id
|
||||||
};
|
};
|
||||||
const serializedParams = this.$httpParamSerializer(params);
|
this.$http.get(`email/driver-route`, {params}).then(() => {
|
||||||
const url = `email/driver-route?${serializedParams}`;
|
|
||||||
this.$http.get(url).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$translate.instant('Report sent'));
|
this.vnApp.showSuccess(this.$translate.instant('Report sent'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -76,7 +73,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate', 'aclService', '$httpParamSerializer'];
|
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
|
||||||
|
|
||||||
ngModule.component('vnRouteDescriptor', {
|
ngModule.component('vnRouteDescriptor', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<vn-crud-model
|
<vn-crud-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="Routes/{{$ctrl.$stateParams.id}}/getTickets"
|
url="Routes/{{$ctrl.$params.id}}/getTickets"
|
||||||
order="priority ASC"
|
order="priority ASC"
|
||||||
data="$ctrl.tickets"
|
data="$ctrl.tickets"
|
||||||
auto-load="true">
|
auto-load="true">
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
</vn-tool-bar>
|
</vn-tool-bar>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-card class="vn-mt-md">
|
<vn-card class="vn-mt-md">
|
||||||
<vn-table model="model" auto-load="false">
|
<vn-table model="model" auto-load="false" vn-droppable="$ctrl.onDrop($event)">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th shrink>
|
<vn-th shrink>
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
translate-attr="::{title: 'Remove ticket'}"
|
translate-attr="{title: 'Remove ticket'}"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
ng-click="$ctrl.showDeleteConfirm(ticket.id)"
|
ng-click="$ctrl.showDeleteConfirm(ticket.id)"
|
||||||
tabindex="-1">
|
tabindex="-1">
|
||||||
|
|
|
@ -1,26 +1,24 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import Section from 'salix/components/section';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller {
|
class Controller extends Section {
|
||||||
constructor($stateParams, $scope, $translate, $http, vnApp, $filter) {
|
constructor($element, $scope, $filter) {
|
||||||
this.$translate = $translate;
|
super($element, $scope);
|
||||||
this.$stateParams = $stateParams;
|
|
||||||
this.$ = $scope;
|
|
||||||
this.$http = $http;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
this.$filter = $filter;
|
this.$filter = $filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get route() {
|
||||||
|
return this._route;
|
||||||
|
}
|
||||||
|
|
||||||
set route(value) {
|
set route(value) {
|
||||||
this._route = value;
|
this._route = value;
|
||||||
if (value)
|
if (value)
|
||||||
this.buildPossibleTicketsFilter();
|
this.buildPossibleTicketsFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
get route() {
|
|
||||||
return this._route;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isChecked() {
|
get isChecked() {
|
||||||
if (this.tickets) {
|
if (this.tickets) {
|
||||||
for (let instance of this.tickets)
|
for (let instance of this.tickets)
|
||||||
|
@ -104,7 +102,6 @@ class Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
showDeleteConfirm(id) {
|
showDeleteConfirm(id) {
|
||||||
this.selectedTicket = id;
|
this.selectedTicket = id;
|
||||||
this.$.confirm.show();
|
this.$.confirm.show();
|
||||||
|
@ -122,7 +119,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVolume() {
|
updateVolume() {
|
||||||
let url = `Routes/${this.$stateParams.id}/updateVolume`;
|
let url = `Routes/${this.$params.id}/updateVolume`;
|
||||||
this.$http.post(url).then(() => {
|
this.$http.post(url).then(() => {
|
||||||
this.card.reload();
|
this.card.reload();
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
|
@ -130,7 +127,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
guessPriority() {
|
guessPriority() {
|
||||||
let query = `Routes/${this.$stateParams.id}/guessPriority/`;
|
let query = `Routes/${this.$params.id}/guessPriority/`;
|
||||||
this.$http.get(query).then(() => {
|
this.$http.get(query).then(() => {
|
||||||
this.vnApp.showSuccess(this.$translate.instant('Order changed'));
|
this.vnApp.showSuccess(this.$translate.instant('Order changed'));
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
|
@ -171,9 +168,39 @@ class Controller {
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDrop($event) {
|
||||||
|
const ticketId = $event.dataTransfer.getData('Text');
|
||||||
|
|
||||||
|
if (isNaN(ticketId)) {
|
||||||
|
const regexp = new RegExp(/\/ticket\/([0-9]+)\//i);
|
||||||
|
const matches = ticketId.match(regexp);
|
||||||
|
|
||||||
|
if (matches && matches.length)
|
||||||
|
this.insert(matches[1]);
|
||||||
|
else
|
||||||
|
this.vnApp.showError(this.$translate.instant('Ticket not found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNaN(ticketId))
|
||||||
|
this.insert(ticketId);
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(id) {
|
||||||
|
const params = {routeFk: this.route.id};
|
||||||
|
this.$http.patch(`Tickets/${id}`, params).then(() => {
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
|
this.$.model.refresh();
|
||||||
|
this.card.reload();
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.status == 404)
|
||||||
|
return this.vnApp.showError(this.$translate.instant('Ticket not found'));
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$translate', '$http', 'vnApp', '$filter'];
|
Controller.$inject = ['$element', '$scope', '$filter'];
|
||||||
|
|
||||||
ngModule.component('vnRouteTickets', {
|
ngModule.component('vnRouteTickets', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
import './index.js';
|
import './index';
|
||||||
|
|
||||||
describe('Route', () => {
|
describe('Route', () => {
|
||||||
let controller;
|
let controller;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
|
let $scope;
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
beforeEach(ngModule('route'));
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
controller = $componentController('vnRouteTickets');
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element('<vn-route-tickets></vn-route-tickets>');
|
||||||
|
controller = $componentController('vnRouteTickets', {$element, $scope});
|
||||||
|
controller.route = {id: 1};
|
||||||
|
controller.$.model = {refresh: () => {}};
|
||||||
|
controller.card = {reload: () => {}};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('route setter/getter', () => {
|
describe('route setter/getter', () => {
|
||||||
|
@ -86,7 +92,6 @@ describe('Route', () => {
|
||||||
|
|
||||||
describe('setPriority()', () => {
|
describe('setPriority()', () => {
|
||||||
it('should set a ticket priority', () => {
|
it('should set a ticket priority', () => {
|
||||||
controller.$.model = {refresh: () => {}};
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
jest.spyOn(controller.$.model, 'refresh');
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
const ticketId = 1;
|
const ticketId = 1;
|
||||||
|
@ -175,16 +180,14 @@ describe('Route', () => {
|
||||||
|
|
||||||
describe('updateVolume()', () => {
|
describe('updateVolume()', () => {
|
||||||
it('should perform a POST query then call both reload and refresh methods', () => {
|
it('should perform a POST query then call both reload and refresh methods', () => {
|
||||||
controller.$.model = {refresh: () => {}};
|
controller.$params = {id: 999};
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
controller.$stateParamds = {id: 999};
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
jest.spyOn(controller.$.model, 'refresh');
|
||||||
jest.spyOn(controller.card, 'reload');
|
jest.spyOn(controller.card, 'reload');
|
||||||
|
|
||||||
let ticketId = 1;
|
let ticketId = 1;
|
||||||
controller.selectedTicket = ticketId;
|
controller.selectedTicket = ticketId;
|
||||||
|
|
||||||
const url = `Routes/${controller.$stateParams.id}/updateVolume`;
|
const url = `Routes/${controller.$params.id}/updateVolume`;
|
||||||
$httpBackend.expectPOST(url).respond('ok');
|
$httpBackend.expectPOST(url).respond('ok');
|
||||||
controller.updateVolume();
|
controller.updateVolume();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
@ -196,12 +199,11 @@ describe('Route', () => {
|
||||||
|
|
||||||
describe('guessPriority()', () => {
|
describe('guessPriority()', () => {
|
||||||
it('should perform a GET query then call both refresh and showSuccess methods', () => {
|
it('should perform a GET query then call both refresh and showSuccess methods', () => {
|
||||||
controller.$.model = {refresh: () => {}};
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
jest.spyOn(controller.$.model, 'refresh');
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
controller.$stateParams = {id: 99};
|
controller.$params = {id: 99};
|
||||||
|
|
||||||
const url = `Routes/${controller.$stateParams.id}/guessPriority/`;
|
const url = `Routes/${controller.$params.id}/guessPriority/`;
|
||||||
$httpBackend.expectGET(url).respond('ok');
|
$httpBackend.expectGET(url).respond('ok');
|
||||||
controller.guessPriority();
|
controller.guessPriority();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
@ -288,4 +290,66 @@ describe('Route', () => {
|
||||||
expect(controller.setTicketsRoute('cancel')).toEqual(jasmine.any(Promise));
|
expect(controller.setTicketsRoute('cancel')).toEqual(jasmine.any(Promise));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onDrop()', () => {
|
||||||
|
it('should call the insert method when dragging a ticket number', () => {
|
||||||
|
jest.spyOn(controller, 'insert');
|
||||||
|
|
||||||
|
const expectedTicketId = '11';
|
||||||
|
const draggedElement = '11';
|
||||||
|
const $event = {
|
||||||
|
dataTransfer: {
|
||||||
|
getData: () => draggedElement
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller.onDrop($event);
|
||||||
|
|
||||||
|
expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the insert method when dragging a ticket link', () => {
|
||||||
|
jest.spyOn(controller, 'insert');
|
||||||
|
|
||||||
|
const expectedTicketId = '11';
|
||||||
|
const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
|
||||||
|
const $event = {
|
||||||
|
dataTransfer: {
|
||||||
|
getData: () => draggedElement
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller.onDrop($event);
|
||||||
|
|
||||||
|
expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when dragging an invalid ticket link', () => {
|
||||||
|
jest.spyOn(controller.vnApp, 'showError');
|
||||||
|
|
||||||
|
const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
|
||||||
|
const $event = {
|
||||||
|
dataTransfer: {
|
||||||
|
getData: () => draggedElement
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller.onDrop($event);
|
||||||
|
|
||||||
|
expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('insert()', () => {
|
||||||
|
it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
|
||||||
|
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
||||||
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
|
||||||
|
const ticketId = 11;
|
||||||
|
|
||||||
|
$httpBackend.expect('PATCH', `Tickets/11`).respond({id: 11});
|
||||||
|
controller.insert(ticketId);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,3 +6,4 @@ Delete ticket from route?: ¿Quitar el ticket de la ruta?
|
||||||
Sort routes: Ordenar rutas
|
Sort routes: Ordenar rutas
|
||||||
Add ticket: Añadir ticket
|
Add ticket: Añadir ticket
|
||||||
Tickets to add: Tickets a añadir
|
Tickets to add: Tickets a añadir
|
||||||
|
Ticket not found: No se ha encontrado el ticket
|
|
@ -34,7 +34,7 @@ describe('ticket-request confirm()', () => {
|
||||||
expect(error.message).toEqual(`That item doesn't exists`);
|
expect(error.message).toEqual(`That item doesn't exists`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should throw an error if the item is not available`, async() => {
|
it('should throw an error if the item is not available', async() => {
|
||||||
const requestId = 5;
|
const requestId = 5;
|
||||||
const itemId = 4;
|
const itemId = 4;
|
||||||
const quantity = 99999;
|
const quantity = 99999;
|
||||||
|
|
|
@ -67,6 +67,10 @@ module.exports = Self => {
|
||||||
arg: 'problems',
|
arg: 'problems',
|
||||||
type: 'Boolean',
|
type: 'Boolean',
|
||||||
description: `Whether to show only tickets with problems`
|
description: `Whether to show only tickets with problems`
|
||||||
|
}, {
|
||||||
|
arg: 'pending',
|
||||||
|
type: 'Boolean',
|
||||||
|
description: `Whether to show only tickets with state 'Pending'`
|
||||||
}, {
|
}, {
|
||||||
arg: 'mine',
|
arg: 'mine',
|
||||||
type: 'Boolean',
|
type: 'Boolean',
|
||||||
|
@ -130,7 +134,7 @@ module.exports = Self => {
|
||||||
dateTo.setHours(23, 59, 0, 0);
|
dateTo.setHours(23, 59, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let where = buildFilter(ctx.args, (param, value) => {
|
const where = buildFilter(ctx.args, (param, value) => {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'search':
|
case 'search':
|
||||||
return /^\d+$/.test(value)
|
return /^\d+$/.test(value)
|
||||||
|
@ -155,6 +159,17 @@ module.exports = Self => {
|
||||||
return {'c.salesPersonFk': {inq: teamIds}};
|
return {'c.salesPersonFk': {inq: teamIds}};
|
||||||
case 'alertLevel':
|
case 'alertLevel':
|
||||||
return {'ts.alertLevel': value};
|
return {'ts.alertLevel': value};
|
||||||
|
case 'pending':
|
||||||
|
if (value) {
|
||||||
|
return {and: [
|
||||||
|
{'st.alertLevel': 0},
|
||||||
|
{'st.code': {neq: 'OK'}}
|
||||||
|
]};
|
||||||
|
} else {
|
||||||
|
return {and: [
|
||||||
|
{'st.alertLevel': {gt: 0}}
|
||||||
|
]};
|
||||||
|
}
|
||||||
case 'id':
|
case 'id':
|
||||||
case 'clientFk':
|
case 'clientFk':
|
||||||
case 'agencyModeFk':
|
case 'agencyModeFk':
|
||||||
|
@ -244,7 +259,6 @@ module.exports = Self => {
|
||||||
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
|
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
|
||||||
LEFT JOIN tmp.ticketTotal tt ON tt.ticketFk = f.id`);
|
LEFT JOIN tmp.ticketTotal tt ON tt.ticketFk = f.id`);
|
||||||
|
|
||||||
|
|
||||||
let condition;
|
let condition;
|
||||||
let hasProblem;
|
let hasProblem;
|
||||||
let range;
|
let range;
|
||||||
|
|
|
@ -32,7 +32,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
let alertLevel = state ? state.alertLevel : null;
|
let alertLevel = state ? state.alertLevel : null;
|
||||||
let ticket = await Self.app.models.Ticket.findById(id, {
|
let ticket = await Self.app.models.Ticket.findById(id, {
|
||||||
fields: ['isDeleted', 'clientFk', 'refFk'],
|
fields: ['clientFk'],
|
||||||
include: [{
|
include: [{
|
||||||
relation: 'client',
|
relation: 'client',
|
||||||
scope: {
|
scope: {
|
||||||
|
@ -42,13 +42,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
const isLocked = await Self.app.models.Ticket.isLocked(id);
|
||||||
|
|
||||||
const isDeleted = ticket && ticket.isDeleted;
|
const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0);
|
||||||
const isOnDelivery = (alertLevel && alertLevel > 0);
|
|
||||||
const isNormalClient = ticket && ticket.client().type().code == 'normal';
|
const isNormalClient = ticket && ticket.client().type().code == 'normal';
|
||||||
const isInvoiced = ticket && ticket.refFk;
|
const validAlertAndRoleNormalClient = (alertLevelGreaterThanZero && isNormalClient && !isValidRole);
|
||||||
|
|
||||||
if (!ticket || isInvoiced || isDeleted || (isOnDelivery && isNormalClient && !isValidRole))
|
if (!ticket || validAlertAndRoleNormalClient || isLocked)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('isLocked', {
|
||||||
|
description: 'Check if a ticket is invoiced or deleted',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'the ticket id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'boolean',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/isLocked`,
|
||||||
|
verb: 'get'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.isLocked = async id => {
|
||||||
|
const ticket = await Self.app.models.Ticket.findById(id, {
|
||||||
|
fields: ['isDeleted', 'refFk']
|
||||||
|
});
|
||||||
|
|
||||||
|
const isDeleted = ticket && ticket.isDeleted;
|
||||||
|
const isInvoiced = ticket && ticket.refFk;
|
||||||
|
|
||||||
|
if (!ticket || isInvoiced || isDeleted)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
|
@ -41,6 +41,34 @@ describe('ticket filter()', () => {
|
||||||
const firstRow = result[0];
|
const firstRow = result[0];
|
||||||
|
|
||||||
expect(result.length).toEqual(1);
|
expect(result.length).toEqual(1);
|
||||||
expect(firstRow.ticketFk).toEqual(11);
|
expect(firstRow.id).toEqual(11);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the tickets with grouped state "Pending" and not "Ok"', async() => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 9}}, args: {pending: true}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
const firstRow = result[0];
|
||||||
|
const secondRow = result[1];
|
||||||
|
const thirdRow = result[2];
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
expect(firstRow.state).toEqual('Arreglar');
|
||||||
|
expect(secondRow.state).toEqual('Arreglar');
|
||||||
|
expect(thirdRow.state).toEqual('Arreglar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the tickets that are not pending', async() => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 9}}, args: {pending: false}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
const firstRow = result[0];
|
||||||
|
const secondRow = result[1];
|
||||||
|
const thirdRow = result[2];
|
||||||
|
|
||||||
|
expect(result.length).toEqual(13);
|
||||||
|
expect(firstRow.state).toEqual('Entregado');
|
||||||
|
expect(secondRow.state).toEqual('Entregado');
|
||||||
|
expect(thirdRow.state).toEqual('Entregado');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('ticket isEditable()', () => {
|
describe('ticket isEditable()', () => {
|
||||||
it('should return false if the given ticket is not editable', async() => {
|
|
||||||
let ctx = {req: {accessToken: {userId: 9}}};
|
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 2);
|
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if the given ticket does not exist', async() => {
|
it('should return false if the given ticket does not exist', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 9}}};
|
let ctx = {req: {accessToken: {userId: 9}}};
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 99999);
|
let result = await app.models.Ticket.isEditable(ctx, 99999);
|
||||||
|
@ -15,37 +8,46 @@ describe('ticket isEditable()', () => {
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if the given ticket isDeleted', async() => {
|
it(`should return false if the given ticket isn't invoiced but isDeleted`, async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 9}}};
|
let ctx = {req: {accessToken: {userId: 9}}};
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 19);
|
let deletedTicket = await app.models.Ticket.findOne({
|
||||||
|
where: {
|
||||||
|
invoiceOut: null,
|
||||||
|
isDeleted: true
|
||||||
|
},
|
||||||
|
fields: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = await app.models.Ticket.isEditable(ctx, deletedTicket.id);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if the given ticket is editable', async() => {
|
it('should return true if the given ticket is editable', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 9}}};
|
let ctx = {req: {accessToken: {userId: 9}}};
|
||||||
|
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 16);
|
let result = await app.models.Ticket.isEditable(ctx, 16);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to edit a deleted or invoiced ticket if the role is salesAssistant', async() => {
|
it('should not be able to edit a deleted or invoiced ticket even for salesAssistant', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 21}}};
|
let ctx = {req: {accessToken: {userId: 21}}};
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 8);
|
let result = await app.models.Ticket.isEditable(ctx, 19);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to edit a deleted or invoiced ticket if the role is productionBoss', async() => {
|
it('should not be able to edit a deleted or invoiced ticket even for productionBoss', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 50}}};
|
let ctx = {req: {accessToken: {userId: 50}}};
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 8);
|
let result = await app.models.Ticket.isEditable(ctx, 19);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be able to edit a deleted or invoiced ticket if the role is salesPerson', async() => {
|
it('should not be able to edit a deleted or invoiced ticket even for salesPerson', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 18}}};
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
let result = await app.models.Ticket.isEditable(ctx, 8);
|
let result = await app.models.Ticket.isEditable(ctx, 19);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('ticket isLocked()', () => {
|
||||||
|
it('should return true if the given ticket does not exist', async() => {
|
||||||
|
let result = await app.models.Ticket.isLocked(99999);
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if the given ticket is invoiced', async() => {
|
||||||
|
let invoicedTicket = await app.models.Ticket.findOne({
|
||||||
|
where: {invoiceOut: {neq: null}},
|
||||||
|
fields: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = await app.models.Ticket.isLocked(invoicedTicket.id);
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return true if the given ticket isn't invoiced but deleted`, async() => {
|
||||||
|
let deletedTicket = await app.models.Ticket.findOne({
|
||||||
|
where: {
|
||||||
|
invoiceOut: null,
|
||||||
|
isDeleted: true
|
||||||
|
},
|
||||||
|
fields: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = await app.models.Ticket.isLocked(deletedTicket.id);
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,13 +3,22 @@ const app = require('vn-loopback/server/server');
|
||||||
describe('ticket makeInvoice()', () => {
|
describe('ticket makeInvoice()', () => {
|
||||||
let invoice;
|
let invoice;
|
||||||
let ticketId = 11;
|
let ticketId = 11;
|
||||||
|
const okState = 3;
|
||||||
|
|
||||||
afterAll(async done => {
|
afterAll(async done => {
|
||||||
let ticket = await app.models.Ticket.findById(11);
|
let ticket = await app.models.Ticket.findById(11);
|
||||||
await ticket.updateAttributes({refFk: null});
|
await ticket.updateAttributes({refFk: null});
|
||||||
|
|
||||||
let ticketTracking = await app.models.TicketTracking.findOne({order: 'id DESC', limit: 1});
|
let ticketTrackings = await app.models.TicketTracking.find({
|
||||||
await ticketTracking.destroy();
|
where: {
|
||||||
|
ticketFk: ticketId,
|
||||||
|
stateFk: {neq: okState}
|
||||||
|
},
|
||||||
|
order: 'id DESC'
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let state of ticketTrackings)
|
||||||
|
await state.destroy();
|
||||||
|
|
||||||
let invoiceOut = await app.models.InvoiceOut.findById(invoice.invoiceFk);
|
let invoiceOut = await app.models.InvoiceOut.findById(invoice.invoiceFk);
|
||||||
await invoiceOut.destroy();
|
await invoiceOut.destroy();
|
||||||
|
|
|
@ -35,6 +35,7 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.updateDiscount = async(ctx, id, salesIds, newDiscount) => {
|
Self.updateDiscount = async(ctx, id, salesIds, newDiscount) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const tx = await Self.beginTransaction({});
|
const tx = await Self.beginTransaction({});
|
||||||
|
|
||||||
|
@ -68,8 +69,14 @@ module.exports = Self => {
|
||||||
if (!allFromSameTicket)
|
if (!allFromSameTicket)
|
||||||
throw new UserError('All sales must belong to the same ticket');
|
throw new UserError('All sales must belong to the same ticket');
|
||||||
|
|
||||||
const isEditable = await models.Ticket.isEditable(ctx, id);
|
const isLocked = await models.Ticket.isLocked(id);
|
||||||
if (!isEditable)
|
const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson');
|
||||||
|
const state = await Self.app.models.TicketState.findOne({
|
||||||
|
where: {ticketFk: id}
|
||||||
|
});
|
||||||
|
const alertLevel = state ? state.alertLevel : null;
|
||||||
|
|
||||||
|
if (isLocked || (!isSalesPerson && alertLevel > 0 ))
|
||||||
throw new UserError(`The sales of this ticket can't be modified`);
|
throw new UserError(`The sales of this ticket can't be modified`);
|
||||||
|
|
||||||
const ticket = await models.Ticket.findById(id, {
|
const ticket = await models.Ticket.findById(id, {
|
||||||
|
|
|
@ -29,6 +29,7 @@ module.exports = Self => {
|
||||||
require('../methods/ticket/recalculateComponents')(Self);
|
require('../methods/ticket/recalculateComponents')(Self);
|
||||||
require('../methods/ticket/deleteStowaway')(Self);
|
require('../methods/ticket/deleteStowaway')(Self);
|
||||||
require('../methods/ticket/sendSms')(Self);
|
require('../methods/ticket/sendSms')(Self);
|
||||||
|
require('../methods/ticket/isLocked')(Self);
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
Self.observe('before save', async function(ctx) {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Controller {
|
||||||
|
|
||||||
if (!value || !value.id) return;
|
if (!value || !value.id) return;
|
||||||
|
|
||||||
this.onChangeClient(value.clientFk);
|
this.clientAddressesList(value.clientFk);
|
||||||
}
|
}
|
||||||
|
|
||||||
get clientId() {
|
get clientId() {
|
||||||
|
@ -33,7 +33,10 @@ class Controller {
|
||||||
this.ticket.clientFk = value;
|
this.ticket.clientFk = value;
|
||||||
this.ticket.addressFk = null;
|
this.ticket.addressFk = null;
|
||||||
|
|
||||||
this.onChangeClient(value);
|
if (!value) return;
|
||||||
|
|
||||||
|
this.getClientDefaultAddress(value);
|
||||||
|
this.clientAddressesList(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
get addressId() {
|
get addressId() {
|
||||||
|
@ -68,7 +71,6 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
get shipped() {
|
get shipped() {
|
||||||
return this.ticket && this.ticket.shipped;
|
return this.ticket && this.ticket.shipped;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +129,7 @@ class Controller {
|
||||||
/*
|
/*
|
||||||
* Autocompletes address on client change
|
* Autocompletes address on client change
|
||||||
*/
|
*/
|
||||||
onChangeClient(value) {
|
clientAddressesList(value) {
|
||||||
let filter = {
|
let filter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -153,6 +155,14 @@ class Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getClientDefaultAddress(value) {
|
||||||
|
let query = `Clients/${value}`;
|
||||||
|
this.$http.get(query).then(res => {
|
||||||
|
if (res.data)
|
||||||
|
this.ticket.addressFk = res.data.defaultAddressFk;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets an agency from an specified zone
|
* Gets an agency from an specified zone
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,18 +22,18 @@ describe('Ticket', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('ticket() setter', () => {
|
describe('ticket() setter', () => {
|
||||||
it('should set ticket property and call onChangeClient() method', () => {
|
it('should set ticket property and call clientAddressesList() method', () => {
|
||||||
jest.spyOn(controller, 'onChangeClient');
|
jest.spyOn(controller, 'clientAddressesList');
|
||||||
controller.ticket = {id: 1, clientFk: 101};
|
controller.ticket = {id: 1, clientFk: 101};
|
||||||
|
|
||||||
expect(controller.onChangeClient).toHaveBeenCalledWith(101);
|
expect(controller.clientAddressesList).toHaveBeenCalledWith(101);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should not call onChangeClient() method as the ticket doesn't have an ID`, () => {
|
it(`should not call clientAddressesList() method as the ticket doesn't have an ID`, () => {
|
||||||
jest.spyOn(controller, 'onChangeClient');
|
jest.spyOn(controller, 'clientAddressesList');
|
||||||
controller.ticket = {};
|
controller.ticket = {};
|
||||||
|
|
||||||
expect(controller.onChangeClient).not.toHaveBeenCalledWith();
|
expect(controller.clientAddressesList).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -46,12 +46,12 @@ describe('Ticket', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('clientId() setter', () => {
|
describe('clientId() setter', () => {
|
||||||
it('should set clientId property and call onChangeClient() method ', () => {
|
it('should set clientId property and call clientAddressesList() method ', () => {
|
||||||
jest.spyOn(controller, 'onChangeClient');
|
jest.spyOn(controller, 'clientAddressesList');
|
||||||
controller.ticket = {id: 1, clientId: 101};
|
controller.ticket = {id: 1, clientId: 101};
|
||||||
controller.clientId = 102;
|
controller.clientId = 102;
|
||||||
|
|
||||||
expect(controller.onChangeClient).toHaveBeenCalledWith(102);
|
expect(controller.clientAddressesList).toHaveBeenCalledWith(102);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -155,7 +155,6 @@ describe('Ticket', () => {
|
||||||
};
|
};
|
||||||
controller.landed = landed;
|
controller.landed = landed;
|
||||||
|
|
||||||
|
|
||||||
expect(controller.getShipped).toHaveBeenCalledWith(expectedResult);
|
expect(controller.getShipped).toHaveBeenCalledWith(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -230,7 +229,7 @@ describe('Ticket', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onChangeClient()', () => {
|
describe('clientAddressesList()', () => {
|
||||||
it('should return a list of addresses from choosed client', async() => {
|
it('should return a list of addresses from choosed client', async() => {
|
||||||
const clientId = 102;
|
const clientId = 102;
|
||||||
let filter = {
|
let filter = {
|
||||||
|
@ -253,7 +252,18 @@ describe('Ticket', () => {
|
||||||
|
|
||||||
$httpBackend.when('GET', `Clients/${clientId}/addresses?filter=${filter}`).respond(200);
|
$httpBackend.when('GET', `Clients/${clientId}/addresses?filter=${filter}`).respond(200);
|
||||||
$httpBackend.expect('GET', `Clients/${clientId}/addresses?filter=${filter}`);
|
$httpBackend.expect('GET', `Clients/${clientId}/addresses?filter=${filter}`);
|
||||||
controller.onChangeClient(clientId);
|
controller.clientAddressesList(clientId);
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getClientDefaultAddress()', () => {
|
||||||
|
it('should return the default address from choosed client', async() => {
|
||||||
|
const clientId = 102;
|
||||||
|
|
||||||
|
$httpBackend.when('GET', `Clients/${clientId}`).respond(200);
|
||||||
|
$httpBackend.expect('GET', `Clients/${clientId}`);
|
||||||
|
controller.getClientDefaultAddress(clientId);
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,3 +2,4 @@ Price (PPU): Precio (Ud.)
|
||||||
New (PPU): Nuevo (Ud.)
|
New (PPU): Nuevo (Ud.)
|
||||||
Difference: Diferencia
|
Difference: Diferencia
|
||||||
Charge difference to: Cargar diferencia a
|
Charge difference to: Cargar diferencia a
|
||||||
|
The ticket has been unrouted: El ticket ha sido desenrutado
|
|
@ -2,10 +2,10 @@ import ngModule from '../module';
|
||||||
import Component from 'core/lib/component';
|
import Component from 'core/lib/component';
|
||||||
|
|
||||||
class Controller extends Component {
|
class Controller extends Component {
|
||||||
constructor($element, $, aclService, $httpParamSerializer) {
|
constructor($element, $, $httpParamSerializer) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.aclService = aclService;
|
|
||||||
this.$httpParamSerializer = $httpParamSerializer;
|
this.$httpParamSerializer = $httpParamSerializer;
|
||||||
|
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{
|
{
|
||||||
name: 'Add turn',
|
name: 'Add turn',
|
||||||
|
@ -220,7 +220,8 @@ class Controller extends Component {
|
||||||
showDeliveryNote() {
|
showDeliveryNote() {
|
||||||
const params = {
|
const params = {
|
||||||
clientId: this.ticket.client.id,
|
clientId: this.ticket.client.id,
|
||||||
ticketId: this.ticket.id
|
ticketId: this.ticket.id,
|
||||||
|
authorization: this.vnToken.token
|
||||||
};
|
};
|
||||||
const serializedParams = this.$httpParamSerializer(params);
|
const serializedParams = this.$httpParamSerializer(params);
|
||||||
let url = `api/report/delivery-note?${serializedParams}`;
|
let url = `api/report/delivery-note?${serializedParams}`;
|
||||||
|
@ -332,7 +333,7 @@ class Controller extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'aclService', '$httpParamSerializer'];
|
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
|
||||||
|
|
||||||
ngModule.component('vnTicketDescriptor', {
|
ngModule.component('vnTicketDescriptor', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -51,11 +51,6 @@
|
||||||
{{::document.dms.description}}
|
{{::document.dms.description}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>
|
|
||||||
<vn-check disabled="true"
|
|
||||||
field="document.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<a target="_blank"
|
<a target="_blank"
|
||||||
title="{{'Download file' | translate}}"
|
title="{{'Download file' | translate}}"
|
||||||
|
|
|
@ -8,17 +8,6 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-auto-search
|
<vn-auto-search
|
||||||
on-search="$ctrl.onSearch($params)">
|
on-search="$ctrl.onSearch($params)">
|
||||||
<append style="display: none;">
|
|
||||||
<vn-icon-menu
|
|
||||||
vn-id="more-button"
|
|
||||||
icon="more_vert"
|
|
||||||
show-filter="false"
|
|
||||||
value-field="callback"
|
|
||||||
translate-fields="['name']"
|
|
||||||
on-change="$ctrl.onMoreChange(value)"
|
|
||||||
on-open="$ctrl.onMoreOpen()">
|
|
||||||
</vn-icon-menu>
|
|
||||||
</append>
|
|
||||||
</vn-auto-search>
|
</vn-auto-search>
|
||||||
<vn-data-viewer
|
<vn-data-viewer
|
||||||
model="model"
|
model="model"
|
||||||
|
@ -137,13 +126,28 @@
|
||||||
</vn-table>
|
</vn-table>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
</vn-data-viewer>
|
</vn-data-viewer>
|
||||||
<a
|
|
||||||
ui-sref="ticket.create"
|
<div fixed-bottom-right>
|
||||||
vn-tooltip="New ticket"
|
<vn-vertical style="align-items: center;">
|
||||||
|
<vn-button class="round message xs vn-mb-sm"
|
||||||
|
icon="icon-recovery"
|
||||||
|
ng-show="$ctrl.totalChecked > 0"
|
||||||
|
ng-click="$ctrl.openBalanceDialog()"
|
||||||
|
vn-tooltip="Payment on account..."
|
||||||
|
tooltip-position="left">
|
||||||
|
</vn-button>
|
||||||
|
|
||||||
|
<a ui-sref="ticket.create">
|
||||||
|
<vn-button class="round md vn-mb-sm"
|
||||||
|
icon="add"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
fixed-bottom-right>
|
vn-tooltip="New ticket"
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
tooltip-position="left">
|
||||||
</a>
|
</vn-button>
|
||||||
|
</a>
|
||||||
|
</vn-vertical>
|
||||||
|
</div>
|
||||||
|
|
||||||
<vn-popup vn-id="summary">
|
<vn-popup vn-id="summary">
|
||||||
<vn-ticket-summary ticket="$ctrl.selectedTicket"></vn-ticket-summary>
|
<vn-ticket-summary ticket="$ctrl.selectedTicket"></vn-ticket-summary>
|
||||||
</vn-popup>
|
</vn-popup>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import UserError from 'core/lib/user-error';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
|
@ -9,33 +10,45 @@ export default class Controller {
|
||||||
this.$stateParams = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.selectedTicket = null;
|
this.selectedTicket = null;
|
||||||
this.moreOptions = [
|
|
||||||
{
|
|
||||||
name: 'Payment on account...',
|
|
||||||
always: true,
|
|
||||||
callback: () => {
|
|
||||||
this.setBalanceCreateDialog();
|
|
||||||
this.$.balanceCreateDialog.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setBalanceCreateDialog() {
|
openBalanceDialog() {
|
||||||
let data = this.$.tickets;
|
const checkedTickets = this.checked;
|
||||||
let description = [];
|
const description = [];
|
||||||
this.$.balanceCreateDialog.amountPaid = 0;
|
this.$.balanceCreateDialog.amountPaid = 0;
|
||||||
if (data) {
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
const firstTicketClientId = checkedTickets[0].clientFk;
|
||||||
if (data[i].checked) {
|
const isSameClient = checkedTickets.every(ticket => {
|
||||||
this.$.balanceCreateDialog.amountPaid += data[i].total;
|
return ticket.clientFk == firstTicketClientId;
|
||||||
this.$.balanceCreateDialog.clientFk = data[i].clientFk;
|
});
|
||||||
description.push(`${data[i].id}`);
|
|
||||||
}
|
if (!isSameClient)
|
||||||
}
|
throw new UserError('You cannot make a payment on account from multiple clients');
|
||||||
|
|
||||||
|
for (let ticket of checkedTickets) {
|
||||||
|
this.$.balanceCreateDialog.amountPaid += ticket.total;
|
||||||
|
this.$.balanceCreateDialog.clientFk = ticket.clientFk;
|
||||||
|
description.push(`${ticket.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$.balanceCreateDialog.description = 'Albaran: ';
|
this.$.balanceCreateDialog.description = 'Albaran: ';
|
||||||
this.$.balanceCreateDialog.description += description.join(', ');
|
this.$.balanceCreateDialog.description += description.join(', ');
|
||||||
|
this.$.balanceCreateDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
get checked() {
|
||||||
|
const tickets = this.$.tickets || [];
|
||||||
|
const checkedLines = [];
|
||||||
|
for (let ticket of tickets) {
|
||||||
|
if (ticket.checked)
|
||||||
|
checkedLines.push(ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkedLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalChecked() {
|
||||||
|
return this.checked.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
getScopeDates(days) {
|
getScopeDates(days) {
|
||||||
|
@ -51,7 +64,7 @@ export default class Controller {
|
||||||
|
|
||||||
onSearch(params) {
|
onSearch(params) {
|
||||||
if (params) {
|
if (params) {
|
||||||
if (typeof(params.scopeDays) === 'number')
|
if (typeof (params.scopeDays) === 'number')
|
||||||
Object.assign(params, this.getScopeDates(params.scopeDays));
|
Object.assign(params, this.getScopeDates(params.scopeDays));
|
||||||
// Set default params to 1 scope days
|
// Set default params to 1 scope days
|
||||||
else if (Object.entries(params).length == 0)
|
else if (Object.entries(params).length == 0)
|
||||||
|
|
|
@ -82,12 +82,14 @@ describe('Component vnTicketIndex', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setBalanceCreateDialog()', () => {
|
describe('openBalanceDialog()', () => {
|
||||||
it('should fill the object for the component balanceCreateDialog', () => {
|
it('should fill the object for the component balanceCreateDialog', () => {
|
||||||
|
controller.$.balanceCreateDialog = {show: () => {}};
|
||||||
|
jest.spyOn(controller.$.balanceCreateDialog, 'show').mockReturnThis();
|
||||||
|
|
||||||
controller.$.tickets = tickets;
|
controller.$.tickets = tickets;
|
||||||
controller.$.balanceCreateDialog = {};
|
|
||||||
controller.$.balanceCreateDialog.amountPaid = 0;
|
controller.$.balanceCreateDialog.amountPaid = 0;
|
||||||
controller.setBalanceCreateDialog();
|
controller.openBalanceDialog();
|
||||||
|
|
||||||
let description = controller.$.balanceCreateDialog.description;
|
let description = controller.$.balanceCreateDialog.description;
|
||||||
let amountPaid = controller.$.balanceCreateDialog.amountPaid;
|
let amountPaid = controller.$.balanceCreateDialog.amountPaid;
|
||||||
|
@ -96,4 +98,26 @@ describe('Component vnTicketIndex', () => {
|
||||||
expect(amountPaid).toEqual(50.5);
|
expect(amountPaid).toEqual(50.5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('checked()', () => {
|
||||||
|
it('should return an array of checked tickets', () => {
|
||||||
|
controller.$.tickets = tickets;
|
||||||
|
const result = controller.checked;
|
||||||
|
const firstRow = result[0];
|
||||||
|
const secondRow = result[1];
|
||||||
|
|
||||||
|
expect(result.length).toEqual(2);
|
||||||
|
expect(firstRow.id).toEqual(2);
|
||||||
|
expect(secondRow.id).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('totalChecked()', () => {
|
||||||
|
it('should return the total number of checked tickets', () => {
|
||||||
|
controller.$.tickets = tickets;
|
||||||
|
const result = controller.checked;
|
||||||
|
|
||||||
|
expect(result.length).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -165,8 +165,8 @@
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>
|
<vn-td number>
|
||||||
<span ng-class="{'link': $ctrl.isEditable}"
|
<span ng-class="{'link': !$ctrl.isLocked}"
|
||||||
title="{{$ctrl.isEditable ? 'Edit discount' : ''}}"
|
title="{{!$ctrl.isLocked ? 'Edit discount' : ''}}"
|
||||||
ng-click="$ctrl.showEditDiscountPopover($event, sale)">
|
ng-click="$ctrl.showEditDiscountPopover($event, sale)">
|
||||||
{{(sale.discount / 100) | percentage}}
|
{{(sale.discount / 100) | percentage}}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -46,6 +46,7 @@ class Controller {
|
||||||
set ticket(value) {
|
set ticket(value) {
|
||||||
this._ticket = value;
|
this._ticket = value;
|
||||||
this.isTicketEditable();
|
this.isTicketEditable();
|
||||||
|
this.isTicketLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
get sales() {
|
get sales() {
|
||||||
|
@ -354,7 +355,7 @@ class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
showEditDiscountPopover(event, sale) {
|
showEditDiscountPopover(event, sale) {
|
||||||
if (!this.isEditable) return;
|
if (this.isLocked) return;
|
||||||
|
|
||||||
this.sale = sale;
|
this.sale = sale;
|
||||||
this.edit = [{
|
this.edit = [{
|
||||||
|
@ -540,6 +541,12 @@ class Controller {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTicketLocked() {
|
||||||
|
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`).then(res => {
|
||||||
|
this.isLocked = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
hasOneSaleSelected() {
|
hasOneSaleSelected() {
|
||||||
if (this.totalCheckedLines() === 1)
|
if (this.totalCheckedLines() === 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue