Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into test
gitea/salix/test This commit looks good
Details
gitea/salix/test This commit looks good
Details
This commit is contained in:
commit
615cfe15cc
|
@ -62,7 +62,7 @@ module.exports = Self => {
|
||||||
*/
|
*/
|
||||||
Self.hasRole = async function(userId, name) {
|
Self.hasRole = async function(userId, name) {
|
||||||
let roles = await Self.getRoles(userId);
|
let roles = await Self.getRoles(userId);
|
||||||
return roles.find(role => role == name);
|
return roles.some(role => role == name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,6 +26,12 @@ CREATE TABLE `vn`.`zoneEvent` (
|
||||||
CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`zoneEvent`
|
||||||
|
ADD COLUMN `type` ENUM('day', 'indefinitely', 'range') NOT NULL AFTER `zoneFk`,
|
||||||
|
ADD COLUMN `dated` DATE NULL DEFAULT NULL AFTER `type`,
|
||||||
|
CHANGE COLUMN `from` `started` DATE NULL DEFAULT NULL ,
|
||||||
|
CHANGE COLUMN `to` `ended` DATE NULL DEFAULT NULL ;
|
||||||
|
|
||||||
CREATE TABLE `vn`.`zoneExclusion` (
|
CREATE TABLE `vn`.`zoneExclusion` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`zoneFk` int(11) NOT NULL,
|
`zoneFk` int(11) NOT NULL,
|
||||||
|
@ -45,3 +51,6 @@ ADD CONSTRAINT `fk_zone_1`
|
||||||
REFERENCES `vn`.`warehouse` (`id`)
|
REFERENCES `vn`.`warehouse` (`id`)
|
||||||
ON DELETE NO ACTION
|
ON DELETE NO ACTION
|
||||||
ON UPDATE CASCADE;
|
ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`zoneExclusion`
|
||||||
|
CHANGE COLUMN `day` `dated` DATE NOT NULL ;
|
|
@ -37,11 +37,11 @@ BEGIN
|
||||||
WHERE z.agencyModeFk != vAgencyModeFk;
|
WHERE z.agencyModeFk != vAgencyModeFk;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT e.`from`, e.`to`, e.weekDays
|
SELECT e.`type`, e.dated, e.`started`, e.`ended`, e.weekDays
|
||||||
FROM tmp.zone t
|
FROM tmp.zone t
|
||||||
JOIN zoneEvent e ON e.zoneFk = t.id;
|
JOIN zoneEvent e ON e.zoneFk = t.id;
|
||||||
|
|
||||||
SELECT DISTINCT e.`day`
|
SELECT DISTINCT e.dated
|
||||||
FROM tmp.zone t
|
FROM tmp.zone t
|
||||||
JOIN zoneExclusion e ON e.zoneFk = t.id;
|
JOIN zoneExclusion e ON e.zoneFk = t.id;
|
||||||
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
|
|
||||||
DROP PROCEDURE IF EXISTS `vn`.`zone_getOptionsForLanding`;
|
|
||||||
DELIMITER $$
|
|
||||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zone_getOptionsForLanding`(vLanded DATE)
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Gets computed options for the passed zones and delivery date.
|
|
||||||
*
|
|
||||||
* @table tmp.zones(id) The zones ids
|
|
||||||
* @param vLanded The delivery date
|
|
||||||
* @return tmp.zoneOption The computed options
|
|
||||||
*/
|
|
||||||
DECLARE vHour TIME DEFAULT TIME(NOW());
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tTemp;
|
|
||||||
CREATE TEMPORARY TABLE tTemp
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT t.id zoneFk,
|
|
||||||
TIME(e.`hour`) `hour`,
|
|
||||||
e.travelingDays,
|
|
||||||
e.price,
|
|
||||||
e.bonus,
|
|
||||||
CASE
|
|
||||||
WHEN e.`from` IS NULL AND e.`to` IS NULL
|
|
||||||
THEN 3
|
|
||||||
WHEN e.`to` IS NULL
|
|
||||||
THEN 2
|
|
||||||
ELSE 1
|
|
||||||
END specificity
|
|
||||||
FROM tmp.zone t
|
|
||||||
JOIN zoneEvent e ON e.zoneFk = t.id
|
|
||||||
WHERE (e.`from` = vLanded AND e.`to` IS NULL)
|
|
||||||
OR (
|
|
||||||
(e.`from` IS NULL OR vLanded BETWEEN e.`from` AND e.`to`)
|
|
||||||
AND e.weekDays & (1 << WEEKDAY(vLanded))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- XXX: Compatibility with the deprecated #zoneCalendar table
|
|
||||||
|
|
||||||
INSERT INTO tTemp
|
|
||||||
SELECT t.id zoneFk,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
c.price,
|
|
||||||
c.bonus,
|
|
||||||
4
|
|
||||||
FROM tmp.zone t
|
|
||||||
JOIN zoneCalendar c ON c.zoneFk = t.id
|
|
||||||
WHERE c.delivered = vLanded;
|
|
||||||
|
|
||||||
DELETE t FROM tTemp t
|
|
||||||
JOIN zoneExclusion e
|
|
||||||
ON e.zoneFk = t.zoneFk AND e.`day` = vLanded;
|
|
||||||
|
|
||||||
UPDATE tTemp t
|
|
||||||
JOIN zone z ON z.id = t.zoneFk
|
|
||||||
SET t.`hour` = IFNULL(t.`hour`, TIME(z.`hour`)),
|
|
||||||
t.travelingDays = IFNULL(t.travelingDays, z.travelingDays),
|
|
||||||
t.price = IFNULL(t.price, z.price),
|
|
||||||
t.bonus = IFNULL(t.bonus, z.bonus);
|
|
||||||
|
|
||||||
DELETE FROM tTemp
|
|
||||||
WHERE (@shipped := TIMESTAMPADD(DAY, -travelingDays, vLanded)) < CURDATE()
|
|
||||||
OR @shipped = CURDATE() AND vHour > `hour`;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
|
|
||||||
CREATE TEMPORARY TABLE tmp.zoneOption
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT *
|
|
||||||
FROM (
|
|
||||||
SELECT * FROM tTemp
|
|
||||||
ORDER BY zoneFk, specificity
|
|
||||||
) t
|
|
||||||
GROUP BY zoneFk;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tTemp;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ BEGIN
|
||||||
JOIN zone z ON z.id = zo.zoneFk
|
JOIN zone z ON z.id = zo.zoneFk
|
||||||
JOIN zoneWarehouse zw ON zw.zoneFk = z.id
|
JOIN zoneWarehouse zw ON zw.zoneFk = z.id
|
||||||
WHERE agencyModeFk = vAgencyModeFk
|
WHERE agencyModeFk = vAgencyModeFk
|
||||||
AND warehouseFk = vWarehouseFk;
|
AND zw.warehouseFk = vWarehouseFk;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE
|
DROP TEMPORARY TABLE
|
||||||
tmp.zone,
|
tmp.zone,
|
|
@ -0,0 +1,67 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `zone_getOptionsForLanding`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getOptionsForLanding`(vLanded DATE)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Gets computed options for the passed zones and delivery date.
|
||||||
|
*
|
||||||
|
* @table tmp.zones(id) The zones ids
|
||||||
|
* @param vLanded The delivery date
|
||||||
|
* @return tmp.zoneOption The computed options
|
||||||
|
*/
|
||||||
|
DECLARE vHour TIME DEFAULT TIME(NOW());
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tTemp;
|
||||||
|
CREATE TEMPORARY TABLE tTemp
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT t.id zoneFk,
|
||||||
|
IFNULL(TIME(e.`hour`), TIME(z.`hour`)) `hour`,
|
||||||
|
IFNULL(e.travelingDays, z.travelingDays) travelingDays,
|
||||||
|
IFNULL(e.price, z.price) price,
|
||||||
|
IFNULL(e.bonus, z.bonus) bonus,
|
||||||
|
CASE
|
||||||
|
WHEN e.`type` = 'day'
|
||||||
|
THEN 1
|
||||||
|
WHEN e.`type` = 'range'
|
||||||
|
THEN 2
|
||||||
|
ELSE 3
|
||||||
|
END specificity
|
||||||
|
FROM tmp.zone t
|
||||||
|
JOIN zone z ON z.id = t.id
|
||||||
|
JOIN zoneEvent e ON e.zoneFk = t.id
|
||||||
|
WHERE (
|
||||||
|
e.`type` = 'day'
|
||||||
|
AND e.dated = vLanded
|
||||||
|
) OR (
|
||||||
|
e.`type` != 'day'
|
||||||
|
AND e.weekDays & (1 << WEEKDAY(vLanded))
|
||||||
|
AND (e.`started` IS NULL OR vLanded >= e.`started`)
|
||||||
|
AND (e.`ended` IS NULL OR vLanded <= e.`ended`)
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE t FROM tTemp t
|
||||||
|
JOIN zoneExclusion e
|
||||||
|
ON e.zoneFk = t.zoneFk AND e.`dated` = vLanded;
|
||||||
|
|
||||||
|
DELETE FROM tTemp
|
||||||
|
WHERE (@shipped := TIMESTAMPADD(DAY, -travelingDays, vLanded)) < CURDATE()
|
||||||
|
OR @shipped = CURDATE() AND vHour > `hour`;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
|
||||||
|
CREATE TEMPORARY TABLE tmp.zoneOption
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT *
|
||||||
|
FROM (
|
||||||
|
SELECT * FROM tTemp
|
||||||
|
ORDER BY zoneFk, specificity
|
||||||
|
) t
|
||||||
|
GROUP BY zoneFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tTemp;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `zone_getOptionsForShipment`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getOptionsForShipment`(vShipped DATE)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Gets computed options for the passed zones and shipping date.
|
||||||
|
*
|
||||||
|
* @table tmp.zones(id) The zones ids
|
||||||
|
* @param vShipped The shipping date
|
||||||
|
* @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options
|
||||||
|
*/
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tLandings;
|
||||||
|
CREATE TEMPORARY TABLE tLandings
|
||||||
|
(INDEX (eventFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT e.id eventFk,
|
||||||
|
@travelingDays := IFNULL(e.travelingDays, z.travelingDays) travelingDays,
|
||||||
|
TIMESTAMPADD(DAY, @travelingDays, vShipped) landed
|
||||||
|
FROM tmp.zone t
|
||||||
|
JOIN zone z ON z.id = t.id
|
||||||
|
JOIN zoneEvent e ON e.zoneFk = t.id;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tTemp;
|
||||||
|
CREATE TEMPORARY TABLE tTemp
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT t.id zoneFk,
|
||||||
|
IFNULL(TIME(e.`hour`), TIME(z.`hour`)) `hour`,
|
||||||
|
IFNULL(e.price, z.price) price,
|
||||||
|
IFNULL(e.bonus, z.bonus) bonus,
|
||||||
|
CASE
|
||||||
|
WHEN e.`type` = 'day'
|
||||||
|
THEN 1
|
||||||
|
WHEN e.`type` = 'range'
|
||||||
|
THEN 2
|
||||||
|
ELSE 3
|
||||||
|
END specificity,
|
||||||
|
l.travelingDays,
|
||||||
|
l.landed
|
||||||
|
FROM tmp.zone t
|
||||||
|
JOIN zone z ON z.id = t.id
|
||||||
|
JOIN zoneEvent e ON e.zoneFk = t.id
|
||||||
|
JOIN tLandings l ON l.eventFk = e.id
|
||||||
|
WHERE (
|
||||||
|
e.`type` = 'day'
|
||||||
|
AND e.`dated` = l.landed
|
||||||
|
) OR (
|
||||||
|
e.`type` != 'day'
|
||||||
|
AND e.weekDays & (1 << WEEKDAY(l.landed))
|
||||||
|
AND (e.`started` IS NULL OR l.landed >= e.`started`)
|
||||||
|
AND (e.`ended` IS NULL OR l.landed <= e.`ended`)
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE t FROM tTemp t
|
||||||
|
JOIN zoneExclusion e
|
||||||
|
ON e.zoneFk = t.zoneFk AND e.`dated` = t.landed;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
|
||||||
|
CREATE TEMPORARY TABLE tmp.zoneOption
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT *
|
||||||
|
FROM (
|
||||||
|
SELECT * FROM tTemp
|
||||||
|
ORDER BY zoneFk, specificity
|
||||||
|
) t
|
||||||
|
GROUP BY zoneFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tTemp,
|
||||||
|
tLandings;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
USE `vn`;
|
|
||||||
DROP procedure IF EXISTS `ticketCreateWithUser`;
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
USE `vn`$$
|
|
||||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticketCreateWithUser`(
|
|
||||||
vClientId INT
|
|
||||||
,vShipped DATE
|
|
||||||
,vWarehouseFk INT
|
|
||||||
,vCompanyFk INT
|
|
||||||
,vAddressFk INT
|
|
||||||
,vAgencyModeFk INT
|
|
||||||
,vRouteFk INT
|
|
||||||
,vlanded DATE
|
|
||||||
,vUserId INT
|
|
||||||
,OUT vNewTicket INT)
|
|
||||||
BEGIN
|
|
||||||
|
|
||||||
DECLARE vZoneFk INT;
|
|
||||||
|
|
||||||
IF vClientId IS NULL THEN
|
|
||||||
CALL util.throw ('CLIENT_NOT_ESPECIFIED');
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF NOT vAddressFk OR vAddressFk IS NULL THEN
|
|
||||||
SELECT id INTO vAddressFk
|
|
||||||
FROM address
|
|
||||||
WHERE clientFk = vClientId AND isDefaultAddress;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF vAgencyModeFk IS NOT NULL THEN
|
|
||||||
|
|
||||||
CALL vn.zone_getShippedWarehouse(vlanded, vAddressFk, vAgencyModeFk);
|
|
||||||
|
|
||||||
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetShipped
|
|
||||||
WHERE shipped = vShipped AND warehouseFk = vWarehouseFk LIMIT 1;
|
|
||||||
|
|
||||||
IF vZoneFk IS NULL OR vZoneFk = 0 THEN
|
|
||||||
CALL util.throw ('NOT_ZONE_WITH_THIS_PARAMETERS');
|
|
||||||
END IF;
|
|
||||||
END IF;
|
|
||||||
INSERT INTO vn2008.Tickets (
|
|
||||||
Id_Cliente,
|
|
||||||
Fecha,
|
|
||||||
Id_Consigna,
|
|
||||||
Id_Agencia,
|
|
||||||
Alias,
|
|
||||||
warehouse_id,
|
|
||||||
Id_Ruta,
|
|
||||||
empresa_id,
|
|
||||||
landing,
|
|
||||||
zoneFk
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
vClientId,
|
|
||||||
vShipped,
|
|
||||||
a.id,
|
|
||||||
vAgencyModeFk,
|
|
||||||
a.nickname,
|
|
||||||
vWarehouseFk,
|
|
||||||
IF(vRouteFk,vRouteFk,NULL),
|
|
||||||
vCompanyFk,
|
|
||||||
vlanded,
|
|
||||||
vZoneFk
|
|
||||||
FROM address a
|
|
||||||
JOIN agencyMode am ON am.id = a.agencyModeFk
|
|
||||||
WHERE a.id = vAddressFk;
|
|
||||||
|
|
||||||
SET vNewTicket = LAST_INSERT_ID();
|
|
||||||
|
|
||||||
INSERT INTO ticketObservation(ticketFk, observationTypeFk, description)
|
|
||||||
SELECT vNewTicket, ao.observationTypeFk, ao.description
|
|
||||||
FROM addressObservation ao
|
|
||||||
JOIN address a ON a.id = ao.addressFk
|
|
||||||
WHERE a.id = vAddressFk;
|
|
||||||
|
|
||||||
INSERT INTO vn.ticketLog
|
|
||||||
SET originFk = vNewTicket, userFk = vUserId, `action` = 'insert', description = CONCAT('Ha creado el ticket:', ' ', vNewTicket);
|
|
||||||
|
|
||||||
IF (SELECT ct.isCreatedAsServed FROM vn.clientType ct JOIN vn.client c ON c.typeFk = ct.code WHERE c.id = vClientId ) <> FALSE THEN
|
|
||||||
INSERT INTO vncontrol.inter(state_id, Id_Ticket, Id_Trabajador)
|
|
||||||
SELECT id, vNewTicket, getWorker()
|
|
||||||
FROM state
|
|
||||||
WHERE `code` = 'DELIVERED';
|
|
||||||
END IF;
|
|
||||||
END$$
|
|
||||||
|
|
||||||
DELIMITER ;
|
|
|
@ -1,83 +0,0 @@
|
||||||
|
|
||||||
USE `vn`;
|
|
||||||
DROP procedure IF EXISTS `vn`.`zone_getOptionsForLanding`;
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
USE `vn`$$
|
|
||||||
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getOptionsForLanding`(vLanded DATE)
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Gets computed options for the passed zones and delivery date.
|
|
||||||
*
|
|
||||||
* @table tmp.zones(id) The zones ids
|
|
||||||
* @param vLanded The delivery date
|
|
||||||
* @return tmp.zoneOption The computed options
|
|
||||||
*/
|
|
||||||
DECLARE vHour TIME DEFAULT TIME(NOW());
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tTemp;
|
|
||||||
CREATE TEMPORARY TABLE tTemp
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT t.id zoneFk,
|
|
||||||
TIME(e.`hour`) `hour`,
|
|
||||||
e.travelingDays,
|
|
||||||
e.price,
|
|
||||||
e.bonus,
|
|
||||||
CASE
|
|
||||||
WHEN e.`from` IS NULL AND e.`to` IS NULL
|
|
||||||
THEN 3
|
|
||||||
WHEN e.`to` IS NULL
|
|
||||||
THEN 2
|
|
||||||
ELSE 1
|
|
||||||
END specificity
|
|
||||||
FROM tmp.zone t
|
|
||||||
JOIN zoneEvent e ON e.zoneFk = t.id
|
|
||||||
WHERE (e.`from` = vLanded AND e.`to` IS NULL)
|
|
||||||
OR (
|
|
||||||
(e.`from` IS NULL OR vLanded BETWEEN e.`from` AND e.`to`)
|
|
||||||
AND e.weekDays & (1 << WEEKDAY(vLanded))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- XXX: Compatibility with the deprecated #zoneCalendar table
|
|
||||||
|
|
||||||
INSERT INTO tTemp
|
|
||||||
SELECT t.id zoneFk,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
c.price,
|
|
||||||
c.bonus,
|
|
||||||
4
|
|
||||||
FROM tmp.zone t
|
|
||||||
JOIN zoneCalendar c ON c.zoneFk = t.id
|
|
||||||
WHERE c.delivered = vLanded;
|
|
||||||
|
|
||||||
DELETE t FROM tTemp t
|
|
||||||
JOIN zoneExclusion e
|
|
||||||
ON e.zoneFk = t.zoneFk AND e.`day` = vLanded;
|
|
||||||
|
|
||||||
UPDATE tTemp t
|
|
||||||
JOIN zone z ON z.id = t.zoneFk
|
|
||||||
SET t.`hour` = IFNULL(t.`hour`, TIME(z.`hour`)),
|
|
||||||
t.travelingDays = IFNULL(t.travelingDays, z.travelingDays),
|
|
||||||
t.price = IFNULL(t.price, z.price),
|
|
||||||
t.bonus = IFNULL(t.bonus, z.bonus);
|
|
||||||
|
|
||||||
DELETE FROM tTemp
|
|
||||||
WHERE (@shipped := TIMESTAMPADD(DAY, -travelingDays, vLanded)) < CURDATE()
|
|
||||||
OR @shipped = CURDATE() AND vHour > `hour`;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
|
|
||||||
CREATE TEMPORARY TABLE tmp.zoneOption
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT *
|
|
||||||
FROM (
|
|
||||||
SELECT * FROM tTemp
|
|
||||||
ORDER BY zoneFk, specificity
|
|
||||||
) t
|
|
||||||
GROUP BY zoneFk;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tTemp;
|
|
||||||
END$$
|
|
||||||
|
|
||||||
DELIMITER ;
|
|
||||||
;
|
|
|
@ -1,65 +0,0 @@
|
||||||
USE `vn`;
|
|
||||||
DROP procedure IF EXISTS `zone_getOptionsForShipment`;
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
USE `vn`$$
|
|
||||||
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getOptionsForShipment`(vShipped DATE)
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Gets computed options for the passed zones and shipping date.
|
|
||||||
*
|
|
||||||
* @table tmp.zones(id) The zones ids
|
|
||||||
* @param vShipped The shipping date
|
|
||||||
* @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options
|
|
||||||
*/
|
|
||||||
DECLARE vHour TIME DEFAULT TIME(NOW());
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tTemp;
|
|
||||||
CREATE TEMPORARY TABLE tTemp
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT t.id zoneFk,
|
|
||||||
TIME(e.`hour`) `hour`,
|
|
||||||
e.travelingDays,
|
|
||||||
e.price,
|
|
||||||
e.bonus,
|
|
||||||
CASE
|
|
||||||
WHEN e.`from` IS NULL AND e.`to` IS NULL
|
|
||||||
THEN 3
|
|
||||||
WHEN e.`to` IS NULL
|
|
||||||
THEN 2
|
|
||||||
ELSE 1
|
|
||||||
END specificity
|
|
||||||
FROM tmp.zone t
|
|
||||||
JOIN zoneEvent e ON e.zoneFk = t.id
|
|
||||||
WHERE (e.`from` = TIMESTAMPADD(DAY, e.travelingDays, vShipped) AND e.`to` IS NULL)
|
|
||||||
OR (
|
|
||||||
(e.`from` IS NULL OR TIMESTAMPADD(DAY, e.travelingDays, vShipped) BETWEEN e.`from` AND e.`to`)
|
|
||||||
AND e.weekDays & (1 << WEEKDAY(TIMESTAMPADD(DAY, e.travelingDays, vShipped)))
|
|
||||||
);
|
|
||||||
|
|
||||||
DELETE t FROM tTemp t
|
|
||||||
JOIN zoneExclusion e
|
|
||||||
ON e.zoneFk = t.zoneFk AND TIMESTAMPADD(DAY,-t.travelingDays, e.`day`) = vShipped;
|
|
||||||
|
|
||||||
UPDATE tTemp t
|
|
||||||
JOIN zone z ON z.id = t.zoneFk
|
|
||||||
SET t.`hour` = IFNULL(t.`hour`, TIME(z.`hour`)),
|
|
||||||
t.travelingDays = IFNULL(t.travelingDays, z.travelingDays),
|
|
||||||
t.price = IFNULL(t.price, z.price),
|
|
||||||
t.bonus = IFNULL(t.bonus, z.bonus);
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
|
|
||||||
CREATE TEMPORARY TABLE tmp.zoneOption
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT *
|
|
||||||
FROM (
|
|
||||||
SELECT * FROM tTemp
|
|
||||||
ORDER BY zoneFk, specificity
|
|
||||||
) t
|
|
||||||
GROUP BY zoneFk;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tTemp;
|
|
||||||
END$$
|
|
||||||
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
USE `vn`;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`payMethod`
|
||||||
|
ADD COLUMN `code` VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' NULL AFTER `id`;
|
||||||
|
|
||||||
|
UPDATE `vn`.`payMethod` SET `code` = 'bankDraft' WHERE (`id` = '4');
|
||||||
|
UPDATE `vn`.`payMethod` SET `code` = 'card' WHERE (`id` = '5');
|
|
@ -0,0 +1,116 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticketClosure`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticketClosure`()
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Realiza el cierre de todos los
|
||||||
|
* tickets de la table ticketClosure.
|
||||||
|
*/
|
||||||
|
DECLARE vDone BOOL;
|
||||||
|
DECLARE vClientFk INT;
|
||||||
|
DECLARE vTicketFk INT;
|
||||||
|
DECLARE vIsTaxDataChecked BOOL;
|
||||||
|
DECLARE vCompanyFk INT;
|
||||||
|
DECLARE vShipped DATE;
|
||||||
|
DECLARE vPriority INT DEFAULT 1;
|
||||||
|
DECLARE vReportDeliveryNote INT DEFAULT 1;
|
||||||
|
DECLARE vNewInvoiceId INT;
|
||||||
|
DECLARE vHasDailyInvoice BOOL;
|
||||||
|
DECLARE vWithPackage BOOL;
|
||||||
|
|
||||||
|
DECLARE cur CURSOR FOR
|
||||||
|
SELECT ticketFk FROM tmp.ticketClosure;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketClosure2;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticketClosure2
|
||||||
|
SELECT ticketFk FROM tmp.ticketClosure;
|
||||||
|
INSERT INTO tmp.ticketClosure
|
||||||
|
SELECT id FROM stowaway s
|
||||||
|
JOIN tmp.ticketClosure2 tc ON s.shipFk = tc.ticketFk;
|
||||||
|
OPEN cur;
|
||||||
|
|
||||||
|
proc: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
|
||||||
|
FETCH cur INTO vTicketFk;
|
||||||
|
|
||||||
|
IF vDone THEN
|
||||||
|
LEAVE proc;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- ticketClosure start
|
||||||
|
SELECT
|
||||||
|
c.id,
|
||||||
|
c.isTaxDataChecked,
|
||||||
|
t.companyFk,
|
||||||
|
t.shipped,
|
||||||
|
co.hasDailyInvoice,
|
||||||
|
w.isManaged
|
||||||
|
INTO vClientFk,
|
||||||
|
vIsTaxDataChecked,
|
||||||
|
vCompanyFk,
|
||||||
|
vShipped,
|
||||||
|
vHasDailyInvoice,
|
||||||
|
vWithPackage
|
||||||
|
FROM ticket t
|
||||||
|
JOIN `client` c ON c.id = t.clientFk
|
||||||
|
JOIN province p ON p.id = c.provinceFk
|
||||||
|
JOIN country co ON co.id = p.countryFk
|
||||||
|
JOIN warehouse w ON w.id = t.warehouseFk
|
||||||
|
WHERE t.id = vTicketFk;
|
||||||
|
|
||||||
|
INSERT INTO ticketPackaging (ticketFk, packagingFk, quantity)
|
||||||
|
(SELECT vTicketFk, p.id, COUNT(*)
|
||||||
|
FROM expedition e
|
||||||
|
JOIN packaging p ON p.itemFk = e.itemFk
|
||||||
|
WHERE e.ticketFk = vTicketFk AND p.isPackageReturnable
|
||||||
|
AND vWithPackage
|
||||||
|
GROUP BY p.itemFk);
|
||||||
|
|
||||||
|
-- No retornables o no catalogados
|
||||||
|
INSERT INTO sale (itemFk, ticketFk, concept, quantity, price, isPriceFixed)
|
||||||
|
(SELECT e.itemFk, vTicketFk, i.name, COUNT(*) AS amount, getSpecialPrice(e.itemFk, vClientFk), 1
|
||||||
|
FROM expedition e
|
||||||
|
JOIN item i ON i.id = e.itemFk
|
||||||
|
LEFT JOIN packaging p ON p.itemFk = i.id
|
||||||
|
WHERE e.ticketFk = vTicketFk AND IFNULL(p.isPackageReturnable, 0) = 0
|
||||||
|
AND getSpecialPrice(e.itemFk, vClientFk) > 0
|
||||||
|
GROUP BY e.itemFk);
|
||||||
|
|
||||||
|
IF(vHasDailyInvoice) THEN
|
||||||
|
|
||||||
|
-- Facturacion rapida
|
||||||
|
CALL ticketTrackingAdd(vTicketFk, 'DELIVERED', NULL);
|
||||||
|
-- Facturar si está contabilizado
|
||||||
|
IF vIsTaxDataChecked THEN
|
||||||
|
CALL invoiceOut_newFromClient(
|
||||||
|
vClientFk,
|
||||||
|
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'M')),
|
||||||
|
vShipped,
|
||||||
|
vCompanyFk,
|
||||||
|
NULL,
|
||||||
|
vNewInvoiceId);
|
||||||
|
END IF;
|
||||||
|
ELSE
|
||||||
|
-- Albaran_print
|
||||||
|
CALL ticketTrackingAdd(vTicketFk, (SELECT vn.getAlert3State(vTicketFk)), NULL);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- ticketClosure end
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
CLOSE cur;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketClosure2;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -84,3 +84,25 @@ BEGIN
|
||||||
END IF;
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
||||||
|
USE `vn`;
|
||||||
|
CREATE
|
||||||
|
OR REPLACE ALGORITHM = UNDEFINED
|
||||||
|
DEFINER = `root`@`%`
|
||||||
|
SQL SECURITY DEFINER
|
||||||
|
VIEW `vn`.`ticketRequest__` AS
|
||||||
|
SELECT
|
||||||
|
`t`.`Id_ORDEN` AS `id`,
|
||||||
|
`t`.`ORDEN` AS `description`,
|
||||||
|
`t`.`requesterFk` AS `requesterFk`,
|
||||||
|
`t`.`attenderFk` AS `attenderFk`,
|
||||||
|
`t`.`CANTIDAD` AS `quantity`,
|
||||||
|
`t`.`Id_ARTICLE` AS `itemFk`,
|
||||||
|
`t`.`PRECIOMAX` AS `price`,
|
||||||
|
`t`.`isOk` AS `isOk`,
|
||||||
|
`t`.`Id_Movimiento` AS `saleFk`,
|
||||||
|
`t`.`ticketFk` AS `ticketFk`,
|
||||||
|
`t`.`COMENTARIO` AS `response`,
|
||||||
|
`t`.`odbc_date` AS `created`
|
||||||
|
FROM
|
||||||
|
`vn2008`.`Ordenes` `t`;
|
||||||
|
|
|
@ -62,13 +62,13 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
|
||||||
(19,'Francia', 1, 'FR', 1, 27),
|
(19,'Francia', 1, 'FR', 1, 27),
|
||||||
(30,'Canarias', 1, 'IC', 1, 24);
|
(30,'Canarias', 1, 'IC', 1, 24);
|
||||||
|
|
||||||
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`)
|
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Warehouse One', 1, 1, 1, 1, 1, 1),
|
(1, 'Warehouse One', 1, 1, 1, 1, 1, 1, 1),
|
||||||
(2, 'Warehouse Two', 1, 1, 1, 1, 0, 0),
|
(2, 'Warehouse Two', 1, 1, 1, 1, 0, 0, 1),
|
||||||
(3, 'Warehouse Three', 1, 1, 1, 1, 0, 0),
|
(3, 'Warehouse Three', 1, 1, 1, 1, 0, 0, 0),
|
||||||
(4, 'Warehouse Four', 1, 1, 1, 1, 0, 0),
|
(4, 'Warehouse Four', 1, 1, 1, 1, 0, 0, 0),
|
||||||
(5, 'Warehouse Five', 1, 1, 1, 1, 0, 0);
|
(5, 'Warehouse Five', 1, 1, 1, 1, 0, 0, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`)
|
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1619,227 +1619,227 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
|
||||||
(8, 5, 0),
|
(8, 5, 0),
|
||||||
(8, 1, 1);
|
(8, 1, 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `from`)
|
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 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, 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, 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, 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, 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, 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, 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, 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, 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)),
|
||||||
(2, DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
|
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
|
||||||
(3, CURDATE()),
|
(3, 'day', CURDATE()),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
||||||
(3, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
||||||
(4, CURDATE()),
|
(4, 'day', CURDATE()),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
||||||
(4, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
||||||
(5, CURDATE()),
|
(5, 'day', CURDATE()),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
||||||
(5, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
||||||
(6, CURDATE()),
|
(6, 'day', CURDATE()),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
|
||||||
(6, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
|
||||||
(7, CURDATE()),
|
(7, 'day', CURDATE()),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(7, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
|
||||||
(8, CURDATE()),
|
(8, 'day', CURDATE()),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
|
||||||
(8, DATE_ADD(CURDATE(), INTERVAL +6 DAY));
|
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY));
|
||||||
|
|
||||||
INSERT INTO `vn`.`workerTimeControl`(`userFk`,`timed`,`manual`)
|
INSERT INTO `vn`.`workerTimeControl`(`userFk`,`timed`,`manual`, `direction`)
|
||||||
VALUES
|
VALUES
|
||||||
(106, CONCAT(CURDATE(), ' 07:00'), TRUE),
|
(106, CONCAT(CURDATE(), ' 07:00'), TRUE, 'in'),
|
||||||
(106, CONCAT(CURDATE(), ' 10:00'), TRUE),
|
(106, CONCAT(CURDATE(), ' 10:00'), TRUE, 'middle'),
|
||||||
(106, CONCAT(CURDATE(), ' 10:10'), TRUE),
|
(106, CONCAT(CURDATE(), ' 10:10'), TRUE, 'middle'),
|
||||||
(106, CONCAT(CURDATE(), ' 15:00'), TRUE);
|
(106, CONCAT(CURDATE(), ' 15:00'), TRUE, 'out');
|
||||||
|
|
||||||
INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `code`)
|
INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `code`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1951,3 +1951,8 @@ INSERT INTO `vn`.`userPhone`(`id`, `userFk`, `typeFk`, `phone`)
|
||||||
(65, 107, 'businessPhone', 700987987),
|
(65, 107, 'businessPhone', 700987987),
|
||||||
(67, 106, 'businessPhone', 1111111112),
|
(67, 106, 'businessPhone', 1111111112),
|
||||||
(68, 106, 'personalPhone', 1111111113);
|
(68, 106, 'personalPhone', 1111111113);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`)
|
||||||
|
VALUES
|
||||||
|
(1, 43200, 129600, 734400, 43200, 50400);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
// #1885
|
||||||
|
xdescribe('order_confirmWithUser()', () => {
|
||||||
|
it('should confirm an order', async() => {
|
||||||
|
let stmts = [];
|
||||||
|
let stmt;
|
||||||
|
|
||||||
|
stmts.push('START TRANSACTION');
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
orderFk: 10,
|
||||||
|
userId: 9
|
||||||
|
};
|
||||||
|
// problema: la funcion order_confirmWithUser tiene una transacción, por tanto esta nunca hace rollback
|
||||||
|
stmt = new ParameterizedSQL('CALL hedera.order_confirmWithUser(?, ?)', [
|
||||||
|
params.orderFk,
|
||||||
|
params.userId
|
||||||
|
]);
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
stmt = new ParameterizedSQL('SELECT confirmed FROM hedera.order WHERE id = ?', [
|
||||||
|
params.orderFk
|
||||||
|
]);
|
||||||
|
let orderIndex = stmts.push(stmt) - 1;
|
||||||
|
|
||||||
|
stmts.push('ROLLBACK');
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await app.models.Ticket.rawStmt(sql);
|
||||||
|
|
||||||
|
savedDescription = result[orderIndex][0].confirmed;
|
||||||
|
|
||||||
|
expect(savedDescription).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -679,34 +679,35 @@ export default {
|
||||||
saturdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button',
|
saturdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button',
|
||||||
sundayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(7) > vn-icon-button',
|
sundayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(7) > vn-icon-button',
|
||||||
confirmButton: '.vn-dialog.shown tpl-buttons > button',
|
confirmButton: '.vn-dialog.shown tpl-buttons > button',
|
||||||
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > span',
|
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > span',
|
firstEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > span',
|
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > span',
|
firstEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > span',
|
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > span',
|
firstEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > vn-chip > div',
|
||||||
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > span',
|
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > vn-chip > div',
|
||||||
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > span',
|
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > span',
|
secondEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > span',
|
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > span',
|
secondEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > span',
|
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > span',
|
secondEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > vn-chip > div',
|
||||||
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > span',
|
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > vn-chip > div',
|
||||||
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > span',
|
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > div',
|
||||||
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > span',
|
thirdEntryOfMondayDelete: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > vn-icon[icon="cancel"]',
|
||||||
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > span',
|
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > vn-chip > div',
|
||||||
thirdEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > span',
|
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > vn-chip > div',
|
||||||
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > span',
|
thirdEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > vn-chip > div',
|
||||||
thirdEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > span',
|
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > vn-chip > div',
|
||||||
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > span',
|
thirdEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > vn-chip > div',
|
||||||
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > span',
|
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > vn-chip > div',
|
||||||
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > span',
|
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > vn-chip > div',
|
||||||
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > span',
|
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > vn-chip > div',
|
||||||
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > span',
|
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > vn-chip > div',
|
||||||
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > span',
|
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > vn-chip > div',
|
||||||
fourthEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > span',
|
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > vn-chip > div',
|
||||||
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > span',
|
fourthEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > vn-chip > div',
|
||||||
|
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > vn-chip > div',
|
||||||
mondayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(1)',
|
mondayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(1)',
|
||||||
tuesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
|
tuesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
|
||||||
wednesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(3)',
|
wednesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(3)',
|
||||||
|
@ -717,7 +718,8 @@ export default {
|
||||||
weekWorkedHours: 'vn-worker-time-control vn-side-menu vn-label-value > section > span',
|
weekWorkedHours: 'vn-worker-time-control vn-side-menu vn-label-value > section > span',
|
||||||
nextMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_right]',
|
nextMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_right]',
|
||||||
secondWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(8) > .day-number',
|
secondWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(8) > .day-number',
|
||||||
navigateBackToIndex: 'vn-worker-descriptor vn-icon[icon="chevron_left"]'
|
navigateBackToIndex: 'vn-worker-descriptor vn-icon[icon="chevron_left"]',
|
||||||
|
acceptDeleteDialog: '.vn-confirm.shown button[response="accept"]'
|
||||||
},
|
},
|
||||||
invoiceOutIndex: {
|
invoiceOutIndex: {
|
||||||
searchInvoiceOutInput: `vn-searchbar input`,
|
searchInvoiceOutInput: `vn-searchbar input`,
|
||||||
|
|
|
@ -35,8 +35,30 @@ describe('Worker time control path', () => {
|
||||||
expect(result).toEqual(scanTime);
|
expect(result).toEqual(scanTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should scan out Hank Pym and forget to scan in from the break`, async() => {
|
it(`should scan in Hank Pym for a wrong hour and forget to scan in from the break`, async() => {
|
||||||
const scanTime = '15:00';
|
const scanTime = '18:00';
|
||||||
|
const result = await nightmare
|
||||||
|
.waitToClick(selectors.workerTimeControl.mondayAddTimeButton)
|
||||||
|
.pickTime(selectors.workerTimeControl.timeDialogInput, scanTime)
|
||||||
|
.waitToClick(selectors.workerTimeControl.confirmButton)
|
||||||
|
.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfMonday, 'innerText');
|
||||||
|
|
||||||
|
expect(result).toEqual(scanTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should delete the wrong entry for Hank Pym`, async() => {
|
||||||
|
const wrongScanTime = '18:00';
|
||||||
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.thirdEntryOfMonday, wrongScanTime)
|
||||||
|
.waitToClick(selectors.workerTimeControl.thirdEntryOfMondayDelete)
|
||||||
|
.waitToClick(selectors.workerTimeControl.acceptDeleteDialog)
|
||||||
|
.waitForLastSnackbar();
|
||||||
|
|
||||||
|
expect(result).toEqual('Entry removed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should scan out Hank Pym to leave early`, async() => {
|
||||||
|
const scanTime = '14:00';
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitToClick(selectors.workerTimeControl.mondayAddTimeButton)
|
.waitToClick(selectors.workerTimeControl.mondayAddTimeButton)
|
||||||
.pickTime(selectors.workerTimeControl.timeDialogInput, scanTime)
|
.pickTime(selectors.workerTimeControl.timeDialogInput, scanTime)
|
||||||
|
@ -54,7 +76,7 @@ describe('Worker time control path', () => {
|
||||||
.waitToClick(selectors.workerTimeControl.confirmButton)
|
.waitToClick(selectors.workerTimeControl.confirmButton)
|
||||||
.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfMonday, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfMonday, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('15:00');
|
expect(result).toEqual('14:00');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should the third entry be the scan in from break`, async() => {
|
it(`should the third entry be the scan in from break`, async() => {
|
||||||
|
@ -67,9 +89,10 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 hours`, async() => {
|
it(`should check Hank Pym worked 8 hours`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '07:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('07:00 h.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -120,6 +143,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 happy hours`, async() => {
|
it(`should check Hank Pym worked 8 happy hours`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.tuesdayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.tuesdayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.tuesdayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -173,6 +197,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 cheerfull hours`, async() => {
|
it(`should check Hank Pym worked 8 cheerfull hours`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.wednesdayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.wednesdayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.wednesdayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -226,6 +251,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 joyfull hours`, async() => {
|
it(`should check Hank Pym worked 8 joyfull hours`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.thursdayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.thursdayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.thursdayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -279,6 +305,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 hours with a smile on his face`, async() => {
|
it(`should check Hank Pym worked 8 hours with a smile on his face`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.fridayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.fridayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.fridayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -319,6 +346,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 hours with all his will`, async() => {
|
it(`should check Hank Pym worked 8 hours with all his will`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.saturdayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.saturdayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.saturdayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -350,6 +378,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it(`should check Hank Pym worked 8 glad hours`, async() => {
|
it(`should check Hank Pym worked 8 glad hours`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
|
.waitForTextInElement(selectors.workerTimeControl.sundayWorkedHours, '08:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.sundayWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.sundayWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(result).toEqual('08:00 h.');
|
expect(result).toEqual('08:00 h.');
|
||||||
|
@ -387,10 +416,10 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
it('should Hank Pym check his hours are alright', async() => {
|
it('should Hank Pym check his hours are alright', async() => {
|
||||||
const wholeWeekHours = await nightmare
|
const wholeWeekHours = await nightmare
|
||||||
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 h.')
|
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '55:00 h.')
|
||||||
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
|
||||||
|
|
||||||
expect(wholeWeekHours).toEqual('56:00 h.');
|
expect(wholeWeekHours).toEqual('55:00 h.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,13 +24,12 @@ vn-chip {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 2em;
|
|
||||||
|
|
||||||
& > vn-avatar {
|
& > vn-avatar {
|
||||||
margin-left: -0.7em;
|
margin-left: -0.7em;
|
||||||
margin-right: .3em;
|
margin-right: .3em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
height: 1.9em;
|
height: 2em;
|
||||||
width: 2em;
|
width: 2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<span
|
<span
|
||||||
ng-repeat="day in $ctrl.days"
|
ng-repeat="day in $ctrl.days"
|
||||||
translate-attr="::{title: day.name}"
|
translate-attr="::{title: day.name}"
|
||||||
ng-class="{marked: $ctrl.field[day.code]}"
|
ng-class="{marked: $ctrl.field[day.index]}"
|
||||||
ng-click="$ctrl.field[day.code] = !$ctrl.field[day.code]">
|
ng-click="$ctrl.toggleDay(day.index)">
|
||||||
{{day.localeChar}}
|
{{day.localeChar}}
|
||||||
</span>
|
</span>
|
|
@ -8,6 +8,13 @@ export default class WdayPicker extends FormInput {
|
||||||
this.days = vnWeekDays.locales;
|
this.days = vnWeekDays.locales;
|
||||||
this.initTabIndex();
|
this.initTabIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleDay(index) {
|
||||||
|
let field = this.field;
|
||||||
|
if (!field) field = [];
|
||||||
|
field[index] = !field[index];
|
||||||
|
this.change(field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WdayPicker.$inject = ['$element', '$scope', 'vnWeekDays'];
|
WdayPicker.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {Array} days Weekdays data array with the same indexes as Date.getDay()
|
||||||
|
* @property {Object} map Weekdays data map using weekday codes as key
|
||||||
|
* @property {Array} localeCodes Locale weekday codes indexes depend on current locale
|
||||||
|
* @property {Array} locale Weekday data array with indexes depending on current locale
|
||||||
|
*
|
||||||
|
* Weekday properties:
|
||||||
|
*
|
||||||
|
* @property {Number} index The weekday index acording to Date.getDay()
|
||||||
|
* @property {String} code The weekday code
|
||||||
|
* @property {String} name The weekday name
|
||||||
|
* @property {String} char The first weekday letter
|
||||||
|
* @property {String} abr The abreviated 3 letters weekday name
|
||||||
|
* @property {String} locale The weekday name in current locale
|
||||||
|
* @property {String} localeChar The first weekday letter in current locale
|
||||||
|
* @property {String} localeAbr The abreviated 3 letters weekday name in current locale
|
||||||
|
*/
|
||||||
class WeekDays {
|
class WeekDays {
|
||||||
constructor($translate) {
|
constructor($translate) {
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
|
@ -65,6 +82,34 @@ class WeekDays {
|
||||||
for (let code of this.localeCodes)
|
for (let code of this.localeCodes)
|
||||||
this.locales.push(this.map[code]);
|
this.locales.push(this.map[code]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fromSet(weekDays) {
|
||||||
|
let wdays = [];
|
||||||
|
|
||||||
|
if (weekDays) {
|
||||||
|
let codes = weekDays.split(',');
|
||||||
|
for (let code of codes) {
|
||||||
|
let data = this.map[code];
|
||||||
|
if (data) wdays[data.index] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wdays;
|
||||||
|
}
|
||||||
|
|
||||||
|
toSet(wdays) {
|
||||||
|
let weekDays = [];
|
||||||
|
|
||||||
|
if (wdays) {
|
||||||
|
for (let i = 0; i < wdays.length; i++) {
|
||||||
|
if (!wdays[i]) continue;
|
||||||
|
let data = this.days[i];
|
||||||
|
if (data) weekDays.push(data.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return weekDays.join(',');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WeekDays.$inject = ['$translate'];
|
WeekDays.$inject = ['$translate'];
|
||||||
|
|
||||||
|
|
|
@ -113,5 +113,9 @@
|
||||||
"You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
|
"You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
|
||||||
"You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
|
"You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
|
||||||
"You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
|
"You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
|
||||||
"Has deleted the ticket id": "Ha eliminado el ticket id [#{{id}}]({{{url}}})"
|
"Has deleted the ticket id": "Ha eliminado el ticket id [#{{id}}]({{{url}}})",
|
||||||
|
"You should specify a date": "Debes especificar una fecha",
|
||||||
|
"You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fín",
|
||||||
|
"Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fín",
|
||||||
|
"You should mark at least one week day": "Debes marcar al menos un día de la semana"
|
||||||
}
|
}
|
|
@ -47,6 +47,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
let rsIndex = stmts.push(
|
let rsIndex = stmts.push(
|
||||||
`SELECT * FROM tmp.zoneGetLanded`) - 1;
|
`SELECT * FROM tmp.zoneGetLanded`) - 1;
|
||||||
|
stmts.push(`DROP TEMPORARY TABLE tmp.zoneGetLanded`);
|
||||||
|
|
||||||
let sql = ParameterizedSQL.join(stmts, ';');
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
let landed = await Self.rawStmt(sql);
|
let landed = await Self.rawStmt(sql);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
// Petición #1848
|
|
||||||
xdescribe('agency getLanded()', () => {
|
describe('agency getLanded()', () => {
|
||||||
it('should return a landing date', async() => {
|
it('should return a landing date', async() => {
|
||||||
const shipped = new Date();
|
const shipped = new Date();
|
||||||
|
shipped.setDate(shipped.getDate() + 1);
|
||||||
const addressFk = 121;
|
const addressFk = 121;
|
||||||
const agencyModeFk = 7;
|
const agencyModeFk = 7;
|
||||||
const warehouseFk = 1;
|
const warehouseFk = 1;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
// Petición #1848
|
describe('agency getShipped()', () => {
|
||||||
|
|
||||||
xdescribe('agency getShipped()', () => {
|
|
||||||
it('should return a shipment date', async() => {
|
it('should return a shipment date', async() => {
|
||||||
const landed = new Date();
|
const landed = new Date();
|
||||||
|
landed.setDate(landed.getDate() + 1);
|
||||||
const addressFk = 121;
|
const addressFk = 121;
|
||||||
const agencyModeFk = 7;
|
const agencyModeFk = 7;
|
||||||
const warehouseFk = 1;
|
const warehouseFk = 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
// Petición #1848
|
|
||||||
xdescribe('Agency landsThatDay()', () => {
|
describe('Agency landsThatDay()', () => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
it('should return a list of agencies that can land a shipment on a day for an address', async() => {
|
it('should return a list of agencies that can land a shipment on a day for an address', async() => {
|
||||||
let agencies = await app.models.Agency.landsThatDay(101, today);
|
let agencies = await app.models.Agency.landsThatDay(101, today);
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethod('removeByDate', {
|
|
||||||
description: 'Removes one or more delivery dates for a zone',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts: [{
|
|
||||||
arg: 'zoneFk',
|
|
||||||
type: 'Number',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'dates',
|
|
||||||
type: ['Date'],
|
|
||||||
required: true,
|
|
||||||
}],
|
|
||||||
returns: {
|
|
||||||
type: 'object',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/removeByDate`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.removeByDate = (zoneFk, dates) => {
|
|
||||||
return Self.destroyAll({zoneFk, delivered: {inq: dates}});
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -31,7 +31,6 @@ module.exports = Self => {
|
||||||
fields: [
|
fields: [
|
||||||
'name',
|
'name',
|
||||||
'hour',
|
'hour',
|
||||||
'warehouseFk',
|
|
||||||
'agencyModeFk',
|
'agencyModeFk',
|
||||||
'travelingDays',
|
'travelingDays',
|
||||||
'price',
|
'price',
|
||||||
|
@ -47,7 +46,8 @@ module.exports = Self => {
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
// Find all original selected days
|
// Find all original selected days
|
||||||
const calendarDays = await models.ZoneCalendar.find({
|
const calendarDays = await models.ZoneEvent.find({
|
||||||
|
fields: {id: false},
|
||||||
where: {zoneFk: id}
|
where: {zoneFk: id}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await models.ZoneIncluded.create(newIncludedGeo, options);
|
await models.ZoneIncluded.create(newIncludedGeo, options);
|
||||||
await models.ZoneCalendar.create(newCalendayDays, options);
|
await models.ZoneEvent.create(newCalendayDays, options);
|
||||||
await tx.commit();
|
await tx.commit();
|
||||||
|
|
||||||
return newZone;
|
return newZone;
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
|
||||||
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethod('editPrices', {
|
|
||||||
description: 'Changes the price and bonus of a delivery day',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts: [{
|
|
||||||
arg: 'id',
|
|
||||||
type: 'Number',
|
|
||||||
description: 'The zone id',
|
|
||||||
http: {source: 'path'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'delivered',
|
|
||||||
type: 'Date',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'price',
|
|
||||||
type: 'Number',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'bonus',
|
|
||||||
type: 'Number',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'option',
|
|
||||||
type: 'String',
|
|
||||||
required: true,
|
|
||||||
}],
|
|
||||||
returns: {
|
|
||||||
type: 'object',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/:id/editPrices`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.editPrices = async(id, delivered, price, bonus, option) => {
|
|
||||||
const models = Self.app.models;
|
|
||||||
|
|
||||||
let filter = {
|
|
||||||
where: {
|
|
||||||
zoneFk: id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let where;
|
|
||||||
let shouldPropagate = true;
|
|
||||||
|
|
||||||
if (option == 'Only this day') {
|
|
||||||
shouldPropagate = false;
|
|
||||||
where = {delivered};
|
|
||||||
} else if (option == 'From this day') {
|
|
||||||
where = {
|
|
||||||
delivered: {
|
|
||||||
gte: delivered
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
filter = mergeFilters(filter, {where});
|
|
||||||
|
|
||||||
const days = await models.ZoneCalendar.find(filter);
|
|
||||||
const areAllFromSameZone = days.every(day => day.zoneFk === id);
|
|
||||||
|
|
||||||
if (!areAllFromSameZone)
|
|
||||||
throw new UserError('All delivery days must belong to the same zone');
|
|
||||||
|
|
||||||
if (shouldPropagate) {
|
|
||||||
const zone = await models.Zone.findById(id);
|
|
||||||
zone.updateAttributes({price, bonus});
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.ZoneCalendar.updateAll(filter.where, {price, bonus});
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,81 +0,0 @@
|
||||||
const app = require('vn-loopback/server/server');
|
|
||||||
// Petición #1848
|
|
||||||
xdescribe('agency editPrices()', () => {
|
|
||||||
const zoneId = 1;
|
|
||||||
let originalZone;
|
|
||||||
|
|
||||||
beforeAll(async done => {
|
|
||||||
originalZone = await app.models.Zone.findById(zoneId);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async done => {
|
|
||||||
await await app.models.ZoneCalendar.updateAll({zoneFk: zoneId}, {
|
|
||||||
price: originalZone.price,
|
|
||||||
bonus: originalZone.bonus
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply price and bonus for a selected day', async() => {
|
|
||||||
const delivered = new Date();
|
|
||||||
delivered.setHours(0, 0, 0, 0);
|
|
||||||
await app.models.Zone.editPrices(zoneId, delivered, 4.00, 2.00, 'Only this day');
|
|
||||||
|
|
||||||
const editedDays = await app.models.ZoneCalendar.find({
|
|
||||||
where: {
|
|
||||||
zoneFk: zoneId,
|
|
||||||
delivered: delivered
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const firstEditedDay = editedDays[0];
|
|
||||||
|
|
||||||
expect(editedDays.length).toEqual(1);
|
|
||||||
expect(firstEditedDay.price).toEqual(4.00);
|
|
||||||
expect(firstEditedDay.bonus).toEqual(2.00);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply price and bonus for all delivery days starting from selected day', async() => {
|
|
||||||
const delivered = new Date();
|
|
||||||
delivered.setHours(0, 0, 0, 0);
|
|
||||||
await app.models.Zone.editPrices(1, delivered, 5.50, 1.00, 'From this day');
|
|
||||||
|
|
||||||
const editedDays = await app.models.ZoneCalendar.find({
|
|
||||||
where: {
|
|
||||||
zoneFk: zoneId,
|
|
||||||
delivered: {
|
|
||||||
gte: delivered
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const firstEditedDay = editedDays[0];
|
|
||||||
const lastEditedDay = editedDays[editedDays.length - 1];
|
|
||||||
|
|
||||||
expect(editedDays.length).toEqual(5);
|
|
||||||
expect(firstEditedDay.price).toEqual(5.50);
|
|
||||||
expect(firstEditedDay.bonus).toEqual(1.00);
|
|
||||||
expect(lastEditedDay.price).toEqual(5.50);
|
|
||||||
expect(lastEditedDay.bonus).toEqual(1.00);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply price and bonus for all delivery days', async() => {
|
|
||||||
const delivered = new Date();
|
|
||||||
delivered.setHours(0, 0, 0, 0);
|
|
||||||
await app.models.Zone.editPrices(1, delivered, 7.00, 0.00, 'All days');
|
|
||||||
|
|
||||||
const editedDays = await app.models.ZoneCalendar.find({
|
|
||||||
where: {
|
|
||||||
zoneFk: zoneId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const firstEditedDay = editedDays[0];
|
|
||||||
const lastEditedDay = editedDays[editedDays.length - 1];
|
|
||||||
|
|
||||||
expect(editedDays.length).toEqual(5);
|
|
||||||
expect(firstEditedDay.price).toEqual(7.00);
|
|
||||||
expect(firstEditedDay.bonus).toEqual(0.00);
|
|
||||||
expect(lastEditedDay.price).toEqual(7.00);
|
|
||||||
expect(lastEditedDay.bonus).toEqual(0.00);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
"ZoneExclusion": {
|
"ZoneExclusion": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"ZoneCalendar": {
|
|
||||||
"dataSource": "vn"
|
|
||||||
},
|
|
||||||
"ZoneIncluded": {
|
"ZoneIncluded": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
require('../methods/zone-calendar/removeByDate')(Self);
|
|
||||||
};
|
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"name": "ZoneCalendar",
|
|
||||||
"base": "VnModel",
|
|
||||||
"options": {
|
|
||||||
"mysql": {
|
|
||||||
"table": "zoneCalendar"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"zoneFk": {
|
|
||||||
"id": true,
|
|
||||||
"type": "Number"
|
|
||||||
},
|
|
||||||
"delivered": {
|
|
||||||
"id": true,
|
|
||||||
"type": "Date"
|
|
||||||
},
|
|
||||||
"price": {
|
|
||||||
"type": "Number"
|
|
||||||
},
|
|
||||||
"bonus": {
|
|
||||||
"type": "Number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"relations": {
|
|
||||||
"zone": {
|
|
||||||
"type": "belongsTo",
|
|
||||||
"model": "Zone",
|
|
||||||
"foreignKey": "zoneFk"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,35 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
function rangeValid(err) {
|
Self.validate('range', function(err) {
|
||||||
if (this.from && this.to && this.from >= this.to)
|
if (this.type == 'range'
|
||||||
|
&& !this.started
|
||||||
|
&& !this.ended)
|
||||||
err();
|
err();
|
||||||
}
|
}, {
|
||||||
Self.validate('rangeValid', rangeValid, {
|
message: `You should specify at least a start or end date`
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.validate('validRange', function(err) {
|
||||||
|
if (this.type == 'range'
|
||||||
|
&& this.started
|
||||||
|
&& this.ended
|
||||||
|
&& this.started >= this.ended)
|
||||||
|
err();
|
||||||
|
}, {
|
||||||
message: `Start date should be lower than end date`
|
message: `Start date should be lower than end date`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Self.validate('dated', function(err) {
|
||||||
|
if (this.type == 'day' && !this.dated)
|
||||||
|
err();
|
||||||
|
}, {
|
||||||
|
message: `You should specify a date`
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.validate('weekDays', function(err) {
|
||||||
|
if (['range', 'indefinitely'].indexOf(this.type) !== -1
|
||||||
|
&& !this.weekDays)
|
||||||
|
err();
|
||||||
|
}, {
|
||||||
|
message: `You should mark at least one week day`
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,10 +15,16 @@
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
||||||
"from": {
|
"type": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"dated": {
|
||||||
"type": "Date"
|
"type": "Date"
|
||||||
},
|
},
|
||||||
"to": {
|
"started": {
|
||||||
|
"type": "Date"
|
||||||
|
},
|
||||||
|
"ended": {
|
||||||
"type": "Date"
|
"type": "Date"
|
||||||
},
|
},
|
||||||
"weekDays": {
|
"weekDays": {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
||||||
"day": {
|
"dated": {
|
||||||
"type": "Date",
|
"type": "Date",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/zone/clone')(Self);
|
require('../methods/zone/clone')(Self);
|
||||||
require('../methods/zone/editPrices')(Self);
|
|
||||||
require('../methods/zone/getLeaves')(Self);
|
require('../methods/zone/getLeaves')(Self);
|
||||||
require('../methods/zone/getEvents')(Self);
|
require('../methods/zone/getEvents')(Self);
|
||||||
require('../methods/zone/toggleIsIncluded')(Self);
|
require('../methods/zone/toggleIsIncluded')(Self);
|
||||||
|
|
|
@ -3,8 +3,9 @@ import Component from 'core/lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller extends Component {
|
class Controller extends Component {
|
||||||
constructor($element, $) {
|
constructor($element, $, vnWeekDays) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
|
this.vnWeekDays = vnWeekDays;
|
||||||
this.nMonths = 4;
|
this.nMonths = 4;
|
||||||
|
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
|
@ -54,19 +55,29 @@ class Controller extends Component {
|
||||||
this._data = value;
|
this._data = value;
|
||||||
|
|
||||||
value = value || {};
|
value = value || {};
|
||||||
this.events = value.events;
|
|
||||||
this.exclusions = value.exclusions;
|
|
||||||
|
|
||||||
if (this.events) {
|
this.events = value.events;
|
||||||
let codes = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
||||||
for (event of this.events) {
|
function toStamp(date) {
|
||||||
event.wdays = [];
|
return date && new Date(date).setHours(0, 0, 0, 0);
|
||||||
if (!event.weekDays) continue;
|
}
|
||||||
let weekDays = event.weekDays.split(',');
|
|
||||||
for (let wday of weekDays) {
|
this.exclusionsMap = {};
|
||||||
let index = codes.indexOf(wday);
|
let exclusions = value.exclusions;
|
||||||
if (index !== -1) event.wdays[index] = true;
|
|
||||||
}
|
if (exclusions) {
|
||||||
|
for (let exclusion of exclusions)
|
||||||
|
this.exclusionsMap[toStamp(exclusion.dated)] = exclusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
let events = value.events;
|
||||||
|
|
||||||
|
if (events) {
|
||||||
|
for (event of events) {
|
||||||
|
event.dated = toStamp(event.dated);
|
||||||
|
event.ended = toStamp(event.ended);
|
||||||
|
event.started = toStamp(event.started);
|
||||||
|
event.wdays = this.vnWeekDays.fromSet(event.weekDays);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,17 +89,9 @@ class Controller extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshEvents() {
|
refreshEvents() {
|
||||||
function getDate(date) {
|
|
||||||
return date && new Date(date).setHours(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let exclusionsMap = {};
|
|
||||||
if (this.exclusions) {
|
|
||||||
for (let exclusion of this.exclusions)
|
|
||||||
exclusionsMap[getDate(exclusion.day)] = exclusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.days = {};
|
this.days = {};
|
||||||
|
if (!this.data) return;
|
||||||
|
|
||||||
let day = new Date(this.firstDay.getTime());
|
let day = new Date(this.firstDay.getTime());
|
||||||
|
|
||||||
while (day <= this.lastDay) {
|
while (day <= this.lastDay) {
|
||||||
|
@ -99,23 +102,24 @@ class Controller extends Component {
|
||||||
if (this.events) {
|
if (this.events) {
|
||||||
for (let event of this.events) {
|
for (let event of this.events) {
|
||||||
let match;
|
let match;
|
||||||
let from = getDate(event.from);
|
|
||||||
let to = getDate(event.to);
|
|
||||||
|
|
||||||
if (event.from && event.to) {
|
switch (event.type) {
|
||||||
match = stamp >= from && stamp <= to
|
case 'day':
|
||||||
&& event.wdays[wday];
|
match = event.dated == stamp;
|
||||||
} else if (event.from)
|
break;
|
||||||
match = from == stamp;
|
default:
|
||||||
else
|
match = event.wdays[wday]
|
||||||
match = event.wdays[wday];
|
&& (!event.started || stamp >= event.started)
|
||||||
|
&& (!event.ended || stamp <= event.ended);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
dayEvents.push(event);
|
dayEvents.push(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let exclusion = exclusionsMap[stamp];
|
let exclusion = this.exclusionsMap[stamp];
|
||||||
|
|
||||||
if (dayEvents.length || exclusion) {
|
if (dayEvents.length || exclusion) {
|
||||||
let dayData = {};
|
let dayData = {};
|
||||||
|
@ -152,6 +156,7 @@ class Controller extends Component {
|
||||||
return dayData && dayData.exclusion ? 'excluded' : '';
|
return dayData && dayData.exclusion ? 'excluded' : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
ngModule.component('vnZoneCalendar', {
|
ngModule.component('vnZoneCalendar', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
<mg-ajax path="Zones/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.zone"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.zone.name"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.zone.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Warehouse"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.zone.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Agency"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
label="Traveling days"
|
|
||||||
ng-model="$ctrl.zone.travelingDays"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-time
|
|
||||||
vn-one
|
|
||||||
label="Estimated hour (ETD)"
|
|
||||||
ng-model="$ctrl.zone.hour"
|
|
||||||
rule>
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.zone.price"
|
|
||||||
min="0.00"
|
|
||||||
step="0.50"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Bonus"
|
|
||||||
ng-model="$ctrl.zone.bonus"
|
|
||||||
min="0.00"
|
|
||||||
step="0.50"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit label="Save"></vn-submit>
|
|
||||||
<vn-button ui-sref="zone.card.location" label="Cancel"></vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -42,17 +42,17 @@
|
||||||
class="vn-item">
|
class="vn-item">
|
||||||
<vn-item-section>
|
<vn-item-section>
|
||||||
<div
|
<div
|
||||||
ng-if="::row.from && !row.to"
|
ng-if="::row.type == 'day'"
|
||||||
class="vn-mb-sm">
|
class="vn-mb-sm">
|
||||||
{{::row.from | date:'dd/MM/yy'}}
|
{{::row.dated | date:'dd/MM/yy'}}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ng-if="::!row.from || row.to"
|
ng-if="::row.type != 'day'"
|
||||||
class="vn-mb-sm ellipsize">
|
class="vn-mb-sm ellipsize">
|
||||||
<span ng-if="row.to">
|
<span ng-if="row.type == 'range'">
|
||||||
{{::row.from | date:'dd/MM/yy'}} - {{::row.to | date:'dd/MM/yy'}}
|
{{::row.started | date:'dd/MM/yy'}} - {{::row.ended | date:'dd/MM/yy'}}
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="!row.to" translate>
|
<span ng-if="row.type == 'indefinitely'" translate>
|
||||||
Indefinitely
|
Indefinitely
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="row.weekDays">
|
<span ng-if="row.weekDays">
|
||||||
|
@ -94,40 +94,40 @@
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
<vn-vertical class="vn-pb-md">
|
<vn-vertical class="vn-pb-md">
|
||||||
<vn-radio
|
<vn-radio
|
||||||
ng-model="$ctrl.eventType"
|
ng-model="$ctrl.selected.type"
|
||||||
label="One day"
|
label="One day"
|
||||||
val="day">
|
val="day">
|
||||||
</vn-radio>
|
</vn-radio>
|
||||||
<vn-radio
|
<vn-radio
|
||||||
ng-model="$ctrl.eventType"
|
ng-model="$ctrl.selected.type"
|
||||||
label="Indefinitely"
|
label="Indefinitely"
|
||||||
val="indefinitely">
|
val="indefinitely">
|
||||||
</vn-radio>
|
</vn-radio>
|
||||||
<vn-radio
|
<vn-radio
|
||||||
ng-model="$ctrl.eventType"
|
ng-model="$ctrl.selected.type"
|
||||||
label="Range of dates"
|
label="Range of dates"
|
||||||
val="range">
|
val="range">
|
||||||
</vn-radio>
|
</vn-radio>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
<vn-wday-picker
|
<vn-wday-picker
|
||||||
ng-if="$ctrl.eventType != 'day'"
|
ng-if="$ctrl.selected.type != 'day'"
|
||||||
ng-model="$ctrl.selected.wdays"
|
ng-model="$ctrl.selected.wdays"
|
||||||
class="vn-mt-sm vn-mb-md">
|
class="vn-mt-sm vn-mb-md">
|
||||||
</vn-wday-picker>
|
</vn-wday-picker>
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
ng-if="$ctrl.eventType == 'day'"
|
ng-if="$ctrl.selected.type == 'day'"
|
||||||
label="Day"
|
label="Day"
|
||||||
ng-model="$ctrl.selected.from">
|
ng-model="$ctrl.selected.dated">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
<vn-horizontal
|
<vn-horizontal
|
||||||
ng-if="$ctrl.eventType == 'range'">
|
ng-if="$ctrl.selected.type == 'range'">
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
label="From"
|
label="From"
|
||||||
ng-model="$ctrl.selected.from">
|
ng-model="$ctrl.selected.started">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
label="To"
|
label="To"
|
||||||
ng-model="$ctrl.selected.to">
|
ng-model="$ctrl.selected.ended">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-input-time
|
<vn-input-time
|
||||||
|
@ -162,7 +162,7 @@
|
||||||
</input>
|
</input>
|
||||||
<button
|
<button
|
||||||
ng-if="!$ctrl.isNew"
|
ng-if="!$ctrl.isNew"
|
||||||
response="DELETE"
|
response="delete"
|
||||||
translate>
|
translate>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Component from 'core/lib/component';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
class Controller extends Component {
|
class Controller extends Section {
|
||||||
constructor($element, $, vnWeekDays) {
|
constructor($element, $, vnWeekDays) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.vnWeekDays = vnWeekDays;
|
this.vnWeekDays = vnWeekDays;
|
||||||
|
@ -27,13 +27,13 @@ class Controller extends Component {
|
||||||
formatWdays(weekDays) {
|
formatWdays(weekDays) {
|
||||||
if (!weekDays) return;
|
if (!weekDays) return;
|
||||||
|
|
||||||
let abrWdays = [];
|
let abrWdays = weekDays
|
||||||
for (let wday of weekDays.split(','))
|
.split(',')
|
||||||
abrWdays.push(this.vnWeekDays.map[wday].localeAbr);
|
.map(wday => this.vnWeekDays.map[wday].localeAbr);
|
||||||
|
|
||||||
return abrWdays.length < 7
|
return abrWdays.length < 7
|
||||||
? abrWdays.join(', ')
|
? abrWdays.join(', ')
|
||||||
: this._('Everyday');
|
: this.$t('Everyday');
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelection(days, type, weekday, data) {
|
onSelection(days, type, weekday, data) {
|
||||||
|
@ -66,37 +66,28 @@ class Controller extends Component {
|
||||||
|
|
||||||
edit(row) {
|
edit(row) {
|
||||||
this.isNew = false;
|
this.isNew = false;
|
||||||
|
|
||||||
if (row.from && !row.to)
|
|
||||||
this.eventType = 'day';
|
|
||||||
else if (!row.from)
|
|
||||||
this.eventType = 'indefinitely';
|
|
||||||
else
|
|
||||||
this.eventType = 'range';
|
|
||||||
|
|
||||||
this.selected = angular.copy(row);
|
this.selected = angular.copy(row);
|
||||||
this.selected.wdays = {};
|
this.selected.wdays = this.vnWeekDays.fromSet(row.weekDays);
|
||||||
|
|
||||||
if (row.weekDays) {
|
|
||||||
let weekDays = row.weekDays.split(',');
|
|
||||||
for (let day of weekDays)
|
|
||||||
this.selected.wdays[day] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$.dialog.show();
|
this.$.dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
create(days, type, weekday) {
|
create(days, type, weekday) {
|
||||||
this.isNew = true;
|
this.isNew = true;
|
||||||
this.eventType = type == 'day' ? 'day' : 'indefinitely';
|
|
||||||
|
|
||||||
if (type == 'weekday') {
|
if (type == 'weekday') {
|
||||||
let wdays = [];
|
let wdays = [];
|
||||||
let code = this.vnWeekDays.days[weekday].code;
|
wdays[weekday] = true;
|
||||||
wdays[code] = true;
|
|
||||||
this.selected = {wdays};
|
this.selected = {
|
||||||
} else
|
type: 'indefinitely',
|
||||||
this.selected = {from: days[0]};
|
wdays
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.selected = {
|
||||||
|
type: 'day',
|
||||||
|
dated: days[0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.$.dialog.show();
|
this.$.dialog.show();
|
||||||
}
|
}
|
||||||
|
@ -105,24 +96,18 @@ class Controller extends Component {
|
||||||
switch (response) {
|
switch (response) {
|
||||||
case 'accept': {
|
case 'accept': {
|
||||||
let selected = this.selected;
|
let selected = this.selected;
|
||||||
|
let type = selected.type;
|
||||||
|
|
||||||
if (this.eventType == 'indefinitely') {
|
selected.weekDays = this.vnWeekDays.toSet(selected.wdays);
|
||||||
selected.from = null;
|
|
||||||
selected.to = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.eventType != 'day') {
|
if (type == 'day')
|
||||||
let weekDays = [];
|
|
||||||
|
|
||||||
for (let wday in selected.wdays) {
|
|
||||||
if (selected.wdays[wday])
|
|
||||||
weekDays.push(wday);
|
|
||||||
}
|
|
||||||
|
|
||||||
selected.weekDays = weekDays.join(',');
|
|
||||||
} else {
|
|
||||||
selected.to = null;
|
|
||||||
selected.weekDays = '';
|
selected.weekDays = '';
|
||||||
|
else
|
||||||
|
selected.dated = null;
|
||||||
|
|
||||||
|
if (type != 'range') {
|
||||||
|
selected.started = null;
|
||||||
|
selected.ended = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let req;
|
let req;
|
||||||
|
@ -138,7 +123,7 @@ class Controller extends Component {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'DELETE':
|
case 'delete':
|
||||||
return this.onDelete(this.selected.id)
|
return this.onDelete(this.selected.id)
|
||||||
.then(response => response == 'accept');
|
.then(response => response == 'accept');
|
||||||
}
|
}
|
||||||
|
@ -162,8 +147,8 @@ class Controller extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusionCreate(days) {
|
exclusionCreate(days) {
|
||||||
let exclusions = days.map(day => {
|
let exclusions = days.map(dated => {
|
||||||
return {day};
|
return {dated};
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$http.post(this.exclusionsPath, exclusions)
|
this.$http.post(this.exclusionsPath, exclusions)
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Name"
|
|
||||||
ng-model="filter.name">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Agency"
|
|
||||||
ng-model="filter.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="filter.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
ngModule.component('vnLocationSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: SearchPanel
|
|
||||||
});
|
|
|
@ -1,6 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
// Petición #1848
|
|
||||||
xdescribe('claimBeginning', () => {
|
describe('claimBeginning', () => {
|
||||||
let ticket;
|
let ticket;
|
||||||
let refundTicketSales;
|
let refundTicketSales;
|
||||||
let salesInsertedInClaimEnd;
|
let salesInsertedInClaimEnd;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<section class="photo" ng-repeat="photo in $ctrl.photos">
|
<section class="photo" ng-repeat="photo in $ctrl.photos">
|
||||||
<section class="image vn-shadow" on-error-src
|
<section class="image vn-shadow" on-error-src
|
||||||
ng-style="{'background': 'url(/api/dms/' + photo.dmsFk + '/downloadFile?access_token=' + $ctrl.accessToken + ')'}"
|
ng-style="{'background': 'url(/api/dms/' + photo.dmsFk + '/downloadFile?access_token=' + $ctrl.accessToken + ')'}"
|
||||||
zoom-image="dms/{{::photo.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
|
zoom-image="/api/dms/{{::photo.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
|
||||||
</section>
|
</section>
|
||||||
<section class="actions">
|
<section class="actions">
|
||||||
<vn-button
|
<vn-button
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
// Petición #1848
|
describe('order catalogFilter()', () => {
|
||||||
xdescribe('order catalogFilter()', () => {
|
|
||||||
it('should return an array of items', async() => {
|
it('should return an array of items', async() => {
|
||||||
let filter = {
|
let filter = {
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
// Petición #1848
|
|
||||||
|
|
||||||
xdescribe('order getItemTypeAvailable()', () => {
|
describe('order getItemTypeAvailable()', () => {
|
||||||
it('should call the getItemTypeAvailable method with a valid order and item category', async() => {
|
it('should call the getItemTypeAvailable method with a valid order and item category', async() => {
|
||||||
let orderId = 11;
|
let orderId = 11;
|
||||||
let itemCategoryId = 1;
|
let itemCategoryId = 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
// Petición #1848
|
|
||||||
xdescribe('ticket componentUpdate()', () => {
|
describe('ticket componentUpdate()', () => {
|
||||||
const ticketId = 11;
|
const ticketId = 11;
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const tomorrow = new Date();
|
const tomorrow = new Date();
|
||||||
|
|
|
@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server');
|
||||||
let UserError = require('vn-loopback/util/user-error');
|
let UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
|
||||||
xdescribe('ticket new()', () => {
|
describe('ticket new()', () => {
|
||||||
let ticket;
|
let ticket;
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
let ctx = {req: {accessToken: {userId: 1}}};
|
let ctx = {req: {accessToken: {userId: 1}}};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
let UserError = require('vn-loopback/util/user-error');
|
let UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
xdescribe('sale priceDifference()', () => {
|
describe('sale priceDifference()', () => {
|
||||||
it('should return ticket price differences', async() => {
|
it('should return ticket price differences', async() => {
|
||||||
let tomorrow = new Date();
|
let tomorrow = new Date();
|
||||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
|
|
|
@ -46,7 +46,8 @@ class Controller {
|
||||||
this.getShipped({
|
this.getShipped({
|
||||||
landed: this.ticket.landed,
|
landed: this.ticket.landed,
|
||||||
addressFk: value,
|
addressFk: value,
|
||||||
agencyModeFk: this.ticket.agencyModeFk
|
agencyModeFk: this.ticket.agencyModeFk,
|
||||||
|
warehouseFk: this.ticket.warehouseFk
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +78,8 @@ class Controller {
|
||||||
this.getLanded({
|
this.getLanded({
|
||||||
shipped: value,
|
shipped: value,
|
||||||
addressFk: this.ticket.addressFk,
|
addressFk: this.ticket.addressFk,
|
||||||
agencyModeFk: this.ticket.agencyModeFk
|
agencyModeFk: this.ticket.agencyModeFk,
|
||||||
|
warehouseFk: this.ticket.warehouseFk
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +92,8 @@ class Controller {
|
||||||
this.getShipped({
|
this.getShipped({
|
||||||
landed: value,
|
landed: value,
|
||||||
addressFk: this.ticket.addressFk,
|
addressFk: this.ticket.addressFk,
|
||||||
agencyModeFk: this.ticket.agencyModeFk
|
agencyModeFk: this.ticket.agencyModeFk,
|
||||||
|
warehouseFk: this.ticket.warehouseFk
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +107,8 @@ class Controller {
|
||||||
this.getLanded({
|
this.getLanded({
|
||||||
shipped: this.ticket.shipped,
|
shipped: this.ticket.shipped,
|
||||||
addressFk: this.ticket.addressFk,
|
addressFk: this.ticket.addressFk,
|
||||||
agencyModeFk: value
|
agencyModeFk: value,
|
||||||
|
warehouseFk: this.ticket.warehouseFk
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +201,6 @@ class Controller {
|
||||||
this.$http.get(query, {params}).then(res => {
|
this.$http.get(query, {params}).then(res => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
this.ticket.zoneFk = res.data.zoneFk;
|
this.ticket.zoneFk = res.data.zoneFk;
|
||||||
this.ticket.agencyModeFk = res.data.agencyModeFk;
|
|
||||||
this.ticket.landed = res.data.landed;
|
this.ticket.landed = res.data.landed;
|
||||||
this.ticket.shipped = params.shipped;
|
this.ticket.shipped = params.shipped;
|
||||||
} else {
|
} else {
|
||||||
|
@ -217,7 +220,6 @@ class Controller {
|
||||||
this.$http.get(query, {params}).then(res => {
|
this.$http.get(query, {params}).then(res => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
this.ticket.zoneFk = res.data.zoneFk;
|
this.ticket.zoneFk = res.data.zoneFk;
|
||||||
this.ticket.agencyModeFk = res.data.agencyModeFk;
|
|
||||||
this.ticket.landed = params.landed;
|
this.ticket.landed = params.landed;
|
||||||
this.ticket.shipped = res.data.shipped;
|
this.ticket.shipped = res.data.shipped;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -69,14 +69,15 @@ describe('Ticket', () => {
|
||||||
controller.ticket.addressFk = 99;
|
controller.ticket.addressFk = 99;
|
||||||
controller.addressId = 100;
|
controller.addressId = 100;
|
||||||
const landed = new Date();
|
const landed = new Date();
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
landed: landed,
|
landed: landed,
|
||||||
addressFk: 100,
|
addressFk: 100,
|
||||||
agencyModeFk: 7
|
agencyModeFk: 7,
|
||||||
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.landed = landed;
|
controller.landed = landed;
|
||||||
|
|
||||||
expect(controller.getShipped).toHaveBeenCalledWith(spectedResult);
|
expect(controller.getShipped).toHaveBeenCalledWith(expectedResult);
|
||||||
expect(controller.ticket.addressFk).toEqual(100);
|
expect(controller.ticket.addressFk).toEqual(100);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -95,14 +96,15 @@ describe('Ticket', () => {
|
||||||
controller.ticket.warehouseId = 1;
|
controller.ticket.warehouseId = 1;
|
||||||
controller.warehouseId = 2;
|
controller.warehouseId = 2;
|
||||||
const landed = new Date();
|
const landed = new Date();
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
landed: landed,
|
landed: landed,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7
|
agencyModeFk: 7,
|
||||||
|
warehouseFk: 2
|
||||||
};
|
};
|
||||||
controller.landed = landed;
|
controller.landed = landed;
|
||||||
|
|
||||||
expect(controller.getShipped).toHaveBeenCalledWith(spectedResult);
|
expect(controller.getShipped).toHaveBeenCalledWith(expectedResult);
|
||||||
expect(controller.ticket.warehouseFk).toEqual(2);
|
expect(controller.ticket.warehouseFk).toEqual(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -120,14 +122,15 @@ describe('Ticket', () => {
|
||||||
it('should set shipped property and call getLanded() method ', () => {
|
it('should set shipped property and call getLanded() method ', () => {
|
||||||
spyOn(controller, 'getLanded');
|
spyOn(controller, 'getLanded');
|
||||||
const shipped = new Date();
|
const shipped = new Date();
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
shipped: shipped,
|
shipped: shipped,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7
|
agencyModeFk: 7,
|
||||||
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.shipped = shipped;
|
controller.shipped = shipped;
|
||||||
|
|
||||||
expect(controller.getLanded).toHaveBeenCalledWith(spectedResult);
|
expect(controller.getLanded).toHaveBeenCalledWith(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -144,15 +147,16 @@ describe('Ticket', () => {
|
||||||
it('should set shipped property and call getShipped() method ', () => {
|
it('should set shipped property and call getShipped() method ', () => {
|
||||||
spyOn(controller, 'getShipped');
|
spyOn(controller, 'getShipped');
|
||||||
const landed = new Date();
|
const landed = new Date();
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
landed: landed,
|
landed: landed,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: 7
|
agencyModeFk: 7,
|
||||||
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.landed = landed;
|
controller.landed = landed;
|
||||||
|
|
||||||
|
|
||||||
expect(controller.getShipped).toHaveBeenCalledWith(spectedResult);
|
expect(controller.getShipped).toHaveBeenCalledWith(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -169,30 +173,32 @@ describe('Ticket', () => {
|
||||||
spyOn(controller, 'getLanded');
|
spyOn(controller, 'getLanded');
|
||||||
const shipped = new Date();
|
const shipped = new Date();
|
||||||
const agencyModeId = 8;
|
const agencyModeId = 8;
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
shipped: shipped,
|
shipped: shipped,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: agencyModeId
|
agencyModeFk: agencyModeId,
|
||||||
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.ticket.shipped = shipped;
|
controller.ticket.shipped = shipped;
|
||||||
controller.agencyModeId = 8;
|
controller.agencyModeId = 8;
|
||||||
|
|
||||||
expect(controller.getLanded).toHaveBeenCalledWith(spectedResult);
|
expect(controller.getLanded).toHaveBeenCalledWith(expectedResult);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing if attempting to set the same agencyMode id', () => {
|
it('should do nothing if attempting to set the same agencyMode id', () => {
|
||||||
spyOn(controller, 'getShipped');
|
spyOn(controller, 'getShipped');
|
||||||
const landed = new Date();
|
const landed = new Date();
|
||||||
const agencyModeId = 7;
|
const agencyModeId = 7;
|
||||||
const spectedResult = {
|
const expectedResult = {
|
||||||
landed: landed,
|
landed: landed,
|
||||||
addressFk: 121,
|
addressFk: 121,
|
||||||
agencyModeFk: agencyModeId
|
agencyModeFk: agencyModeId,
|
||||||
|
warehouseFk: 1
|
||||||
};
|
};
|
||||||
controller.ticket.landed = landed;
|
controller.ticket.landed = landed;
|
||||||
controller.agencyModeId = 7;
|
controller.agencyModeId = 7;
|
||||||
|
|
||||||
expect(controller.getShipped).not.toHaveBeenCalledWith(spectedResult);
|
expect(controller.getShipped).not.toHaveBeenCalledWith(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('addTime', {
|
Self.remoteMethodCtx('addTimeEntry', {
|
||||||
description: 'Adds a new hour registry',
|
description: 'Adds a new hour registry',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
|
@ -16,12 +16,12 @@ module.exports = Self => {
|
||||||
root: true
|
root: true
|
||||||
}],
|
}],
|
||||||
http: {
|
http: {
|
||||||
path: `/addTime`,
|
path: `/addTimeEntry`,
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.addTime = async(ctx, data) => {
|
Self.addTimeEntry = async(ctx, data) => {
|
||||||
const Worker = Self.app.models.Worker;
|
const Worker = Self.app.models.Worker;
|
||||||
const myUserId = ctx.req.accessToken.userId;
|
const myUserId = ctx.req.accessToken.userId;
|
||||||
const myWorker = await Worker.findOne({where: {userFk: myUserId}});
|
const myWorker = await Worker.findOne({where: {userFk: myUserId}});
|
|
@ -0,0 +1,41 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('deleteTimeEntry', {
|
||||||
|
description: 'Deletes a manual time entry for a worker if the user role is above the worker',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The time entry id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'boolean',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/deleteTimeEntry`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.deleteTimeEntry = async(ctx, id) => {
|
||||||
|
const currentUserId = ctx.req.accessToken.userId;
|
||||||
|
const workerModel = Self.app.models.Worker;
|
||||||
|
|
||||||
|
const targetTimeEntry = await Self.findById(id);
|
||||||
|
|
||||||
|
const isSubordinate = await workerModel.isSubordinate(ctx, targetTimeEntry.userFk);
|
||||||
|
const isHHRR = await Self.app.models.Account.hasRole(currentUserId, 'hr');
|
||||||
|
|
||||||
|
const notAllowed = isSubordinate === false || (isSubordinate && currentUserId == targetTimeEntry.userFk && !isHHRR);
|
||||||
|
|
||||||
|
if (notAllowed)
|
||||||
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
return Self.rawSql('CALL vn.workerTimeControl_remove(?, ?)', [
|
||||||
|
targetTimeEntry.userFk, targetTimeEntry.timed]);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,99 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('workerTimeControl addTimeEntry()', () => {
|
||||||
|
let insertedTime;
|
||||||
|
|
||||||
|
it('should fail to add a time entry if the target user is not a subordinate', async() => {
|
||||||
|
let error;
|
||||||
|
let ctx = {req: {accessToken: {userId: 1}}};
|
||||||
|
let data = {
|
||||||
|
workerFk: 2,
|
||||||
|
timed: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
expect(error.statusCode).toBe(400);
|
||||||
|
expect(error.message).toBe(`You don't have enough privileges`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to add if the current and the target user are the same and is not team boss', async() => {
|
||||||
|
let error;
|
||||||
|
let ctx = {req: {accessToken: {userId: 1}}};
|
||||||
|
let data = {
|
||||||
|
workerFk: 1,
|
||||||
|
timed: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
expect(error.statusCode).toBe(400);
|
||||||
|
expect(error.message).toBe(`You don't have enough privileges`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add if the current user is team boss and the target user is a subordinate', async() => {
|
||||||
|
todayAtSix = new Date();
|
||||||
|
todayAtSix.setHours(18, 30, 0, 0);
|
||||||
|
|
||||||
|
let teamBossId = 13;
|
||||||
|
let ctx = {req: {accessToken: {userId: teamBossId}}};
|
||||||
|
let data = {
|
||||||
|
workerFk: teamBossId,
|
||||||
|
timed: todayAtSix
|
||||||
|
};
|
||||||
|
|
||||||
|
await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||||
|
|
||||||
|
insertedTime = await app.models.WorkerTimeControl.findOne({where: {timed: data.timed}});
|
||||||
|
|
||||||
|
let createdTimeEntry = await app.models.WorkerTimeControl.findById(insertedTime.id);
|
||||||
|
|
||||||
|
expect(createdTimeEntry).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should try but fail to delete the created time entry for the team boss as team boss', async() => {
|
||||||
|
let error;
|
||||||
|
let teamBossId = 13;
|
||||||
|
let ctx = {req: {accessToken: {userId: teamBossId}}};
|
||||||
|
|
||||||
|
let createdTimeEntry = await app.models.WorkerTimeControl.findById(insertedTime.id);
|
||||||
|
|
||||||
|
expect(createdTimeEntry).toBeDefined();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await app.models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
expect(error.statusCode).toBe(400);
|
||||||
|
expect(error.message).toBe(`You don't have enough privileges`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the created time entry for the team boss as HHRR', async() => {
|
||||||
|
let HHRRId = 37;
|
||||||
|
let ctx = {req: {accessToken: {userId: HHRRId}}};
|
||||||
|
|
||||||
|
let createdTimeEntry = await app.models.WorkerTimeControl.findById(insertedTime.id);
|
||||||
|
|
||||||
|
expect(createdTimeEntry).toBeDefined();
|
||||||
|
|
||||||
|
ctx.req.accessToken.userId = HHRRId;
|
||||||
|
await app.models.WorkerTimeControl.deleteTimeEntry(ctx, insertedTime.id);
|
||||||
|
|
||||||
|
createdTimeEntry = await app.models.WorkerTimeControl.findById(insertedTime.id);
|
||||||
|
|
||||||
|
expect(createdTimeEntry).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,67 @@
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getWorkedHours', {
|
||||||
|
description: 'returns the total worked hours per day for a given range of dates in format YYYY-mm-dd hh:mm:ss',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'from',
|
||||||
|
type: 'Date',
|
||||||
|
required: true,
|
||||||
|
description: `The from date`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'to',
|
||||||
|
type: 'Date',
|
||||||
|
required: true,
|
||||||
|
description: `The to date`
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: ['Object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/getWorkedHours`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getWorkedHours = async(id, from, to) => {
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const stmts = [];
|
||||||
|
|
||||||
|
let worker = await Self.app.models.Worker.findById(id);
|
||||||
|
let userId = worker.userFk;
|
||||||
|
|
||||||
|
stmts.push(`
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS
|
||||||
|
tmp.timeControlCalculate,
|
||||||
|
tmp.timeBusinessCalculate
|
||||||
|
`);
|
||||||
|
|
||||||
|
stmts.push(new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [userId, from, to]));
|
||||||
|
stmts.push(new ParameterizedSQL('CALL vn.timeBusiness_calculateByUser(?, ?, ?)', [userId, from, to]));
|
||||||
|
let resultIndex = stmts.push(`
|
||||||
|
SELECT tbc.dated, tbc.timeWorkSeconds expectedHours, tcc.timeWorkSeconds workedHours
|
||||||
|
FROM tmp.timeBusinessCalculate tbc
|
||||||
|
LEFT JOIN tmp.timeControlCalculate tcc ON tcc.dated = tbc.dated
|
||||||
|
`) - 1;
|
||||||
|
stmts.push(`
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS
|
||||||
|
tmp.timeControlCalculate,
|
||||||
|
tmp.timeBusinessCalculate
|
||||||
|
`);
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await conn.executeStmt(sql);
|
||||||
|
|
||||||
|
return result[resultIndex];
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
Author : Enrique Blasco BLanquer
|
|
||||||
Date: 28 de mayo de 2019
|
|
||||||
*/
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethodCtx('getWorkerInfo', {
|
|
||||||
description: 'Get worker info (name, isWorking, total worked hours ...)',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
returns: [{
|
|
||||||
type: 'Object',
|
|
||||||
root: true
|
|
||||||
}],
|
|
||||||
http: {
|
|
||||||
path: `/getWorkerInfo`,
|
|
||||||
verb: 'GET'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.getWorkerInfo = async(ctx, data) => {
|
|
||||||
let prevHour = new Date(); // default value to start work
|
|
||||||
let diff = 0; // difference of value between two dates
|
|
||||||
let isOdd = true; // determine if timed is odd or not in db
|
|
||||||
const myUserId = ctx.req.accessToken.userId; // get user id
|
|
||||||
|
|
||||||
|
|
||||||
// 1 get name and photo for the user
|
|
||||||
let [user] = await Self.rawSql(`SELECT u.name, t.Foto FROM vn.user u INNER JOIN vn2008.Trabajadores t ON u.id = t.user_id WHERE id = ?;`, [myUserId]);
|
|
||||||
// 2 get all jornaly work time registered
|
|
||||||
let workedHours = await Self.rawSql(`SELECT * FROM vn.workerTimeControl WHERE userFk = ? AND DATE(timed) = CURDATE() ORDER BY timed ASC;`, [myUserId]);
|
|
||||||
let today = new Date();
|
|
||||||
// 3 get the number of hours to work in one day
|
|
||||||
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
|
|
||||||
let [hoursForDay] = await Self.rawSql(`SELECT cl.hours_week AS hoursWeek,
|
|
||||||
GROUP_CONCAT(DISTINCT LEFT(j.start,2) ORDER BY j.start ASC SEPARATOR '-') start ,
|
|
||||||
GROUP_CONCAT(DISTINCT LEFT(j.end,2) ORDER BY j.end ASC SEPARATOR '-') end,
|
|
||||||
CAST(IFNULL((SUM(TIME_TO_SEC(j.end))-SUM(TIME_TO_SEC(j.start)))/3600,if(cl.hours_week=40
|
|
||||||
AND DAYOFWEEK(t.dated) IN(2,3,4,5,6),8,0)) AS DECIMAL(10,2)) workingHours
|
|
||||||
FROM vn.time t
|
|
||||||
LEFT JOIN postgresql.business b ON t.dated BETWEEN b.date_start AND ifnull(b.date_end,? )
|
|
||||||
LEFT JOIN postgresql.profile AS pr ON b.client_id = pr.profile_id
|
|
||||||
LEFT JOIN postgresql.person AS p ON pr.person_id = p.person_id
|
|
||||||
LEFT JOIN vn.worker AS w ON p.id_trabajador = w.id
|
|
||||||
LEFT JOIN postgresql.business_labour AS bl ON b.business_id = bl.business_id
|
|
||||||
LEFT JOIN postgresql.calendar_labour_type AS cl ON bl.calendar_labour_type_id = cl.calendar_labour_type_id
|
|
||||||
LEFT JOIN postgresql.journey AS j ON j.business_id = b.business_id and j.day_id=WEEKDAY(t.dated)+1
|
|
||||||
WHERE t.dated BETWEEN ? AND ? AND userFk = ?
|
|
||||||
GROUP BY w.userFk,dated`, [date, date, date, myUserId]);
|
|
||||||
|
|
||||||
// 4 Add all the hours and see the total worked
|
|
||||||
for (hour of workedHours) {
|
|
||||||
if (!isOdd)
|
|
||||||
diff += Math.abs((new Date(hour.timed)).getTime() - prevHour.getTime());
|
|
||||||
else
|
|
||||||
prevHour = new Date(hour.timed);
|
|
||||||
|
|
||||||
isOdd = !isOdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5 calculate hours and minutes from a number value
|
|
||||||
let decimalTime = diff / 1000 / 3600;
|
|
||||||
decimalTime = decimalTime * 60 * 60;
|
|
||||||
let hours = Math.floor((decimalTime / (60 * 60)));
|
|
||||||
decimalTime = decimalTime - (hours * 60 * 60);
|
|
||||||
let minutes = Math.floor((decimalTime / 60));
|
|
||||||
|
|
||||||
// 6 default total hours
|
|
||||||
let totalHours = '7:40';
|
|
||||||
let hoursWeek = 40;
|
|
||||||
|
|
||||||
// 7 Get the hours you have to work today and the hours to work in a week
|
|
||||||
if (hoursForDay != null) {
|
|
||||||
// If it exceeds 5 hours we take 20 minutes of breakfast.
|
|
||||||
if (hoursForDay.workingHours > 5)
|
|
||||||
hoursForDay.workingHours -= 20 * 0.016666;
|
|
||||||
let decimalTime = parseFloat(hoursForDay.workingHours);
|
|
||||||
decimalTime = decimalTime * 60 * 60;
|
|
||||||
let hoursDay = Math.floor((decimalTime / (60 * 60)));
|
|
||||||
decimalTime = decimalTime - (hoursDay * 60 * 60);
|
|
||||||
let minutesDay = Math.floor((decimalTime / 60));
|
|
||||||
totalHours = hoursDay + ':' + minutesDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 8 return value
|
|
||||||
if (hoursForDay != null)
|
|
||||||
hoursWeek = hoursForDay.hoursWeek;
|
|
||||||
return {
|
|
||||||
'name': user.name,
|
|
||||||
'hours': hours,
|
|
||||||
'minutes': minutes,
|
|
||||||
'today': today,
|
|
||||||
'isWorking': !isOdd,
|
|
||||||
'lastDate': prevHour,
|
|
||||||
'totalHours': totalHours,
|
|
||||||
'hoursWeek': hoursWeek
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('timeControl', {
|
||||||
|
description: 'Returns a range of worked hours for a given worker id',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dateFrom',
|
||||||
|
type: 'datetime',
|
||||||
|
required: true,
|
||||||
|
description: 'the date from the time control begins in format YYYY-mm-dd-hh:mm:ss'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dateTo',
|
||||||
|
type: 'datetime',
|
||||||
|
required: true,
|
||||||
|
description: 'the date when the time control finishes in format YYYY-mm-dd-hh:mm:ss'
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: ['Object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/timeControl`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.timeControl = async(id, from, to) => {
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const stmts = [];
|
||||||
|
|
||||||
|
stmts.push(new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [id, from, to]));
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await conn.executeStmt(sql);
|
||||||
|
|
||||||
|
|
||||||
|
return result[0];
|
||||||
|
};
|
||||||
|
};
|
|
@ -2,7 +2,8 @@ const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/worker-time-control/filter')(Self);
|
require('../methods/worker-time-control/filter')(Self);
|
||||||
require('../methods/worker-time-control/addTime')(Self);
|
require('../methods/worker-time-control/addTimeEntry')(Self);
|
||||||
|
require('../methods/worker-time-control/deleteTimeEntry')(Self);
|
||||||
|
|
||||||
Self.rewriteDbError(function(err) {
|
Self.rewriteDbError(function(err) {
|
||||||
if (err.code === 'ER_DUP_ENTRY')
|
if (err.code === 'ER_DUP_ENTRY')
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
},
|
},
|
||||||
"order": {
|
"order": {
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
|
},
|
||||||
|
"direction": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -26,6 +29,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Account",
|
"model": "Account",
|
||||||
"foreignKey": "userFk"
|
"foreignKey": "userFk"
|
||||||
|
},
|
||||||
|
"worker": {
|
||||||
|
"type": "hasOne",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "userFk"
|
||||||
},
|
},
|
||||||
"warehouse": {
|
"warehouse": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
|
|
|
@ -2,5 +2,5 @@ module.exports = Self => {
|
||||||
require('../methods/worker/filter')(Self);
|
require('../methods/worker/filter')(Self);
|
||||||
require('../methods/worker/mySubordinates')(Self);
|
require('../methods/worker/mySubordinates')(Self);
|
||||||
require('../methods/worker/isSubordinate')(Self);
|
require('../methods/worker/isSubordinate')(Self);
|
||||||
require('../methods/worker/getWorkerInfo')(Self);
|
require('../methods/worker/getWorkedHours')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,24 +8,47 @@
|
||||||
<vn-table model="model" auto-load="false">
|
<vn-table model="model" auto-load="false">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-td ng-repeat="weekday in $ctrl.weekDays" center>
|
<vn-td ng-repeat="weekday in $ctrl.weekDays" center>
|
||||||
<div translate>{{::$ctrl.weekdayNames[$index].name}}</div>
|
<div class="weekday" translate>{{::$ctrl.weekdayNames[$index].name}}</div>
|
||||||
<span>{{::weekday.dated | date: 'dd'}}</span>
|
<div>
|
||||||
<span title="{{::weekday.dated | date: 'MMMM' | translate}}" translate>
|
<span>{{::weekday.dated | date: 'dd'}}</span>
|
||||||
{{::weekday.dated | date: 'MMMM'}}
|
<span title="{{::weekday.dated | date: 'MMMM' | translate}}" translate>
|
||||||
</span>
|
{{::weekday.dated | date: 'MMMM'}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<vn-chip
|
||||||
|
title="{{::weekday.event.name}}"
|
||||||
|
ng-class="{invisible: !weekday.event}">
|
||||||
|
<vn-avatar
|
||||||
|
ng-style="::{backgroundColor: weekday.event.color}">
|
||||||
|
</vn-avatar>
|
||||||
|
<div>
|
||||||
|
{{::weekday.event.name}}
|
||||||
|
</div>
|
||||||
|
</vn-chip>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-td ng-repeat="weekday in $ctrl.weekDays" class="hours vn-pa-none" center>
|
<vn-td ng-repeat="weekday in $ctrl.weekDays" class="hours vn-pa-none" expand center>
|
||||||
<section ng-repeat="hour in weekday.hours" center>
|
<section ng-repeat="hour in weekday.hours" center>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
icon="arrow_{{($index % 2) == 0 ? 'forward' : 'back'}}"
|
icon="{{
|
||||||
title="{{(($index % 2) == 0 ? 'In' : 'Out') | translate}}">
|
::hour.direction == 'in' ? 'arrow_forward' : 'arrow_back'
|
||||||
|
}}"
|
||||||
|
title="{{
|
||||||
|
::(hour.direction == 'in' ? 'In' : 'Out') | translate
|
||||||
|
}}"
|
||||||
|
ng-class="::{'invisible': hour.direction == 'middle'}">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<span class="chip {{$ctrl.hourColor(hour)}}">{{hour.timed | date: 'HH:mm'}}</span>
|
<vn-chip
|
||||||
|
ng-class="::{'colored': hour.manual}"
|
||||||
|
removable="::hour.manual"
|
||||||
|
translate-attr="{title: 'Category'}"
|
||||||
|
on-remove="$ctrl.showDeleteDialog(hour)">
|
||||||
|
{{::hour.timed | date: 'HH:mm'}}
|
||||||
|
</vn-chip>
|
||||||
</section>
|
</section>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
|
@ -33,7 +56,7 @@
|
||||||
<vn-tfoot>
|
<vn-tfoot>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-td ng-repeat="weekday in $ctrl.weekDays" center>
|
<vn-td ng-repeat="weekday in $ctrl.weekDays" center>
|
||||||
{{$ctrl.getWeekdayTotalHours(weekday)}} h.
|
{{$ctrl.formatHours(weekday.workedHours)}} h.
|
||||||
</vn-td>
|
</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
|
@ -56,6 +79,10 @@
|
||||||
label="Week total"
|
label="Week total"
|
||||||
value="{{$ctrl.weekTotalHours}} h.">
|
value="{{$ctrl.weekTotalHours}} h.">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
|
<vn-label-value
|
||||||
|
label="Finish at"
|
||||||
|
value="{{$ctrl.getFinishTime()}}">
|
||||||
|
</vn-label-value>
|
||||||
</div>
|
</div>
|
||||||
<vn-calendar
|
<vn-calendar
|
||||||
class="vn-pt-md"
|
class="vn-pt-md"
|
||||||
|
@ -85,3 +112,9 @@
|
||||||
<button response="accept" translate>Save</button>
|
<button response="accept" translate>Save</button>
|
||||||
</tpl-buttons>
|
</tpl-buttons>
|
||||||
</vn-dialog>
|
</vn-dialog>
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="delete-entry-dialog"
|
||||||
|
on-accept="$ctrl.deleteTimeEntry()"
|
||||||
|
message="This time entry will be deleted"
|
||||||
|
question="Are you sure you want to delete this entry?">
|
||||||
|
</vn-confirm>
|
|
@ -1,12 +1,9 @@
|
||||||
|
import Component from 'core/lib/component';
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
class Controller extends Component {
|
||||||
class Controller {
|
constructor($element, $, vnWeekDays) {
|
||||||
constructor($scope, $http, $stateParams, $element, vnWeekDays) {
|
super($element, $);
|
||||||
this.$stateParams = $stateParams;
|
|
||||||
this.$ = $scope;
|
|
||||||
this.$http = $http;
|
|
||||||
this.$element = $element;
|
|
||||||
this.weekDays = [];
|
this.weekDays = [];
|
||||||
this.weekdayNames = vnWeekDays.locales;
|
this.weekdayNames = vnWeekDays.locales;
|
||||||
}
|
}
|
||||||
|
@ -34,9 +31,20 @@ class Controller {
|
||||||
this.started = started;
|
this.started = started;
|
||||||
|
|
||||||
let ended = new Date(started.getTime());
|
let ended = new Date(started.getTime());
|
||||||
ended.setDate(ended.getDate() + 7);
|
ended.setHours(23, 59, 59, 59);
|
||||||
|
ended.setDate(ended.getDate() + 6);
|
||||||
this.ended = ended;
|
this.ended = ended;
|
||||||
|
|
||||||
|
this.weekDays = [];
|
||||||
|
let dayIndex = new Date(started.getTime());
|
||||||
|
|
||||||
|
while (dayIndex < ended) {
|
||||||
|
this.weekDays.push({
|
||||||
|
dated: new Date(dayIndex.getTime())
|
||||||
|
});
|
||||||
|
dayIndex.setDate(dayIndex.getDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
this.fetchHours();
|
this.fetchHours();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,86 +57,118 @@ class Controller {
|
||||||
|
|
||||||
set hours(value) {
|
set hours(value) {
|
||||||
this._hours = value;
|
this._hours = value;
|
||||||
this.weekDays = [];
|
|
||||||
if (!this.hours) return;
|
|
||||||
|
|
||||||
let dayIndex = new Date(this.started.getTime());
|
for (const weekDay of this.weekDays) {
|
||||||
|
if (value) {
|
||||||
while (dayIndex < this.ended) {
|
let day = weekDay.dated.getDay();
|
||||||
let weekDay = dayIndex.getDay();
|
weekDay.hours = value
|
||||||
|
.filter(hour => new Date(hour.timed).getDay() == day)
|
||||||
let hours = this.hours
|
.sort((a, b) => new Date(a.timed) - new Date(b.timed));
|
||||||
.filter(hour => new Date(hour.timed).getDay() == weekDay)
|
} else
|
||||||
.sort((a, b) => new Date(a.timed) - new Date(b.timed));
|
weekDay.hours = null;
|
||||||
|
|
||||||
this.weekDays.push({
|
|
||||||
dated: new Date(dayIndex.getTime()),
|
|
||||||
hours
|
|
||||||
});
|
|
||||||
dayIndex.setDate(dayIndex.getDate() + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchHours() {
|
fetchHours() {
|
||||||
const params = {workerFk: this.$stateParams.id};
|
const params = {workerFk: this.$params.id};
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {and: [
|
where: {and: [
|
||||||
{timed: {gte: this.started}},
|
{timed: {gte: this.started}},
|
||||||
{timed: {lt: this.ended}}
|
{timed: {lte: this.ended}}
|
||||||
]}
|
]}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$.model.applyFilter(filter, params);
|
this.$.model.applyFilter(filter, params);
|
||||||
|
|
||||||
|
this.getAbsences();
|
||||||
|
this.getWorkedHours(this.started, this.ended);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEvents(day) {
|
hasEvents(day) {
|
||||||
return day >= this.started && day < this.ended;
|
return day >= this.started && day < this.ended;
|
||||||
}
|
}
|
||||||
|
|
||||||
hourColor(weekDay) {
|
getWorkedHours(from, to) {
|
||||||
return weekDay.manual ? 'alert' : 'warning';
|
this.weekTotalHours = null;
|
||||||
|
let weekTotalHours = 0;
|
||||||
|
let params = {
|
||||||
|
id: this.$params.id,
|
||||||
|
from: from,
|
||||||
|
to: to
|
||||||
|
};
|
||||||
|
|
||||||
|
const query = `Workers/${this.$params.id}/getWorkedHours`;
|
||||||
|
return this.$http.get(query, {params}).then(res => {
|
||||||
|
const workDays = res.data;
|
||||||
|
const map = new Map();
|
||||||
|
|
||||||
|
for (const workDay of workDays) {
|
||||||
|
workDay.dated = new Date(workDay.dated);
|
||||||
|
map.set(workDay.dated, workDay);
|
||||||
|
weekTotalHours += workDay.workedHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const weekDay of this.weekDays) {
|
||||||
|
const workDay = workDays.find(day => {
|
||||||
|
let from = new Date(day.dated);
|
||||||
|
from.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let to = new Date(day.dated);
|
||||||
|
to.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
|
return weekDay.dated >= from && weekDay.dated <= to;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (workDay) {
|
||||||
|
weekDay.expectedHours = workDay.expectedHours;
|
||||||
|
weekDay.workedHours = workDay.workedHours;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.weekTotalHours = weekTotalHours;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getWeekdayTotalHours(weekday) {
|
getFinishTime() {
|
||||||
if (weekday.hours.length == 0) return 0;
|
if (!this.weekDays) return;
|
||||||
|
|
||||||
const hours = weekday.hours;
|
let today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
let totalStamp = 0;
|
let todayInWeek = this.weekDays.find(day => day.dated.getTime() === today.getTime());
|
||||||
|
|
||||||
hours.forEach((hour, index) => {
|
if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
|
||||||
let currentHour = new Date(hour.timed);
|
const remainingTime = todayInWeek.workedHours ? ((todayInWeek.expectedHours - todayInWeek.workedHours) * 1000) : null;
|
||||||
let previousHour = new Date(hour.timed);
|
const lastKnownEntry = todayInWeek.hours[todayInWeek.hours.length - 1];
|
||||||
|
const lastKnownTime = new Date(lastKnownEntry.timed).getTime();
|
||||||
|
const finishTimeStamp = lastKnownTime && remainingTime ? lastKnownTime + remainingTime : null;
|
||||||
|
|
||||||
if (index > 0 && (index % 2 == 1))
|
if (finishTimeStamp) {
|
||||||
previousHour = new Date(hours[index - 1].timed);
|
let finishDate = new Date(finishTimeStamp);
|
||||||
|
let hour = finishDate.getHours();
|
||||||
|
let minute = finishDate.getMinutes();
|
||||||
|
|
||||||
const dif = Math.abs(previousHour - currentHour);
|
if (hour < 10) hour = `0${hour}`;
|
||||||
|
if (minute < 10) minute = `0${minute}`;
|
||||||
|
|
||||||
totalStamp += dif;
|
return `${hour}:${minute} h.`;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (totalStamp / 3600 / 1000 > 5)
|
set weekTotalHours(totalHours) {
|
||||||
totalStamp += (20 * 60 * 1000);
|
if (!totalHours) return this._weekTotalHours = this.formatHours(0);
|
||||||
|
|
||||||
weekday.total = totalStamp;
|
this._weekTotalHours = this.formatHours(totalHours);
|
||||||
|
|
||||||
return this.formatHours(totalStamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get weekTotalHours() {
|
get weekTotalHours() {
|
||||||
let total = 0;
|
return this._weekTotalHours;
|
||||||
|
|
||||||
this.weekDays.forEach(weekday => {
|
|
||||||
if (weekday.total)
|
|
||||||
total += weekday.total;
|
|
||||||
});
|
|
||||||
return this.formatHours(total);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
formatHours(timestamp) {
|
formatHours(timestamp) {
|
||||||
let hour = Math.floor(timestamp / 3600 / 1000);
|
timestamp = timestamp || 0;
|
||||||
let min = Math.floor(timestamp / 60 / 1000 - 60 * hour);
|
|
||||||
|
let hour = Math.floor(timestamp / 3600);
|
||||||
|
let min = Math.floor(timestamp / 60 - 60 * hour);
|
||||||
|
|
||||||
if (hour < 10) hour = `0${hour}`;
|
if (hour < 10) hour = `0${hour}`;
|
||||||
if (min < 10) min = `0${min}`;
|
if (min < 10) min = `0${min}`;
|
||||||
|
@ -148,15 +188,76 @@ class Controller {
|
||||||
addTime(response) {
|
addTime(response) {
|
||||||
if (response !== 'accept') return;
|
if (response !== 'accept') return;
|
||||||
let data = {
|
let data = {
|
||||||
workerFk: this.$stateParams.id,
|
workerFk: this.$params.id,
|
||||||
timed: this.newTime
|
timed: this.newTime
|
||||||
};
|
};
|
||||||
this.$http.post(`WorkerTimeControls/addTime`, data)
|
this.$http.post(`WorkerTimeControls/addTimeEntry`, data)
|
||||||
.then(() => this.fetchHours());
|
.then(() => this.fetchHours());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showDeleteDialog(hour) {
|
||||||
|
this.timeEntryToDelete = hour;
|
||||||
|
this.$.deleteEntryDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTimeEntry() {
|
||||||
|
const entryId = this.timeEntryToDelete.id;
|
||||||
|
|
||||||
|
this.$http.post(`WorkerTimeControls/${entryId}/deleteTimeEntry`).then(() => {
|
||||||
|
this.fetchHours();
|
||||||
|
this.vnApp.showSuccess(this.$t('Entry removed'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getAbsences() {
|
||||||
|
let params = {
|
||||||
|
workerFk: this.$params.id,
|
||||||
|
started: this.started,
|
||||||
|
ended: this.ended
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.$http.get(`WorkerCalendars/absences`, {params})
|
||||||
|
.then(res => this.onData(res.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
onData(data) {
|
||||||
|
const events = {};
|
||||||
|
|
||||||
|
let addEvent = (day, event) => {
|
||||||
|
events[new Date(day).getTime()] = event;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data.holidays) {
|
||||||
|
data.holidays.forEach(holiday => {
|
||||||
|
const holidayDetail = holiday.detail && holiday.detail.description;
|
||||||
|
const holidayType = holiday.type && holiday.type.name;
|
||||||
|
const holidayName = holidayDetail || holidayType;
|
||||||
|
|
||||||
|
addEvent(holiday.dated, {
|
||||||
|
name: holidayName,
|
||||||
|
color: '#ff0'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.absences) {
|
||||||
|
data.absences.forEach(absence => {
|
||||||
|
const type = absence.absenceType;
|
||||||
|
addEvent(absence.dated, {
|
||||||
|
name: type.name,
|
||||||
|
color: type.rgb
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.weekDays.forEach(day => {
|
||||||
|
const timestamp = day.dated.getTime();
|
||||||
|
if (events[timestamp])
|
||||||
|
day.event = events[timestamp];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$http', '$stateParams', '$element', 'vnWeekDays'];
|
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||||
|
|
||||||
ngModule.component('vnWorkerTimeControl', {
|
ngModule.component('vnWorkerTimeControl', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,111 +1,115 @@
|
||||||
import './index.js';
|
import './index.js';
|
||||||
|
|
||||||
describe('Worker', () => {
|
|
||||||
describe('Component vnWorkerTimeControl', () => {
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
let $element;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('worker'));
|
describe('Component vnWorkerTimeControl', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let $scope;
|
||||||
|
let $element;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($compile, $rootScope, $stateParams, _$httpBackend_) => {
|
beforeEach(ngModule('worker'));
|
||||||
$stateParams.id = 1;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$element = $compile('<vn-worker-time-control></vn-worker-time-control>')($scope);
|
|
||||||
controller = $element.controller('vnWorkerTimeControl');
|
|
||||||
}));
|
|
||||||
|
|
||||||
afterEach(() => {
|
beforeEach(angular.mock.inject(($componentController, $compile, $rootScope, $stateParams, _$httpBackend_) => {
|
||||||
$scope.$destroy();
|
$stateParams.id = 1;
|
||||||
$element.remove();
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
$element = angular.element('<vn-worker-time-control></vn-worker-time-control>');
|
||||||
|
controller = $componentController('vnWorkerTimeControl', {$element, $scope});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('date() setter', () => {
|
||||||
|
it(`should set the weekDays, the date in the controller and call fetchHours`, () => {
|
||||||
|
let today = new Date();
|
||||||
|
spyOn(controller, 'fetchHours');
|
||||||
|
|
||||||
|
controller.date = today;
|
||||||
|
|
||||||
|
expect(controller._date).toEqual(today);
|
||||||
|
expect(controller.started).toBeDefined();
|
||||||
|
expect(controller.ended).toBeDefined();
|
||||||
|
expect(controller.weekDays.length).toEqual(7);
|
||||||
|
expect(controller.fetchHours).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('hours() setter', () => {
|
describe('hours() setter', () => {
|
||||||
it(`should set hours data at it's corresponding week day`, () => {
|
it(`should set hours data at it's corresponding week day`, () => {
|
||||||
let wednesday = new Date(controller.started.getTime());
|
let today = new Date();
|
||||||
wednesday.setDate(wednesday.getDate() + 2);
|
spyOn(controller, 'fetchHours');
|
||||||
|
|
||||||
$httpBackend.whenRoute('GET', 'WorkerTimeControls/filter')
|
controller.date = today;
|
||||||
.respond([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
timed: controller.started.toJSON(),
|
|
||||||
userFk: 1
|
|
||||||
}, {
|
|
||||||
id: 2,
|
|
||||||
timed: wednesday.toJSON(),
|
|
||||||
userFk: 1
|
|
||||||
}, {
|
|
||||||
id: 3,
|
|
||||||
timed: wednesday.toJSON(),
|
|
||||||
userFk: 1
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
$httpBackend.flush();
|
let hours = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
timed: controller.started.toJSON(),
|
||||||
|
userFk: 1
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
timed: controller.ended.toJSON(),
|
||||||
|
userFk: 1
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
timed: controller.ended.toJSON(),
|
||||||
|
userFk: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
expect(controller.weekDays.length).toEqual(7);
|
controller.hours = hours;
|
||||||
expect(controller.weekDays[0].hours.length).toEqual(1);
|
|
||||||
expect(controller.weekDays[2].hours.length).toEqual(2);
|
expect(controller.weekDays.length).toEqual(7);
|
||||||
});
|
expect(controller.weekDays[0].hours.length).toEqual(1);
|
||||||
|
expect(controller.weekDays[6].hours.length).toEqual(2);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getWeekdayTotalHours() ', () => {
|
describe('getWorkedHours() ', () => {
|
||||||
it(`should return a total worked hours from 07:00 to 15:00`, () => {
|
it(`should `, () => {
|
||||||
const hourOne = new Date();
|
let today = new Date();
|
||||||
hourOne.setHours(7, 0, 0, 0);
|
spyOn(controller, 'fetchHours');
|
||||||
const hourTwo = new Date();
|
|
||||||
hourTwo.setHours(10, 0, 0, 0);
|
|
||||||
const hourThree = new Date();
|
|
||||||
hourThree.setHours(10, 20, 0, 0);
|
|
||||||
const hourFour = new Date();
|
|
||||||
hourFour.setHours(15, 0, 0, 0);
|
|
||||||
|
|
||||||
const weekday = {hours: [
|
controller.date = today;
|
||||||
{id: 1, timed: hourOne},
|
|
||||||
{id: 2, timed: hourTwo},
|
|
||||||
{id: 3, timed: hourThree},
|
|
||||||
{id: 4, timed: hourFour}
|
|
||||||
]};
|
|
||||||
|
|
||||||
const result = controller.getWeekdayTotalHours(weekday);
|
let sixHoursInSeconds = 6 * 60 * 60;
|
||||||
|
let tenHoursInSeconds = 10 * 60 * 60;
|
||||||
|
let response = [
|
||||||
|
{
|
||||||
|
dated: today,
|
||||||
|
expectedHours: sixHoursInSeconds,
|
||||||
|
workedHours: tenHoursInSeconds,
|
||||||
|
|
||||||
expect(result).toEqual('08:00');
|
},
|
||||||
});
|
];
|
||||||
});
|
$httpBackend.whenRoute('GET', 'Workers/:id/getWorkedHours')
|
||||||
|
.respond(response);
|
||||||
|
|
||||||
describe('weekTotalHours() ', () => {
|
today.setHours(0, 0, 0, 0);
|
||||||
it(`should return a total worked hours from a week`, () => {
|
|
||||||
const hourOne = new Date();
|
|
||||||
hourOne.setHours(7, 0, 0, 0);
|
|
||||||
const hourTwo = new Date();
|
|
||||||
hourTwo.setHours(10, 0, 0, 0);
|
|
||||||
const hourThree = new Date();
|
|
||||||
hourThree.setHours(10, 20, 0, 0);
|
|
||||||
const hourFour = new Date();
|
|
||||||
hourFour.setHours(15, 0, 0, 0);
|
|
||||||
|
|
||||||
const weekday = {hours: [
|
let weekOffset = today.getDay() - 1;
|
||||||
{id: 1, timed: hourOne},
|
if (weekOffset < 0) weekOffset = 6;
|
||||||
{id: 2, timed: hourTwo},
|
|
||||||
{id: 3, timed: hourThree},
|
|
||||||
{id: 4, timed: hourFour}
|
|
||||||
]};
|
|
||||||
controller.weekDays = [weekday];
|
|
||||||
|
|
||||||
const weekdayHours = controller.getWeekdayTotalHours(weekday);
|
let started = new Date(today.getTime());
|
||||||
const weekHours = controller.weekTotalHours;
|
started.setDate(started.getDate() - weekOffset);
|
||||||
|
controller.started = started;
|
||||||
|
|
||||||
expect(weekdayHours).toEqual('08:00');
|
let ended = new Date(started.getTime());
|
||||||
expect(weekHours).toEqual('08:00');
|
ended.setHours(23, 59, 59, 59);
|
||||||
});
|
ended.setDate(ended.getDate() + 6);
|
||||||
|
controller.ended = ended;
|
||||||
|
|
||||||
|
controller.getWorkedHours(controller.started, controller.ended);
|
||||||
|
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.weekDays.length).toEqual(7);
|
||||||
|
expect(controller.weekDays[weekOffset].expectedHours).toEqual(response[0].expectedHours);
|
||||||
|
expect(controller.weekDays[weekOffset].workedHours).toEqual(response[0].workedHours);
|
||||||
|
expect(controller.weekTotalHours).toEqual('10:00');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('formatHours() ', () => {
|
describe('formatHours() ', () => {
|
||||||
it(`should format a passed timestamp to hours and minutes`, () => {
|
it(`should format a passed timestamp to hours and minutes`, () => {
|
||||||
const result = controller.formatHours(3600000);
|
const result = controller.formatHours(3600);
|
||||||
|
|
||||||
expect(result).toEqual('01:00');
|
expect(result).toEqual('01:00');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,3 +5,7 @@ Hours: Horas
|
||||||
Add time: Añadir hora
|
Add time: Añadir hora
|
||||||
Week total: Total semana
|
Week total: Total semana
|
||||||
Current week: Semana actual
|
Current week: Semana actual
|
||||||
|
This time entry will be deleted: Se borrará la hora fichada
|
||||||
|
Are you sure you want to delete this entry?: ¿Seguro que quieres eliminarla?
|
||||||
|
Finish at: Termina a las
|
||||||
|
Entry removed: Fichada borrada
|
|
@ -1,11 +1,12 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
vn-worker-time-control {
|
vn-worker-time-control {
|
||||||
vn-thead > vn-tr > vn-td > div {
|
vn-thead > vn-tr > vn-td > div.weekday {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
color: $color-main
|
color: $color-main
|
||||||
}
|
}
|
||||||
vn-td.hours {
|
vn-td.hours {
|
||||||
|
min-width: 100px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
|
||||||
& > section {
|
& > section {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
.grid-block {
|
.grid-block {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
background-color: #FFF;
|
||||||
min-height: 40px
|
min-height: 40px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +23,6 @@
|
||||||
height: 40px
|
height: 40px
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-block.white {
|
|
||||||
background-color: #FFF
|
|
||||||
}
|
|
||||||
|
|
||||||
.columns {
|
.columns {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"app": {
|
"app": {
|
||||||
"host": "http://localhost:5000",
|
"host": "http://localhost:5000",
|
||||||
"port": 3000,
|
"port": 3000,
|
||||||
"senderMail": "nocontestar@verdnatura.es",
|
"senderEmail": "nocontestar@verdnatura.es",
|
||||||
|
"reportEmail": "cau@verdnatura.es",
|
||||||
"senderName": "Verdnatura"
|
"senderName": "Verdnatura"
|
||||||
},
|
},
|
||||||
"i18n": {
|
"i18n": {
|
||||||
|
|
|
@ -4,13 +4,13 @@ buttons:
|
||||||
privacy:
|
privacy:
|
||||||
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla
|
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla
|
||||||
· www.verdnatura.es · clientes@verdnatura.es
|
· www.verdnatura.es · clientes@verdnatura.es
|
||||||
disclaimer: '- AVIS - Ce message est privé et confidentiel et doit être utilisé.exclusivamente
|
disclaimer: "- AVIS - Ce message est privé et confidentiel et doit être utilisé
|
||||||
por la persona destinataria del mismo. Si has recibido este mensajepor error,
|
exclusivement par le destinataire. Si vous avez reçu ce message par erreur,
|
||||||
te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier documentoadjunto
|
veuillez en informer l'expéditeur et supprimer ce message ainsi que tous les
|
||||||
que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad
|
documents joints qu'il pourrait contenir. Verdnatura Levante SL ne renonce pas à la
|
||||||
ni aningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente
|
confidentialité ni aux privilèges résultant d'une transmission erronée ou d'un dysfonctionnement.
|
||||||
no se haceresponsable de los cambios, alteraciones, errores u omisiones que pudieran
|
De même, il n'est pas responsable des modifications, altérations, erreurs ou
|
||||||
hacerse al mensaje una vez enviado.'
|
omissions qui pourraient être apportées au message une fois envoyé."
|
||||||
law: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de
|
law: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de
|
||||||
Datos de Carácter Personal, te comunicamos que los datos personales que facilites
|
Datos de Carácter Personal, te comunicamos que los datos personales que facilites
|
||||||
se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,pudiendo en
|
se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,pudiendo en
|
||||||
|
|
|
@ -10,13 +10,20 @@ module.exports = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
find(query, params) {
|
/**
|
||||||
|
* Makes a query from a raw sql
|
||||||
|
* @param {String} query - The raw SQL query
|
||||||
|
* @param {Object} params - Parameterized values
|
||||||
|
*
|
||||||
|
* @return {Object} - Result
|
||||||
|
*/
|
||||||
|
rawSql(query, params) {
|
||||||
return this.pool.query(query, params).then(([rows]) => {
|
return this.pool.query(query, params).then(([rows]) => {
|
||||||
return rows;
|
return rows;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
findOne(query, params) {
|
findOne(query, params) {
|
||||||
return this.find(query, params).then(([rows]) => rows);
|
return this.rawSql(query, params).then(([rows]) => rows);
|
||||||
},
|
},
|
||||||
findFromDef() {
|
findFromDef() {
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ const validator = {
|
||||||
if (invalidProps.length > 0) {
|
if (invalidProps.length > 0) {
|
||||||
const required = invalidProps.join(', ');
|
const required = invalidProps.join(', ');
|
||||||
|
|
||||||
throw new Error(`Required params not found [${required}]`);
|
throw new Error(`Required properties not found [${required}]`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: ['isPreview']
|
props: ['isPreview']
|
||||||
|
|
|
@ -1,51 +1,6 @@
|
||||||
const Report = require('./report');
|
|
||||||
const Email = require('./email');
|
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
app.get(`/api/report/:name`, async(req, res, next) => {
|
// Import methods
|
||||||
const args = req.query;
|
require('../methods/closure')(app);
|
||||||
const requiredArgs = ['clientId'];
|
require('../methods/report')(app);
|
||||||
|
require('../methods/email')(app);
|
||||||
const hasRequiredArgs = requiredArgs.every(arg => {
|
|
||||||
return args[arg];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!hasRequiredArgs)
|
|
||||||
res.json({message: 'Required params recipient, clientId'});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const report = new Report(req.params.name, args);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
res.setHeader('Content-type', 'application/pdf');
|
|
||||||
stream.pipe(res);
|
|
||||||
} catch (e) {
|
|
||||||
next(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get(`/api/email/:name`, async(req, res, next) => {
|
|
||||||
const args = req.query;
|
|
||||||
const requiredArgs = ['recipient', 'clientId'];
|
|
||||||
|
|
||||||
const hasRequiredArgs = requiredArgs.every(arg => {
|
|
||||||
return args[arg];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!hasRequiredArgs)
|
|
||||||
res.json({message: 'Required params recipient, clientId'});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const email = new Email(req.params.name, args);
|
|
||||||
if (args.isPreview === 'true') {
|
|
||||||
const rendered = await email.render();
|
|
||||||
|
|
||||||
res.send(rendered);
|
|
||||||
} else {
|
|
||||||
await email.send();
|
|
||||||
res.status(200).json({message: 'Sent'});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
next(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const nodemailer = require('nodemailer');
|
const nodemailer = require('nodemailer');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
const db = require('./database');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init() {
|
init() {
|
||||||
|
@ -8,15 +9,30 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
send(options) {
|
send(options) {
|
||||||
options.from = `${config.app.senderName} <${config.app.senderMail}>`;
|
options.from = `${config.app.senderName} <${config.app.senderEmail}>`;
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
if (!config.smtp.auth.user)
|
if (!config.smtp.auth.user)
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
|
|
||||||
options.to = config.app.senderMail;
|
options.to = config.app.senderEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.transporter.sendMail(options);
|
let error;
|
||||||
|
return this.transporter.sendMail(options).catch(err => {
|
||||||
|
error = err;
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}).finally(async() => {
|
||||||
|
await db.rawSql(`
|
||||||
|
INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status)
|
||||||
|
VALUES (:recipient, :sender, 1, :subject, :body, :status)`, {
|
||||||
|
sender: config.app.senderEmail,
|
||||||
|
recipient: options.to,
|
||||||
|
subject: options.subject,
|
||||||
|
body: options.text || options.html,
|
||||||
|
status: error && error.message || 'Sent'
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
const db = require('../core/database');
|
||||||
|
const Email = require('../core/email');
|
||||||
|
const smtp = require('../core/smtp');
|
||||||
|
const config = require('../core/config');
|
||||||
|
|
||||||
|
module.exports = app => {
|
||||||
|
app.get('/api/closure', async function(req, res) {
|
||||||
|
const failedtickets = [];
|
||||||
|
const tickets = await db.rawSql(`
|
||||||
|
SELECT
|
||||||
|
t.id,
|
||||||
|
t.clientFk,
|
||||||
|
c.email recipient
|
||||||
|
FROM expedition e
|
||||||
|
JOIN ticket t ON t.id = e.ticketFk
|
||||||
|
JOIN client c ON c.id = t.clientFk
|
||||||
|
JOIN warehouse w ON w.id = t.warehouseFk AND hasComission
|
||||||
|
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
|
||||||
|
WHERE ts.code = 'PACKED'
|
||||||
|
AND DATE(t.shipped) BETWEEN DATE_ADD(CURDATE(), INTERVAL -2 DAY) AND CURDATE()
|
||||||
|
AND t.refFk IS NULL
|
||||||
|
GROUP BY e.ticketFk`);
|
||||||
|
|
||||||
|
for (const ticket of tickets) {
|
||||||
|
try {
|
||||||
|
await db.rawSql(`CALL vn.ticketClosureTicket(:ticketId)`, {
|
||||||
|
ticketId: ticket.id
|
||||||
|
});
|
||||||
|
|
||||||
|
const args = {
|
||||||
|
ticketId: ticket.id,
|
||||||
|
clientId: ticket.clientFk,
|
||||||
|
recipient: ticket.recipient
|
||||||
|
};
|
||||||
|
const email = new Email('delivery-note-link', args);
|
||||||
|
await email.send();
|
||||||
|
} catch (error) {
|
||||||
|
// Save tickets on a list of failed ids
|
||||||
|
failedtickets.push({
|
||||||
|
id: ticket.id,
|
||||||
|
stacktrace: error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send email with failed tickets
|
||||||
|
if (failedtickets.length > 0) {
|
||||||
|
let body = 'This following tickets has failed:<br/><br/>';
|
||||||
|
|
||||||
|
for (ticket of failedtickets) {
|
||||||
|
body += `Ticket: <strong>${ticket.id}</strong>
|
||||||
|
<br/> <strong>${ticket.stacktrace}</strong><br/><br/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
smtp.send({
|
||||||
|
to: config.app.reportEmail,
|
||||||
|
subject: '[API] Nightly ticket closure has failed',
|
||||||
|
html: body
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: 'Closure executed successfully'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,32 @@
|
||||||
|
const Email = require('../core/email');
|
||||||
|
|
||||||
|
module.exports = app => {
|
||||||
|
app.get(`/api/email/:name`, async(req, res, next) => {
|
||||||
|
const args = req.query;
|
||||||
|
const requiredArgs = ['clientId', 'recipient'];
|
||||||
|
const argList = requiredArgs.join(',');
|
||||||
|
const hasRequiredArgs = requiredArgs.every(arg => {
|
||||||
|
return args[arg];
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!hasRequiredArgs)
|
||||||
|
throw new Error(`Required properties not found [${argList}]`);
|
||||||
|
|
||||||
|
const email = new Email(req.params.name, args);
|
||||||
|
if (args.isPreview === 'true') {
|
||||||
|
const rendered = await email.render();
|
||||||
|
|
||||||
|
res.send(rendered);
|
||||||
|
} else {
|
||||||
|
await email.send();
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: 'Sent'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
next(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
const Report = require('../core/report');
|
||||||
|
|
||||||
|
module.exports = app => {
|
||||||
|
app.get(`/api/report/:name`, async(req, res, next) => {
|
||||||
|
const args = req.query;
|
||||||
|
const requiredArgs = ['clientId'];
|
||||||
|
const argList = requiredArgs.join(',');
|
||||||
|
const hasRequiredArgs = requiredArgs.every(arg => {
|
||||||
|
return args[arg];
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!hasRequiredArgs)
|
||||||
|
throw new Error(`Required properties not found [${argList}]`);
|
||||||
|
|
||||||
|
const report = new Report(req.params.name, args);
|
||||||
|
const stream = await report.toPdfStream();
|
||||||
|
res.setHeader('Content-type', 'application/pdf');
|
||||||
|
stream.pipe(res);
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,4 +1,6 @@
|
||||||
[{
|
[
|
||||||
"filename": "claim-pickup-order.pdf",
|
{
|
||||||
"component": "claim-pickup"
|
"filename": "claim-pickup-order.pdf",
|
||||||
}]
|
"component": "claim-pickup"
|
||||||
|
}
|
||||||
|
]
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }}</h1>
|
||||||
<p>{{$t('description.dear')}},</p>
|
<p>{{$t('description.dear')}},</p>
|
||||||
<p>{{$t('description.instructions')}}</p>
|
<p>{{$t('description.instructions')}}</p>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }}</h1>
|
||||||
<p>{{$t('dearClient')}},</p>
|
<p>{{$t('dearClient')}},</p>
|
||||||
<p v-html="$t('clientData')"></p>
|
<p v-html="$t('clientData')"></p>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
const Stylesheet = require(`${appPath}/core/stylesheet`);
|
||||||
|
|
||||||
|
module.exports = new Stylesheet([
|
||||||
|
`${appPath}/common/css/spacing.css`,
|
||||||
|
`${appPath}/common/css/misc.css`,
|
||||||
|
`${appPath}/common/css/layout.css`,
|
||||||
|
`${appPath}/common/css/email.css`,
|
||||||
|
`${__dirname}/style.css`])
|
||||||
|
.mergeStyles();
|
|
@ -0,0 +1,5 @@
|
||||||
|
.external-link {
|
||||||
|
border: 2px dashed #8dba25;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-align: center
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html v-bind:lang="locale">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
<title>{{ $t('subject') }}</title>
|
||||||
|
<style type="text/css">
|
||||||
|
a {
|
||||||
|
color: #8dba25
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table class="grid">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<!-- Empty block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block empty"></div>
|
||||||
|
</div>
|
||||||
|
<!-- Header block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block">
|
||||||
|
<email-header
|
||||||
|
v-bind:is-preview="isPreview"
|
||||||
|
v-bind:locale="locale">
|
||||||
|
</email-header>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block vn-pa-lg">
|
||||||
|
<h1>{{ $t('title') }}</h1>
|
||||||
|
<p>{{$t('dear')}}</p>
|
||||||
|
<p v-html="$t('description', [ticketId])"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block vn-px-lg">
|
||||||
|
<p>{{$t('copyLink')}}</p>
|
||||||
|
<div class="external-link vn-pa-sm vn-m-md">
|
||||||
|
https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={{ticketId}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block vn-pa-lg">
|
||||||
|
<p v-html="$t('poll')"></p>
|
||||||
|
<p v-html="$t('help')"></p>
|
||||||
|
<p v-html="$t('conclusion')"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block">
|
||||||
|
<email-footer
|
||||||
|
v-bind:is-preview="isPreview"
|
||||||
|
v-bind:locale="locale">
|
||||||
|
</email-footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Empty block -->
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block empty"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,16 @@
|
||||||
|
const Component = require(`${appPath}/core/component`);
|
||||||
|
const emailHeader = new Component('email-header');
|
||||||
|
const emailFooter = new Component('email-footer');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'delivery-note-link',
|
||||||
|
components: {
|
||||||
|
'email-header': emailHeader.build(),
|
||||||
|
'email-footer': emailFooter.build()
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
ticketId: {
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
subject: Aquí tienes tu albarán
|
||||||
|
title: "Aquí tienes tu albarán"
|
||||||
|
dear: Estimado cliente
|
||||||
|
description: Ya está disponible el albarán correspondiente al pedido <strong>{0}</strong>. <br/>
|
||||||
|
Puedes verlo haciendo clic <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">en este enlace</a>.
|
||||||
|
copyLink: 'Como alternativa, puedes copiar el siguiente enlace en tu navegador:'
|
||||||
|
poll: Si lo deseas, puedes responder a nuestra encuesta de satisfacción para
|
||||||
|
ayudarnos a prestar un mejor servicio. ¡Tu opinión es muy importante para nosotros!
|
||||||
|
help: Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para
|
||||||
|
atenderte!</strong>
|
||||||
|
conclusion: ¡Gracias por tu atención!
|
|
@ -0,0 +1,10 @@
|
||||||
|
subject: Voici votre bon de livraison
|
||||||
|
title: "Voici votre bon de livraison"
|
||||||
|
dear: Cher client,
|
||||||
|
description: Le bon de livraison correspondant à la commande <strong>{0}</strong> est maintenant disponible.<br/>
|
||||||
|
Vous pouvez le voir en cliquant <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}" target="_blank">sur ce lien</a>.
|
||||||
|
copyLink: 'Vous pouvez également copier le lien suivant dans votre navigateur:'
|
||||||
|
poll: Si vous le souhaitez, vous pouvez répondre à notre questionaire de satisfaction
|
||||||
|
pour nous aider à améliorer notre service. Votre avis est très important pour nous!
|
||||||
|
help: N'hésitez pas nous envoyer toute doute ou question, <strong>nous sommes là pour vous aider!</strong>
|
||||||
|
conclusion: Merci pour votre attention!
|
|
@ -1,4 +1,6 @@
|
||||||
[{
|
[
|
||||||
"filename": "delivery-note.pdf",
|
{
|
||||||
"component": "delivery-note"
|
"filename": "delivery-note.pdf",
|
||||||
}]
|
"component": "delivery-note"
|
||||||
|
}
|
||||||
|
]
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }}</h1>
|
||||||
<p>{{$t('dear')}},</p>
|
<p>{{$t('dear')}},</p>
|
||||||
<p v-html="$t('description', [ticketId])"></p>
|
<p v-html="$t('description', [ticketId])"></p>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
[{
|
[
|
||||||
"filename": "driver-route.pdf",
|
{
|
||||||
"component": "driver-route"
|
"filename": "driver-route.pdf",
|
||||||
}]
|
"component": "driver-route"
|
||||||
|
}
|
||||||
|
]
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }}</h1>
|
||||||
<p>{{$t('description.instructions')}}</p>
|
<p>{{$t('description.instructions')}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
[{
|
[
|
||||||
"filename": "letter-debtor.pdf",
|
{
|
||||||
"component": "letter-debtor"
|
"filename": "letter-debtor.pdf",
|
||||||
}]
|
"component": "letter-debtor"
|
||||||
|
}
|
||||||
|
]
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }}</h1>
|
||||||
<p>{{ $t('sections.introduction.title') }},</p>
|
<p>{{ $t('sections.introduction.title') }},</p>
|
||||||
<p>{{ $t('sections.introduction.description') }}</p>
|
<p>{{ $t('sections.introduction.description') }}</p>
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row" v-if="isPreview">
|
<div class="grid-row" v-if="isPreview">
|
||||||
<div class="grid-block white vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<attachment v-for="attachment in attachments"
|
<attachment v-for="attachment in attachments"
|
||||||
v-bind:key="attachment.filename"
|
v-bind:key="attachment.filename"
|
||||||
v-bind:attachment="attachment"
|
v-bind:attachment="attachment"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue