Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into dev
gitea/salix/dev There was a failure building this commit Details

This commit is contained in:
Bernat 2019-11-19 11:43:00 +01:00
commit 12825f0503
446 changed files with 6078 additions and 5635 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
coverage
node_modules
dist/*
dist
e2e/dms/*/
!e2e/dms/c4c
!e2e/dms/c81

View File

@ -28,8 +28,10 @@ module.exports = Self => {
const models = Self.app.models;
const accessToken = ctx.req.accessToken;
const sender = await models.Account.findById(accessToken.userId);
const recipient = to.replace('@', '');
return sendMessage(to, `@${sender.name}: ${message}`);
if (sender.name != recipient)
return sendMessage(to, `@${sender.name}: ${message}`);
};
async function sendMessage(name, message) {
@ -70,6 +72,12 @@ module.exports = Self => {
}
function send(uri, body) {
if (process.env.NODE_ENV !== 'production') {
return new Promise(resolve => {
return resolve({statusCode: 200, message: 'Fake notification sent'});
});
}
const options = {
method: 'POST',
uri: uri,

View File

@ -0,0 +1,18 @@
const app = require('vn-loopback/server/server');
describe('chat sendMessage()', () => {
it('should return a "Fake notification sent" as response', async() => {
let ctx = {req: {accessToken: {userId: 1}}};
let response = await app.models.Chat.sendMessage(ctx, '@salesPerson', 'I changed something');
expect(response.statusCode).toEqual(200);
expect(response.message).toEqual('Fake notification sent');
});
it('should not return a response', async() => {
let ctx = {req: {accessToken: {userId: 18}}};
let response = await app.models.Chat.sendMessage(ctx, '@salesPerson', 'I changed something');
expect(response).toBeUndefined();
});
});

View File

@ -62,7 +62,7 @@ module.exports = Self => {
*/
Self.hasRole = async function(userId, name) {
let roles = await Self.getRoles(userId);
return roles.find(role => role == name);
return roles.some(role => role == name);
};
/**

View File

@ -26,6 +26,12 @@ CREATE TABLE `vn`.`zoneEvent` (
CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) 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` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`zoneFk` int(11) NOT NULL,
@ -35,9 +41,16 @@ CREATE TABLE `vn`.`zoneExclusion` (
KEY `zoneFk` (`zoneFk`),
CONSTRAINT `zoneExclusion_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
ALTER TABLE `vn`.`zone`
DROP FOREIGN KEY `fk_zone_1`;
ALTER TABLE `vn`.`zone`
CHANGE COLUMN `warehouseFk` `warehouseFk` SMALLINT(6) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE `vn`.`zone`
ADD CONSTRAINT `fk_zone_1`
FOREIGN KEY (`warehouseFk`)
REFERENCES `vn`.`warehouse` (`id`)
ON DELETE NO ACTION
ON UPDATE CASCADE;
ALTER TABLE `vn`.`zone`
DROP FOREIGN KEY `fk_zone_1`;
ALTER TABLE `vn`.`zone`
DROP COLUMN `warehouseFk`,
DROP INDEX `fk_zone_1_idx`;
ALTER TABLE `vn`.`zoneExclusion`
CHANGE COLUMN `day` `dated` DATE NOT NULL ;

View File

@ -1,10 +1,12 @@
USE `vn`;
DROP procedure IF EXISTS `zone_getEvents`;
DROP PROCEDURE IF EXISTS `vn`.`zone_getEvents`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zone_getEvents`(
vAgencyModeFk INT,
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getEvents`(
vProvinceFk INT,
vPostCode VARCHAR(255))
vPostCode VARCHAR(255),
vAgencyModeFk INT)
BEGIN
/**
* Returns available events for the passed province/postcode and agency.
@ -13,9 +15,9 @@ BEGIN
* @param vProvinceFk The province id
* @param vPostCode The postcode or %NULL to use the province
*/
DECLARE vGeoFk INT;
IF vPostCode IS NOT NULL THEN
DECLARE vGeoFk INT;
IF vPostCode IS NOT NULL THEN
SELECT p.geoFk INTO vGeoFk
FROM postCode p
JOIN town t ON t.id = p.townFk
@ -24,24 +26,27 @@ BEGIN
ELSE
SELECT geoFk INTO vGeoFk
FROM province
WHERE id = vProvinceFk;
END IF;
WHERE id = vProvinceFk;
END IF;
CALL zone_getFromGeo(vGeoFk);
DELETE t FROM tmp.zone t
JOIN zone z ON z.id = t.id
WHERE z.agencyModeFk != vAgencyModeFk;
SELECT e.`from`, e.`to`, e.weekDays
CALL zone_getFromGeo(vGeoFk);
IF vAgencyModeFk IS NOT NULL THEN
DELETE t FROM tmp.zone t
JOIN zone z ON z.id = t.id
WHERE z.agencyModeFk != vAgencyModeFk;
END IF;
SELECT e.`type`, e.dated, e.`started`, e.`ended`, e.weekDays
FROM tmp.zone t
JOIN zoneEvent e ON e.zoneFk = t.id;
SELECT DISTINCT e.`day`
SELECT DISTINCT e.dated
FROM tmp.zone t
JOIN zoneExclusion e ON e.zoneFk = t.id;
DROP TEMPORARY TABLE tmp.zone;
END$$
DELIMITER ;

View File

@ -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 ;

View File

@ -28,7 +28,7 @@ BEGIN
JOIN zone z ON z.id = zo.zoneFk
JOIN zoneWarehouse zw ON zw.zoneFk = z.id
WHERE agencyModeFk = vAgencyModeFk
AND warehouseFk = vWarehouseFk;
AND zw.warehouseFk = vWarehouseFk;
DROP TEMPORARY TABLE
tmp.zone,

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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 ;
;

View File

@ -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 ;

View File

@ -0,0 +1,10 @@
USE `vn`;
UPDATE `vn`.`country` SET `ibanLength` = '24' WHERE (`id` = 1);
UPDATE `vn`.`country` SET `ibanLength` = '27' WHERE (`id` = 2);
UPDATE `vn`.`country` SET `ibanLength` = '22' WHERE (`id` = 3);
UPDATE `vn`.`country` SET `ibanLength` = '24' WHERE (`id` = 4);
UPDATE `vn`.`country` SET `ibanLength` = '18' WHERE (`id` = 5);
UPDATE `vn`.`country` SET `ibanLength` = '25' WHERE (`id` = 8);
UPDATE `vn`.`country` SET `ibanLength` = '27' WHERE (`id` = 19);
UPDATE `vn`.`country` SET `ibanLength` = '24' WHERE (`id` = 30);

View File

@ -0,0 +1,3 @@
USE `vn`;
CREATE DEFINER=`root`@`%` EVENT `department_doCalc` ON SCHEDULE EVERY 15 SECOND STARTS '2019-11-15 00:00:00' ON COMPLETION PRESERVE ENABLE DO CALL vn.department_doCalc

View File

@ -0,0 +1,8 @@
USE `vn`;
UPDATE `vn`.`sample` SET `description` = 'Bienvenida como nuevo cliente' WHERE (`id` = '12');
UPDATE `vn`.`sample` SET `description` = 'Instalación y configuración de impresora de coronas' WHERE (`id` = '13');
UPDATE `vn`.`sample` SET `description` = 'Solicitud de domiciliación bancaria' WHERE (`id` = '14');
UPDATE `vn`.`sample` SET `description` = 'Aviso inicial por saldo deudor' WHERE (`id` = '15');
UPDATE `vn`.`sample` SET `description` = 'Aviso reiterado por saldo deudor' WHERE (`id` = '16');
UPDATE `vn`.`sample` SET `isVisible` = '0' WHERE (`id` = '17');

View File

@ -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 ;

View File

@ -0,0 +1,108 @@
USE `vn`;
ALTER TABLE `vn`.`ticketRequest`
DROP FOREIGN KEY `fgnAtender`;
ALTER TABLE `vn`.`ticketRequest`
CHANGE COLUMN `atenderFk` `attenderFk` INT(11) NULL DEFAULT NULL ;
ALTER TABLE `vn`.`ticketRequest`
ADD CONSTRAINT `fgnAtender`
FOREIGN KEY (`attenderFk`)
REFERENCES `vn`.`worker` (`id`)
ON UPDATE CASCADE;
USE `vn2008`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn2008`.`Ordenes` AS
SELECT
`tr`.`id` AS `Id_ORDEN`,
`tr`.`description` AS `ORDEN`,
`tr`.`requesterFk` AS `requesterFk`,
`tr`.`attenderFk` AS `attenderFk`,
`tr`.`quantity` AS `CANTIDAD`,
`tr`.`itemFk` AS `Id_ARTICLE`,
`tr`.`price` AS `PRECIOMAX`,
`tr`.`isOk` AS `isOk`,
`tr`.`saleFk` AS `Id_Movimiento`,
`tr`.`ticketFk` AS `ticketFk`,
`tr`.`response` AS `COMENTARIO`,
`tr`.`created` AS `odbc_date`,
`tr`.`ordered` AS `datORDEN`,
`tr`.`shipped` AS `datTICKET`,
`tr`.`salesPersonCode` AS `CodVENDEDOR`,
`tr`.`buyerCode` AS `CodCOMPRADOR`,
`tr`.`price__` AS `PREU`,
`tr`.`clientFk` AS `Id_CLIENTE`,
`tr`.`ok__` AS `OK`,
`tr`.`total` AS `TOTAL`,
`tr`.`buyed` AS `datCOMPRA`,
`tr`.`ko__` AS `KO`
FROM
`vn`.`ticketRequest` `tr`;
USE `vn`;
DROP TRIGGER IF EXISTS `vn`.`ticketRequest_beforeInsert`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`ticketRequest_beforeInsert` BEFORE INSERT ON `ticketRequest` FOR EACH ROW
BEGIN
IF NEW.ticketFk IS NULL THEN
SET NEW.ticketFk = (SELECT s.ticketFk FROM sale s WHERE s.id = NEW.saleFk);
END IF;
IF NEW.requesterFk IS NULL THEN
SET NEW.requesterFk = (SELECT w.id FROM worker w WHERE w.code = NEW.salesPersonCode);
END IF;
IF NEW.attenderFk IS NULL THEN
SET NEW.attenderFk = (SELECT w.id FROM worker w WHERE w.code = NEW.buyerCode);
END IF;
END$$
DELIMITER ;
DROP TRIGGER IF EXISTS `vn`.`ticketRequest_beforeUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`ticketRequest_beforeUpdate` BEFORE UPDATE ON `ticketRequest` FOR EACH ROW
BEGIN
IF NEW.saleFk <> OLD.saleFk THEN
SET NEW.ticketFk = (SELECT s.ticketFk FROM sale s WHERE s.id = NEW.saleFk);
END IF;
IF NEW.salesPersonCode <> OLD.salesPersonCode THEN
SET NEW.requesterFk = (SELECT w.id FROM worker w WHERE w.code = NEW.salesPersonCode);
END IF;
IF NEW.buyerCode <> OLD.buyerCode THEN
SET NEW.attenderFk = (SELECT w.id FROM worker w WHERE w.code = NEW.buyerCode);
END IF;
END$$
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`;

View File

@ -53,13 +53,14 @@ INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossF
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`)
VALUES
(1, 'España', 0, 'ES', 1, 22),
(2, 'Italia', 1, 'IT', 1, 25),
(3, 'Alemania', 1, 'DE', 1, 20),
(4, 'Rumania', 1, 'RO', 1, 22),
(5, 'Holanda', 1, 'NL', 1, 16),
(19,'Francia', 1, 'FR', 1, 25),
(30,'Canarias', 1, 'IC', 1, 22);
(1, 'España', 0, 'ES', 1, 24),
(2, 'Italia', 1, 'IT', 1, 27),
(3, 'Alemania', 1, 'DE', 1, 22),
(4, 'Rumania', 1, 'RO', 1, 24),
(5, 'Holanda', 1, 'NL', 1, 18),
(8, 'Portugal', 1, 'PT', 1, 27),
(19,'Francia', 1, 'FR', 1, 27),
(30,'Canarias', 1, 'IC', 1, 24);
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`)
VALUES
@ -195,9 +196,9 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
VALUES
(101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(102, 'Petter Parker', '87945234L', 'Spider man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 19, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1),
(105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 8, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1),
(106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1),
(107, 'Hank Pym', '09854837G', 'Ant man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1),
(108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1),
@ -1467,7 +1468,7 @@ INSERT INTO `vn2008`.`workerTeam`(`id`, `team`, `user`)
(5, 3, 103),
(6, 3, 104);
INSERT INTO `vn`.`ticketRequest`(`id`, `description`, `requesterFk`, `atenderFk`, `quantity`, `itemFk`, `price`, `isOk`, `saleFk`, `ticketFk`, `created`)
INSERT INTO `vn`.`ticketRequest`(`id`, `description`, `requesterFk`, `attenderFk`, `quantity`, `itemFk`, `price`, `isOk`, `saleFk`, `ticketFk`, `created`)
VALUES
(1, 'Ranged weapon longbow 2m', 18, 35, 5, 1, 9.10, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY)),
(2, 'Melee weapon combat first 15cm', 18, 35, 10, 2, 1.07, 0, NULL, 1, DATE_ADD(CURDATE(), INTERVAL -15 DAY)),
@ -1614,227 +1615,227 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
(8, 5, 0),
(8, 1, 1);
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `from`)
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
VALUES
(1, 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, 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, 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, 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, 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)),
(3, CURDATE()),
(3, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(3, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(4, CURDATE()),
(4, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(4, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(5, CURDATE()),
(5, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(5, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(6, CURDATE()),
(6, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(6, DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(7, CURDATE()),
(7, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(7, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(7, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(7, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(7, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(7, DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(8, CURDATE()),
(8, DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(8, DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(8, DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(8, DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(8, DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(8, DATE_ADD(CURDATE(), INTERVAL +6 DAY));
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
(3, 'day', CURDATE()),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(3, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(4, 'day', CURDATE()),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(4, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(5, 'day', CURDATE()),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(5, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(6, 'day', CURDATE()),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +7 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +8 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +9 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +10 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +11 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +12 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +13 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +14 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +15 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +16 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +17 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +18 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +19 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +20 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +21 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +22 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +23 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +24 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +25 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +26 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +27 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +28 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +29 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +30 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +31 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +32 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +33 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +34 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +35 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +36 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +37 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +38 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +39 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +40 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +41 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +42 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +43 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +44 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +45 DAY)),
(6, 'day', DATE_ADD(CURDATE(), INTERVAL +46 DAY)),
(7, 'day', CURDATE()),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +5 DAY)),
(7, 'day', DATE_ADD(CURDATE(), INTERVAL +6 DAY)),
(8, 'day', CURDATE()),
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +1 DAY)),
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +2 DAY)),
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +3 DAY)),
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +4 DAY)),
(8, 'day', DATE_ADD(CURDATE(), INTERVAL +5 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
(106, CONCAT(CURDATE(), ' 07:00'), TRUE),
(106, CONCAT(CURDATE(), ' 10:00'), TRUE),
(106, CONCAT(CURDATE(), ' 10:10'), TRUE),
(106, CONCAT(CURDATE(), ' 15:00'), TRUE);
(106, CONCAT(CURDATE(), ' 07:00'), TRUE, 'in'),
(106, CONCAT(CURDATE(), ' 10:00'), TRUE, 'middle'),
(106, CONCAT(CURDATE(), ' 10:10'), TRUE, 'middle'),
(106, CONCAT(CURDATE(), ' 15:00'), TRUE, 'out');
INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `code`)
VALUES
@ -1946,3 +1947,8 @@ INSERT INTO `vn`.`userPhone`(`id`, `userFk`, `typeFk`, `phone`)
(65, 107, 'businessPhone', 700987987),
(67, 106, 'businessPhone', 1111111112),
(68, 106, 'personalPhone', 1111111113);
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`)
VALUES
(1, 43200, 129600, 734400, 43200, 50400);

View File

@ -5,25 +5,14 @@ describe('buyUltimateFromInterval()', () => {
let today;
let future;
beforeAll(() => {
let date = new Date();
let month = `${date.getMonth() + 1}`;
let futureMonth = `${date.getMonth() + 2}`;
let day = date.getDate();
let year = date.getFullYear();
let futureYear = year;
let now = new Date();
now.setHours(0, 0, 0, 0);
today = now;
if (month.toString().length < 2) month = '0' + month;
if (futureMonth.toString().length < 2) futureMonth = '0' + futureMonth;
if (futureMonth.toString() == '13') {
futureMonth = '01';
futureYear + 1;
}
if (day.toString().length < 2) day = `0${day}`;
today = [year, month, day].join('-');
future = [futureYear, futureMonth, day].join('-');
let futureDate = new Date(now);
let futureMonth = now.getMonth() + 1;
futureDate.setMonth(futureMonth);
future = futureDate;
});
it(`should create a temporal table with it's data`, async() => {
@ -65,8 +54,8 @@ describe('buyUltimateFromInterval()', () => {
expect(buyUltimateFromIntervalTable[0].buyFk).toEqual(3);
expect(buyUltimateFromIntervalTable[1].buyFk).toEqual(5);
expect(buyUltimateFromIntervalTable[0].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[1].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[0].landed).toEqual(today);
expect(buyUltimateFromIntervalTable[1].landed).toEqual(today);
});
it(`should create a temporal table with it's data in which started value is assigned to ended`, async() => {
@ -101,8 +90,8 @@ describe('buyUltimateFromInterval()', () => {
expect(buyUltimateFromIntervalTable[0].buyFk).toEqual(3);
expect(buyUltimateFromIntervalTable[1].buyFk).toEqual(5);
expect(buyUltimateFromIntervalTable[0].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[1].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[0].landed).toEqual(today);
expect(buyUltimateFromIntervalTable[1].landed).toEqual(today);
});
it(`should create a temporal table with it's data in which ended value is a date in the future`, async() => {
@ -137,7 +126,7 @@ describe('buyUltimateFromInterval()', () => {
expect(buyUltimateFromIntervalTable[0].buyFk).toEqual(3);
expect(buyUltimateFromIntervalTable[1].buyFk).toEqual(5);
expect(buyUltimateFromIntervalTable[0].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[1].landed).toEqual(new Date(today));
expect(buyUltimateFromIntervalTable[0].landed).toEqual(today);
expect(buyUltimateFromIntervalTable[1].landed).toEqual(today);
});
});

View File

@ -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();
});
});

View File

@ -7,8 +7,6 @@ import config from './config.js';
let currentUser;
let actions = {
// Generic extensions
clickIfExists: async function(selector) {
let exists = await this.exists(selector);
if (exists) await this.click(selector);
@ -25,8 +23,6 @@ let actions = {
}, selector);
},
// Salix specific extensions
changeLanguageToEnglish: async function() {
let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]';
@ -49,14 +45,15 @@ let actions = {
login: async function(userName) {
if (currentUser !== userName) {
let logoutClicked = await this.clickIfExists('#logout');
let accountClicked = await this.clickIfExists('#user');
if (logoutClicked) {
if (accountClicked) {
let buttonSelector = '.vn-dialog.shown button[response=accept]';
await this.wait(buttonSelector => {
return document.querySelector(buttonSelector) != null
|| location.hash == '#!/login';
}, buttonSelector);
await this.waitToClick('#logout')
.wait(buttonSelector => {
return document.querySelector(buttonSelector) != null
|| location.hash == '#!/login';
}, buttonSelector);
await this.clickIfExists(buttonSelector);
}
@ -72,7 +69,7 @@ let actions = {
currentUser = userName;
} else
await this.waitToClick('vn-topbar a[ui-sref="home"]');
await this.waitToClick('a[ui-sref=home]');
},
waitForLogin: async function(userName) {
@ -189,7 +186,7 @@ let actions = {
let element = selectorMatches[0];
if (selectorMatches.length > 1)
throw new Error(`multiple matches of ${elementSelector} found`);
throw new Error(`Multiple matches of ${elementSelector} found`);
let isVisible = false;
if (element) {
@ -347,7 +344,7 @@ let actions = {
.write('vn-searchbar input', searchValue)
.click('vn-searchbar vn-icon[icon="search"]')
.wait(100)
.waitForNumberOfElements('.searchResult', 1)
.waitForNumberOfElements('.search-result', 1)
.evaluate(() => {
return document.querySelector('ui-view vn-card vn-table') != null;
})
@ -362,15 +359,16 @@ let actions = {
accessToSection: function(sectionRoute) {
return this.wait(`vn-left-menu`)
.evaluate(sectionRoute => {
return document.querySelector(`vn-left-menu ul li ul li > a[ui-sref="${sectionRoute}"]`) != null;
return document.querySelector(`vn-left-menu li li > a[ui-sref="${sectionRoute}"]`) != null;
}, sectionRoute)
.then(nested => {
if (!nested)
return this.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`);
if (nested) {
this.waitToClick('vn-left-menu vn-item-section > vn-icon[icon=keyboard_arrow_down]')
.wait('vn-left-menu .expanded');
}
return this.waitToClick('vn-left-menu .collapsed')
.wait('vn-left-menu .expanded')
.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`);
return this.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`)
.waitForSpinnerLoad();
});
},
@ -429,10 +427,7 @@ let actions = {
},
waitForSpinnerLoad: function() {
return this.wait(() => {
const element = document.querySelector('vn-spinner > div');
return element.style.display == 'none';
});
return this.waitUntilNotPresent('vn-topbar vn-spinner');
}
};

View File

@ -13,9 +13,7 @@ module.exports = function createNightmare(width = 1280, height = 720) {
x: 0,
y: 0,
waitTimeout: 2000,
// openDevTools: {
// mode: 'detach'
// }
// openDevTools: {mode: 'detach'}
}).viewport(width, height);
nightmare.on('console', (type, message, ...args) => {

View File

@ -9,7 +9,7 @@ export default {
invoiceOutButton: '.modules-menu > li[ui-sref="invoiceOut.index"]',
claimsButton: '.modules-menu > li[ui-sref="claim.index"]',
returnToModuleIndexButton: 'a[ui-sref="order.index"]',
userMenuButton: 'vn-topbar #user',
userMenuButton: '#user',
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
userLocalCompany: '.user-popover vn-autocomplete[ng-model="$ctrl.localCompanyFk"]',
@ -23,7 +23,7 @@ export default {
clientsIndex: {
searchClientInput: `vn-textfield input`,
searchButton: 'vn-searchbar vn-icon[icon="search"]',
searchResult: 'vn-client-index .vn-list-item',
searchResult: 'vn-client-index .vn-item',
createClientButton: `vn-float-button`,
othersButton: 'vn-left-menu li[name="Others"] > a'
},
@ -180,7 +180,7 @@ export default {
acceptDeleteButton: '.vn-confirm.shown button[response="accept"]'
},
itemsIndex: {
searchIcon: 'vn-item-index vn-searchbar vn-icon[icon="search"]',
searchIcon: 'vn-searchbar vn-icon[icon="search"]',
createItemButton: `vn-float-button`,
searchResult: 'vn-item-index a.vn-tr',
searchResultPreviewButton: 'vn-item-index .buttons > [icon="desktop_windows"]',
@ -221,7 +221,7 @@ export default {
moreMenuRegularizeButton: '.vn-drop-down.shown li[name="Regularize stock"]',
regularizeQuantityInput: '.vn-dialog.shown tpl-body > div > vn-textfield input',
regularizeWarehouseAutocomplete: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.warehouseFk"]',
editButton: 'vn-item-card vn-item-descriptor vn-float-button[icon="edit"]',
editButton: 'vn-item-descriptor vn-float-button[icon="edit"]',
regularizeSaveButton: '.vn-dialog.shown tpl-buttons > button',
inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]',
navigateBackToIndex: 'vn-item-descriptor vn-icon[icon="chevron_left"]'
@ -324,20 +324,20 @@ export default {
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button'
},
ticketsIndex: {
openAdvancedSearchButton: 'vn-ticket-index vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"] input',
newTicketButton: 'vn-ticket-index > a',
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
searchTicketInput: `vn-ticket-index vn-textfield input`,
searchWeeklyTicketInput: `vn-ticket-weekly-index vn-textfield input`,
searchWeeklyClearInput: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon=clear]',
searchTicketInput: `vn-searchbar input`,
searchWeeklyTicketInput: `vn-searchbar input`,
searchWeeklyClearInput: 'vn-searchbar vn-icon[icon=clear]',
advancedSearchButton: 'vn-ticket-search-panel button[type=submit]',
searchButton: 'vn-ticket-index vn-searchbar vn-icon[icon="search"]',
searchWeeklyButton: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon="search"]',
searchButton: 'vn-searchbar vn-icon[icon="search"]',
searchWeeklyButton: 'vn-searchbar vn-icon[icon="search"]',
moreMenu: 'vn-ticket-index vn-icon-menu[icon=more_vert]',
moreMenuWeeklyTickets: '.vn-drop-down.shown li:nth-child(2)',
menuWeeklyTickets: 'vn-left-menu [ui-sref="ticket.weekly.index"]',
sixthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tr:nth-child(6) vn-autocomplete[ng-model="weekly.weekDay"] input',
weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr',
firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
@ -472,7 +472,7 @@ export default {
zoneAutocomplete: 'vn-autocomplete[ng-model="$ctrl.zoneId"]',
nextStepButton: 'vn-step-control .buttons > section:last-child vn-button',
finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]',
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > form > vn-card > vn-horizontal > table > tfoot > tr > td:nth-child(4)',
stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two vn-tfoot > vn-tr > :nth-child(6)',
chargesReasonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.option"]',
},
ticketComponents: {
@ -516,9 +516,9 @@ export default {
saveStateButton: `button[type=submit]`
},
claimsIndex: {
searchClaimInput: `vn-claim-index vn-textfield input`,
searchClaimInput: `vn-searchbar input`,
searchResult: 'vn-claim-index vn-card > vn-table > div > vn-tbody > a',
searchButton: 'vn-claim-index vn-searchbar vn-icon[icon="search"]'
searchButton: 'vn-searchbar vn-icon[icon="search"]'
},
claimDescriptor: {
moreMenu: 'vn-claim-descriptor vn-icon-menu[icon=more_vert]',
@ -584,7 +584,7 @@ export default {
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
searchOrderInput: `vn-order-index vn-textfield input`,
searchButton: 'vn-order-index vn-searchbar vn-icon[icon="search"]',
searchButton: 'vn-searchbar vn-icon[icon="search"]',
createOrderButton: `vn-float-button`,
},
orderDescriptor: {
@ -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',
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',
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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) > span',
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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) > span',
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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) > span',
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > span',
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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) > span',
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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) > span',
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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) > span',
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > span',
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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) > span',
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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) > span',
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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) > span',
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > span',
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > 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) > span',
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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) > span',
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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) > span',
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > 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) > vn-chip > div',
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) > vn-chip > div',
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) > vn-chip > div',
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) > vn-chip > div',
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) > vn-chip > div',
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) > vn-chip > div',
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) > vn-chip > div',
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > div',
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"]',
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > vn-chip > div',
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > 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) > vn-chip > div',
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > 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) > vn-chip > div',
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > 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) > vn-chip > div',
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > 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) > vn-chip > div',
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > 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) > vn-chip > div',
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)',
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)',
@ -717,11 +718,12 @@ export default {
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]',
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: {
searchInvoiceOutInput: `vn-invoice-out-index vn-textfield input`,
searchButton: 'vn-invoice-out-index vn-searchbar vn-icon[icon="search"]',
searchInvoiceOutInput: `vn-searchbar input`,
searchButton: 'vn-searchbar vn-icon[icon="search"]',
searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
},
invoiceOutDescriptor: {

View File

@ -30,7 +30,7 @@ describe('Login path', () => {
it('should log in', async() => {
const url = await nightmare
.doLogin('employee', null)
.wait('#logout')
.wait('#user')
.parsedUrl();
expect(url.hash).toEqual('#!/');

View File

@ -35,8 +35,30 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should scan out Hank Pym and forget to scan in from the break`, async() => {
const scanTime = '15:00';
it(`should scan in Hank Pym for a wrong hour and forget to scan in from the break`, async() => {
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
.waitToClick(selectors.workerTimeControl.mondayAddTimeButton)
.pickTime(selectors.workerTimeControl.timeDialogInput, scanTime)
@ -54,7 +76,7 @@ describe('Worker time control path', () => {
.waitToClick(selectors.workerTimeControl.confirmButton)
.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() => {
@ -67,9 +89,10 @@ describe('Worker time control path', () => {
it(`should check Hank Pym worked 8 hours`, async() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '07:00 h.')
.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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.tuesdayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.tuesdayWorkedHours, 'innerText');
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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.wednesdayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.wednesdayWorkedHours, 'innerText');
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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.thursdayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.thursdayWorkedHours, 'innerText');
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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.fridayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.fridayWorkedHours, 'innerText');
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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.saturdayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.saturdayWorkedHours, 'innerText');
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() => {
const result = await nightmare
.waitForTextInElement(selectors.workerTimeControl.sundayWorkedHours, '08:00 h.')
.waitToGetProperty(selectors.workerTimeControl.sundayWorkedHours, 'innerText');
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() => {
const wholeWeekHours = await nightmare
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 h.')
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '55:00 h.')
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
expect(wholeWeekHours).toEqual('56:00 h.');
expect(wholeWeekHours).toEqual('55:00 h.');
});
});
});

View File

@ -80,7 +80,7 @@ describe('Item summary path', () => {
it('should search for other item', async() => {
const result = await nightmare
.clearInput('vn-item-index vn-searchbar input')
.clearInput('vn-searchbar input')
.waitToClick(selectors.itemsIndex.searchButton)
.write(selectors.itemsIndex.searchItemInput, 'Melee weapon combat fist 15cm')
.waitToClick(selectors.itemsIndex.searchButton)

View File

@ -7,7 +7,7 @@ describe('Ticket expeditions and log path', () => {
beforeAll(() => {
return nightmare
.loginAndModule('production', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.expedition');
});

View File

@ -7,7 +7,7 @@ describe('Ticket Create packages path', () => {
beforeAll(() => {
return nightmare
.loginAndModule('employee', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.package');
});

View File

@ -8,7 +8,7 @@ describe('Ticket Create new tracking state path', () => {
beforeAll(() => {
return nightmare
.loginAndModule('production', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.tracking.index');
});
@ -44,7 +44,7 @@ describe('Ticket Create new tracking state path', () => {
beforeAll(() => {
return nightmare
.loginAndModule('salesPerson', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.tracking.index');
});

View File

@ -7,7 +7,7 @@ describe('Ticket List components path', () => {
beforeAll(() => {
return nightmare
.loginAndModule('employee', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.components');
});

View File

@ -11,8 +11,7 @@ describe('Ticket descriptor path', () => {
it('should count the amount of tickets in the turns section', async() => {
const result = await nightmare
.waitToClick(selectors.ticketsIndex.moreMenu)
.waitToClick(selectors.ticketsIndex.moreMenuWeeklyTickets)
.waitToClick(selectors.ticketsIndex.menuWeeklyTickets)
.wait(selectors.ticketsIndex.weeklyTicket)
.countElement(selectors.ticketsIndex.weeklyTicket);
@ -72,8 +71,7 @@ describe('Ticket descriptor path', () => {
it('should confirm the ticket 11 was added on thursday', async() => {
const result = await nightmare
.waitToClick(selectors.ticketsIndex.moreMenu)
.waitToClick(selectors.ticketsIndex.moreMenuWeeklyTickets)
.waitToClick(selectors.ticketsIndex.menuWeeklyTickets)
.waitToGetProperty(selectors.ticketsIndex.sixthWeeklyTicket, 'value');
expect(result).toEqual('Thursday');
@ -132,8 +130,7 @@ describe('Ticket descriptor path', () => {
it('should confirm the ticket 11 was added on saturday', async() => {
const result = await nightmare
.waitToClick(selectors.ticketsIndex.moreMenu)
.waitToClick(selectors.ticketsIndex.moreMenuWeeklyTickets)
.waitToClick(selectors.ticketsIndex.menuWeeklyTickets)
.waitToGetProperty(selectors.ticketsIndex.sixthWeeklyTicket, 'value');
expect(result).toEqual('Saturday');
@ -160,7 +157,7 @@ describe('Ticket descriptor path', () => {
it('should confirm the sixth weekly ticket was deleted', async() => {
const result = await nightmare
.waitToClick('vn-ticket-weekly-index vn-searchbar vn-icon[icon=clear]')
.waitToClick('vn-searchbar vn-icon[icon=clear]')
.waitToClick(selectors.ticketsIndex.searchWeeklyButton)
.waitForNumberOfElements(selectors.ticketsIndex.searchWeeklyResult, 5)
.countElement(selectors.ticketsIndex.searchWeeklyResult);

View File

@ -7,7 +7,7 @@ describe('Ticket purchase request path', () => {
beforeAll(() => {
nightmare
.loginAndModule('salesPerson', 'ticket')
.accessToSearchResult('id:16')
.accessToSearchResult('16')
.accessToSection('ticket.card.request.index');
});

View File

@ -1,5 +1,4 @@
import selectors from '../../helpers/selectors.js';
import config from '../../helpers/config.js';
import createNightmare from '../../helpers/nightmare';
describe('Ticket diary path', () => {
@ -31,12 +30,9 @@ describe('Ticket diary path', () => {
});
it(`should navigate to the item diary from the 1st sale item id descriptor popover`, async() => {
const itemId = 2;
const url = await nightmare
.waitToClick(selectors.ticketSummary.firstSaleItemId)
.waitToClick(selectors.ticketSummary.popoverDiaryButton)
.waitForLogin('employee')
.goto(`${config.url}#!/item/${itemId}/diary?warehouseFk=1&ticketFk=1`)
.parsedUrl();
expect(url.hash).toContain('/diary');

View File

@ -9,8 +9,7 @@ describe('Ticket descriptor path', () => {
.loginAndModule('salesperson', 'ticket');
});
// Excluded waiting for #1874
xdescribe('Delete ticket', () => {
describe('Delete ticket', () => {
it('should search for an specific ticket', async() => {
const result = await nightmare
.write(selectors.ticketsIndex.searchTicketInput, 18)

View File

@ -21,7 +21,7 @@ describe('Ticket services path', () => {
.isDisabled(selectors.ticketService.firstAddDescriptionButton);
expect(result).toBeTruthy();
});
}, 100000);
it('should receive an error if you attempt to save a service without access rights', async() => {
const result = await nightmare

View File

@ -208,11 +208,9 @@ export default class Autocomplete extends Field {
onContainerKeyDown(event) {
if (event.defaultPrevented) return;
switch (event.key) {
case 'ArrowUp':
case 'ArrowDown':
case 'Enter':
this.showDropDown();
break;
default:

View File

@ -7,7 +7,7 @@ export default class ButtonMenu extends Button {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.$transclude = $transclude;
$element.on('click', e => this.onClick(e));
$element.on('click', e => this.onButtonClick(e));
}
get model() {
@ -41,8 +41,7 @@ export default class ButtonMenu extends Button {
Object.assign(this.$.dropDown, props);
}
onClick(event) {
if (this.disabled) return;
onButtonClick(event) {
if (event.defaultPrevented) return;
this.emit('open');
this.showDropDown();

View File

@ -14,7 +14,7 @@ describe('Component vnButtonMenu', () => {
$element.remove();
});
describe('onClick(event)', () => {
describe('onButtonClick(event)', () => {
it(`should emit the open event`, () => {
spyOn(controller, 'emit');
@ -23,7 +23,7 @@ describe('Component vnButtonMenu', () => {
bubbles: true,
cancelable: true
});
controller.onClick(event);
controller.onButtonClick(event);
expect(controller.emit).toHaveBeenCalledWith('open');
});

View File

@ -39,19 +39,19 @@
}
&.colored {
color: white;
background-color: $color-main;
background-color: $color-button;
box-shadow: 0 .15em .15em 0 rgba(0, 0, 0, .3);
transition: background 200ms ease-in-out;
&:not(.disabled) {
&:hover,
&:focus {
background-color: lighten($color-main, 10%);
background-color: lighten($color-button, 10%);
}
}
}
&.flat {
color: $color-main;
color: $color-button;
background-color: transparent;
box-shadow: none;
transition: background 200ms ease-in-out;

View File

@ -19,7 +19,7 @@
}
&.checked > .btn {
border-color: transparent;
background-color: $color-main;
background-color: $color-button;
& > .mark {
top: 0;

View File

@ -24,13 +24,12 @@ vn-chip {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
line-height: 2em;
& > vn-avatar {
margin-left: -0.7em;
margin-right: .3em;
vertical-align: middle;
height: 1.9em;
height: 2em;
width: 2em;
}
}

View File

@ -14,7 +14,9 @@ class DatePicker extends Field {
let value = this.input.value;
if (value) {
date = new Date(value);
let ymd = value.split('-')
.map(e => parseInt(e));
date = new Date(ymd[0], ymd[1] - 1, ymd[2]);
if (this.field) {
let orgDate = this.field instanceof Date

View File

@ -3,6 +3,10 @@ describe('Component vnDatePicker', () => {
let $element;
let $ctrl;
let today;
today = new Date();
today.setHours(0, 0, 0, 0);
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($compile, $rootScope, _$filter_) => {
@ -18,14 +22,19 @@ describe('Component vnDatePicker', () => {
describe('field() setter', () => {
it(`should display the formated the date`, () => {
let today;
today = new Date();
today.setHours(0, 0, 0, 0);
$ctrl.field = today;
let displayed = $filter('date')(today, 'yyyy-MM-dd');
expect($ctrl.value).toEqual(displayed);
});
});
describe('onValueUpdate()', () => {
it(`should change the picker value to selected date`, () => {
$ctrl.value = $filter('date')(today, 'yyyy-MM-dd');
$ctrl.input.dispatchEvent(new Event('change'));
expect($ctrl.field).toEqual(today);
});
});
});

View File

@ -29,6 +29,10 @@ export default class Dialog extends Popup {
* @return {Promise} A promise that will be resolved with response when dialog is closed
*/
show(data, responseHandler) {
if (this.shown)
return this.$q.reject(new Error('Dialog already shown'));
super.show();
if (typeof data == 'function') {
responseHandler = data;
data = null;
@ -36,27 +40,27 @@ export default class Dialog extends Popup {
this.data = data;
this.showHandler = responseHandler;
super.show();
return this.$q(resolve => {
this.resolve = resolve;
});
}
/**
* Hides the dialog.
* Hides the dialog resolving the promise returned by show().
*
* @param {String} response The response
*/
hide(response) {
if (!this.shown) return;
this.showHandler = null;
super.hide();
this.showHandler = null;
if (this.resolve)
this.resolve(response);
}
/**
* Calls the response handler.
* Calls the response handlers.
*
* @param {String} response The response code
* @return {Boolean} The response handler return

View File

@ -28,14 +28,6 @@ describe('Component vnDialog', () => {
expect(called).toBeTruthy();
});
it(`should hide the dialog when response is given`, () => {
controller.show();
spyOn(controller, 'hide');
controller.respond('answer');
expect(controller.hide).toHaveBeenCalledWith('answer');
});
it(`should not hide the dialog when false is returned from response handler`, () => {
controller.show(() => false);
spyOn(controller, 'hide');
@ -46,12 +38,13 @@ describe('Component vnDialog', () => {
});
describe('hide()', () => {
it(`should do nothing if it's already hidden`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
it(`should resolve the promise returned by show`, () => {
let resolved = true;
controller.show().then(() => resolved = true);
controller.hide();
$scope.$apply();
expect(controller.onResponse).not.toHaveBeenCalledWith();
expect(resolved).toBeTruthy();
});
});
@ -94,7 +87,7 @@ describe('Component vnDialog', () => {
expect(controller.onAccept).toHaveBeenCalledWith({$response: 'accept'});
});
it(`should resolve the promise returned by show() with response when hidden`, () => {
it(`should resolve the promise returned by show() with response`, () => {
let response;
controller.show().then(res => response = res);
controller.respond('response');

View File

@ -36,7 +36,7 @@
background-color: transparent;
border: none;
border-radius: .1em;
color: $color-main;
color: $color-button;
font-family: vn-font-bold;
padding: .7em;
margin: -0.7em;

View File

@ -5,6 +5,7 @@ import template from './index.html';
import ArrayModel from '../array-model/array-model';
import CrudModel from '../crud-model/crud-model';
import {mergeWhere} from 'vn-loopback/util/filter';
import focus from '../../lib/focus';
/**
* @event select Thrown when model item is selected
@ -86,9 +87,11 @@ export default class DropDown extends Popover {
* @param {String} search The initial search term or %null
*/
show(parent, search) {
this._activeOption = -1;
if (this.shown) return;
super.show(parent);
this._activeOption = -1;
this.list = this.popup.querySelector('.list');
this.ul = this.popup.querySelector('ul');
@ -102,21 +105,25 @@ export default class DropDown extends Popover {
this.search = search;
this.buildList();
let input = this.popup.querySelector('input');
setTimeout(() => input.focus());
focus(this.popup.querySelector('input'));
}
onClose() {
hide() {
if (!this.shown) return;
super.hide();
this.document.removeEventListener('keydown', this.docKeyDownHandler);
this.docKeyDownHandler = null;
this.list.removeEventListener('scroll', this.listScrollHandler);
this.listScrollHandler = null;
}
onClose() {
this.destroyList();
this.list = null;
this.ul = null;
this.destroyList();
super.onClose();
}
@ -387,7 +394,7 @@ export default class DropDown extends Popover {
let filter = {
order,
limit: this.limit || 8
limit: this.limit || 30
};
if (model instanceof CrudModel) {

View File

@ -28,8 +28,7 @@
ng-transclude="append"
class="append">
</div>
<div class="icons post">
</div>
<div class="icons post"></div>
<div class="underline blur"></div>
<div class="underline focus"></div>
</div>

View File

@ -50,7 +50,7 @@ export default class Field extends FormInput {
}
set value(value) {
this.field = value;
this.input.value = value;
}
get value() {

View File

@ -2,6 +2,7 @@
.vn-field {
display: inline-block;
box-sizing: border-box;
width: 100%;
& > .container {
@ -22,7 +23,7 @@
top: 18px;
line-height: 20px;
pointer-events: none;
color: $color-font-secondary;
color: $color-font-bg-marginal;
transition-property: top, color, font-size;
transition-duration: 400ms;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
@ -67,7 +68,11 @@
}
& > input {
position: relative;
color: $color-font;
&::placeholder {
color: $color-font-bg;
}
&[type=time],
&[type=date],
&[type=password] {
@ -121,12 +126,13 @@
& > .icons {
display: flex;
align-items: center;
color: $color-font-secondary;
color: $color-font-bg-marginal;
}
& > .prepend > prepend,
& > .append > append,
& > .icons {
display: flex;
align-items: center;
& > vn-icon {
font-size: 24px;
@ -159,7 +165,7 @@
}
&.focus {
height: 2px;
background-color: $color-main;
background-color: $color-primary;
left: 50%;
width: 0;
transition-property: width, left, background-color;
@ -190,13 +196,57 @@
}
}
}
&.standout {
border-radius: .1em;
background-color: rgba(255, 255, 255, .1);
padding: 0 12px;
transition-property: background-color, color;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
& > .container {
& > .underline {
display: none;
}
& > .infix > .control > * {
color: $color-font-dark;
&::placeholder {
color: $color-font-bg-dark;
}
}
& > .prepend,
& > .append,
& > .icons {
color: $color-font-bg-dark-marginal;
}
}
&.focused {
background-color: $color-bg-panel;
& > .container {
& > .infix > .control > * {
color: $color-font;
&::placeholder {
color: $color-font-bg;
}
}
& > .prepend,
& > .append,
& > .icons {
color: $color-font-bg-marginal;
}
}
}
}
&.not-empty,
&.focused,
&.invalid {
& > .container > .infix {
& > label {
top: 5px;
color: $color-main;
color: $color-primary;
padding: 0;
font-size: 12px;
}

View File

@ -2,7 +2,7 @@
.vn-icon-button {
@extend %clickable-light;
color: $color-main;
color: $color-button;
& > button {
padding: .2em !important;

View File

@ -41,6 +41,7 @@ import './list';
import './popover';
import './popup';
import './radio';
import './slot';
import './submit';
import './table';
import './td-editable';

View File

@ -1,45 +1,102 @@
@import "./effects";
/*
ul.menu {
list-style-type: none;
padding: 0;
padding-top: $spacing-md;
margin: 0;
font-size: inherit;
& > li > a {
@extend %clickable;
display: block;
color: inherit;
padding: .6em 2em;
}
}
*/
vn-list,
.vn-list {
display: block;
max-width: $width-sm;
margin: 0 auto;
padding: 0;
list-style-type: none;
a.vn-list-item {
@extend %clickable;
vn-list,
.vn-list {
vn-item,
.vn-item {
padding-left: $spacing-lg;
}
}
.vn-list-item {
border-bottom: $border-thin-light;
display: block;
text-decoration: none;
color: inherit;
& > vn-horizontal {
&.separated {
vn-item,
.vn-item {
border-bottom: $border-thin-light;
padding: $spacing-md;
& > vn-one {
overflow: hidden;
&:last-child {
border-bottom: none;
}
& > .buttons {
align-items: center;
}
}
}
vn-item,
.vn-item {
@extend %clickable;
display: flex;
align-items: center;
color: inherit;
padding: $spacing-sm $spacing-md;
text-decoration: none;
min-height: 40px;
box-sizing: border-box;
&.separated {
border-bottom: $border-thin-light;
vn-icon-button {
opacity: .4;
margin-left: .5em;
transition: opacity 250ms ease-out;
padding: 0;
font-size: 1.2em;
&:hover {
opacity: 1;
}
&:last-child {
border-bottom: none;
}
}
&.active {
@extend %active;
}
& > vn-item-section {
overflow: hidden;
flex: 1;
&[avatar] {
display: flex;
flex: none;
align-items: center;
margin-right: $spacing-md;
& > .vn-icon {
font-size: 1.2em;
}
}
&[side] {
display: flex;
flex: none;
align-items: center;
& > .vn-button {
opacity: .4;
margin-left: .5em;
transition: opacity 250ms ease-out;
padding: 0;
font-size: 1.05em;
&:hover {
opacity: 1;
}
}
}
}
vn-empty-rows {
display: block;
text-align: center;
padding: 1.5em;
box-sizing: border-box;
}
}
}

View File

@ -98,8 +98,9 @@ export default class Popup extends Component {
onClose() {
this.closeTimeout = null;
this.popup.remove();
this.$contentScope.$destroy();
this.popup = null;
this.$contentScope.$destroy();
this.$contentScope = null;
this.windowEl = null;
this.emit('close');
}

View File

@ -9,7 +9,7 @@
}
}
&.checked > .btn {
border-color: $color-main;
border-color: $color-button;
& > .mark {
position: absolute;
@ -19,7 +19,7 @@
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
background-color: $color-main;
background-color: $color-button;
}
}
&.disabled.checked > .btn > .mark {

View File

@ -5,7 +5,7 @@
-webkit-appearance: none;
margin-top: -5px;
border-radius: 50%;
background: $color-main;
background: $color-button;
border: none;
height: 12px;
width: 12px;
@ -15,7 +15,7 @@
transition-timing-function: ease-out;
}
&:focus::#{$thumb-selector} {
box-shadow: 0 0 0 10px rgba($color-main, .2);
box-shadow: 0 0 0 10px rgba($color-button, .2);
}
&:active::#{$thumb-selector} {
transform: scale(1.5);
@ -29,7 +29,7 @@
width: 100%;
height: 3px;
cursor: inherit;
background: $color-secondary;
background: $color-marginal;
border-radius: 2px;
border: none;
}
@ -40,7 +40,7 @@
font-size: 12px;
&.main {
color: $color-main;
color: $color-button;
}
&.min-label {
float: left;

View File

@ -1,17 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Component vnSearchbar doSearch() should define searchString, call onSearch and the model applyFilter method 1`] = `"function search() { [native code] } 0:i 1:d 2:: 3:( ) 4:1 5:2 6:3 7:4 8:5 9:6"`;
exports[`Component vnSearchbar onPanelSubmit() should hide the popover, and set the filter as it wasn't defined 1`] = `Object {}`;
exports[`Component vnSearchbar onPanelSubmit() should hide the popover, compact the filter 1`] = `
Object {
"id": 999,
}
`;
exports[`Component vnSearchbar onSubmit() should define the controller's filter 1`] = `
Object {
"search": "id: 999",
}
`;

View File

@ -1,14 +1,26 @@
<form ng-submit="$ctrl.onSubmit()">
<vn-textfield
class="dense"
class="dense standout"
placeholder="{{::'Search' | translate}}"
ng-model="$ctrl.searchString">
<prepend>
<vn-icon
icon="search"
ng-click="$ctrl.clearFilter(); $ctrl.onSubmit()"
ng-click="$ctrl.onSubmit()"
pointer>
</vn-icon>
<div class="search-params">
<span
ng-repeat="param in $ctrl.params"
class="search-param"
title="{{param.chip}}">
<vn-icon
icon="close"
ng-click="$ctrl.removeParam($index)">
</vn-icon>
{{param.chip}}
</span>
</div>
</prepend>
<append>
<vn-icon

View File

@ -1,7 +1,8 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
import {buildFilter} from 'vn-loopback/util/filter';
import focus from '../../lib/focus';
import './style.scss';
/**
* An input specialized to perform searches, it allows to use a panel
@ -11,56 +12,66 @@ import {buildFilter} from 'vn-loopback/util/filter';
* by calling the exprBuilder function for each non-null parameter.
*
* @property {Object} filter A key-value object with filter parameters
* @property {Function} onSearch Function to call when search is submited
* @property {SearchPanel} panel The panel used for advanced searches
* @property {CrudModel} model The model used for searching
* @property {Function} exprBuilder If defined, is used to build each non-null param expresion
*/
export default class Controller extends Component {
constructor($element, $scope, $compile, $state, $transitions) {
super($element, $scope);
this.$element = $element;
this.$compile = $compile;
this.$state = $state;
this.$ = $scope;
let criteria = {to: this.$state.current.name};
this.deregisterCallback = $transitions.onSuccess(criteria,
() => this.onStateChange());
constructor($element, $) {
super($element, $);
this.searchState = '.';
this._filter = null;
this.autoLoad = false;
let criteria = {};
this.deregisterCallback = this.$transitions.onSuccess(
criteria, () => this.onStateChange());
}
$postLink() {
if (this.filter === null)
this.onStateChange();
this.onStateChange();
}
set filter(value) {
this._filter = value;
this.$state.go('.', {q: JSON.stringify(value)}, {location: 'replace'});
$onDestroy() {
this.deregisterCallback();
}
get filter() {
return this._filter;
}
onStateChange() {
this._filter = null;
if (this.$state.params.q) {
try {
this._filter = JSON.parse(this.$state.params.q);
} catch (e) {
console.error(e);
}
}
this.doSearch();
set filter(value) {
this._filter = value;
this.toBar(value);
}
get shownFilter() {
return this._filter != null ? this._filter : this.suggestedFilter;
return this.filter != null
? this.filter
: this.suggestedFilter;
}
get searchString() {
return this._searchString;
}
set searchString(value) {
this._searchString = value;
if (value == null) this.params = [];
}
onStateChange() {
let filter = null;
if (this.$state.is(this.searchState)) {
if (this.$params.q) {
try {
filter = JSON.parse(this.$params.q);
} catch (e) {
console.error(e);
}
}
focus(this.element.querySelector('vn-textfield input'));
}
this.filter = filter;
}
openPanel(event) {
@ -88,21 +99,136 @@ export default class Controller extends Component {
onPanelSubmit(filter) {
this.$.popover.hide();
filter = compact(filter);
this.filter = filter != null ? filter : {};
let element = this.element.querySelector('vn-textfield input');
element.select();
element.focus();
filter = filter != null ? filter : {};
this.doSearch(filter);
}
onSubmit() {
this.filter = this.getObjectFromString(this.searchString);
this.doSearch(this.fromBar());
}
removeParam(index) {
this.params.splice(index, 1);
this.doSearch(this.fromBar());
}
doSearch(filter) {
this.filter = filter;
let opts = this.$state.is(this.searchState)
? {location: 'replace'} : null;
this.$state.go(this.searchState,
{q: JSON.stringify(filter)}, opts);
}
fromBar() {
let filter = {};
if (this.searchString)
filter.search = this.searchString;
if (this.params) {
for (let param of this.params)
filter[param.key] = param.value;
}
return filter;
}
toBar(filter) {
this.params = [];
this.searchString = filter && filter.search;
if (!filter) return;
let keys = Object.keys(filter);
keys.forEach(key => {
if (key == 'search') return;
let value = filter[key];
let chip;
if (typeof value == 'string'
&& /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value))
value = new Date(value);
switch (typeof value) {
case 'boolean':
chip = `${value ? '' : 'not '}${key}`;
break;
case 'number':
case 'string':
chip = `${key}: ${value}`;
break;
default:
if (value instanceof Date) {
let format = 'yyyy-MM-dd';
if (value.getHours() || value.getMinutes())
format += ' HH:mm';
chip = `${key}: ${this.$filter('date')(value, format)}`;
} else
chip = key;
}
this.params.push({chip, key, value});
});
}
}
ngModule.vnComponent('vnSearchbar', {
controller: Controller,
template: require('./searchbar.html'),
bindings: {
searchState: '@?',
filter: '<?',
suggestedFilter: '<?',
panel: '@',
info: '@?'
}
});
/**
* @property {CrudModel} model The model used for searching
* @property {Function} exprBuilder If defined, is used to build each non-null param expresion
* @property {Function} onSearch Function to call when search is submited
*/
class AutoSearch {
constructor($state, $transitions) {
this.$state = $state;
this.$transitions = $transitions;
let criteria = {to: this.$state.current.name};
this.deregisterCallback = this.$transitions.onSuccess(criteria,
() => this.onStateChange());
this.fetchFilter();
}
$postLink() {
if (this.filter !== null)
this.doSearch();
}
$onDestroy() {
this.deregisterCallback();
}
fetchFilter() {
if (this.$state.params.q) {
try {
this.filter = JSON.parse(this.$state.params.q);
} catch (e) {
console.error(e);
}
} else
this.filter = null;
}
onStateChange() {
this.fetchFilter();
this.doSearch();
}
doSearch() {
this.searchString = this.getStringFromObject(this.shownFilter);
let filter = this._filter;
let filter = this.filter;
if (filter == null && this.autoload)
filter = {};
@ -141,94 +267,17 @@ export default class Controller extends Component {
exprBuilder(param, value) {
return {[param]: value};
}
/**
* Finds pattern key:value or key:(extra value) and passes it to object.
*
* @param {String} searchString The search string
* @return {Object} The parsed object
*/
getObjectFromString(searchString) {
let result = {};
if (searchString) {
let regex = /((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi;
let findPattern = searchString.match(regex);
let remnantString = searchString.replace(regex, '').trim();
if (findPattern) {
for (let i = 0; i < findPattern.length; i++) {
let aux = findPattern[i].split(':');
let property = aux[0];
let value = aux[1].replace(/\(|\)/g, '');
result[property] = value.trim();
}
}
if (remnantString)
result.search = remnantString;
}
return result;
}
/**
* Passes an object to pattern key:value or key:(extra value).
*
* @param {Object} searchObject The search object
* @return {String} The passed string
*/
getStringFromObject(searchObject) {
let search = [];
if (searchObject) {
let keys = Object.keys(searchObject);
keys.forEach(key => {
if (key == 'search') return;
let value = searchObject[key];
let valueString;
if (typeof value === 'string' && value.indexOf(' ') !== -1)
valueString = `(${value})`;
else if (value instanceof Date)
valueString = value.toJSON();
else {
switch (typeof value) {
case 'number':
case 'string':
case 'boolean':
valueString = `${value}`;
}
}
if (valueString)
search.push(`${key}:${valueString}`);
});
if (searchObject.search)
search.unshift(searchObject.search);
}
return search.length ? search.join(' ') : '';
}
$onDestroy() {
this.deregisterCallback();
}
}
Controller.$inject = ['$element', '$scope', '$compile', '$state', '$transitions'];
AutoSearch.$inject = ['$state', '$transitions'];
ngModule.component('vnSearchbar', {
template: require('./searchbar.html'),
ngModule.vnComponent('vnAutoSearch', {
controller: AutoSearch,
bindings: {
filter: '<?',
suggestedFilter: '<?',
onSearch: '&?',
panel: '@',
model: '<?',
onSearch: '&?',
exprBuilder: '&?',
paramBuilder: '&?',
autoLoad: '<?',
info: '@?'
},
controller: Controller
paramBuilder: '&?'
}
});
/**
@ -251,7 +300,7 @@ function compact(obj) {
} else if (typeof obj == 'object' && obj.constructor == Object) {
let keys = Object.keys(obj);
for (let key of keys) {
if (key.substr(0, 2) == '$$' || compact(obj[key]) === undefined)
if (key.charAt(0) == '$' || compact(obj[key]) === undefined)
delete obj[key];
}
if (Object.keys(obj).length == 0)

View File

@ -4,164 +4,149 @@ describe('Component vnSearchbar', () => {
let controller;
let $element;
let $state;
let $params;
let $scope;
let filter = {id: 1, search: 'needle'};
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($componentController, _$state_, $rootScope) => {
beforeEach(angular.mock.inject(($componentController, $rootScope, _$state_) => {
$scope = $rootScope.$new();
$state = _$state_;
$element = angular.element(`<vn-textfield><input></input></vn-textfield>`);
$params = $state.params;
$params.q = JSON.stringify(filter);
$element = angular.element(`<div></div>`);
controller = $componentController('vnSearchbar', {$element, $scope});
controller.panel = 'vn-client-search-panel';
}));
describe('$postLink()', () => {
it(`should not call onStateChange() if filter is defined`, () => {
spyOn(controller, 'onStateChange');
controller.filter = {};
it(`should fetch the filter from the state if it's in the filter state`, () => {
controller.$postLink();
expect(controller.onStateChange).not.toHaveBeenCalledWith();
expect(controller.filter).toEqual(filter);
expect(controller.searchString).toBe('needle');
expect(controller.params.length).toBe(1);
});
it(`should call onStateChange() if filter is null`, () => {
spyOn(controller, 'onStateChange');
controller.filter = null;
it(`should not fetch the filter from the state if not in the filter state`, () => {
controller.searchState = 'other.state';
controller.$postLink();
expect(controller.onStateChange).toHaveBeenCalledWith();
});
});
describe('onStateChange()', () => {
it(`should set a formated _filter in the controller`, () => {
spyOn(controller, 'doSearch');
Object.assign($state.params, {q: '{"id": 999}'});
controller.onStateChange();
expect(controller._filter).toEqual({id: 999});
expect(controller.doSearch).toHaveBeenCalledWith();
});
});
describe('shownFilter() getter', () => {
it(`should return the _filter if not NULL`, () => {
controller.filter = '{"id": 999}';
let shownFilter = controller.shownFilter;
expect(shownFilter).toEqual(controller._filter);
expect(shownFilter).not.toEqual(controller.suggestedFilter);
});
it(`should return the suggested filter if filter is NULL`, () => {
controller.suggestedFilter = '{"id": 888}';
let shownFilter = controller.shownFilter;
expect(shownFilter).not.toEqual(controller._filter);
expect(shownFilter).toEqual(controller.suggestedFilter);
expect(controller.filter).toBeNull();
expect(controller.searchString).toBeNull();
expect(controller.params.length).toBe(0);
});
});
describe('filter() setter', () => {
it(`should call $state.go() to replace the current state location instead of creating a new one`, () => {
controller._filter = {};
spyOn($state, 'go');
controller.filter = {expected: 'filter'};
it(`should update the bar params and search`, () => {
let withoutHours = new Date(2000, 1, 1);
let withHours = new Date(withoutHours.getTime());
withHours.setHours(12, 30, 15, 10);
expect(controller._filter).toEqual(controller.filter);
expect($state.go).toHaveBeenCalledWith('.', Object({q: '{"expected":"filter"}'}), Object({location: 'replace'}));
controller.filter = {
search: 'needle',
withHours: withHours.toJSON(),
withoutHours: withoutHours.toJSON(),
boolean: true,
negated: false,
myObjectProp: {myProp: 1}
};
let chips = {};
for (let param of controller.params || [])
chips[param.key] = param.chip;
expect(controller.searchString).toBe('needle');
expect(chips.withHours).toBe('withHours: 2000-02-01 12:30');
expect(chips.withoutHours).toBe('withoutHours: 2000-02-01');
expect(chips.boolean).toBe('boolean');
expect(chips.negated).toBe('not negated');
expect(chips.myObjectProp).toBe('myObjectProp');
});
});
describe('shownFilter() getter', () => {
it(`should return the _filter if not null`, () => {
controller.filter = filter;
controller.suggestedFilter = {sugestedParam: 'suggestedValue'};
expect(controller.shownFilter).toEqual(filter);
});
it(`should return the suggested filter if filter is null`, () => {
controller.filter = null;
controller.suggestedFilter = {sugestedParam: 'suggestedValue'};
expect(controller.shownFilter).toEqual(controller.suggestedFilter);
});
});
describe('searchString() setter', () => {
it(`should clear the whole filter when it's null`, () => {
controller.filter = filter;
controller.searchString = null;
expect(controller.searchString).toBeNull();
expect(controller.params.length).toBe(0);
});
});
describe('onPanelSubmit()', () => {
it(`should hide the popover, and set the filter as it wasn't defined`, () => {
it(`should compact and define the filter`, () => {
controller.$.popover = {hide: jasmine.createSpy('hide')};
const filter = undefined;
const filter = {
id: 1,
thisKeyShouldBePurged: null,
alsoThis: [],
andThis: {emptyProp: undefined, nullProp: null},
dontForgetThis: [null, undefined],
myObject: {keepThis: true, butNotThis: null},
myArray: [null, undefined, true]
};
controller.onPanelSubmit(filter);
expect(controller.filter).toMatchSnapshot();
});
it(`should hide the popover, compact the filter`, () => {
controller.$.popover = {hide: jasmine.createSpy('hide')};
const filter = {id: 999, thisKeyShouldBePurged: null};
controller.onPanelSubmit(filter);
expect(controller.filter).toMatchSnapshot();
expect(controller.filter).toEqual({
id: 1,
myObject: {keepThis: true},
myArray: [true]
});
});
});
describe('onSubmit()', () => {
it(`should define the controller's filter`, () => {
controller.searchString = 'id: 999';
it(`should define the filter`, () => {
controller.filter = filter;
controller.searchString = 'mySearch';
controller.onSubmit();
expect(controller.filter).toMatchSnapshot();
expect(controller.filter).toEqual({id: 1, search: 'mySearch'});
});
});
describe('removeParam()', () => {
it(`should remove the parameter from the filter`, () => {
controller.filter = filter;
controller.removeParam(0);
expect(controller.filter).toEqual({search: 'needle'});
});
});
describe('doSearch()', () => {
it(`should define searchString, call onSearch and the model applyFilter method`, () => {
controller._filter = 'id: 123456';
controller.autoload = true;
controller.onSearch = jasmine.createSpy('onSearch');
controller.model = {applyFilter: jasmine.createSpy('applyFilter')};
controller.paramBuilder = jasmine.createSpy('paramBuilder').and.returnValue({'param': `${controller._filter}`});
it(`should go to the search state and pass the filter as query param`, () => {
spyOn($state, 'go');
controller.searchState = 'search.state';
controller.doSearch(filter);
let queryParams = {q: JSON.stringify(filter)};
controller.doSearch();
expect(controller.searchString).toMatchSnapshot();
expect(controller.onSearch).toHaveBeenCalledWith({'$params': `${controller._filter}`});
expect(controller.model.applyFilter).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Object));
});
it(`should define searchString, call onSearch and the model clear method`, () => {
controller._filter = null;
controller.autoload = false;
controller.onSearch = jasmine.createSpy('onSearch');
controller.model = {clear: jasmine.createSpy('clear')};
controller.paramBuilder = jasmine.createSpy('paramBuilder').and.returnValue({'param': `${controller._filter}`});
controller.doSearch();
expect(controller.searchString).toEqual('');
expect(controller.onSearch).toHaveBeenCalledWith({'$params': null});
expect(controller.model.clear).toHaveBeenCalledWith();
});
});
describe('getObjectFromString()', () => {
it(`should return a formated object based on the string received for basic search`, () => {
let result = controller.getObjectFromString('Bruce Wayne');
expect(result).toEqual({search: 'Bruce Wayne'});
});
it(`should return a formated object based on the string received for advanced search`, () => {
let result = controller.getObjectFromString('id:101 name:(Bruce Wayne)');
expect(result).toEqual({id: '101', name: 'Bruce Wayne'});
});
it(`should format the object grouping any unmatched part of the instring of the string to the search property`, () => {
let string = 'I am the search id:101 name:(Bruce Wayne) concatenated value';
let result = controller.getObjectFromString(string);
expect(result).toEqual({
id: '101',
name: 'Bruce Wayne',
search: 'I am the search concatenated value'
});
expect($state.go).toHaveBeenCalledWith('search.state', queryParams, null);
expect(controller.filter).toEqual(filter);
});
});
});

View File

@ -2,7 +2,40 @@
vn-searchbar {
display: block;
width: 100%;
max-width: 35em;
margin: 0 auto;
.search-params {
flex: 1;
margin: .05em 0;
overflow: visible;
display: flex;
max-width: 24em;
& > .search-param {
color: rgba(0, 0, 0, .6);
background-color: rgba(0, 0, 0, .1);
padding: .1em .4em;
margin-left: .2em;
display: inline-block;
border-radius: .8em;
max-width: 12em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
& > vn-icon {
font-size: inherit;
vertical-align: middle;
cursor: pointer;
border-radius: 50%;
&:hover {
color: rgba(0, 0, 0, .8);
}
}
}
}
}
.search-panel {

View File

@ -0,0 +1,81 @@
import ngModule from '../../module';
import './portal';
import './style.scss';
export class Slot {
constructor($element, vnSlotService) {
this.$element = $element;
this.vnSlotService = vnSlotService;
this.$content = null;
}
$onDestroy() {
this.unregister();
}
set name(value) {
this.unregister();
this._name = value;
this.vnSlotService.slots[value] = this;
}
get name() {
return this._name;
}
unregister() {
if (this.name)
this.vnSlotService.slots[this.name] = undefined;
}
setContent($content) {
if (this.$content) {
this.$content.detach();
this.$content = null;
}
this.$content = $content;
if (this.$content) this.$element.append($content);
this.$element[0].style.display = $content ? 'block' : 'none';
}
}
Slot.$inject = ['$element', 'vnSlotService'];
ngModule.vnComponent('vnSlot', {
controller: Slot,
bindings: {
name: '@?'
}
});
export class SlotService {
constructor() {
this.stacks = {};
this.slots = {};
}
push(slot, $transclude) {
if (!this.stacks[slot]) this.stacks[slot] = [];
this.stacks[slot].unshift($transclude);
this.refreshContent(slot);
}
pop(slot) {
let $content = this.stacks[slot].shift();
this.refreshContent(slot);
if ($content && typeof $content == 'object')
$content.remove();
}
refreshContent(slot) {
if (!this.slots[slot]) return;
let $content = this.stacks[slot][0];
if (typeof $content == 'function') {
$content(clone => {
$content = this.stacks[slot][0] = clone;
});
}
this.slots[slot].setContent($content);
}
}
ngModule.service('vnSlotService', SlotService);

View File

@ -0,0 +1,28 @@
import ngModule from '../../module';
/**
* Component used to fill slots with content.
*/
export default class Portal {
constructor($transclude, vnSlotService) {
this.$transclude = $transclude;
this.vnSlotService = vnSlotService;
}
$postLink() {
this.vnSlotService.push(this.slot, this.$transclude);
}
$onDestroy() {
this.vnSlotService.pop(this.slot);
}
}
Portal.$inject = ['$transclude', 'vnSlotService'];
ngModule.component('vnPortal', {
controller: Portal,
transclude: true,
bindings: {
slot: '@'
}
});

View File

@ -0,0 +1,3 @@
vn-slot {
display: block;
}

View File

@ -6,6 +6,7 @@
cy="50"
r="20"
fill="none"
stroke="currentColor"
stroke-miterlimit="10">
</circle>
</svg>

View File

@ -4,6 +4,7 @@ vn-spinner {
display: inline-block;
min-height: 28px;
min-width: 28px;
color: $color-main;
& > .loader {
position: relative;
@ -29,7 +30,6 @@ vn-spinner {
margin: auto;
& > .path {
stroke: $color-main;
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
stroke-linecap: square;

View File

@ -3,8 +3,8 @@
vn-table {
display: block;
overflow: auto;
width: 100%;
overflow: auto;
}
.vn-table {
width: 100%;

View File

@ -40,10 +40,10 @@
background-color: rgba(0, 0, 0, .1);
}
&.checked > .btn {
border-color: $color-main;
border-color: $color-button;
& > .focus-mark {
background-color: rgba($color-main, .15);
background-color: rgba($color-button, .15);
}
}
&.disabled {

View File

@ -36,13 +36,14 @@ vn-treeview-childs {
}
vn-treeview-child {
line-height: 38px;
font-size: 16px;
display: block;
.node {
@extend %clickable;
display: flex;
padding: 5px;
padding: 2px;
align-items: center;
}
& > div > .arrow {

View File

@ -2,7 +2,7 @@
<span
ng-repeat="day in $ctrl.days"
translate-attr="::{title: day.name}"
ng-class="{marked: $ctrl.field[day.code]}"
ng-click="$ctrl.field[day.code] = !$ctrl.field[day.code]">
ng-class="{marked: $ctrl.field[day.index]}"
ng-click="$ctrl.toggleDay(day.index)">
{{day.localeChar}}
</span>

View File

@ -8,6 +8,13 @@ export default class WdayPicker extends FormInput {
this.days = vnWeekDays.locales;
this.initTabIndex();
}
toggleDay(index) {
let field = this.field;
if (!field) field = [];
field[index] = !field[index];
this.change(field);
}
}
WdayPicker.$inject = ['$element', '$scope', 'vnWeekDays'];

View File

@ -20,7 +20,7 @@
background-color: rgba(0, 0, 0, .05);
&.marked {
background: $color-main;
background: $color-button;
color: $color-font-dark;
}
}

View File

@ -12,14 +12,23 @@ export function directive() {
restrict: 'A',
link: function($scope, $element, $attrs) {
let id = kebabToCamel($attrs.vnId);
let $ctrl = $element[0].$ctrl
? $element[0].$ctrl
: $element.controller($element[0].tagName.toLowerCase());
if (!id)
throw new Error(`vnId: Attribute can't be null`);
$scope[id] = $ctrl || $element[0];
let $ctrl = $element[0].$ctrl
? $element[0].$ctrl
: $element.controller($element[0].tagName.toLowerCase());
let ctrl = $ctrl || $element[0];
$scope[id] = ctrl;
if (!$scope.hasOwnProperty('$ctrl')) {
while ($scope && !$scope.hasOwnProperty('$ctrl'))
$scope = Object.getPrototypeOf($scope);
if ($scope) $scope[id] = ctrl;
}
}
};
}

View File

@ -107,6 +107,7 @@ function runFn(
$compile,
$filter,
$interpolate,
$window,
vnApp) {
Object.assign(Component.prototype, {
$translate,
@ -119,6 +120,7 @@ function runFn(
$compile,
$filter,
$interpolate,
$window,
vnApp
});
}
@ -133,6 +135,7 @@ runFn.$inject = [
'$compile',
'$filter',
'$interpolate',
'$window',
'vnApp'
];

Some files were not shown because too many files have changed in this diff Show More