Merge branch 'dev' into 7912-wasteCost
gitea/salix/pipeline/pr-dev This commit looks good
Details
gitea/salix/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
3871c9c505
|
@ -18,14 +18,13 @@ BEGIN
|
||||||
* Solo retorna el primer problema, en caso de no ocurrir ningún error se añadirá
|
* Solo retorna el primer problema, en caso de no ocurrir ningún error se añadirá
|
||||||
* fichada a la tabla vn.workerTimeControl
|
* fichada a la tabla vn.workerTimeControl
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DECLARE vLastIn DATETIME;
|
DECLARE vLastIn DATETIME;
|
||||||
DECLARE vLastOut DATETIME;
|
DECLARE vLastOut DATETIME;
|
||||||
DECLARE vNextIn DATETIME;
|
DECLARE vNextIn DATETIME;
|
||||||
DECLARE vNextOut DATETIME;
|
DECLARE vNextOut DATETIME;
|
||||||
DECLARE vNextDirection ENUM('in', 'out');
|
DECLARE vNextDirection ENUM('in', 'out');
|
||||||
DECLARE vLastDirection ENUM('in', 'out');
|
DECLARE vLastDirection ENUM('in', 'out');
|
||||||
DECLARE vDayMaxTime INTEGER;
|
DECLARE vDayMaxTime INTEGER;
|
||||||
DECLARE vDayBreak INT;
|
DECLARE vDayBreak INT;
|
||||||
DECLARE vShortWeekBreak INT;
|
DECLARE vShortWeekBreak INT;
|
||||||
DECLARE vLongWeekBreak INT;
|
DECLARE vLongWeekBreak INT;
|
||||||
|
@ -40,6 +39,7 @@ BEGIN
|
||||||
DECLARE vIsManual BOOLEAN DEFAULT TRUE;
|
DECLARE vIsManual BOOLEAN DEFAULT TRUE;
|
||||||
DECLARE vMaxWorkShortCycle INT;
|
DECLARE vMaxWorkShortCycle INT;
|
||||||
DECLARE vMaxWorkLongCycle INT;
|
DECLARE vMaxWorkLongCycle INT;
|
||||||
|
DECLARE vReentryWaitTime TIME DEFAULT NULL;
|
||||||
|
|
||||||
DECLARE EXIT HANDLER FOR SQLSTATE '45000'
|
DECLARE EXIT HANDLER FOR SQLSTATE '45000'
|
||||||
BEGIN
|
BEGIN
|
||||||
|
@ -52,19 +52,19 @@ BEGIN
|
||||||
WHERE w.id = vWorkerFk;
|
WHERE w.id = vWorkerFk;
|
||||||
|
|
||||||
SELECT `description` INTO vErrorMessage
|
SELECT `description` INTO vErrorMessage
|
||||||
FROM workerTimeControlError
|
FROM workerTimeControlError
|
||||||
WHERE `code` = vErrorCode;
|
WHERE `code` = vErrorCode;
|
||||||
|
|
||||||
IF vErrorMessage IS NULL THEN
|
IF vErrorMessage IS NULL THEN
|
||||||
SET vErrorMessage = 'Error sin definir';
|
SET vErrorMessage = 'Error sin definir';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT vErrorMessage `error`;
|
SELECT CONCAT(vErrorMessage, IFNULL(DATE_FORMAT(vReentryWaitTime, '%i:%s'), '')) `error`;
|
||||||
SELECT CONCAT(vUserName,
|
SELECT CONCAT(vUserName,
|
||||||
' no ha podido fichar por el siguiente problema: ',
|
' no ha podido fichar por el siguiente problema: ',
|
||||||
vErrorMessage)
|
vErrorMessage)
|
||||||
INTO vErrorMessage;
|
INTO vErrorMessage;
|
||||||
|
|
||||||
CALL mail_insert( vMailTo, vMailTo, 'Error al fichar', vErrorMessage);
|
CALL mail_insert( vMailTo, vMailTo, 'Error al fichar', vErrorMessage);
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
@ -97,19 +97,19 @@ BEGIN
|
||||||
JOIN workerTimeControlConfig wc
|
JOIN workerTimeControlConfig wc
|
||||||
WHERE b.workerFk = vWorkerFk
|
WHERE b.workerFk = vWorkerFk
|
||||||
AND vDated BETWEEN b.started AND IFNULL(b.ended, vDated);
|
AND vDated BETWEEN b.started AND IFNULL(b.ended, vDated);
|
||||||
|
|
||||||
-- CONTRATO EN VIGOR
|
-- CONTRATO EN VIGOR
|
||||||
IF vDayBreak IS NULL THEN
|
IF vDayBreak IS NULL THEN
|
||||||
SET vErrorCode = 'INACTIVE_BUSINESS';
|
SET vErrorCode = 'INACTIVE_BUSINESS';
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- FICHADAS A FUTURO
|
-- FICHADAS A FUTURO
|
||||||
IF vTimed > util.VN_NOW() + INTERVAL 1 MINUTE THEN
|
IF vTimed > util.VN_NOW() + INTERVAL 1 MINUTE THEN
|
||||||
SET vErrorCode = 'IS_NOT_ALLOWED_FUTURE';
|
SET vErrorCode = 'IS_NOT_ALLOWED_FUTURE';
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- VERIFICAR SI ESTÁ PERMITIDO TRABAJAR
|
-- VERIFICAR SI ESTÁ PERMITIDO TRABAJAR
|
||||||
CALL timeBusiness_calculateByWorker(vWorkerFk, vDated, vDated);
|
CALL timeBusiness_calculateByWorker(vWorkerFk, vDated, vDated);
|
||||||
SELECT isAllowedToWork INTO vIsAllowedToWork
|
SELECT isAllowedToWork INTO vIsAllowedToWork
|
||||||
|
@ -124,6 +124,16 @@ BEGIN
|
||||||
|
|
||||||
-- DIRECCION CORRECTA
|
-- DIRECCION CORRECTA
|
||||||
CALL workerTimeControl_direction(vWorkerFk, vTimed);
|
CALL workerTimeControl_direction(vWorkerFk, vTimed);
|
||||||
|
|
||||||
|
SELECT reentryWaitTime INTO vReentryWaitTime
|
||||||
|
FROM tmp.workerTimeControlDirection
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF vReentryWaitTime IS NOT NULL THEN
|
||||||
|
SET vErrorCode = 'WAIT_TIME';
|
||||||
|
CALL util.throw(vErrorCode);
|
||||||
|
END IF;
|
||||||
|
|
||||||
IF (SELECT
|
IF (SELECT
|
||||||
IF((IF(option1 IN ('inMiddle', 'outMiddle'),
|
IF((IF(option1 IN ('inMiddle', 'outMiddle'),
|
||||||
'middle',
|
'middle',
|
||||||
|
@ -138,13 +148,13 @@ BEGIN
|
||||||
) THEN
|
) THEN
|
||||||
SET vIsError = TRUE;
|
SET vIsError = TRUE;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
|
||||||
IF vIsError THEN
|
IF vIsError THEN
|
||||||
SET vErrorCode = 'WRONG_DIRECTION';
|
SET vErrorCode = 'WRONG_DIRECTION';
|
||||||
IF(SELECT option1 IS NULL AND option2 IS NULL
|
IF(SELECT option1 IS NULL AND option2 IS NULL
|
||||||
FROM tmp.workerTimeControlDirection) THEN
|
FROM tmp.workerTimeControlDirection) THEN
|
||||||
|
|
||||||
SET vErrorCode = 'DAY_MAX_TIME';
|
SET vErrorCode = 'DAY_MAX_TIME';
|
||||||
END IF;
|
END IF;
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
|
@ -158,7 +168,7 @@ BEGIN
|
||||||
AND timed < vTimed
|
AND timed < vTimed
|
||||||
ORDER BY timed DESC
|
ORDER BY timed DESC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
IF (SELECT IF(vDirection = 'in',
|
IF (SELECT IF(vDirection = 'in',
|
||||||
MOD(COUNT(*), 2) ,
|
MOD(COUNT(*), 2) ,
|
||||||
IF (vDirection = 'out', NOT MOD(COUNT(*), 2), FALSE))
|
IF (vDirection = 'out', NOT MOD(COUNT(*), 2), FALSE))
|
||||||
|
@ -169,7 +179,7 @@ BEGIN
|
||||||
SET vErrorCode = 'ODD_WORKERTIMECONTROL';
|
SET vErrorCode = 'ODD_WORKERTIMECONTROL';
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- DESCANSO DIARIO
|
-- DESCANSO DIARIO
|
||||||
SELECT timed INTO vLastOut
|
SELECT timed INTO vLastOut
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
|
@ -178,7 +188,7 @@ BEGIN
|
||||||
AND timed < vTimed
|
AND timed < vTimed
|
||||||
ORDER BY timed DESC
|
ORDER BY timed DESC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
SELECT timed INTO vNextIn
|
SELECT timed INTO vNextIn
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
|
@ -186,7 +196,7 @@ BEGIN
|
||||||
AND timed > vTimed
|
AND timed > vTimed
|
||||||
ORDER BY timed ASC
|
ORDER BY timed ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
CASE vDirection
|
CASE vDirection
|
||||||
WHEN 'in' THEN
|
WHEN 'in' THEN
|
||||||
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) <= vDayBreak THEN
|
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) <= vDayBreak THEN
|
||||||
|
@ -204,11 +214,9 @@ BEGIN
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IF (vDirection IN('in', 'out')) THEN
|
IF (vDirection IN('in', 'out')) THEN
|
||||||
-- VERIFICA MAXIMO TIEMPO DESDE ENTRADA HASTA LA SALIDA
|
-- VERIFICA MAXIMO TIEMPO DESDE ENTRADA HASTA LA SALIDA
|
||||||
|
|
||||||
SELECT timed INTO vNextOut
|
SELECT timed INTO vNextOut
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
|
@ -216,7 +224,7 @@ BEGIN
|
||||||
AND timed > vTimed
|
AND timed > vTimed
|
||||||
ORDER BY timed ASC
|
ORDER BY timed ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
SELECT direction INTO vNextDirection
|
SELECT direction INTO vNextDirection
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
|
@ -224,7 +232,7 @@ BEGIN
|
||||||
AND timed > vTimed
|
AND timed > vTimed
|
||||||
ORDER BY timed ASC
|
ORDER BY timed ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
SELECT direction INTO vLastDirection
|
SELECT direction INTO vLastDirection
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
|
@ -232,34 +240,34 @@ BEGIN
|
||||||
AND timed < vTimed
|
AND timed < vTimed
|
||||||
ORDER BY timed ASC
|
ORDER BY timed ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
IF (vDirection ='in'
|
IF (vDirection ='in'
|
||||||
AND vNextDirection = 'out'
|
AND vNextDirection = 'out'
|
||||||
AND UNIX_TIMESTAMP(vNextOut) - UNIX_TIMESTAMP(vTimed) > vDayMaxTime) OR
|
AND UNIX_TIMESTAMP(vNextOut) - UNIX_TIMESTAMP(vTimed) > vDayMaxTime) OR
|
||||||
(vDirection ='out'
|
(vDirection ='out'
|
||||||
AND vLastDirection = 'in'
|
AND vLastDirection = 'in'
|
||||||
AND UNIX_TIMESTAMP(vTimed) -UNIX_TIMESTAMP(vLastIn) > vDayMaxTime) THEN
|
AND UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastIn) > vDayMaxTime) THEN
|
||||||
SET vErrorCode = 'DAY_MAX_TIME';
|
SET vErrorCode = 'DAY_MAX_TIME';
|
||||||
CALL util.throw(vErrorCode);
|
CALL util.throw(vErrorCode);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- VERIFICA DESCANSO SEMANAL
|
-- VERIFICA DESCANSO SEMANAL
|
||||||
|
|
||||||
WITH wtc AS(
|
WITH wtc AS(
|
||||||
(SELECT timed
|
(SELECT timed
|
||||||
FROM vn.workerTimeControl
|
FROM vn.workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
AND direction IN ('in', 'out')
|
AND direction IN ('in', 'out')
|
||||||
AND timed BETWEEN vTimed - INTERVAL (vWeekScope * 2) SECOND
|
AND timed BETWEEN vTimed - INTERVAL (vWeekScope * 2) SECOND
|
||||||
AND vTimed + INTERVAL (vWeekScope * 2) SECOND )
|
AND vTimed + INTERVAL (vWeekScope * 2) SECOND )
|
||||||
UNION
|
UNION
|
||||||
(SELECT vTimed)
|
(SELECT vTimed)
|
||||||
), wtcGap AS(
|
), wtcGap AS(
|
||||||
SELECT timed,
|
SELECT timed,
|
||||||
TIMESTAMPDIFF(SECOND, LAG(timed) OVER (ORDER BY timed), timed) gap
|
TIMESTAMPDIFF(SECOND, LAG(timed) OVER (ORDER BY timed), timed) gap
|
||||||
FROM wtc
|
FROM wtc
|
||||||
ORDER BY timed
|
ORDER BY timed
|
||||||
), wtcBreak AS(
|
), wtcBreak AS(
|
||||||
SELECT timed,
|
SELECT timed,
|
||||||
IF(IFNULL(gap, 0) > vShortWeekBreak, TRUE, FALSE) hasShortBreak,
|
IF(IFNULL(gap, 0) > vShortWeekBreak, TRUE, FALSE) hasShortBreak,
|
||||||
IF(IFNULL(gap, 0) > vLongWeekBreak, TRUE, FALSE) hasLongBreak
|
IF(IFNULL(gap, 0) > vLongWeekBreak, TRUE, FALSE) hasLongBreak
|
||||||
|
@ -270,8 +278,8 @@ BEGIN
|
||||||
SUM(hasShortBreak) OVER (ORDER BY timed) breakCounter ,
|
SUM(hasShortBreak) OVER (ORDER BY timed) breakCounter ,
|
||||||
LEAD(hasLongBreak) OVER (ORDER BY timed) nextHasLongBreak
|
LEAD(hasLongBreak) OVER (ORDER BY timed) nextHasLongBreak
|
||||||
FROM wtcBreak
|
FROM wtcBreak
|
||||||
)SELECT TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed)) > vMaxWorkLongCycle OR
|
)SELECT TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed)) > vMaxWorkLongCycle OR
|
||||||
(TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed))> vMaxWorkShortCycle
|
(TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed))> vMaxWorkShortCycle
|
||||||
AND NOT SUM(IFNULL(nextHasLongBreak, 1)))
|
AND NOT SUM(IFNULL(nextHasLongBreak, 1)))
|
||||||
hasError INTO vIsError
|
hasError INTO vIsError
|
||||||
FROM wtcBreakCounter
|
FROM wtcBreakCounter
|
||||||
|
@ -291,5 +299,6 @@ BEGIN
|
||||||
|
|
||||||
SELECT LAST_INSERT_ID() id;
|
SELECT LAST_INSERT_ID() id;
|
||||||
|
|
||||||
END$$
|
END
|
||||||
|
$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -1,39 +1,45 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`workerTimeControl_direction`(vWorkerFk VARCHAR(10), vTimed DATETIME)
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`workerTimeControl_direction`(
|
||||||
|
vWorkerFk VARCHAR(10),
|
||||||
|
vTimed DATETIME
|
||||||
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Devuelve que direcciones de fichadas son lógicas a partir de la anterior fichada
|
* Devuelve que direcciones de fichadas son lógicas a partir de la anterior fichada,
|
||||||
* @param vWorkerFk Identificador del trabajador
|
* @param vWorkerFk Identificador del trabajador
|
||||||
* @return (option1, option2)
|
* @return tmp.workerTimeControlDirection(option1, option2, reentryWaitTime)
|
||||||
* Los valores posibles de retorno son ('in', 'inMiddle', 'outMiddle', 'out')
|
* Valores posibles options('in', 'inMiddle', 'outMiddle', 'out')
|
||||||
*/
|
*/
|
||||||
DECLARE vLastIn DATETIME ;
|
DECLARE vLastIn DATETIME;
|
||||||
DECLARE vIsMiddleOdd BOOLEAN ;
|
DECLARE vLastMiddleIn DATETIME;
|
||||||
|
DECLARE vIsMiddleOdd BOOLEAN;
|
||||||
DECLARE vMailTo VARCHAR(50) DEFAULT NULL;
|
DECLARE vMailTo VARCHAR(50) DEFAULT NULL;
|
||||||
DECLARE vUserName VARCHAR(50) DEFAULT NULL;
|
DECLARE vUserName VARCHAR(50) DEFAULT NULL;
|
||||||
|
DECLARE vReentryWaitTime TIME;
|
||||||
|
|
||||||
IF (vTimed IS NULL) THEN
|
IF (vTimed IS NULL) THEN
|
||||||
SET vTimed = util.VN_NOW();
|
SET vTimed = util.VN_NOW();
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT timed INTO vLastIn
|
SELECT timed INTO vLastIn
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
AND direction = 'in'
|
AND direction = 'in'
|
||||||
AND timed < vTimed
|
AND timed < vTimed
|
||||||
ORDER BY timed DESC
|
ORDER BY timed DESC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
SELECT (COUNT(*)mod 2 = 1) INTO vIsMiddleOdd
|
SELECT (COUNT(*)mod 2 = 1) INTO vIsMiddleOdd
|
||||||
FROM workerTimeControl
|
FROM workerTimeControl
|
||||||
WHERE userFk = vWorkerFk
|
WHERE userFk = vWorkerFk
|
||||||
AND direction = 'middle'
|
AND direction = 'middle'
|
||||||
AND timed BETWEEN vLastIn AND vTimed;
|
AND timed BETWEEN vLastIn AND vTimed;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.workerTimeControlDirection;
|
DROP TEMPORARY TABLE IF EXISTS tmp.workerTimeControlDirection;
|
||||||
CREATE TEMPORARY TABLE tmp.workerTimeControlDirection
|
CREATE TEMPORARY TABLE tmp.workerTimeControlDirection
|
||||||
SELECT IF(isCorrect, option1, NULL) option1,
|
SELECT IF(isCorrect, option1, NULL) option1,
|
||||||
IF(isCorrect, option2, NULL) option2
|
IF(isCorrect, option2, NULL) option2,
|
||||||
|
CAST(NULL AS TIME) reentryWaitTime
|
||||||
FROM( SELECT IF(w.direction <> 'out' AND (UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(w.timed) > wc.dayBreak), FALSE, TRUE) isCorrect,
|
FROM( SELECT IF(w.direction <> 'out' AND (UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(w.timed) > wc.dayBreak), FALSE, TRUE) isCorrect,
|
||||||
CASE WHEN w.direction ='in' THEN 'inMiddle'
|
CASE WHEN w.direction ='in' THEN 'inMiddle'
|
||||||
WHEN w.direction = 'out' THEN 'in'
|
WHEN w.direction = 'out' THEN 'in'
|
||||||
|
@ -59,6 +65,26 @@ BEGIN
|
||||||
VALUES('in', NULL);
|
VALUES('in', NULL);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF (SELECT option1 ='outMiddle' AND option2 IS NULL FROM tmp.workerTimeControlDirection) THEN
|
||||||
|
SELECT timed INTO vLastMiddleIn
|
||||||
|
FROM workerTimeControl
|
||||||
|
WHERE userFk = vWorkerFk
|
||||||
|
AND timed < vTimed
|
||||||
|
ORDER BY timed DESC
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
SELECT TIMEDIFF(vLastMiddleIn + INTERVAL wtc.maxTimeToBreak SECOND, vTimed) INTO vReentryWaitTime
|
||||||
|
FROM tmp.workerTimeControlDirection wt
|
||||||
|
JOIN workerTimeControlConfig wtc
|
||||||
|
WHERE TIME(vLastMiddleIn) BETWEEN wtc.mandatoryBreakFrom AND wtc.mandatoryBreakTo
|
||||||
|
AND TIMESTAMPDIFF(SECOND, vLastMiddleIn, vTimed) < wtc.maxTimeToBreak;
|
||||||
|
|
||||||
|
IF vReentryWaitTime THEN
|
||||||
|
UPDATE tmp.workerTimeControlDirection
|
||||||
|
SET reentryWaitTime = vReentryWaitTime;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
IF (SELECT option1 IS NULL AND option2 IS NULL FROM tmp.workerTimeControlDirection) THEN
|
IF (SELECT option1 IS NULL AND option2 IS NULL FROM tmp.workerTimeControlDirection) THEN
|
||||||
SELECT CONCAT(u.name, '@verdnatura.es'), CONCAT(w.firstName, ' ', w.lastName)
|
SELECT CONCAT(u.name, '@verdnatura.es'), CONCAT(w.firstName, ' ', w.lastName)
|
||||||
INTO vMailTo, vUserName
|
INTO vMailTo, vUserName
|
||||||
|
@ -66,10 +92,10 @@ BEGIN
|
||||||
JOIN worker w ON w.bossFk = u.id
|
JOIN worker w ON w.bossFk = u.id
|
||||||
WHERE w.id = vWorkerFk;
|
WHERE w.id = vWorkerFk;
|
||||||
|
|
||||||
CALL mail_insert(
|
CALL mail_insert(
|
||||||
vMailTo,
|
vMailTo,
|
||||||
vMailTo,
|
vMailTo,
|
||||||
'Error al fichar',
|
'Error al fichar',
|
||||||
CONCAT(vUserName, ' tiene problemas para fichar'));
|
CONCAT(vUserName, ' tiene problemas para fichar'));
|
||||||
END IF;
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
ALTER TABLE vn.workerTimeControlConfig
|
||||||
|
ADD COLUMN `mandatoryBreakFrom` time DEFAULT '12:00:00'
|
||||||
|
COMMENT 'Tiempo desde el que se obligará a realizar un descanso para jornada partida';
|
||||||
|
ALTER TABLE vn.workerTimeControlConfig
|
||||||
|
ADD COLUMN `mandatoryBreakTo` time DEFAULT '15:00:00';
|
||||||
|
|
||||||
|
INSERT INTO vn.workerTimeControlError (`code`, `description`)
|
||||||
|
VALUES ('WAIT_TIME', 'El descanso terminará en ');
|
|
@ -45,7 +45,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error trying to change a middle hour to out not resting 12h', async() => {
|
it('should throw an error trying to change a middle hour to out not resting 12h', async() => {
|
||||||
activeCtx.accessToken.userId = HHRRId;
|
activeCtx.accessToken.userId = HHRRId;
|
||||||
const workerId = teamBossId;
|
const workerId = teamBossId;
|
||||||
|
@ -61,7 +61,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
const middleTime ="2000-12-26T11:00:00.000Z";
|
const middleTime ="2000-12-26T11:00:00.000Z";
|
||||||
ctx.args = {timed: middleTime, direction: 'middle'};
|
ctx.args = {timed: middleTime, direction: 'middle'};
|
||||||
const middleEntryTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
const middleEntryTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
const direction = 'out';
|
const direction = 'out';
|
||||||
await models.WorkerTimeControl.updateTimeEntry(ctx, middleEntryTime.id, direction, options);
|
await models.WorkerTimeControl.updateTimeEntry(ctx, middleEntryTime.id, direction, options);
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
|
@ -87,7 +87,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
ctx.args = {timed: middleTime, direction: 'middle'};
|
ctx.args = {timed: middleTime, direction: 'middle'};
|
||||||
const middleEntryTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
const middleEntryTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
middleEntryTime.updateAttribute('manual', false);
|
middleEntryTime.updateAttribute('manual', false);
|
||||||
|
|
||||||
const direction = 'out';
|
const direction = 'out';
|
||||||
const outTimeEntryId = await models.WorkerTimeControl.updateTimeEntry(ctx, middleEntryTime.id, direction, options);
|
const outTimeEntryId = await models.WorkerTimeControl.updateTimeEntry(ctx, middleEntryTime.id, direction, options);
|
||||||
|
|
||||||
|
@ -111,10 +111,10 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
|
|
||||||
ctx.args = {timed: "2000-12-25T22:00:00.000Z", direction: 'middle'};
|
ctx.args = {timed: "2000-12-25T22:00:00.000Z", direction: 'middle'};
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
ctx.args = {timed: "2000-12-25T22:30:00.000Z", direction: 'middle'};
|
ctx.args = {timed: "2000-12-25T22:30:00.000Z", direction: 'middle'};
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
ctx.args = {timed: "2000-12-26T01:00:00.000Z", direction: 'in'};
|
ctx.args = {timed: "2000-12-26T01:00:00.000Z", direction: 'in'};
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
todayAtTwo.setHours(2, 0, 0, 0);
|
todayAtTwo.setHours(2, 0, 0, 0);
|
||||||
ctx.args = {timed: todayAtTwo, direction: 'middle'};
|
ctx.args = {timed: todayAtTwo, direction: 'middle'};
|
||||||
const middleTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
const middleTime = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
const direction = 'out';
|
const direction = 'out';
|
||||||
const outTimeEntryId = await models.WorkerTimeControl.updateTimeEntry(
|
const outTimeEntryId = await models.WorkerTimeControl.updateTimeEntry(
|
||||||
ctx, middleTime.id, direction, options
|
ctx, middleTime.id, direction, options
|
||||||
|
@ -204,7 +204,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
|
|
||||||
const {direction: updatedDirection} = await models.WorkerTimeControl.findById(outTimeEntryId,{fields:['direction']},options);
|
const {direction: updatedDirection} = await models.WorkerTimeControl.findById(outTimeEntryId,{fields:['direction']},options);
|
||||||
expect(updatedDirection).toEqual('out');
|
expect(updatedDirection).toEqual('out');
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
|
@ -544,7 +544,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('for 72h weekly rest', () => {
|
describe('for 72h weekly rest', () => {
|
||||||
|
|
||||||
it('should throw an error when work 11 consecutive days', async() => {
|
it('should throw an error when work 11 consecutive days', async() => {
|
||||||
let date = Date.vnNew();
|
let date = Date.vnNew();
|
||||||
date.setMonth(date.getMonth() - 1);
|
date.setMonth(date.getMonth() - 1);
|
||||||
|
@ -598,7 +598,7 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
|
|
||||||
expect(error.message).toBe(`Descanso semanal`);
|
expect(error.message).toBe(`Descanso semanal`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when the 72h weekly rest is fulfilled', async() => {
|
it('should throw an error when the 72h weekly rest is fulfilled', async() => {
|
||||||
|
|
||||||
let date = Date.vnNew();
|
let date = Date.vnNew();
|
||||||
|
@ -626,6 +626,74 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
|
|
||||||
expect(error).not.toBeDefined;
|
expect(error).not.toBeDefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should enforce a 1-hour break if the break starts between 12:00 and 15:00', async() => {
|
||||||
|
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(11, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(13, 30, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(14, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
expect(error.statusCode).toBe(400);
|
||||||
|
expect(error.message).toMatch(/El descanso terminará en \d{2}:\d{2}/);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow resuming work after a full 1-hour break', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
date.setHours(11, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(14, 00, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(15, 00, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeUndefined();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -95,9 +95,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(14, 59, 0);
|
dated.setHours(04, 59, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(15, 14, 0);
|
dated.setHours(05, 14, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -124,9 +124,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(15, 0, 0);
|
dated.setHours(05, 0, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(15, 15, 0);
|
dated.setHours(05, 15, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -153,9 +153,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(14, 59, 0);
|
dated.setHours(04, 59, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(15, 24, 0);
|
dated.setHours(05, 24, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -182,9 +182,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(15, 0, 0);
|
dated.setHours(05, 0, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(15, 25, 0);
|
dated.setHours(05, 25, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -211,9 +211,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(14, 59, 0);
|
dated.setHours(04, 59, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(15, 59, 0);
|
dated.setHours(05, 59, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -240,9 +240,9 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
await populateWeek(dated, monday, monday, ctx, hankPymId, options);
|
||||||
dated.setHours(15, 0, 0);
|
dated.setHours(05, 0, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
dated.setHours(16, 0, 0);
|
dated.setHours(06, 0, 0);
|
||||||
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
await addTimeEntry(ctx, dated, 'middle', hankPymId, options);
|
||||||
|
|
||||||
const start = new Date(dated - 1);
|
const start = new Date(dated - 1);
|
||||||
|
@ -286,10 +286,10 @@ async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) {
|
||||||
dateEnd.setDate(dateStart.getDate() + dayEnd);
|
dateEnd.setDate(dateStart.getDate() + dayEnd);
|
||||||
|
|
||||||
for (let i = dayStart; i <= dayEnd; i++) {
|
for (let i = dayStart; i <= dayEnd; i++) {
|
||||||
dateStart.setHours(10, 0, 0);
|
dateStart.setHours(00, 0, 0);
|
||||||
ctx.args = {timed: dateStart, direction: 'in'};
|
ctx.args = {timed: dateStart, direction: 'in'};
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
dateStart.setHours(18, 0, 0);
|
dateStart.setHours(08, 0, 0);
|
||||||
ctx.args = {timed: dateStart, direction: 'out'};
|
ctx.args = {timed: dateStart, direction: 'out'};
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
dateStart.setDate(dateStart.getDate() + 1);
|
dateStart.setDate(dateStart.getDate() + 1);
|
||||||
|
|
Loading…
Reference in New Issue