Merge branch 'dev' into 8077-sumDefaulter
gitea/salix/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Robert Ferrús 2024-11-22 05:39:20 +00:00
commit 3adbc9c343
34 changed files with 520 additions and 457 deletions

View File

@ -36,3 +36,7 @@ rules:
jasmine/no-focused-tests: 0
jasmine/prefer-toHaveBeenCalledWith: 0
arrow-spacing: ["error", { "before": true, "after": true }]
no-restricted-syntax:
- "error"
- selector: "NewExpression[callee.name='Date']"
message: "Use Date.vnNew() instead of new Date()."

View File

@ -28,9 +28,10 @@ describe('ticket assign()', () => {
await tx.rollback();
});
it('should throw an error when there is not picking tickets', async() => {
it('should throw an error when there are no picking tickets', async() => {
try {
await models.Collection.assign(ctx, options);
fail('Expected an error to be thrown, but none was thrown.');
} catch (e) {
expect(e.message).toEqual('There are not picking tickets');
}

View File

@ -31,7 +31,7 @@ module.exports = Self => {
return await Self.rawSql(`
INSERT INTO workerActivity (workerFk, workerActivityTypeFk, model)
SELECT ?, ?, ?
FROM workerTimeControlParams wtcp
FROM workerTimeControlConfig wtcc
LEFT JOIN (
SELECT wa.workerFk,
wa.created,
@ -44,7 +44,7 @@ module.exports = Self => {
) sub ON TRUE
WHERE sub.workerFk IS NULL
OR sub.code <> ?
OR TIMESTAMPDIFF(SECOND, sub.created, util.VN_NOW()) > wtcp.dayBreak;`
OR TIMESTAMPDIFF(SECOND, sub.created, util.VN_NOW()) > wtcc.dayBreak;`
, [userId, code, model, userId, code], myOptions);
};
};

View File

@ -1518,19 +1518,19 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
(11, util.VN_CURDATE() - INTERVAL 1 DAY , util.VN_CURDATE(), 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL),
(12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`)
VALUES
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, ''),
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two'),
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three'),
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four'),
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six'),
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1,''),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, ''),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, ''),
(99, 69, '2000-12-01 00:00:00.000', 11, 0, 442, 'IN2009', 'Movement 99', 0, '');
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`, `typeFk`)
VALUES
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two', 'product'),
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three', 'product'),
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four', 'product'),
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five', 'product'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six', 'product'),
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven', 'product'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, '', 'product'),
(99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99', 0, '', 'product');
INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`)
VALUES (2, 4, 1);
@ -2521,10 +2521,6 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`, `code`)
(2, 'Normal', 'normal'),
(3, 'Baja', 'low');
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`)
VALUES
(1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000);
INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11');
INSERT INTO `vn`.`thermograph`(`id`, `model`)
@ -4008,14 +4004,17 @@ INSERT IGNORE INTO pbx.queueMember
UPDATE vn.department SET pbxQueue = '1000' WHERE name = "CAMARA";
UPDATE vn.department SET pbxQueue = '2000' WHERE name = "VENTAS";
INSERT INTO vn.workerRelatives (workerFk, isDescendant, disabilityGradeFk, birthed, adoptionYear, isDependend, isJointCustody, updated)
VALUES
(1106, 1, NULL, 0, NULL, 0, 0, '2024-10-29 08:42:44.000');
INSERT INTO vn.routeAction (id, name, price, isMainlineDelivered) VALUES(1, 'Pintar traje', 50.00, 0);
INSERT INTO vn.routeComplement (id, dated, workerFk, price, routeActionFk) VALUES(1, util.VN_CURDATE(), 9, 50.00, 1);
INSERT INTO srt.buffer (id, x, y, `size`, `length`, stateFk, typeFk, isActive, code, stratus, hasWorkerWaiting, reserve, routeFk, dayMinute, lastUnloaded, hasStrapper, typeDefaultFk, motors, editorFk)
INSERT INTO srt.buffer (id, x, y, `size`, `length`, stateFk, typeFk, isActive, code, stratus, hasWorkerWaiting, reserve, routeFk, dayMinute, lastUnloaded, hasStrapper, typeDefaultFk, motors, editorFk)
VALUES (0, 0, 0, 0, NULL, 3, 1, 0, 'ENT', 0, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(1, 0, 9900, 0, NULL, 1, 0, 0, 'NOK', 0, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(2, 0, 0, 450, 13000, 1, 0, 1, '01A', 1, 1, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(2, 0, 0, 450, 13000, 1, 0, 1, '01A', 1, 1, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(3, 1400, 0, 450, 13000, 1, 0, 1, '01B', 1, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(4, 0, 500, 500, 13000, 1, 4, 1, '02A', 2, 1, NULL, NULL, NULL, NULL, 1, 4, 13, NULL),
(5, 1400, 500, 500, 13000, 1, 4, 1, '02B', 2, 1, NULL, NULL, NULL, NULL, 1, 4, 13, NULL),
@ -4025,10 +4024,12 @@ INSERT INTO srt.buffer (id, x, y, `size`, `length`, stateFk, typeFk, isActive, c
(9, 1400, 1500, 500, 13000, 1, 1, 1, '04B', 4, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(10, 0, 2000, 500, 13000, 1, 1, 1, '05A', 5, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL);
INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel)
INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel)
VALUES (19, '1169'),
(8, '1183');
INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
VALUES ('saysimle-url-mock', 1320);
INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
VALUES ('saysimle-url-mock', 1320);
INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
VALUES (1106,'26493101E','2019-09-20');

View File

@ -1,65 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`timeWorkerControl_getDirection`(vUserFk INT, vTimed DATETIME)
RETURNS varchar(6) CHARSET utf8mb3 COLLATE utf8mb3_unicode_ci
NOT DETERMINISTIC
READS SQL DATA
BEGIN
/**
* Verifica la dirección de la fichada
* @param vUserFk Identificador del trabajador
* @param vTimed Hora de la fichada
* @return Retorna sentido de la fichada 'in, out, middle'
*/
DECLARE vPrevious DATETIME ;
DECLARE vNext DATETIME ;
DECLARE vPreviousDirection VARCHAR(3) ;
DECLARE vNextDirection VARCHAR(3) ;
DECLARE vDayStayMax INT;
DECLARE vTimedSeconds INT;
DECLARE vLastTimeIn INT;
SELECT UNIX_TIMESTAMP(vTimed) INTO vTimedSeconds;
SELECT dayStayMax INTO vDayStayMax
FROM vn.workerTimeControlParams;
SELECT timed, direction INTO vNext,vNextDirection
FROM vn.workerTimeControl
WHERE userFk = vUserFk
AND direction IN ('in','out')
AND timed > vTimed
ORDER BY timed ASC
LIMIT 1;
SELECT timed, direction INTO vPrevious, vPreviousDirection
FROM vn.workerTimeControl
WHERE userFk = vUserFk
AND direction IN ('in','out')
AND timed < vTimed
ORDER BY timed DESC
LIMIT 1;
IF (vTimedSeconds - UNIX_TIMESTAMP(vPrevious) + UNIX_TIMESTAMP(vNext) - vTimedSeconds)<= vDayStayMax AND vPreviousDirection = 'in' AND vNextDirection = 'out' THEN
RETURN 'middle';
END IF;
IF (vTimedSeconds> UNIX_TIMESTAMP(vPrevious)) THEN
IF vPreviousDirection = 'in' THEN
RETURN 'out';
ELSE
SELECT UNIX_TIMESTAMP(MAX(timed)) INTO vLastTimeIn
FROM vn.workerTimeControl
WHERE userFk = vUserFk
AND direction ='in'
AND timed < vPrevious;
IF vTimedSeconds - vLastTimeIn <= vDayStayMax THEN
RETURN 'out';
END IF;
END IF;
END IF;
RETURN 'in';
END$$
DELIMITER ;

View File

@ -9,16 +9,18 @@ BEGIN
*
* @param vSelf Id de entrada
*/
DECLARE vIsEditable BOOL;
DECLARE vIsNotEditable BOOL DEFAULT FALSE;
SELECT e.isBooked INTO vIsEditable
SELECT TRUE INTO vIsNotEditable
FROM `entry` e
JOIN entryType et ON et.code = e.typeFk
WHERE NOT et.isInformal
AND e.id = vSelf;
LEFT JOIN entryType et ON et.code = e.typeFk
WHERE e.id = vSelf
AND e.isBooked
AND (e.typeFk IS NULL OR NOT et.isInformal);
IF vIsEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN
IF vIsNotEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN
CALL util.throw(CONCAT('Entry ', vSelf, ' is not editable'));
END IF;
END$$
DELIMITER ;

View File

@ -48,7 +48,7 @@ BEGIN
iss.itemShelvingFk,
SUM(IFNULL(iss.quantity,0)),
IF(sgd.id, 'PREVIOUS_PREPARATION', 'PREPARED'),
ish.shelvingFk
sh.code
INTO vItemFk,
vSaleFk,
vItemShelvingFk,
@ -58,7 +58,8 @@ BEGIN
FROM itemShelvingSale iss
JOIN sale s ON s.id = iss.saleFk
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
LEFT JOIN vn.saleGroupDetail sgd ON sgd.saleFk = iss.saleFk
LEFT JOIN saleGroupDetail sgd ON sgd.saleFk = iss.saleFk
LEFT JOIN shelving sh ON sh.id = ish.shelvingFk
WHERE iss.id = vItemShelvingSaleFk
AND NOT iss.isPicked;

View File

@ -21,7 +21,8 @@ BEGIN
ish.isChecked,
ic.url,
ish.available,
ish.buyFk
ish.buyFk,
ish.shelvingFk
FROM itemShelving ish
JOIN item i ON i.id = ish.itemFk
JOIN shelving s ON s.id = ish.shelvingFk

View File

@ -5,122 +5,122 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_splitItemPacki
)
BEGIN
/**
* Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado.
* Respeta el id inicial para el tipo propuesto.
* Separa en diferentes tickets según el tipo de empaquetado
* El ticket original conserva las líneas del tipo de empaquetado especificado
* Las líneas sin tipo de empaquetado se asignan al ticket del tipo por defecto.
*
* @param vSelf Id ticket
* @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original
* @param vSelf Id del ticket original
* @param vOriginalItemPackingTypeFk Tipo de empaquetado a mantener en el ticket original
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
*/
DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H';
DECLARE vIsDone BOOLEAN DEFAULT FALSE;
DECLARE vCurrentPackingType VARCHAR(1);
DECLARE vDefaultPackingType VARCHAR(1);
DECLARE vHasOriginalPackingType BOOLEAN;
DECLARE vNewTicketFk INT;
DECLARE vPackingTypesToSplit INT;
DECLARE vDone INT DEFAULT FALSE;
DECLARE vTicketFk INT;
DECLARE vSaleGroup CURSOR FOR
SELECT itemPackingTypeFk
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL
ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC;
DECLARE vItemPackingTypes CURSOR FOR
SELECT DISTINCT itemPackingTypeFk FROM tSalesToMove;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vIsDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
CREATE OR REPLACE TEMPORARY TABLE tSalesToMove (
ticketFk INT,
saleFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE=MEMORY;
SELECT COALESCE(MAX(ic.defaultPackingTypeFk), MAX(i.itemPackingTypeFk)) INTO vDefaultPackingType
FROM vn.sale s
JOIN item i ON i.id = s.itemFk
LEFT JOIN itemConfig ic ON ic.defaultPackingTypeFk = i.itemPackingTypeFk
WHERE s.ticketFk = vSelf
GROUP BY s.ticketFk;
SELECT EXISTS (
SELECT TRUE
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk
) INTO vHasOriginalPackingType;
IF vOriginalItemPackingTypeFk IS NULL OR NOT vHasOriginalPackingType THEN
SET vOriginalItemPackingTypeFk = vDefaultPackingType;
END IF;
START TRANSACTION;
SELECT id
FROM sale
WHERE ticketFk = vSelf
AND NOT quantity
SELECT t.id INTO vTicketFk
FROM ticket t
JOIN sale s ON s.id = t.id
WHERE t.id = vSelf
FOR UPDATE;
DELETE FROM sale
WHERE NOT quantity
AND ticketFk = vSelf;
CREATE OR REPLACE TEMPORARY TABLE tSale
(PRIMARY KEY (id))
ENGINE = MEMORY
SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros
INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk)
SELECT s.id, i.itemPackingTypeFk
FROM sale s
JOIN item i ON i.id = s.itemFk
LEFT JOIN saleVolume sv ON sv.saleFk = s.id
WHERE s.ticketFk = vSelf;
WHERE s.ticketFk = vSelf
AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk;
CREATE OR REPLACE TEMPORARY TABLE tSaleGroup
ENGINE = MEMORY
SELECT itemPackingTypeFk, SUM(litros) totalLitros
FROM tSale
GROUP BY itemPackingTypeFk;
OPEN vItemPackingTypes;
l: LOOP
SET vIsDone = FALSE;
FETCH vItemPackingTypes INTO vCurrentPackingType;
SELECT COUNT(*) INTO vPackingTypesToSplit
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
IF vIsDone THEN
LEAVE l;
END IF;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT(
ticketFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE = MEMORY;
CALL ticket_Clone(vSelf, vNewTicketFk);
CASE vPackingTypesToSplit
WHEN 0 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
WHEN 1 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
SELECT vSelf, itemPackingTypeFk
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
ELSE
OPEN vSaleGroup;
FETCH vSaleGroup INTO vItemPackingTypeFk;
SELECT id INTO vTicketFk
FROM ticket t
WHERE t.id = vNewTicketFk
FOR UPDATE;
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
UPDATE tSalesToMove
SET ticketFk = vNewTicketFk
WHERE itemPackingTypeFk = vCurrentPackingType;
l: LOOP
SET vDone = FALSE;
FETCH vSaleGroup INTO vItemPackingTypeFk;
IF vCurrentPackingType = vDefaultPackingType THEN
INSERT INTO tSalesToMove (ticketFk, saleFk, itemPackingTypeFk)
SELECT vNewTicketFk, s.id, i.itemPackingTypeFk
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
AND i.itemPackingTypeFk IS NULL;
END IF;
IF vDone THEN
LEAVE l;
END IF;
END LOOP;
CLOSE vItemPackingTypes;
CALL ticket_Clone(vSelf, vNewTicketFk);
UPDATE sale s
JOIN tSalesToMove t ON t.saleFk = s.id
SET s.ticketFk = t.ticketFk;
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vNewTicketFk, vItemPackingTypeFk);
END LOOP;
CLOSE vSaleGroup;
SELECT s.id
FROM sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
FOR UPDATE;
UPDATE sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
SET s.ticketFk = t.ticketFk;
SELECT itemPackingTypeFk INTO vItemPackingTypeFk
FROM tSaleGroup sg
WHERE sg.itemPackingTypeFk IS NOT NULL
ORDER BY sg.itemPackingTypeFk
LIMIT 1;
UPDATE sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk
SET s.ticketFk = t.ticketFk
WHERE ts.itemPackingTypeFk IS NULL;
END CASE;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT
ENGINE=MEMORY
SELECT s.ticketFk, MAX(i.itemPackingTypeFk) itemPackingTypeFk
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
GROUP BY s.ticketFk
UNION
SELECT ticketFk, MAX(itemPackingTypeFk)
FROM tSalesToMove
GROUP BY ticketFk;
COMMIT;
DROP TEMPORARY TABLE
tSale,
tSaleGroup;
DROP TEMPORARY TABLE tSalesToMove;
END$$
DELIMITER ;

View File

@ -1,168 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`workerTimeControl_check`(vUserFk INT, vDated DATE,vTabletFk VARCHAR(100))
proc: BEGIN
/**
* Verifica si el empleado puede fichar en el momento actual, si puede fichar llama a 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 vWeekScope INT;
DECLARE vDayStayMax INT;
DECLARE vProblem VARCHAR(20) DEFAULT NULL;
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;
SELECT dayBreak, weekBreak, weekScope, dayWorkMax, dayStayMax
INTO vDayBreak, vWeekBreak, vWeekScope, vDayWorkMax, vDayStayMax
FROM workerTimeControlParams;
SELECT MAX(timed) INTO vLastIn
FROM workerTimeControl
WHERE userFk = vUserFk
AND direction = 'in';
SELECT MAX(timed) INTO vLastOut
FROM workerTimeControl
WHERE userFk = vUserFk
AND direction = 'out';
SELECT CONCAT(u.name,'@verdnatura.es') INTO vTo
FROM account.user u
WHERE u.id = (SELECT bossFk FROM worker WHERE id = vUserFk);
SELECT CONCAT(firstName,' ',lastName) INTO vUserName
FROM worker w
WHERE w.id = vUserFk;
IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastIn) > vDayStayMax THEN -- NUEVA JORNADA
-- VERIFICAR DESCANSO DIARIO
IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastOut) < vDayBreak THEN
SELECT "Descansos 12 h" AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos 12 h") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
-- VERIFICAR FICHADAS IMPARES DEL ÚLTIMO DÍA QUE SE FICHÓ
IF (SELECT MOD(COUNT(*),2) -- <>0
FROM workerTimeControl
WHERE userFk = vUserFk
AND timed >= vLastIn
) THEN
SELECT "Dias con fichadas impares" AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Dias con fichadas impares") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
-- VERIFICAR VACACIONES
SELECT at2.name INTO vCalendarStateType
FROM calendar c
JOIN business b ON b.id = c.businessFk
JOIN absenceType at2 ON at2.id = c.dayOffTypeFk
WHERE c.dated = util.VN_CURDATE()
AND at2.isAllowedToWork = FALSE
AND b.workerFk = vUserFk
LIMIT 1;
IF(LENGTH(vCalendarStateType)) THEN
SELECT vCalendarStateType AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Vacaciones") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
-- VERIFICAR CONTRATO EN VIGOR
IF (SELECT COUNT(*)
FROM business b
WHERE b.workerFk = vUserFk
AND b.started <= vDated
AND IFNULL(b.ended, vDated) >= vDated
) = 0 THEN
SELECT "No hay un contrato en vigor" AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No hay un contrato en vigor") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
-- VERIFICAR DESCANSO SEMANAL
SET @vHasBreakWeek:= FALSE;
SET @vLastTimed:= UNIX_TIMESTAMP((util.VN_NOW() - 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>= (util.VN_NOW() - INTERVAL vWeekScope SECOND)
AND userFk= vUserFk
AND direction IN ('in','out')
ORDER BY timed ASC;
IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastOut) < vWeekBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÉS DE LA ÚLTIMA FICHADA
SELECT "Descansos 36 h" AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos 36 h") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
DROP TEMPORARY TABLE tmp.trash;
ELSE -- DIA ACTUAL
-- VERIFICA QUE EL TIEMPO EFECTIVO NO SUPERE EL MÁXIMO
SELECT IFNULL(SUM(if( mod(wtc.order,2)=1, -UNIX_TIMESTAMP(timed), UNIX_TIMESTAMP(timed))),0) - IF( MOD(COUNT(*),2), UNIX_TIMESTAMP(util.VN_NOW()), 0) INTO vTimedWorked
FROM workerTimeControl wtc
WHERE userFk = vUserFk
AND timed >= vLastIn
ORDER BY timed;
IF vTimedWorked > vDayWorkMax THEN
SELECT "Jornadas" AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Jornadas") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
END IF;
-- VERIFICAR DEPARTAMENTO
/* IF vTabletFk IS NOT NULL THEN
SELECT wtcu.departmentFk INTO vDepartmentFk
FROM workerTimeControlUserInfo wtcu
WHERE wtcu.userFk = vUserFk;
IF (SELECT COUNT(td.tabletFk)
FROM tabletDepartment td
WHERE td.tabletFk = vTabletFk AND td.departmentFk = vDepartmentFk
) = 0 THEN
SELECT "No perteneces a este departamento." AS problem;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No a podido fichar por el siguiente problema: ',"No perteneces a este departamento.") INTO vBody;
CALL mail_insert(vTo,vTo,'error al fichar',vBody);
LEAVE proc;
END IF;
END IF;*/
END$$
DELIMITER ;

View File

@ -38,10 +38,10 @@ BEGIN
CALL travel_throwAwb(NEW.travelFk);
END IF;
SELECT isRaid INTO vIsRaid
SELECT t.isRaid INTO vIsRaid
FROM travel t
JOIN entry e ON e.travelFk = t.id
WHERE entryFk = NEW.id;
WHERE e.id = NEW.id;
SELECT NOT (o.warehouseInFk <=> n.warehouseInFk)
OR NOT (o.warehouseOutFk <=> n.warehouseOutFk)

View File

@ -0,0 +1,23 @@
ALTER TABLE vn.workerRelatives DROP FOREIGN KEY workerRelatives_disabilityGradeFk;
ALTER TABLE vn.workerRelatives DROP FOREIGN KEY workerRelatives_workerFk;
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES
('WorkerRelative','updateAttributes','*','ALLOW','ROLE','hr'),
('WorkerRelative','crud','WRITE','ALLOW','ROLE','hr'),
('WorkerRelative','findById','*','ALLOW','ROLE','hr'),
('WorkerRelative','find','*','ALLOW','ROLE','hr'),
('WorkerRelative','upsert','*','ALLOW','ROLE','hr'),
('WorkerRelative','filter','*','ALLOW','ROLE','hr'),
('WorkerIrpf','updateAttributes','*','ALLOW','ROLE','hr'),
('WorkerIrpf','crud','*','ALLOW','ROLE','hr'),
('WorkerIrpf','findById','*','ALLOW','ROLE','hr'),
('WorkerIrpf','find','*','ALLOW','ROLE','hr'),
('WorkerIrpf','upsert','*','ALLOW','ROLE','hr'),
('WorkerIrpf','filter','*','ALLOW','ROLE','hr'),
('DisabilityGrade','updateAttributes','*','ALLOW','ROLE','hr'),
('DisabilityGrade','crud','*','ALLOW','ROLE','hr'),
('DisabilityGrade','findById','*','ALLOW','ROLE','hr'),
('DisabilityGrade','find','*','ALLOW','ROLE','hr'),
('DisabilityGrade','upsert','*','ALLOW','ROLE','hr');

View File

@ -0,0 +1,40 @@
-- Eliminar registros existentes donde property = '*'
DELETE FROM `salix`.ACL WHERE model = 'entry' AND property = '*';
-- Insertar permisos para los métodos solicitados en el modelo Entry
INSERT INTO `salix`.ACL (model, property, accessType, permission, principalType, principalId)
VALUES
-- Permisos para administrative
('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'isBooked', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'administrative'),
-- Permisos para buyer (excluyendo isBooked)
('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'buyer');

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.itemConfig ADD defaultPackingTypeFk VARCHAR(1) DEFAULT 'H' NULL;

View File

@ -0,0 +1,2 @@
RENAME TABLE vn.workerTimeControlParams TO vn.workerTimeControlParams__;
ALTER TABLE vn.workerTimeControlParams__ COMMENT='@deprecated 2024-11-19';

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada';
ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL
COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada';

View File

@ -240,11 +240,11 @@
"The height must be greater than 50cm": "The height must be greater than 50cm",
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm",
"The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line",
"Invalid or expired verification code": "Invalid or expired verification code",
"There are tickets for this area, delete them first": "There are tickets for this area, delete them first",
"ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}",
"There are tickets for this area, delete them first": "There are tickets for this area, delete them first",
"Payment method is required": "Payment method is required",
"You do not have permission to modify the booked field": "You do not have permission to modify the booked field",
"Invalid or expired verification code": "Invalid or expired verification code",
"ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}",
"The raid information is not correct": "The raid information is not correct",
"Sales already moved": "Sales already moved"
}

View File

@ -385,9 +385,10 @@
"type cannot be blank": "Se debe rellenar el tipo",
"There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero",
"There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén",
"You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
"ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
"The web user's email already exists": "El correo del usuario web ya existe",
"Sales already moved": "Ya han sido transferidas",
"Sales already moved": "Ya han sido transferidas",
"The raid information is not correct": "La información de la redada no es correcta"
}

View File

@ -362,8 +362,9 @@
"The invoices have been created but the PDFs could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré",
"It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré",
"Cannot send mail": "Impossible d'envoyer le mail",
"Original invoice not found": "Facture originale introuvable",
"The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne",
"Original invoice not found": "Facture originale introuvable",
"The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne",
"You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé",
"ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}",
"The web user's email already exists": "L'email de l'internaute existe déjà"
}
}

View File

@ -366,4 +366,4 @@
"The quantity claimed cannot be greater than the quantity of the line": "O valor reclamado não pode ser superior ao valor da linha",
"ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}",
"The web user's email already exists": "O e-mail do utilizador da web já existe."
}
}

View File

@ -1,3 +1,4 @@
const UserError = require('vn-loopback/util/user-error');
const LoopBackContext = require('loopback-context');
module.exports = Self => {
require('../methods/entry/filter')(Self);
@ -18,11 +19,20 @@ module.exports = Self => {
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const loopBackContext = LoopBackContext.getCurrentContext();
const accessToken = {req: loopBackContext.active};
const hasChanges = orgData && changes;
const isBookedChanged = changes.isBooked !== undefined && orgData.isBooked !== changes.isBooked;
if (isBookedChanged) {
const canEditIsBooked = await Self.app.models.ACL.checkAccessAcl(accessToken, 'Entry', 'isBooked', 'READ');
if (!canEditIsBooked)
throw new UserError('You do not have permission to modify the booked field');
}
const observation = changes.observation || orgData.observation;
const hasChanges = orgData && changes;
const observationChanged = hasChanges
&& orgData.observation != observation;
const observationChanged = hasChanges && orgData.observation != observation;
if (observationChanged) {
let tx;
@ -37,8 +47,7 @@ module.exports = Self => {
}
try {
const loopbackContext = LoopBackContext.getCurrentContext();
const userId = loopbackContext.active.accessToken.userId;
const userId = loopBackContext.active.accessToken.userId;
const id = changes.id || orgData.id;
const entry = await Self.app.models.Entry.findById(id, null, myOptions);
await entry.updateAttribute('observationEditorFk', userId, myOptions);

View File

@ -0,0 +1,97 @@
const {models} = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('entry_isEditable trigger', () => {
const activeCtx = {
accessToken: {userId: 5},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {req: activeCtx};
const entryId = 1;
let tx;
let options;
let entry;
beforeEach(async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({active: ctx.req});
tx = await models.Entry.beginTransaction({});
options = {transaction: tx};
entry = await models.Entry.findById(entryId, null, options);
});
afterEach(async() => {
await tx.rollback();
});
async function prepareEntry(isBooked, typeFk) {
let newCreated = Date.vnNew();
await entry.updateAttributes({isBooked, typeFk}, options);
await entry.updateAttributes({dated: newCreated}, options);
}
it('should throw an error when entry is booked and typeFk is null', async() => {
let error;
try {
await prepareEntry(true, null);
} catch (e) {
error = e;
}
expect(error.message).toContain(`Entry ${entryId} is not editable`);
});
it('should throw an error when entry is booked and typeFk is not informal', async() => {
let error;
try {
const type = await models.EntryType.findOne({where: {isInformal: false}}, options);
await prepareEntry(true, type.code);
} catch (e) {
error = e;
}
expect(error.message).toContain(`Entry ${entryId} is not editable`);
});
it('should not throw an error when entry is booked and typeFk is informal', async() => {
let error;
try {
const type = await models.EntryType.findOne({where: {isInformal: true}}, options);
await prepareEntry(true, type.code);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
});
it('should not throw an error when entry is not booked', async() => {
let error;
try {
const type = await models.EntryType.findOne({}, options);
await prepareEntry(false, type.code);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
});
it('should not throw an error when @isModeInventory is true', async() => {
let error;
try {
await models.Application.rawSql('SET @isModeInventory = TRUE;', null, options);
await prepareEntry(true, null);
} catch (e) {
error = e;
} finally {
await models.Application.rawSql('SET @isModeInventory = FALSE;', null, options);
}
expect(error).toBeUndefined();
});
});

View File

@ -15,7 +15,7 @@ module.exports = Self => {
Self.getWithPackaging = async options => {
const models = Self.app.models;
const myOptions = {};
const oneYearAgo = new Date();
const oneYearAgo = Date.vnNew();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
if (typeof options == 'object')

View File

@ -1,26 +1,12 @@
const {models} = require('vn-loopback/server/server');
describe('Supplier getWithPackaging()', () => {
beforeAll.mockLoopBackContext();
it('should return a list of suppliers with an entry of type packaging', async() => {
const typeFk = 'packaging';
const tx = await models.Supplier.beginTransaction({});
const myOptions = {transaction: tx};
try {
const entry = await models.Entry.findOne(
{
where: {
id: 1
},
myOptions
});
await entry.updateAttributes({
typeFk: typeFk,
created: new Date()
});
const result = await models.Supplier.getWithPackaging(myOptions);
expect(result.length).toEqual(1);

View File

@ -16,7 +16,7 @@ module.exports = Self => {
});
Self.checkInbox = async() => {
let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne();
let imapConfig = await Self.app.models.WorkerTimeControlConfig.findOne();
let imap = new Imap({
user: imapConfig.mailUser,
password: imapConfig.mailPass,

View File

@ -58,9 +58,8 @@ module.exports = Self => {
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
throw new UserError(`You don't have enough privileges`);
const labour = await models.WorkerLabour.findById(args.businessFk, {
include: {relation: 'department'}
}, myOptions);
const labour = await models.WorkerLabour.findById(args.businessFk,
{fields: ['started', 'ended', 'businessFk']}, myOptions);
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
throw new UserError(`The contract was not active during the selected date`);
@ -87,7 +86,8 @@ module.exports = Self => {
`SELECT COUNT(*) halfHolidayCounter
FROM vn.calendar c
JOIN vn.business b ON b.id = c.businessFk
WHERE c.dayOffTypeFk = 6
JOIN vn.absenceType at ON at.id = c.dayOffTypeFk
WHERE at.code = 'halfHoliday'
AND b.workerFk = ?
AND c.dated BETWEEN util.firstDayOfYear(?)
AND LAST_DAY(DATE_ADD(?, INTERVAL 12 - MONTH(?) MONTH))`, [id, date, now, now]);
@ -119,25 +119,23 @@ module.exports = Self => {
dated: args.dated
}, myOptions);
const department = labour.department();
if (department && department.notificationEmail) {
const absenceType = await models.AbsenceType.findById(args.absenceTypeId, null, myOptions);
const account = await models.VnUser.findById(userId, null, myOptions);
const subordinated = await models.VnUser.findById(id, null, myOptions);
const url = await Self.app.models.Url.getUrl();
const body = $t('Created absence', {
author: account.nickname,
employee: subordinated.nickname,
absenceType: absenceType.name,
dated: formatDate(args.dated),
workerUrl: `${url}worker/${id}/calendar`
});
await models.Mail.create({
subject: $t('Absence change notification on the labour calendar'),
body: body,
receiver: department.notificationEmail
}, myOptions);
}
const account = await models.VnUser.findById(userId, null, myOptions);
const subordinated = await models.VnUser.findById(id, null, myOptions);
const worker = await models.Worker.findById(subordinated.id, null, myOptions);
const departmentBoss = await models.VnUser.findById(worker.bossFk, null, myOptions);
const url = await Self.app.models.Url.getUrl();
const body = $t('Created absence', {
author: account.nickname,
employee: subordinated.nickname,
absenceType: absenceType.name,
dated: formatDate(args.dated),
workerUrl: `${url}worker/${id}/calendar`
});
await models.Mail.create({
subject: $t('Absence change notification on the labour calendar'),
body: body,
receiver: departmentBoss.email
}, myOptions);
if (tx) await tx.commit();

View File

@ -113,9 +113,6 @@
"WorkerTimeControlConfig": {
"dataSource": "vn"
},
"WorkerTimeControlParams": {
"dataSource": "vn"
},
"WorkerTimeControlMail": {
"dataSource": "vn"
},
@ -125,6 +122,15 @@
"Locker": {
"dataSource": "vn"
},
"WorkerIrpf": {
"dataSource": "vn"
},
"DisabilityGrade": {
"dataSource": "vn"
},
"WorkerRelative": {
"dataSource": "vn"
},
"MedicalReview": {
"dataSource": "vn"
},

View File

@ -0,0 +1,18 @@
{
"name": "DisabilityGrade",
"base": "VnModel",
"options": {
"mysql": {
"table": "disabilityGrade"
}
},
"properties": {
"id": {
"id": true,
"type": "number"
},
"description": {
"type": "string"
}
}
}

View File

@ -0,0 +1,55 @@
{
"name": "WorkerIrpf",
"description": "Model 145 IRPF",
"base": "VnModel",
"options": {
"mysql": {
"table": "workerIrpf"
}
},
"properties": {
"workerFk": {
"type": "number",
"id": 1,
"description": "Identifier"
},
"spouseNif": {
"type": "string"
},
"geographicMobilityDate": {
"type": "date"
},
"disabilityGradeFk": {
"type" : "number"
},
"isDependend": {
"type" : "number"
},
"familySituation": {
"type" : "number"
},
"spousePension": {
"type" : "number"
},
"childPension": {
"type" : "number"
},
"hasHousingPaymentBefore": {
"type" : "number"
},
"hasHousingPaymentAfter": {
"type" : "number"
},
"updated": {
"type" : "date"
}
},
"relations": {
"disabilityGrade": {
"type": "belongsTo",
"model": "disabilityGrade",
"foreignKey": "disabilityGradeFk"
}
}
}

View File

@ -0,0 +1,53 @@
{
"name": "WorkerRelative",
"description": "Model 145 IRPF",
"base": "VnModel",
"options": {
"mysql": {
"table": "workerRelatives"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"workerFk": {
"type": "number"
},
"isDescendant": {
"type": "number"
},
"disabilityGradeFk": {
"type" : "number"
},
"birthed": {
"type" : "number"
},
"adoptionYear": {
"type" : "number"
},
"isDependend": {
"type" : "boolean"
},
"isJointCustody": {
"type" : "boolean"
},
"updated": {
"type" : "date"
}
},
"relations": {
"disabilityGrade": {
"type": "belongsTo",
"model": "disabilityGrade",
"foreignKey": "disabilityGradeFk"
},
"worker": {
"type": "belongsTo",
"model": "VnUser",
"foreignKey": "workerFK"
}
}
}

View File

@ -11,6 +11,15 @@
"id": true,
"type": "number"
},
"mailPass": {
"type": "string"
},
"mailHost": {
"type": "string"
},
"mailUser": {
"type": "string"
},
"breakTime": {
"type": "number"
},
@ -23,5 +32,13 @@
"teleworkingStartBreakTime": {
"type": "number"
}
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -1,35 +0,0 @@
{
"name": "WorkerTimeControlParams",
"description": "imap config",
"base": "VnModel",
"options": {
"mysql": {
"table": "workerTimeControlParams"
}
},
"properties": {
"mailHost": {
"type": "string"
},
"mailUser": {
"type": "string"
},
"mailPass": {
"type": "string"
},
"mailSuccessFolder": {
"type": "string"
},
"mailErrorFolder": {
"type": "string"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -132,6 +132,16 @@
"type": "hasMany",
"model": "WorkerTimeControlMail",
"foreignKey": "workerFk"
},
"irpf": {
"type": "hasMany",
"model": "WorkerIrpf",
"foreignKey": "workerFk"
},
"workerRelative": {
"type": "hasMany",
"model": "WorkerRelative",
"foreignKey": "workerFK"
}
},
"acls": [
@ -317,4 +327,4 @@
]
}
}
}
}

View File

@ -385,7 +385,6 @@ localFixtures:
- workerTimeControl
- workerTimeControlConfig
- workerTimeControlMail
- workerTimeControlParams
- zone
- zoneAgencyMode
- zoneClosure