This commit is contained in:
Juan Ferrer 2019-03-12 15:02:05 +01:00
commit 1c8edefd36
280 changed files with 5458 additions and 3789 deletions

View File

@ -1,3 +1,4 @@
node_modules
print/node_modules
front/node_modules
services

View File

@ -1,4 +1,5 @@
FROM debian:stretch-slim
ENV TZ Europe/Madrid
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
@ -21,6 +22,7 @@ COPY package.json package-lock.json ./
COPY loopback/package.json loopback/
COPY print/package.json print/
RUN npm install --only=prod
RUN npm --prefix ./print install --only=prod ./print
COPY loopback loopback
COPY back back

View File

@ -26,7 +26,7 @@ module.exports = Self => {
});
Self.send = async(ctx, data, transaction) => {
const userId = ctx.req.accessToken.userId;
const userId = ctx.options && ctx.options.accessToken.userId || ctx.req && ctx.req.accessToken.userId;
const models = Self.app.models;
const sender = await models.Account.findById(userId, transaction);
const recipient = await models.Account.findById(data.recipientFk, transaction);

View File

@ -1,72 +1,74 @@
{
"name": "Account",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.user"
}
},
"properties": {
"id": {
"type": "number",
"required": true
},
"name": {
"type": "string",
"required": true
},
"roleFk": {
"type": "number",
"mysql": {
"columnName": "role"
}
},
"nickname": {
"type": "string"
},
"password": {
"type": "string",
"required": true
},
"active": {
"type": "boolean"
},
"email": {
"type": "string"
},
"created": {
"type": "date"
},
"updated": {
"type": "date"
}
},
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"foreignKey": "roleFk"
}
},
"acls": [
{
"property": "login",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}, {
"property": "logout",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}, {
"property": "validateToken",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}
]
"name": "Account",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.user"
}
},
"properties": {
"id": {
"type": "number",
"required": true
},
"name": {
"type": "string",
"required": true
},
"roleFk": {
"type": "number",
"mysql": {
"columnName": "role"
}
},
"nickname": {
"type": "string"
},
"password": {
"type": "string",
"required": true
},
"active": {
"type": "boolean"
},
"email": {
"type": "string"
},
"created": {
"type": "date"
},
"updated": {
"type": "date"
}
},
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"foreignKey": "roleFk"
}
},
"acls": [
{
"property": "login",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
},
{
"property": "logout",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "validateToken",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}
]
}

2
db/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
config.production.ini
config.test.ini

7
db/config.ini Normal file
View File

@ -0,0 +1,7 @@
[client]
host = localhost
port = 3306
user = root
password = password
ssl-mode = DISABLED
enable_cleartext_plugin = ON

View File

@ -1,5 +1,4 @@
#!/bin/bash
#IMPORTANT Any changes in this file are to applyed to mirror file export-data.cmd
echo "USE \`account\`;" > install/dump/dumpedFixtures.sql
mysqldump --defaults-file=connect.ini --no-create-info account role roleRole roleInherit >> install/dump/dumpedFixtures.sql
echo "USE \`salix\`;" >> install/dump/dumpedFixtures.sql

42
db/import-changes.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
ENV=$1
if [ "$ENV" == "production" ]; then
echo ""
echo " ( ( ) ( ( ) ) "
echo " )\ ))\ ) ( /( )\ ) ( * ))\ ) ( /( ( /( "
echo "(()/(()/( )\()|()/( ( )\ ) /(()/( )\()) )\())"
echo " /(_))(_)|(_)\ /(_)) )\ (((_) ( )(_))(_)|(_)\ ((_)\ "
echo "(_))(_)) ((_|_))_ _ ((_))\___(_(_()|_)) ((_) _((_)"
echo "| _ \ _ \ / _ \| \| | | ((/ __|_ _|_ _| / _ \| \| |"
echo "| _/ /| (_) | |) | |_| || (__ | | | | | (_) | . |"
echo "|_| |_|_\ \___/|___/ \___/ \___| |_| |___| \___/|_|\_|"
echo ""
read -p "Are you sure? (Default: no) [yes|no]: " ANSWER
if [ "$ANSWER" != "yes" ]; then
echo "Aborting"
exit;
fi
fi
if [ -z "$ENV" ]; then
ENV="test"
fi
INI_FILE="config.$ENV.ini"
if [ ! -f "$INI_FILE" ]; then
echo "File $INI_FILE doesn't exists"
exit 1
fi
echo "[INFO] Config file: $INI_FILE"
echo "[INFO] Importing changes."
# Import changes
for file in install/changes/*.sql; do
echo "[INFO] -> Applying $file"
mysql --defaults-file="$INI_FILE" < $file
done

View File

@ -2,15 +2,13 @@
export MYSQL_PWD=root
# Dump structure
echo "[INFO] -> Imported ./dump/truncateAll.sql"
mysql -u root -f < ./dump/truncateAll.sql
echo "[INFO] -> Imported ./dump/structure.sql"
mysql -u root -f < ./dump/structure.sql
echo "[INFO] -> Imported ./dump/mysqlPlugins.sql"
mysql -u root -f < ./dump/mysqlPlugins.sql
# Import changes
for file in changes/*/*.sql; do
for file in changes/*.sql; do
echo "[INFO] -> Imported ./$file"
mysql -u root -fc < $file
done

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`id`,`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (149, 'Sip', '*', 'WRITE', 'ALLOW', 'ROLE', 'hr');
INSERT INTO `salix`.`ACL` (`id`,`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (150, 'Sip', '*', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,29 @@
USE `hedera`;
DROP procedure IF EXISTS `orderGetTotal`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `orderGetTotal`()
BEGIN
/**
* Calcula el total con IVA para un conjunto de orders.
*
* @table tmp.order(orderFk) Identificadores de las ordenes a calcular
* @return tmp.orderTotal Total para cada order
*/
CALL orderGetTax;
DROP TEMPORARY TABLE IF EXISTS tmp.orderTotal;
CREATE TEMPORARY TABLE tmp.orderTotal
(INDEX (orderFk))
ENGINE = MEMORY
SELECT o.orderFk, IFNULL(SUM(ot.taxableBase + ot.tax), 0.0) AS total
FROM tmp.order o
LEFT JOIN tmp.orderAmount ot ON o.orderFk = ot.orderFk
GROUP BY orderFk;
DROP TEMPORARY TABLE IF EXISTS tmp.orderTax;
END$$
DELIMITER ;

View File

@ -0,0 +1,36 @@
DROP PROCEDURE IF EXISTS vn.ticketGetVisibleAvailable;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticketGetVisibleAvailable`(
vTicket INT)
BEGIN
DECLARE vVisibleCalc INT;
DECLARE vAvailableCalc INT;
DECLARE vShipped DATE;
DECLARE vWarehouse TINYINT;
DECLARE vAlertLevel INT;
SELECT t.warehouseFk, t.shipped, ts.alertLevel INTO vWarehouse, vShipped, vAlertLevel
FROM ticket t
LEFT JOIN ticketState ts ON ts.ticketFk = vTicket
WHERE t.id = vTicket;
IF vAlertLevel IS NULL OR vAlertLevel = 0 THEN
IF vShipped >= CURDATE() THEN
CALL cache.available_refresh(vAvailableCalc, FALSE, vWarehouse, vShipped);
END IF;
IF vShipped = CURDATE() THEN
CALL cache.visible_refresh(vVisibleCalc, FALSE, vWarehouse);
END IF;
END IF;
SELECT s.id, s.itemFk, s.quantity, s.concept, s.price, s.reserved, s.discount, v.visible, av.available, it.image
FROM sale s
LEFT JOIN cache.visible v ON v.item_id = s.itemFk AND v.calc_id = vVisibleCalc
LEFT JOIN cache.available av ON av.item_id = s.itemFk AND av.calc_id = vAvailableCalc
LEFT JOIN item it ON it.id = s.itemFk
WHERE s.ticketFk = vTicket
ORDER BY s.concept;
END$$
DELIMITER ;

View File

@ -0,0 +1,72 @@
USE `vn`;
DROP procedure IF EXISTS `ticketCalculateSale`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticketCalculateSale`(IN vSale BIGINT)
proc: BEGIN
/*
Este procedimiento bioniza una linea de movimiento
*/
DECLARE vShipped DATE;
DECLARE vWarehouse SMALLINT;
DECLARE vAgencyMode INT;
DECLARE vAddress INT;
DECLARE vTicket BIGINT;
DECLARE vItem BIGINT;
DECLARE vLanded DATE;
DECLARE vTicketFree BOOLEAN DEFAULT TRUE;
SELECT FALSE
INTO vTicketFree
FROM vn.ticket t
JOIN vn.sale s ON s.ticketFk = t.id
LEFT JOIN vn.ticketState ts ON ts.ticketFk = t.id
WHERE s.id = vSale
AND (t.refFk != "" OR (ts.alertLevel > 0 AND s.price != 0))
LIMIT 1;
SELECT ticketFk, itemFk
INTO vTicket, vItem
FROM sale
WHERE id = vSale;
SELECT t.warehouseFk, DATE(t.shipped), t.addressFk, t.agencyModeFk, t.landed
INTO vWarehouse, vShipped, vAddress, vAgencyMode, vLanded
FROM agencyMode a
JOIN ticket t ON t.agencyModeFk = a.id
WHERE t.id = vTicket;
DROP TEMPORARY TABLE IF EXISTS tmp.agencyHourGetShipped;
CREATE TEMPORARY TABLE tmp.agencyHourGetShipped ENGINE = MEMORY
SELECT vWarehouse warehouseFk, vShipped shipped, vLanded landed;
CALL buyUltimate (vWarehouse, vShipped); -- rellena la tabla tmp.buyUltimate con la ultima compra
DELETE FROM tmp.buyUltimate WHERE itemFk != vItem;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot
SELECT vWarehouse warehouseFk, NULL available, vItem itemFk, buyFk
FROM tmp.buyUltimate
WHERE itemFk = vItem;
CALL ticketComponentCalculate(vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
SELECT vSale saleFk,vWarehouse warehouseFk;
CALL ticketComponentUpdateSale(IF(vTicketFree,1,6)); -- si el ticket esta facturado, respeta los precios
-- Log
INSERT INTO vn.ticketLog (originFk, userFk, `action`, description)
VALUES (vTicket, account.userGetId(), 'update', CONCAT('Bionizo linea id ', vSale));
-- Limpieza
DROP TEMPORARY TABLE tmp.buyUltimate;
END$$
DELIMITER ;

View File

@ -0,0 +1,165 @@
USE `vn`;
DROP procedure IF EXISTS `ticketGetProblems`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `ticketGetProblems`()
BEGIN
/*
* Obtiene los problemas de uno o varios tickets
*
* @table tmp.ticketGetProblems(ticketFk, clientFk, warehouseFk, shipped)
* @return tmp.ticketProblems
*/
DECLARE vWarehouse INT;
DECLARE vDate DATE;
DECLARE vAvailableCache INT;
DECLARE vVisibleCache INT;
DECLARE vDone INT DEFAULT 0;
DECLARE vCursor CURSOR FOR
SELECT DISTINCT tt.warehouseFk, date(tt.shipped)
FROM tmp.ticketGetProblems tt
WHERE DATE(tt.shipped) BETWEEN CURDATE()
AND TIMESTAMPADD(DAY, 1.9, CURDATE());
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketProblems;
CREATE TEMPORARY TABLE tmp.ticketProblems (
ticketFk INT(11) PRIMARY KEY,
isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,2) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0,
isAvailable INTEGER(1) DEFAULT 1
) ENGINE = MEMORY;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketList;
CREATE TEMPORARY TABLE tmp.ticketList
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT tp.ticketFk, c.id clientFk
FROM tmp.ticketGetProblems tp
JOIN vn.client c ON c.id = tp.clientFk;
-- Inserta tickets de clientes congelados
INSERT INTO tmp.ticketProblems(ticketFk, isFreezed)
SELECT DISTINCT tl.ticketFk, 1
FROM tmp.ticketList tl
JOIN vn.client c ON c.id = tl.clientFk
WHERE c.isFreezed;
DELETE tl FROM tmp.ticketList tl
JOIN tmp.ticketProblems tp ON tl.ticketFk = tp.ticketFk;
DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt;
CREATE TEMPORARY TABLE tmp.clientGetDebt
(PRIMARY KEY (clientFk))
ENGINE = MEMORY
SELECT DISTINCT clientFk
FROM tmp.ticketList;
CALL clientGetDebt(CURDATE());
-- Inserta tickets de clientes con riesgo
INSERT INTO tmp.ticketProblems(ticketFk, risk)
SELECT DISTINCT tl.ticketFk, r.risk
FROM tmp.ticketList tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.agencyMode a ON t.agencyModeFk = a.id
JOIN tmp.risk r ON r.clientFk = t.clientFk
JOIN vn.client c ON c.id = t.clientFk
WHERE r.risk > c.credit + 10
AND a.deliveryMethodFk != 3
ON DUPLICATE KEY UPDATE
risk = r.risk;
DELETE tl FROM tmp.ticketList tl
JOIN tmp.ticketProblems tp ON tl.ticketFk = tp.ticketFk;
-- Inserta tickets que tengan codigos 100
INSERT INTO tmp.ticketProblems(ticketFk, hasTicketRequest)
SELECT DISTINCT tl.ticketFk, 'Code 100'
FROM tmp.ticketList tl
JOIN vn.ticketRequest tr ON tr.ticketFk = tl.ticketFk
WHERE tr.isOK IS NULL
ON DUPLICATE KEY UPDATE
hasTicketRequest = 1;
DELETE tl FROM tmp.ticketList tl
JOIN tmp.ticketProblems tp ON tl.ticketFk = tp.ticketFk;
OPEN vCursor;
WHILE NOT vDone
DO
FETCH vCursor INTO vWarehouse, vDate;
CALL cache.visible_refresh(vVisibleCache, FALSE, vWarehouse);
CALL cache.available_refresh(vAvailableCache, FALSE, vWarehouse, vDate);
-- Inserta tickets con articulos que no tegan disponible
INSERT INTO tmp.ticketProblems(ticketFk, isAvailable)
SELECT tl.ticketFk, 0
FROM tmp.ticketList tl
JOIN vn.ticket t ON t.id = tl.ticketFk
LEFT JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN cache.visible v ON i.id = v.item_id
AND v.calc_id = vVisibleCache
LEFT JOIN cache.available av ON av.item_id = i.id
AND av.calc_id = vAvailableCache
WHERE date(t.shipped) = vDate
AND categoryFk != 6
AND s.quantity > IFNULL(v.visible, 0)
AND IFNULL(av.available, 0) < 0
AND s.isPicked = FALSE
AND NOT i.generic
AND vWarehouse = t.warehouseFk
GROUP BY tl.ticketFk
ON DUPLICATE KEY UPDATE
isAvailable = 0;
DELETE tl FROM tmp.ticketList tl
JOIN tmp.ticketProblems tp ON tl.ticketFk = tp.ticketFk;
INSERT INTO tmp.ticketProblems(ticketFk, isAvailable)
SELECT tl.ticketFk, 0
FROM tmp.ticketList tl
JOIN vn.ticket t ON t.id = tl.ticketFk
LEFT JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN cache.visible v ON i.id = v.item_id AND v.calc_id = vVisibleCache
LEFT JOIN cache.available av ON av.item_id = i.id AND av.calc_id = vAvailableCache
WHERE IFNULL(av.available, 0) >= 0
AND s.quantity > IFNULL(v.visible, 0)
AND s.isPicked = FALSE
AND s.reserved = FALSE
AND it.categoryFk != 6
AND date(t.shipped) = vDate
AND NOT i.generic
AND CURDATE() = vDate
AND t.warehouseFk = vWarehouse
GROUP BY tl.ticketFk
ON DUPLICATE KEY UPDATE
isAvailable = 0;
DELETE tl FROM tmp.ticketList tl
JOIN tmp.ticketProblems tp ON tl.ticketFk = tp.ticketFk;
END WHILE;
CLOSE vCursor;
SELECT * FROM tmp.ticketProblems;
DROP TEMPORARY TABLE
tmp.clientGetDebt,
tmp.ticketList;
END$$
DELIMITER ;

View File

@ -0,0 +1,21 @@
DROP procedure IF EXISTS `hedera`.`basketGetTax`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`basketGetTax`()
READS SQL DATA
BEGIN
/**
* Returns the taxes for the current client basket.
*
* @treturn tmp.orderTax
*/
DROP TEMPORARY TABLE IF EXISTS tmp.order;
CREATE TEMPORARY TABLE tmp.order
ENGINE = MEMORY
SELECT myBasketGetId() orderFk;
CALL orderGetTax();
DROP TEMPORARY TABLE IF EXISTS tmp.order;
END$$
DELIMITER ;

View File

@ -0,0 +1,36 @@
USE `hedera`;
DROP FUNCTION IF EXISTS `orderGetTotal`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` FUNCTION `orderGetTotal`(vOrder INT) RETURNS decimal(10,2)
READS SQL DATA
DETERMINISTIC
BEGIN
/**
* Obtiene el total de un pedido con el IVA y el recargo de
* equivalencia incluidos.
*
* @param vOrder El identificador del pedido
* @return El total del pedido
*/
DECLARE vTotal DECIMAL(10,2);
DROP TEMPORARY TABLE IF EXISTS tmp.order;
CREATE TEMPORARY TABLE tmp.order
ENGINE = MEMORY
SELECT vOrder orderFk;
CALL orderGetTotal;
SELECT total INTO vTotal FROM tmp.orderTotal;
DROP TEMPORARY TABLE
tmp.order,
tmp.orderTotal;
RETURN vTotal;
END$$
DELIMITER ;

View File

@ -0,0 +1,65 @@
USE `hedera`;
DROP procedure IF EXISTS `orderGetTax`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `orderGetTax`()
READS SQL DATA
BEGIN
/**
* Calcula el IVA, y el recargo de equivalencia de un pedido
* desglosados por tipos.
*
* @param vOrder El identificador del pedido
* @treturn tmp.orderTax Bases imponibles, IVA y recargo de equivalencia
*/
DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany;
CREATE TEMPORARY TABLE tmp.addressCompany
(INDEX (addressFk, companyFk))
ENGINE = MEMORY
SELECT DISTINCT o.address_id addressFk, o.company_id companyFk
FROM tmp.order tmpOrder
JOIN hedera.order o ON o.id = tmpOrder.orderFk;
CALL vn.addressTaxArea ();
-- Calcula el IVA y el recargo desglosado.
DROP TEMPORARY TABLE IF EXISTS tmp.orderTax;
CREATE TEMPORARY TABLE tmp.orderTax
(INDEX (orderFk))
ENGINE = MEMORY
SELECT o.id orderFk,
tc.code,
SUM(m.amount * m.price) taxableBase,
pgc.rate
FROM tmp.order tmpOrder
JOIN `order` o ON o.id = tmpOrder.orderFk
JOIN orderRow m ON m.orderFk = o.id
JOIN vn.item i ON i.id = m.itemFk
JOIN vn.client c ON c.id = o.customer_id
JOIN vn.supplier s ON s.id = o.company_id
JOIN tmp.addressTaxArea ata
ON ata.addressFk = o.address_id AND ata.companyFk = o.company_id
JOIN vn.itemTaxCountry itc
ON itc.itemFk = i.id AND itc.countryFk = s.countryFk
JOIN vn.bookingPlanner bp
ON bp.countryFk = s.countryFk
AND bp.taxAreaFk = ata.areaFk
AND bp.taxClassFk = itc.taxClassFk
JOIN vn.pgc ON pgc.code = bp.pgcFk
JOIN vn.taxClass tc ON tc.id = bp.taxClassFk
GROUP BY tmpOrder.orderFk, pgc.code,pgc.rate
HAVING taxableBase != 0;
DROP TEMPORARY TABLE IF EXISTS tmp.orderAmount;
CREATE TEMPORARY TABLE tmp.orderAmount
(INDEX (orderFk))
ENGINE = MEMORY
SELECT orderFk, taxableBase, SUM(CAST(taxableBase * rate / 100 AS DECIMAL(10, 2))) tax,code
FROM tmp.orderTax
GROUP BY orderFk, code;
END$$
DELIMITER ;

View File

@ -0,0 +1,34 @@
/* Añadir a producción cuando se suba salix */
DROP TRIGGER IF EXISTS vn2008.ConsignatariosAfterUpdate;
USE vn2008;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`ConsignatariosAfterUpdate` AFTER UPDATE ON `Consignatarios` FOR EACH ROW
BEGIN
-- Recargos de equivalencia distintos implican facturacion por consignatario
IF NEW.isEqualizated != OLD.isEqualizated THEN
IF
(SELECT COUNT(*) FROM
(
SELECT DISTINCT (isEqualizated = FALSE) as Equ
FROM Consignatarios
WHERE Id_Cliente = NEW.Id_Cliente
) t1
) > 1
THEN
UPDATE Clientes
SET invoiceByAddress = TRUE
WHERE Id_Cliente = NEW.Id_Cliente;
END IF;
END IF;
END$$
DELIMITER ;
USE vn;

View File

@ -0,0 +1,27 @@
/* Añadir a producción cuando se suba salix */
DROP TRIGGER IF EXISTS vn2008.ConsignatariosBeforeInsert;
USE vn2008;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`ConsignatariosBeforeInsert`
BEFORE INSERT ON `vn2008`.`Consignatarios`
FOR EACH ROW
BEGIN
DECLARE vIsEqualizated BOOLEAN;
CALL pbx.phoneIsValid (NEW.telefono);
CALL pbx.phoneIsValid (NEW.movil);
IF NEW.isEqualizated IS NULL THEN
SELECT RE
INTO vIsEqualizated
FROM Clientes
WHERE Id_Cliente = NEW.Id_Cliente;
SET NEW.isEqualizated = vIsEqualizated;
END IF;
END$$
DELIMITER ;
USE vn;

View File

@ -0,0 +1,16 @@
/* Añadir a producción cuando se suba salix */
DROP TRIGGER IF EXISTS vn2008.ConsignatariosBeforeUpdate;
USE vn2008;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`ConsignatariosBeforeUpdate`
BEFORE UPDATE ON `vn2008`.`Consignatarios`
FOR EACH ROW
BEGIN
CALL pbx.phoneIsValid (NEW.telefono);
CALL pbx.phoneIsValid (NEW.movil);
END$$
DELIMITER ;
USE vn;

View File

@ -0,0 +1,3 @@
/* Añadir a producción cuando se suba salix */
DROP TRIGGER vn2008.ClientesAfterInsert;

View File

@ -0,0 +1,20 @@
/* Añadir a producción cuando se suba salix */
DROP TRIGGER IF EXISTS vn2008.ClientesAfterUpdate;
USE vn2008;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn2008`.`ClientesAfterUpdate`
AFTER UPDATE ON `Clientes`
FOR EACH ROW
BEGIN
IF NEW.default_address AND (NEW.default_address != OLD.default_address) THEN
UPDATE Consignatarios SET predeterminada = FALSE
WHERE Id_cliente = NEW.Id_cliente;
UPDATE Consignatarios SET predeterminada = TRUE
WHERE Id_consigna = NEW.default_address;
END IF;
END$$
DELIMITER ;
USE vn;

View File

@ -0,0 +1,9 @@
/* Script de migración consignatarios.
Añadir a producción cuando se suba salix */
/* USE vn;
UPDATE vn.client c
JOIN vn.address a ON a.clientFk = c.id AND a.isDefaultAddress
SET c.defaultAddressFk = a.id
WHERE c.defaultAddressFk IS NULL */

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
ALTER TABLE `vn`.`itemTaxCountry` AUTO_INCREMENT = 1;
ALTER TABLE `vn2008`.`Consignatarios` AUTO_INCREMENT = 1;
@ -8,7 +10,7 @@ INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`
SELECT id, name, CONCAT(name, 'Nick'),MD5('nightmare'), id, 1, CONCAT(name, '@verdnatura.es')
FROM `account`.`role`;
INSERT INTO `vn`.`worker`(`id`,`workerCode`, `firstName`, `name`, `userFk`)
INSERT INTO `vn2008`.`Trabajadores`(`Id_Trabajador`,`CodigoTrabajador`, `Nombre`, `Apellidos`, `user_id`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id
FROM `vn`.`user`;
@ -29,7 +31,7 @@ INSERT INTO `account`.`user`(`id`,`name`,`password`,`role`,`active`,`email`,`lan
(111, 'Missing', 'ac754a330530832ba1bf7687f577da91', 2 , 0, NULL, 'es'),
(112, 'Trash', 'ac754a330530832ba1bf7687f577da91', 2 , 0, NULL, 'es');
INSERT INTO `vn`.`worker`(`workerCode`, `id`, `firstName`, `name`, `userFk`)
INSERT INTO `vn2008`.`Trabajadores`(`CodigoTrabajador`, `Id_Trabajador`, `Nombre`, `Apellidos`, `user_id`)
VALUES
('LGN', 106, 'David Charles', 'Haller', 106),
('ANT', 107, 'Hank' , 'Pym' , 107),
@ -189,18 +191,23 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`fax`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`,`mailAddress`,`cplusTerIdNifFk`,`hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`)
VALUES
(101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', 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),
(102, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', 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, 1, NULL, 0, 0, 18, 0, 1),
(103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', 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),
(104, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', 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', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', 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, NULL, 0, 1),
(106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', 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@verdnatura.es', 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@verdnatura.es', 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),
(109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', 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, 1, NULL, 0, 0, 19, 0, 1),
(110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', 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, 1, NULL, 0, 0, NULL, 0, 1),
(200, 'Missing', NULL, 'Missing man', 'Anton', 'The space', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1),
(400, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1);
(101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', 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),
(102, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', 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, 1, NULL, 0, 0, 18, 0, 1),
(103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', 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),
(104, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', 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', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', 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, NULL, 0, 1),
(106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', 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@verdnatura.es', 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@verdnatura.es', 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),
(109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', 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, 1, NULL, 0, 0, 19, 0, 1),
(110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', 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, 1, NULL, 0, 0, NULL, 0, 1),
(200, 'Missing', NULL, 'Missing man', 'Anton', 'The space', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1),
(400, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1);
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `phone`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'SILLA', 46460, 623111111, 1, CONCAT(name,'@verdnatura.es'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, CURDATE(), 1
FROM `account`.`role` `r`
WHERE `r`.`hasLogin` = 1;
INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
VALUES
@ -209,38 +216,75 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
( 103, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
( 104, -30, DATE_ADD(CURDATE(), INTERVAL -1 MONTH));
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `isDefaultAddress`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`)
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
VALUES
(101, 'address 01', 'Somewhere in Thailand', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(102, 'address 02', 'Somewhere in Poland', 'Silla', 46460, 1, 3333333333, 444444444, 1, 0, 109, 2, NULL, NULL, 0),
(103, 'address 03', 'Somewhere in Japan', 'Silla', 46460, 1, 3333333333, 444444444, 1, 0, 109, 2, NULL, NULL, 0),
(104, 'address 04', 'Somewhere in Spain', 'Silla', 46460, 1, 3333333333, 444444444, 1, 0, 109, 2, NULL, NULL, 0),
(105, 'address 05', 'Somewhere in Potugal', 'Silla', 46460, 1, 5555555555, 666666666, 1, 0, 109, 2, NULL, NULL, 0),
(106, 'address 06', 'Somewhere in UK', 'Silla', 46460, 1, 5555555555, 666666666, 1, 0, 109, 2, NULL, NULL, 0),
(107, 'address 07', 'Somewhere in Valencia', 'Silla', 46460, 1, 5555555555, 666666666, 1, 0, 109, 2, NULL, NULL, 0),
(108, 'address 08', 'Somewhere in Silla', 'Silla', 46460, 1, 5555555555, 666666666, 1, 0, 109, 2, NULL, NULL, 0),
(109, 'address 09', 'Somewhere in London', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(110, 'address 10', 'Somewhere in Algemesi', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(111, 'address 11', 'Somewhere in Carlet', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(112, 'address 12', 'Somewhere in Campanar', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(113, 'address 13', 'Somewhere in Malilla', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(114, 'address 14', 'Somewhere in France', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(115, 'address 15', 'Somewhere in Birmingham', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(116, 'address 16', 'Somewhere in Scotland', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(117, 'address 17', 'Somewhere in nowhere', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(118, 'address 18', 'Somewhere over the rainbow', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(119, 'address 19', 'Somewhere in Alberic', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(120, 'address 20', 'Somewhere in Montortal', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 109, 2, NULL, NULL, 0),
(121, 'address 21', 'the bat cave', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 101, 2, NULL, NULL, 0),
(122, 'address 22', 'NY roofs', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 102, 2, NULL, NULL, 0),
(123, 'address 23', 'The phone box', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 103, 2, NULL, NULL, 0),
(124, 'address 24', 'Stark tower', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 104, 2, NULL, NULL, 0),
(125, 'address 25', 'The plastic cell', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 105, 2, NULL, NULL, 0),
(126, 'address 26', 'Many places', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 106, 2, NULL, NULL, 0),
(127, 'address 27', 'Your pocket', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 107, 2, NULL, NULL, 0),
(128, 'address 28', 'Cerebro', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 108, 2, NULL, NULL, 0),
(129, 'address 29', 'Luke Cages Bar', 'Silla', 46460, 1, 1111111111, 222222222, 1, 0, 110, 2, NULL, NULL, 0),
(130, 'address 30', 'Non valid address', 'Silla', 46460, 1, 1111111111, 222222222, 0, 0, 101, 2, NULL, NULL, 0);
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1, 1111111111, 222222222, 1, 101, 2, NULL, NULL, 0, 1),
(2, 'Petter Parker', '20 Ingram Street', 'Silla', 46460, 1, 1111111111, 222222222, 1, 102, 2, NULL, NULL, 0, 1),
(3, 'Clark Kent', '344 Clinton Street', 'Silla', 46460, 1, 1111111111, 222222222, 1, 103, 2, NULL, NULL, 0, 1),
(4, 'Tony Stark', '10880 Malibu Point', 'Silla', 46460, 1, 1111111111, 222222222, 1, 104, 2, NULL, NULL, 0, 1),
(5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Silla', 46460, 1, 1111111111, 222222222, 1, 105, 2, NULL, NULL, 0, 1),
(6, 'DavidCharlesHaller', 'Evil hideout', 'Silla', 46460, 1, 1111111111, 222222222, 1, 106, 2, NULL, NULL, 0, 1),
(7, 'Hank Pym', 'Anthill', 'Silla', 46460, 1, 1111111111, 222222222, 1, 107, 2, NULL, NULL, 0, 1),
(8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1, 1111111111, 222222222, 1, 108, 2, NULL, NULL, 0, 1),
(9, 'Bruce Banner', 'Somewhere in New York', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 1),
(10, 'Jessica Jones', 'NYCC 2015 Poster', 'Silla', 46460, 1, 1111111111, 222222222, 1, 110, 2, NULL, NULL, 0, 1),
(11, 'Missing', 'The space', 'Silla', 46460, 1, 1111111111, 222222222, 1, 200, 2, NULL, NULL, 0, 1),
(12, 'Trash', 'New York city', 'Silla', 46460, 1, 1111111111, 222222222, 1, 400, 2, NULL, NULL, 0, 1),
(101, 'address 01', 'Somewhere in Thailand', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(102, 'address 02', 'Somewhere in Poland', 'Silla', 46460, 1, 3333333333, 444444444, 1, 109, 2, NULL, NULL, 0, 0),
(103, 'address 03', 'Somewhere in Japan', 'Silla', 46460, 1, 3333333333, 444444444, 1, 109, 2, NULL, NULL, 0, 0),
(104, 'address 04', 'Somewhere in Spain', 'Silla', 46460, 1, 3333333333, 444444444, 1, 109, 2, NULL, NULL, 0, 0),
(105, 'address 05', 'Somewhere in Potugal', 'Silla', 46460, 1, 5555555555, 666666666, 1, 109, 2, NULL, NULL, 0, 0),
(106, 'address 06', 'Somewhere in UK', 'Silla', 46460, 1, 5555555555, 666666666, 1, 109, 2, NULL, NULL, 0, 0),
(107, 'address 07', 'Somewhere in Valencia', 'Silla', 46460, 1, 5555555555, 666666666, 1, 109, 2, NULL, NULL, 0, 0),
(108, 'address 08', 'Somewhere in Silla', 'Silla', 46460, 1, 5555555555, 666666666, 1, 109, 2, NULL, NULL, 0, 0),
(109, 'address 09', 'Somewhere in London', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(110, 'address 10', 'Somewhere in Algemesi', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(111, 'address 11', 'Somewhere in Carlet', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(112, 'address 12', 'Somewhere in Campanar', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(113, 'address 13', 'Somewhere in Malilla', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(114, 'address 14', 'Somewhere in France', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(115, 'address 15', 'Somewhere in Birmingham', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(116, 'address 16', 'Somewhere in Scotland', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(117, 'address 17', 'Somewhere in nowhere', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(118, 'address 18', 'Somewhere over the rainbow', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(119, 'address 19', 'Somewhere in Alberic', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(120, 'address 20', 'Somewhere in Montortal', 'Silla', 46460, 1, 1111111111, 222222222, 1, 109, 2, NULL, NULL, 0, 0),
(121, 'address 21', 'the bat cave', 'Silla', 46460, 1, 1111111111, 222222222, 1, 101, 2, NULL, NULL, 0, 0),
(122, 'address 22', 'NY roofs', 'Silla', 46460, 1, 1111111111, 222222222, 1, 102, 2, NULL, NULL, 0, 0),
(123, 'address 23', 'The phone box', 'Silla', 46460, 1, 1111111111, 222222222, 1, 103, 2, NULL, NULL, 0, 0),
(124, 'address 24', 'Stark tower', 'Silla', 46460, 1, 1111111111, 222222222, 1, 104, 2, NULL, NULL, 0, 0),
(125, 'address 25', 'The plastic cell', 'Silla', 46460, 1, 1111111111, 222222222, 1, 105, 2, NULL, NULL, 0, 0),
(126, 'address 26', 'Many places', 'Silla', 46460, 1, 1111111111, 222222222, 1, 106, 2, NULL, NULL, 0, 0),
(127, 'address 27', 'Your pocket', 'Silla', 46460, 1, 1111111111, 222222222, 1, 107, 2, NULL, NULL, 0, 0),
(128, 'address 28', 'Cerebro', 'Silla', 46460, 1, 1111111111, 222222222, 1, 108, 2, NULL, NULL, 0, 0),
(129, 'address 29', 'Luke Cages Bar', 'Silla', 46460, 1, 1111111111, 222222222, 1, 110, 2, NULL, NULL, 0, 0),
(130, 'address 30', 'Non valid address', 'Silla', 46460, 1, 1111111111, 222222222, 0, 101, 2, NULL, NULL, 0, 0),
(131, 'Missing', 'The space', 'Silla', 46460, 1, 1111111111, 222222222, 1, 200, 2, NULL, NULL, 0, 0),
(132, 'Trash', 'New York city', 'Silla', 46460, 1, 1111111111, 222222222, 1, 400, 2, NULL, NULL, 0, 0);
INSERT INTO `vn`.`address`( `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `isActive`, `clientFk`, `agencyModeFk`, `isDefaultAddress`)
SELECT name, CONCAT(name, 'Street'), 'SILLA', 46460, 1, 1, id, 2, 1
FROM `account`.`role` `r`
WHERE `r`.`hasLogin` = 1;
UPDATE `vn`.`client` SET defaultAddressFk = 1 WHERE id = 101;
UPDATE `vn`.`client` SET defaultAddressFk = 2 WHERE id = 102;
UPDATE `vn`.`client` SET defaultAddressFk = 3 WHERE id = 103;
UPDATE `vn`.`client` SET defaultAddressFk = 4 WHERE id = 104;
UPDATE `vn`.`client` SET defaultAddressFk = 5 WHERE id = 105;
UPDATE `vn`.`client` SET defaultAddressFk = 6 WHERE id = 106;
UPDATE `vn`.`client` SET defaultAddressFk = 7 WHERE id = 107;
UPDATE `vn`.`client` SET defaultAddressFk = 8 WHERE id = 108;
UPDATE `vn`.`client` SET defaultAddressFk = 9 WHERE id = 109;
UPDATE `vn`.`client` SET defaultAddressFk = 10 WHERE id = 110;
UPDATE `vn`.`client` SET defaultAddressFk = 11 WHERE id = 200;
UPDATE `vn`.`client` SET defaultAddressFk = 12 WHERE id = 400;
UPDATE `vn`.`client` `c`
JOIN `vn`.`address` `a` ON `a`.`clientFk` = `c`.`id`
SET `c`.`defaultAddressFk` = `a`.`id`
WHERE `defaultAddressFk` IS NULL;
INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`)
VALUES
@ -267,15 +311,15 @@ INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`)
INSERT INTO `vn`.`clientObservation`(`id`, `clientFk`, `workerFk`, `text`, `created`)
VALUES
(1, 101, 1, 'Madness, as you know, is like gravity, all it takes is a little push', CURDATE()),
(2, 102, 1, 'With great power, comes great responsibility', CURDATE()),
(3, 103, 3, 'this is a job for Super-Man!', CURDATE()),
(4, 104, 3, 'yes... I am Iron-Man', CURDATE()),
(5, 105, 5, 'They do understand. Our mutant powers make us superior', CURDATE()),
(6, 106, 5, 'My name is Legion, for we are many!', CURDATE()),
(7, 107, 9, 'I think our first move should be calling the Avengers..', CURDATE()),
(8, 108, 9, 'Just because someone stumbles and loses their path, does not mean they are lost forever.', CURDATE()),
(9, 109, 20, 'HULK SMASH! ...', CURDATE()),
(1, 101, 1, 'Madness, as you know, is like gravity, all it takes is a little push', CURDATE()),
(2, 102, 1, 'With great power, comes great responsibility', CURDATE()),
(3, 103, 3, 'this is a job for Super-Man!', CURDATE()),
(4, 104, 3, 'yes... I am Iron-Man', CURDATE()),
(5, 105, 5, 'They do understand. Our mutant powers make us superior', CURDATE()),
(6, 106, 5, 'My name is Legion, for we are many!', CURDATE()),
(7, 107, 9, 'I think our first move should be calling the Avengers..', CURDATE()),
(8, 108, 9, 'Just because someone stumbles and loses their path, does not mean they are lost forever.', CURDATE()),
(9, 109, 20, 'HULK SMASH! ...', CURDATE()),
(10, 110, 20, 'They say everyone is born a hero. But if you let it, life will push you over the line until you are the villain.', CURDATE());
INSERT INTO `vn`.`observationType`(`id`,`description`)
@ -593,11 +637,11 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
(5, 29, -18.72),
(5, 39, 0.02),
(6, 23, 6.5),
(7, 15, 0.29),
(7, 15, 0.2899),
(7, 28, 5.6),
(7, 29, -4.6),
(7, 39, 0.01),
(8, 15, 0.044),
(8, 15, 0.0435),
(8, 21, -0.004),
(8, 28, 20.72),
(8, 29, -19.72),
@ -624,7 +668,7 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
(12, 29, -19.72),
(12, 37, 2),
(12, 39, 0.01),
(13, 15, 0.29),
(13, 15, 0.2899),
(13, 28, 5.6),
(13, 29, -4.6),
(13, 39, 0.01),
@ -793,14 +837,14 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
(1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000),
(2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000),
(3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00),
(4, DATE_ADD(CURDATE(), INTERVAL -30 DAY), DATE_ADD(CURDATE(), INTERVAL -30 DAY), 1, 2, 1, 50.00, 500);
(4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`,`ref`)
VALUES
( 1, 1, DATE_ADD(CURDATE(), INTERVAL -30 DAY), 1, 442, 'Movimiento 1'),
( 2, 2, DATE_ADD(CURDATE(), INTERVAL -30 DAY), 2, 442, 'Movimiento 2'),
( 3, 1, DATE_ADD(CURDATE(), INTERVAL -30 DAY), 3, 442, 'Movimiento 3'),
( 4, 2, DATE_ADD(CURDATE(), INTERVAL -30 DAY), 4, 69, 'Movimiento 4');
( 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 442, 'Movimiento 1'),
( 2, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 442, 'Movimiento 2'),
( 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 442, 'Movimiento 3'),
( 4, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 69, 'Movimiento 4');
INSERT INTO `vn`.`agencyProvince`(`provinceFk`, `agencyFk`, `zone`, `warehouseFk`)
VALUES
@ -927,7 +971,7 @@ INSERT INTO `hedera`.`orderRowComponent`(`rowFk`, `componentFk`, `price`)
(5, 29, -18.72),
(5, 39, 0.02),
(6, 23, 6.5),
(7, 15, 0.29),
(7, 15, 0.2899),
(7, 28, 5.6),
(7, 29, -4.6),
(7, 39, 0.01),
@ -1061,10 +1105,10 @@ INSERT INTO `vn`.`userConfig` (`userFk`, `warehouseFk`, `companyFk`)
INSERT INTO `vn`.`receipt`(`id`, `invoiceFk`, `amountPaid`, `amountUnpaid`, `payed`, `workerFk`, `bankFk`, `clientFk`, `created`, `companyFk`, `isConciliate`)
VALUES
(1, 'Cobro web', 100.50, 0.00, CURDATE(), 9, 1, 101, CURDATE(), 442, 1),
(2, 'Cobro web', 200.50, 0.00, DATE_ADD(CURDATE(), INTERVAL -5 DAY), 9, 1, 101, DATE_ADD(CURDATE(), INTERVAL -5 DAY), 442, 1),
(3, 'Cobro en efectivo', 300.00, 100.00, DATE_ADD(CURDATE(), INTERVAL -10 DAY), 9, 1, 102, DATE_ADD(CURDATE(), INTERVAL -10 DAY), 442, 0),
(4, 'Cobro en efectivo', -400.00, -50.00, DATE_ADD(CURDATE(), INTERVAL -15 DAY), 9, 1, 103, DATE_ADD(CURDATE(), INTERVAL -15 DAY), 442, 0);
(1, 'Cobro web', 100.50, 0.00, CURDATE(), 9, 1, 101, CURDATE(), 442, 1),
(2, 'Cobro web', 200.50, 0.00, DATE_ADD(CURDATE(), INTERVAL -5 DAY), 9, 1, 101, DATE_ADD(CURDATE(), INTERVAL -5 DAY), 442, 1),
(3, 'Cobro en efectivo', 300.00, 100.00, DATE_ADD(CURDATE(), INTERVAL -10 DAY), 9, 1, 102, DATE_ADD(CURDATE(), INTERVAL -10 DAY), 442, 0),
(4, 'Cobro en efectivo', -400.00, -50.00, DATE_ADD(CURDATE(), INTERVAL -15 DAY), 9, 1, 103, DATE_ADD(CURDATE(), INTERVAL -15 DAY), 442, 0);
INSERT INTO `vn2008`.`workerTeam`(`id`, `team`, `user`)
VALUES
@ -1126,5 +1170,3 @@ INSERT INTO `postgresql`.`business_labour`(`business_id`, `notes`, `department_i
VALUES
(1, NULL, 22, 4, 0, 1, 1, 1, 1),
(2, 'From las friday worker ownes the company 1 hour', 23, 1, 0, 1, 0, 1, 1);

View File

@ -18,11 +18,11 @@ let jasmine = new Jasmine();
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
let serviceSpecs = [
'./db/tests/**/*[sS]pec.js'
'./tests/**/*[sS]pec.js'
];
jasmine.loadConfig({
spec_dir: 'services',
spec_dir: 'db',
spec_files: serviceSpecs,
helpers: []
});

View File

@ -183,6 +183,7 @@ describe('ticket ticketCreateWithUser()', () => {
params.landed,
params.userId
]);
stmts.push(stmt);
let ticketAddressIndex = stmts.push(`SELECT addressFk FROM vn.ticket WHERE id = @newTicketId`) - 1;
@ -191,12 +192,9 @@ describe('ticket ticketCreateWithUser()', () => {
params.clientFk,
]);
let clientDefaultAddressIndex = stmts.push(stmt) - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let ticketAddress = result[ticketAddressIndex][0];
let clientDefaultAddress = result[clientDefaultAddressIndex][0];

View File

@ -160,6 +160,16 @@ let actions = {
.catch(done);
},
waitToFocus: function(selector, done) {
this.wait(selector)
.evaluate_now(selector => {
let element = document.querySelector(selector);
element.focus();
}, done, selector)
.then(done)
.catch(done);
},
isVisible: function(selector, done) {
this.wait(selector)
.evaluate_now(elementSelector => {
@ -351,6 +361,7 @@ let actions = {
accessToSearchResult: function(searchValue, done) {
this.write(`vn-searchbar input`, searchValue)
.click(`vn-searchbar vn-icon[icon="search"]`)
.wait(100)
.waitForNumberOfElements('.searchResult', 1)
.evaluate(() => {
return document.querySelector('ui-view vn-card vn-table') != null;

View File

@ -31,6 +31,8 @@ export default {
name: `${components.vnTextfield}[name="name"]`,
taxNumber: `${components.vnTextfield}[name="fi"]`,
socialName: `${components.vnTextfield}[name="socialName"]`,
street: `${components.vnTextfield}[name="street"]`,
city: `${components.vnTextfield}[name="city"]`,
userName: `${components.vnTextfield}[name="userName"]`,
email: `${components.vnTextfield}[name="email"]`,
salesPersonAutocomplete: `vn-autocomplete[field="$ctrl.client.salesPersonFk"]`,
@ -85,6 +87,7 @@ export default {
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: 'vn-client-billing-data > vn-dialog vn-textfield[label="Name"] input',
newBankEntityBIC: 'vn-client-billing-data > vn-dialog vn-textfield[label="Swift / BIC"] input',
newBankEntityCode: 'vn-client-billing-data > vn-dialog vn-textfield[label="Code"] input',
acceptBankEntityButton: 'vn-client-billing-data > vn-dialog button[response="ACCEPT"]',
saveButton: `${components.vnSubmit}`
},
@ -149,6 +152,7 @@ export default {
},
clientLog: {
logButton: `vn-left-menu a[ui-sref="client.card.log"]`,
lastModificationDate: 'vn-client-log > vn-log vn-table vn-tbody > vn-tr > vn-td:nth-child(1)',
lastModificationPreviousValue: 'vn-client-log vn-table vn-td.before',
lastModificationCurrentValue: 'vn-client-log vn-table vn-td.after'
@ -165,10 +169,11 @@ export default {
},
webPayment: {
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"][aria-hidden="false"]'
},
itemsIndex: {
goBackToModuleIndexButton: `vn-ticket-descriptor a[href="#!/ticket/index"]`,
searchIcon: `vn-item-index vn-searchbar vn-icon[icon="search"]`,
goBackToModuleIndexButton: `vn-item-descriptor a[href="#!/item/index"]`,
createItemButton: `${components.vnFloatButton}`,
searchResult: `vn-item-index a.vn-tr`,
searchResultPreviewButton: `vn-item-index .buttons > [icon="desktop_windows"]`,
@ -176,7 +181,23 @@ export default {
acceptClonationAlertButton: `vn-item-index [vn-id="clone"] [response="ACCEPT"]`,
searchItemInput: `vn-searchbar vn-textfield input`,
searchButton: `vn-searchbar vn-icon[icon="search"]`,
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close'
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close',
fieldsToShowButton: 'vn-item-index vn-table > div.ng-scope > div > vn-icon-button[icon="menu"]',
fieldsToShowForm: 'vn-item-index > div > vn-card > div > vn-table > div.ng-scope > div > vn-dialog > div > form',
firstItemImage: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(1)',
firstItemId: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(2)',
idCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(2) > vn-check > md-checkbox',
stemsCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(3) > vn-check > md-checkbox',
sizeCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(4) > vn-check > md-checkbox',
nicheCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(5) > vn-check > md-checkbox',
typeCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(6) > vn-check > md-checkbox',
categoryCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(7) > vn-check > md-checkbox',
intrastadCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(8) > vn-check > md-checkbox',
originCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(9) > vn-check > md-checkbox',
buyerCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(10) > vn-check > md-checkbox',
destinyCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(11) > vn-check > md-checkbox',
taxClassCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(12) > vn-check > md-checkbox',
saveFieldsButton: 'vn-item-index vn-dialog vn-horizontal:nth-child(16) > vn-button > button'
},
itemCreateView: {
temporalName: `${components.vnTextfield}[name="provisionalName"]`,
@ -192,7 +213,9 @@ export default {
regularizeQuantityInput: `vn-item-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-textfield > div > div > div.infix > input`,
regularizeWarehouseAutocomplete: 'vn-item-descriptor vn-dialog vn-autocomplete[field="$ctrl.warehouseFk"]',
editButton: 'vn-item-card vn-item-descriptor vn-float-button[icon="edit"]',
regularizeSaveButton: `vn-item-descriptor > vn-dialog > div > form > div.buttons > tpl-buttons > button`
regularizeSaveButton: `vn-item-descriptor > vn-dialog > div > form > div.buttons > tpl-buttons > button`,
inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]',
navigateBackToIndex: 'vn-item-descriptor vn-icon[icon="chevron_left"]'
},
itemBasicData: {
basicDataButton: `vn-left-menu a[ui-sref="item.card.data"]`,
@ -322,7 +345,7 @@ export default {
packagesButton: `vn-left-menu a[ui-sref="ticket.card.package.index"]`,
firstPackageAutocomplete: `vn-autocomplete[label="Package"]`,
firstQuantityInput: `vn-textfield[label="Quantity"] input`,
firstRemovePackageButton: `vn-icon[vn-tooltip="Remove package"]`,
firstRemovePackageButton: `vn-icon-button[vn-tooltip="Remove package"]`,
addPackageButton: `vn-icon-button[vn-tooltip="Add package"]`,
clearPackageAutocompleteButton: `vn-autocomplete[label="Package"] > div > div > div > vn-icon > i`,
savePackagesButton: `${components.vnSubmit}`
@ -339,12 +362,13 @@ export default {
firstSaleThumbnailImage: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) vn-td:nth-child(3) > img',
firstSaleZoomedImage: 'body > div > div > img',
firstSaleQuantity: `vn-textfield[model="sale.quantity"]:nth-child(1) input`,
firstSaleQuantityCell: `vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable`,
firstSaleQuantityClearInput: `vn-textfield[model="sale.quantity"] div.suffix > i`,
firstSaleID: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(4) > span',
firstSalePrice: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) > vn-td:nth-child(7) > span',
firstSalePriceInput: 'vn-ticket-sale:nth-child(1) > vn-vertical > vn-popover.edit.dialog-summary.ng-isolate-scope.vn-popover.shown > div > div.content > div > vn-textfield',
firstSalePriceInput: 'vn-ticket-sale:nth-child(1) vn-popover.edit.dialog-summary.ng-isolate-scope.vn-popover.shown vn-textfield input',
firstSaleDiscount: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(8) > span',
firstSaleDiscountInput: 'vn-ticket-sale:nth-child(1) vn-ticket-sale-edit-discount > div > vn-textfield > div > div > div.infix > input.ng-not-empty',
firstSaleDiscountInput: 'vn-ticket-sale:nth-child(1) vn-ticket-sale-edit-discount vn-textfield input',
firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(9)',
firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)',
firstSaleColour: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(6) section:nth-child(1)`,
@ -421,7 +445,7 @@ export default {
addServiceButton: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(3) > vn-icon-button > button > vn-icon',
firstDescriptionInput: 'vn-ticket-service vn-textfield[label="Description"] input',
firstQuantityInput: 'vn-ticket-service vn-textfield[label="Quantity"] input',
firstPriceInput: 'vn-ticket-service vn-textfield[label="Price"] input',
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
fistDeleteServiceButton: 'vn-ticket-card > vn-main-block > div.content-block.ng-scope > vn-ticket-service > form > vn-card > div > vn-one:nth-child(1) > vn-horizontal:nth-child(1) > vn-auto > vn-icon-button[icon="delete"]',
serviceLine: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(2) > vn-horizontal',
@ -468,6 +492,17 @@ export default {
secondClaimRedeliveryAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[field="claimDevelopment.claimRedeliveryFk"]',
saveDevelopmentButton: `${components.vnSubmit}`
},
claimAction: {
importClaimButton: 'vn-claim-action vn-button[label="Import claim"]',
importTicketButton: 'vn-claim-action vn-button[label="Import ticket"]',
secondImportableTicket: 'vn-claim-action > vn-vertical > vn-popover > div > div.content > div > vn-table > div > vn-tbody > vn-tr:nth-child(2)',
firstLineDestination: 'vn-claim-action vn-tr:nth-child(1) vn-autocomplete[field="saleClaimed.claimDestinationFk"]',
thirdLineDestination: 'vn-claim-action vn-tr:nth-child(3) vn-autocomplete[field="saleClaimed.claimDestinationFk"]',
firstDeleteLine: 'vn-claim-action vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
secondDeleteLine: 'vn-claim-action vn-tr:nth-child(2) vn-icon-button[icon="delete"]',
thirdDeleteLine: 'vn-claim-action vn-tr:nth-child(3) vn-icon-button[icon="delete"]'
},
ordersIndex: {
searchResult: `vn-order-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr`,
searchResultDate: `vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)`,
@ -500,4 +535,9 @@ export default {
confirmOrder: 'vn-order-line > vn-vertical > vn-button-bar > vn-button > button',
confirmButton: 'vn-order-line > vn-confirm button[response="ACCEPT"]',
},
workerPbx: {
extensionInput: 'vn-worker-pbx vn-textfield[model="$ctrl.worker.sip.extension"] input',
passwordInput: 'vn-worker-pbx vn-textfield[model="$ctrl.worker.sip.secret"] input',
saveButton: 'vn-worker-pbx vn-submit[label="Save"] input'
}
};

View File

@ -0,0 +1,63 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Claim edit basic data path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('administrative', 'claim')
.accessToSearchResult('4')
.accessToSection('claim.card.action');
});
it('should import the claim', async() => {
const result = await nightmare
.waitToClick(selectors.claimAction.importClaimButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should import the eighth ticket', async() => {
const result = await nightmare
.waitToClick(selectors.claimAction.importTicketButton)
.waitToClick(selectors.claimAction.secondImportableTicket)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should edit the fourth line destination field', async() => {
const result = await nightmare
.autocompleteSearch(selectors.claimAction.thirdLineDestination, 'Bueno')
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should delete two first lines', async() => {
const result = await nightmare
.waitToClick(selectors.claimAction.secondDeleteLine)
.waitToClick(selectors.claimAction.firstDeleteLine)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should refresh the view to check the remaining line is the expected one', async() => {
const result = await nightmare
.reloadSection('claim.card.action')
.waitToGetProperty(`${selectors.claimAction.firstLineDestination} input`, 'value');
expect(result).toEqual('Bueno');
});
it('should delete the current first line', async() => {
const result = await nightmare
.waitToClick(selectors.claimAction.firstDeleteLine)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
});

View File

@ -52,6 +52,8 @@ describe('Client create path', () => {
const result = await nightmare
.write(selectors.createClientView.name, 'Carol Danvers')
.write(selectors.createClientView.socialName, 'AVG tax')
.write(selectors.createClientView.street, 'Many places')
.write(selectors.createClientView.city, 'Silla')
.clearInput(selectors.createClientView.email)
.write(selectors.createClientView.email, 'incorrect email format')
.waitToClick(selectors.createClientView.createButton)

View File

@ -58,7 +58,7 @@ describe('Client Edit fiscalData path', () => {
.accessToSection('client.card.fiscalData');
});
it('should receive an error if VIES and EQtax are being ticked together', async() => {
it('should edit the fiscal data', async() => {
const result = await nightmare
.wait(selectors.clientFiscalData.socialNameInput)
.clearInput(selectors.clientFiscalData.socialNameInput)
@ -84,9 +84,17 @@ describe('Client Edit fiscalData path', () => {
.waitToClick(selectors.clientFiscalData.saveButton)
.waitForLastSnackbar();
expect(result).toEqual('Cannot check VIES and Equalization Tax');
expect(result).toEqual('Data saved!');
}, 15000);
it('should propagate the Equalization tax', async() => {
const result = await nightmare
.waitToClick(selectors.clientFiscalData.acceptPropagationButton)
.waitForLastSnackbar();
expect(result).toEqual('Equivalent tax spreaded');
});
it('should receive an error if the fiscal id contains A or B at the beginning', async() => {
const result = await nightmare
.waitToClick(selectors.clientFiscalData.viesCheckbox)
@ -108,14 +116,6 @@ describe('Client Edit fiscalData path', () => {
expect(result).toEqual('Data saved!');
});
it('should propagate the Equalization tax', async() => {
const result = await nightmare
.waitToClick(selectors.clientFiscalData.acceptPropagationButton)
.waitForLastSnackbar();
expect(result).toEqual('Equivalent tax spreaded');
});
// confirm all addresses have now EQtax checked step 1
it(`should click on the addresses button to access to the client's addresses`, async() => {
const url = await nightmare

View File

@ -44,6 +44,7 @@ describe('Client Edit pay method path', () => {
const newcode = await nightmare
.waitToClick(selectors.clientPayMethod.newBankEntityButton)
.write(selectors.clientPayMethod.newBankEntityName, 'Gotham City Bank')
.write(selectors.clientPayMethod.newBankEntityCode, 9999)
.write(selectors.clientPayMethod.newBankEntityBIC, 'GTHMCT')
.waitToClick(selectors.clientPayMethod.acceptBankEntityButton)
.waitToGetProperty(`${selectors.clientPayMethod.swiftBicAutocomplete} input`, 'value');

View File

@ -4,6 +4,8 @@ import createNightmare from '../../helpers/nightmare';
describe('Client log path', () => {
const nightmare = createNightmare();
let date;
beforeAll(() => {
nightmare
.loginAndModule('employee', 'client')
@ -17,6 +19,7 @@ describe('Client log path', () => {
.write(selectors.clientBasicData.nameInput, 'this is a test')
.waitToClick(selectors.clientBasicData.saveButton)
.waitForLastSnackbar();
date = new Date();
expect(result).toEqual('Data saved!');
});
@ -38,9 +41,33 @@ describe('Client log path', () => {
});
it('should check the current value of the last logged change', async() => {
let lastModificationDate = await nightmare
.waitToGetProperty(selectors.clientLog.lastModificationDate, 'innerText');
let lastModificationPreviousValue = await nightmare
.waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText');
let lastModificationCurrentValue = await nightmare
.waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');
expect(lastModificationCurrentValue).toContain('this is a test');
let month = date.getMonth() + 1;
let day = date.getDate();
let year = date.getFullYear();
let hours = date.getHours();
let minutes = date.getMinutes();
if (month.toString().length < 2) month = '0' + month;
if (day.toString().length < 2) day = `0${day}`;
if (hours.toString().length < 2) hours = '0' + hours;
if (minutes.toString().length < 2) minutes = `0${minutes}`;
let today = [day, month, year].join('/');
let time = [hours, minutes].join(':');
let now = [today, time].join(' ');
expect(lastModificationDate).toContain(now);
expect(lastModificationPreviousValue).toEqual('name: DavidCharlesHaller');
expect(lastModificationCurrentValue).toEqual('name: this is a test');
});
});

View File

@ -1,15 +1,14 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
// #860 E2E client/client/src/web-payment/index.js missing fixtures for another client
xdescribe('Client web Payment', () => {
describe('Client web Payment', () => {
const nightmare = createNightmare();
describe('as employee', () => {
beforeAll(() => {
nightmare
.loginAndModule('employee', 'client')
.accessToSearchResult('Bruce Wayne')
.accessToSearchResult('Tony Stark')
.accessToSection('client.card.webPayment');
});
@ -25,13 +24,14 @@ xdescribe('Client web Payment', () => {
beforeAll(() => {
nightmare
.loginAndModule('administrative', 'client')
.accessToSearchResult('Bruce Wayne')
.accessToSearchResult('Tony Stark')
.accessToSection('client.card.webPayment');
});
it('should be able to confirm payments', async() => {
let exists = await nightmare
.waitToClick(selectors.webPayment.confirmFirstPaymentButton)
.wait(selectors.webPayment.firstPaymentConfirmed)
.exists(selectors.webPayment.firstPaymentConfirmed);
expect(exists).toBeTruthy();

View File

@ -7,7 +7,7 @@ describe('Item Create botanical path', () => {
beforeAll(() => {
nightmare
.loginAndModule('buyer', 'item')
.accessToSearchResult('Object5 Weapon 50')
.accessToSearchResult('Object5 Weapon 50 hasVisible:false')
.accessToSection('item.card.botanical');
});

View File

@ -95,7 +95,7 @@ describe('Item Create/Clone path', () => {
it(`should search for the item Infinity Gauntlet`, async() => {
const result = await nightmare
.write(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet')
.write(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet hasVisible:false')
.waitToClick(selectors.itemsIndex.searchButton)
.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
.countElement(selectors.itemsIndex.searchResult);
@ -117,7 +117,7 @@ describe('Item Create/Clone path', () => {
it('should search for the item Infinity Gauntlet and find two', async() => {
const result = await nightmare
.waitToClick(selectors.itemTags.goToItemIndexButton)
.write(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet')
.write(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet hasVisible:false')
.waitToClick(selectors.itemsIndex.searchButton)
.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2)
.countElement(selectors.itemsIndex.searchResult);

View File

@ -1,7 +1,8 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Item regularize path', () => {
// #1186 repearar e2e ticket.sale, item.regularize.
xdescribe('Item regularize path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
@ -176,7 +177,7 @@ describe('Item regularize path', () => {
it('should search for the ticket with id 23 once again', async() => {
const result = await nightmare
.write(selectors.ticketsIndex.searchTicketInput, 'id:23')
.write(selectors.ticketsIndex.searchTicketInput, 'id:24')
.waitToClick(selectors.ticketsIndex.searchButton)
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
.countElement(selectors.ticketsIndex.searchResult);
@ -186,7 +187,7 @@ describe('Item regularize path', () => {
it(`should now click on the search result to access to the ticket summary`, async() => {
const url = await nightmare
.waitForTextInElement(selectors.ticketsIndex.searchResult, '23')
.waitForTextInElement(selectors.ticketsIndex.searchResult, '24')
.waitToClick(selectors.ticketsIndex.searchResult)
.waitForURL('/summary')
.parsedUrl();

View File

@ -0,0 +1,88 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Item index path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('salesPerson', 'item')
.waitToClick(selectors.itemsIndex.searchIcon);
});
it('should click on the fields to show button to open the list of columns to show', async() => {
const visible = await nightmare
.waitToClick(selectors.itemsIndex.fieldsToShowButton)
.isVisible(selectors.itemsIndex.fieldsToShowForm);
expect(visible).toBeTruthy();
});
it('should unmark all checkboxes except the first and the last ones', async() => {
const result = await nightmare
.waitToClick(selectors.itemsIndex.idCheckbox)
.waitToClick(selectors.itemsIndex.stemsCheckbox)
.waitToClick(selectors.itemsIndex.sizeCheckbox)
.waitToClick(selectors.itemsIndex.nicheCheckbox)
.waitToClick(selectors.itemsIndex.typeCheckbox)
.waitToClick(selectors.itemsIndex.categoryCheckbox)
.waitToClick(selectors.itemsIndex.intrastadCheckbox)
.waitToClick(selectors.itemsIndex.originCheckbox)
.waitToClick(selectors.itemsIndex.buyerCheckbox)
.waitToClick(selectors.itemsIndex.destinyCheckbox)
// .waitToClick(selectors.itemsIndex.taxClassCheckbox)
.waitToClick(selectors.itemsIndex.saveFieldsButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should navigate forth and back to see the images column is still visible', async() => {
const imageVisible = await nightmare
.waitToClick(selectors.itemsIndex.searchResult)
.waitToClick(selectors.itemsIndex.goBackToModuleIndexButton)
.waitToClick(selectors.itemsIndex.searchIcon)
.wait(selectors.itemsIndex.searchResult)
.isVisible(selectors.itemsIndex.firstItemImage);
expect(imageVisible).toBeTruthy();
});
it('should check the ids column is not visible', async() => {
const idVisible = await nightmare
.isVisible(selectors.itemsIndex.firstItemId);
expect(idVisible).toBeFalsy();
});
it('should mark all unchecked boxes to leave the index as it was', async() => {
const result = await nightmare
.waitToClick(selectors.itemsIndex.fieldsToShowButton)
.waitToClick(selectors.itemsIndex.idCheckbox)
.waitToClick(selectors.itemsIndex.stemsCheckbox)
.waitToClick(selectors.itemsIndex.sizeCheckbox)
.waitToClick(selectors.itemsIndex.nicheCheckbox)
.waitToClick(selectors.itemsIndex.typeCheckbox)
.waitToClick(selectors.itemsIndex.categoryCheckbox)
.waitToClick(selectors.itemsIndex.intrastadCheckbox)
.waitToClick(selectors.itemsIndex.originCheckbox)
.waitToClick(selectors.itemsIndex.buyerCheckbox)
.waitToClick(selectors.itemsIndex.destinyCheckbox)
// .waitToClick(selectors.itemsIndex.taxClassCheckbox)
.waitToClick(selectors.itemsIndex.saveFieldsButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should now navigate forth and back to see the ids column is now visible', async() => {
const idVisible = await nightmare
.waitToClick(selectors.itemsIndex.searchResult)
.waitToClick(selectors.itemsIndex.goBackToModuleIndexButton)
.waitToClick(selectors.itemsIndex.searchIcon)
.wait(selectors.itemsIndex.searchResult)
.isVisible(selectors.itemsIndex.firstItemId);
expect(idVisible).toBeTruthy();
});
});

View File

@ -0,0 +1,48 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Item regularize path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('developer', 'item')
.accessToSearchResult(1)
.accessToSection('item.card.data');
});
it('should check the descriptor inactive icon is dark as the item is active', async() => {
let darkIcon = await nightmare
.wait(selectors.itemDescriptor.inactiveIcon)
.waitForClassNotPresent(selectors.itemDescriptor.inactiveIcon, 'bright')
.isVisible(selectors.itemDescriptor.inactiveIcon);
expect(darkIcon).toBeTruthy();
});
it('should set the item to inactive', async() => {
let result = await nightmare
.waitToClick(selectors.itemBasicData.isActiveCheckbox)
.waitToClick(selectors.itemBasicData.submitBasicDataButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should reload the section and check the inactive icon is bright', async() => {
let brightIcon = await nightmare
.reloadSection('item.card.data')
.waitForClassPresent(selectors.itemDescriptor.inactiveIcon, 'bright')
.isVisible(selectors.itemDescriptor.inactiveIcon);
expect(brightIcon).toBeTruthy();
});
it('should set the item back to active', async() => {
let result = await nightmare
.waitToClick(selectors.itemBasicData.isActiveCheckbox)
.waitToClick(selectors.itemBasicData.submitBasicDataButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
});

View File

@ -15,21 +15,21 @@ describe('Ticket List sale path', () => {
const value = await nightmare
.waitToGetProperty(selectors.ticketSales.firstSaleColour, 'innerText');
expect(value).toContain('Red');
expect(value).toContain('Yellow');
});
it('should confirm the first ticket sale contains the lenght', async() => {
const value = await nightmare
.waitToGetProperty(selectors.ticketSales.firstSaleText, 'innerText');
expect(value).toContain('3');
expect(value).toContain('5');
});
it('should confirm the first ticket sale contains the price', async() => {
const value = await nightmare
.waitToGetProperty(selectors.ticketSales.firstSalePrice, 'innerText');
expect(value).toContain('1.30');
expect(value).toContain('2.30');
});
it('should confirm the first ticket sale contains the discount', async() => {
@ -43,7 +43,7 @@ describe('Ticket List sale path', () => {
const value = await nightmare
.waitToGetProperty(selectors.ticketSales.firstSaleImport, 'innerText');
expect(value).toContain('19.50');
expect(value).toContain('23');
});
it('should navigate to the catalog by pressing the new item button', async() => {

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
// #1152 refactor ticket.sale, update price no funciona correctamente.
// #1186 repearar e2e ticket.sale, item.regularize.
xdescribe('Ticket Edit sale path', () => {
const nightmare = createNightmare();
@ -138,7 +138,7 @@ xdescribe('Ticket Edit sale path', () => {
it('should try to add a higher quantity value and then receive an error', async() => {
const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleQuantityClearInput)
.waitToFocus(selectors.ticketSales.firstSaleQuantityCell)
.write(selectors.ticketSales.firstSaleQuantity, '9\u000d')
.waitForLastSnackbar();
@ -147,7 +147,7 @@ xdescribe('Ticket Edit sale path', () => {
it('should remove 1 from quantity', async() => {
const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleQuantityClearInput)
.waitToFocus(selectors.ticketSales.firstSaleQuantityCell)
.write(selectors.ticketSales.firstSaleQuantity, '4\u000d')
.waitForLastSnackbar();
@ -180,7 +180,6 @@ xdescribe('Ticket Edit sale path', () => {
it('should update the discount', async() => {
const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleDiscount)
.wait('vn-textfield[label="Discount"] > div[class="container selected"]') // a function selects the text after it's loaded
.write(selectors.ticketSales.firstSaleDiscountInput, '50\u000d')
// .write('body', '\u000d') // simulates enter
.waitForLastSnackbar();
@ -467,7 +466,7 @@ xdescribe('Ticket Edit sale path', () => {
.waitToClick(selectors.ticketSales.moreMenuButton)
.waitToClick(selectors.ticketSales.moreMenuUpdateDiscount)
.write(selectors.ticketSales.moreMenuUpdateDiscountInput, 100)
.write('body', '\u000d') // simulates enter
.write('body', '\u000d')
.waitForTextInElement(selectors.ticketSales.totalImport, '0.00')
.waitToGetProperty(selectors.ticketSales.totalImport, 'innerText');
@ -597,16 +596,16 @@ xdescribe('Ticket Edit sale path', () => {
describe('when state is preparation and loged as salesPerson', () => {
it(`shouldnt be able to edit the sale price`, async() => {
const result = await nightmare
.waitToClick(selectors.ticketSales.firstSalePrice)
.exists(selectors.ticketSales.firstSalePriceInput);
.waitToClick(selectors.ticketSales.firstSaleID)
.exists(selectors.ticketSales.firstSalePrice);
expect(result).toBeFalsy();
});
it(`shouldnt be able to edit the sale discount`, async() => {
const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleDiscount)
.exists(selectors.ticketSales.firstSaleDiscountInput);
.waitToClick(selectors.ticketSales.firstSaleID)
.exists(selectors.ticketSales.firstSaleDiscount);
expect(result).toBeFalsy();
});

View File

@ -7,7 +7,7 @@ describe('Ticket services path', () => {
beforeAll(() => {
nightmare
.loginAndModule('employee', 'ticket')
.accessToSearchResult('id:1')
.accessToSearchResult('1')
.accessToSection('ticket.card.service');
});
@ -24,7 +24,7 @@ describe('Ticket services path', () => {
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
}, 15000);
it('should confirm the service description was edited correctly', async() => {
const result = await nightmare

View File

@ -0,0 +1,35 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('pbx path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('hr', 'worker')
.accessToSearchResult('employee')
.accessToSection('worker.card.pbx');
});
it('should receive an error when the extension exceeds 4 characters', async() => {
const result = await nightmare
.write(selectors.workerPbx.extensionInput, 55555)
.waitToClick(selectors.workerPbx.saveButton)
.waitForLastSnackbar();
expect(result).toEqual('EXTENSION_INVALID_FORMAT');
});
it('should sucessfully save the changes', async() => {
const result = await nightmare
.clearInput(selectors.workerPbx.extensionInput)
.write(selectors.workerPbx.extensionInput, 4444)
.clearInput(selectors.workerPbx.passwordInput)
.write(selectors.workerPbx.passwordInput, 666666)
.waitToClick(selectors.workerPbx.saveButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
});

View File

@ -1,5 +1,6 @@
FROM debian:stretch-slim
EXPOSE 80
ENV TZ Europe/Madrid
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \

View File

@ -15,9 +15,8 @@ export default class Button extends Input {
}
$onInit() {
if (!this.type) {
if (!this.type)
this.type = 'button';
}
}
}
Button.$inject = ['$element'];

View File

@ -10,8 +10,8 @@
</vn-auto>
<vn-one>
<strong>
<span translate>{{$ctrl.defaultDate | date: 'MMMM'}}</span>
<span>{{$ctrl.defaultDate | date: 'yyyy'}}</span>
<span translate>{{$ctrl.defaultDate | dateTime: 'MMMM'}}</span>
<span>{{$ctrl.defaultDate | dateTime: 'yyyy'}}</span>
</strong>
</vn-one>
<vn-auto>
@ -19,7 +19,7 @@
icon="keyboard_arrow_right"
class="pointer"
ng-click="$ctrl.moveNext($ctrl.skip)"
ng-show="$ctrl.displayControls"
ng-show="$ctrl.displayControls">
</vn-icon>
</vn-auto>
</vn-horizontal>

View File

@ -71,8 +71,6 @@ export default class Calendar extends Component {
date.getFullYear(),
date.getMonth(), 1);
this.applyOffset(newDate);
return newDate;
}
@ -87,15 +85,9 @@ export default class Calendar extends Component {
date.getFullYear(),
date.getMonth() + 1, 0);
this.applyOffset(newDate);
return newDate;
}
applyOffset(date) {
date.setTime(date.getTime() - date.getTimezoneOffset() * 60000);
}
repaint() {
const firstWeekday = this.firstDay(this.currentMonth).getDay();
const previousLastDay = this.lastDay(this.previousMonth).getDate();
@ -124,27 +116,14 @@ export default class Calendar extends Component {
}
addDay(date, day, color = '') {
const curDate = new Date();
curDate.setHours(0, 0, 0, 0);
this.applyOffset(curDate);
const newDate = new Date(
date.getFullYear(),
date.getMonth(), day);
this.applyOffset(newDate);
let event = this.events.find(event => {
return event.date >= newDate && event.date <= newDate;
});
/* if (curDate >= newDate && curDate <= newDate)
color = 'orange'; */
/* if (newDate.getMonth() === this.currentMonth.getMonth() && newDate.getDay() == 6)
color = 'light-blue'; */
if (newDate.getMonth() === this.currentMonth.getMonth() && newDate.getDay() == 0)
color = 'red';

View File

@ -28,14 +28,8 @@ class DatePicker extends Component {
onValueUpdate() {
if (this.vp.selectedDates.length) {
let date = this.vp.selectedDates[0];
if (!this.isLocale && !this._iniOptions.enableTime) {
let now = new Date();
let offset = now.getTimezoneOffset() * 60000;
date.setHours(0, 0, 0, 0);
date.setTime(date.getTime() - offset);
}
let offset = date.getTimezoneOffset() * 60000;
date.setTime(date.getTime() - offset);
this._model = date;
} else
this.model = null;
@ -67,8 +61,16 @@ class DatePicker extends Component {
set model(value) {
this._model = value;
this.dateValue = value ? new Date(value) : null;
this.vp.setDate(this.dateValue);
this.dateValue = value;
let date;
if (value && this.iniOptions.enableTime) {
date = new Date(value);
let offset = date.getTimezoneOffset() * 60000;
date.setTime(date.getTime() + offset);
} else
date = value;
this.vp.setDate(date);
this.mdlUpdate();
}
@ -84,6 +86,7 @@ class DatePicker extends Component {
$onDestroy() {
this.vp.destroy();
this.dateValue = undefined;
}
}
DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs'];
@ -91,12 +94,12 @@ DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs'];
ngModule.component('vnDatePicker', {
template: require('./date-picker.html'),
bindings: {
iniOptions: '<?',
model: '=',
label: '@?',
name: '@?',
disabled: '<?',
rule: '<?',
iniOptions: '<?',
isLocale: '<?'
},
controller: DatePicker

View File

@ -3,6 +3,7 @@
<div class="textField">
<div class="leftIcons">
<vn-icon-button
ng-if="$ctrl.displayControls"
icon="remove"
ng-click="$ctrl.remove()"
tabindex="-1"
@ -13,7 +14,7 @@
<input
class="mdl-textfield__input"
type="number"
name="{{$ctrl.name}}"
name="{{::$ctrl.name}}"
ng-model="$ctrl.value"
ng-disabled="$ctrl.disabled"
ng-readonly="$ctrl.readonly"
@ -26,14 +27,15 @@
<div class="selected underline"></div>
<div class="suffix">
<vn-icon-button
ng-if="$ctrl.displayControls"
icon="add"
ng-click="$ctrl.add()"
tabindex="-1"
translate-attr="{title: 'Add'}">
</vn-icon-button>
<i class="material-icons"
ng-if="$ctrl.hasInfo"
vn-tooltip="{{$ctrl.info}}">
ng-if="::$ctrl.hasInfo"
vn-tooltip="{{::$ctrl.info}}">
info_outline
</i>
</div>

View File

@ -3,10 +3,9 @@ import Textfield from '../textfield/textfield';
import './style.scss';
export default class InputNumber extends Textfield {
constructor($element, $scope, $attrs, vnTemplate, $transclude) {
super($element, $scope, $attrs, vnTemplate, $transclude);
this.displayControls = true;
this.input.addEventListener('change', () => {
this.validateValue();
});
@ -56,30 +55,30 @@ export default class InputNumber extends Textfield {
if ((this.validate() !== undefined && !this.validate()) ||
(this.max && this.value > this.max) ||
(this.min && this.value < this.min) ||
(this.step && this.value % this.step != 0)) {
(this.displayControls && (this.step && this.value % this.step != 0)))
this.$element[0].querySelector('.infix').classList.add('invalid', 'validated');
}
if (this.onChange)
this.onChange();
}
add() {
if (this.step && this.value % this.step != 0) {
if (this.step && this.value % this.step != 0)
this.value += (this.step - this.value % this.step);
} else {
else
this.value += this.step;
}
this.validateValue();
}
remove() {
if (this.step && this.value % this.step != 0) {
if (this.step && this.value % this.step != 0)
this.value -= (this.step + this.value % this.step);
} else {
else
this.value -= this.step;
}
this.validateValue();
}
}
@ -95,6 +94,7 @@ ngModule.component('vnInputNumber', {
min: '<?',
max: '<?',
step: '<?',
displayControls: '<?',
rule: '@?',
value: '=model',
validate: '&',

View File

@ -17,7 +17,7 @@
<vn-tbody>
<vn-tr ng-repeat="log in $ctrl.model.data">
<vn-td>
{{::log.creationDate | date:'dd/MM/yyyy HH:mm'}}
{{::log.creationDate | dateTime:'dd/MM/yyyy HH:mm'}}
<div class="changes">
<div>
<span translate class="label">Changed by</span><span class="label">: </span>

View File

@ -0,0 +1,84 @@
import './searchbar.js';
describe('Component vnSearchbar', () => {
let controller;
let $element;
let $state;
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject(($componentController, _$state_) => {
$state = _$state_;
$element = angular.element(`<div></div>`);
controller = $componentController('vnSearchbar', {$element, $state});
controller.panel = 'vn-client-search-panel';
}));
describe('$postLink()', () => {
it(`should not call onStateChange() if filter is defined`, () => {
spyOn(controller, 'onStateChange');
controller.filter = {};
controller.$postLink();
expect(controller.onStateChange).not.toHaveBeenCalledWith();
});
it(`should call onStateChange() if filter is null`, () => {
spyOn(controller, 'onStateChange');
controller.filter = null;
controller.$postLink();
expect(controller.onStateChange).toHaveBeenCalledWith();
});
});
describe('filter() setter', () => {
it(`should call $state.go()`, () => {
controller._filter = {};
spyOn(controller.$state, 'go');
controller.filter = {expected: 'filter'};
expect(controller._filter).toEqual(controller.filter);
expect(controller.$state.go).toHaveBeenCalledWith('.', Object({q: '{"expected":"filter"}'}));
});
});
describe('openPanel()', () => {
it(`should do nothing if the event is prevented`, () => {
let event = {
defaultPrevented: true,
preventDefault: jasmine.createSpy('preventDefault')
};
controller.openPanel(event);
expect(event.preventDefault).not.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'
});
});
});
});

View File

@ -11,7 +11,8 @@ export default class Controller extends Component {
element.tabIndex = 0;
element.addEventListener('focus', () => {
if (this.field) return;
if (this.field || this.disabled) return;
$transclude((tClone, tScope) => {
this.field = tClone;
this.tScope = tScope;
@ -26,7 +27,8 @@ export default class Controller extends Component {
});
element.addEventListener('focusout', event => {
this.destroyTimer();
if (!this.field || this.disabled) return;
// this.destroyTimer();
this.lastEvent = event;
let target = event.relatedTarget;
while (target && target != element)
@ -57,6 +59,9 @@ Controller.$inject = ['$element', '$scope', '$transclude', '$timeout'];
ngModule.component('vnTdEditable', {
template: require('./index.html'),
controller: Controller,
bindings: {
disabled: '<?'
},
transclude: {
text: 'text',
field: '?field'

View File

@ -1,10 +1,24 @@
@import "variables";
vn-td-editable {
cursor: pointer;
text {
cursor: pointer;
display: block
}
outline: none;
position: relative;
&:not([disabled="true"]) {
cursor: initial;
text:hover::after {
font-family: 'salixfont';
float: right;
content: '\e900';
display: block
}
}
&.selected > .text {
visibility: hidden;
}

View File

@ -18,18 +18,15 @@ export default class Textfield extends Input {
if (!this.oldValue)
this.saveOldValue();
});
this.input.addEventListener('keyup', e => {
if (e.key == 'Escape') {
this.value = this.oldValue;
this.cancelled = true;
e.stopPropagation();
}
if (e.key == 'Escape' || e.key == 'Enter')
this.input.blur();
});
if (e.defaultPrevented || e.key != 'Escape')
return;
this.input.addEventListener('blur', () => {
this.value = this.oldValue;
this.cancelled = true;
e.preventDefault();
});
this.input.addEventListener('change', e => {
if (this.onChange && !this.cancelled && (this.oldValue != this.value)) {
this.onChange();
this.saveOldValue();

View File

@ -49,13 +49,26 @@ export function directive($http, $compile, vnApp, $translate) {
}
});
let rule = selectors.join(', ') + '{display: none;}';
if ($scope.css)
document.head.removeChild($scope.css);
$scope.css = document.createElement('style');
document.head.appendChild($scope.css);
$scope.css.appendChild(document.createTextNode(rule));
if ($scope.css || document.querySelector('style[id="uvc"]')) {
let child = document.querySelector('style[id="uvc"]');
child.parentNode.removeChild(child);
}
if (selectors.length) {
let rule = selectors.join(', ') + '{display: none;}';
$scope.css = document.createElement('style');
$scope.css.setAttribute('id', 'uvc');
document.head.appendChild($scope.css);
$scope.css.appendChild(document.createTextNode(rule));
}
$scope.$on('$destroy', () => {
if ($scope.css && document.querySelector('style[id="uvc"]')) {
let child = document.querySelector('style[id="uvc"]');
child.parentNode.removeChild(child);
}
});
}
function saveConfiguration(tableConfiguration) {

View File

@ -9,7 +9,12 @@ dateTime.$inject = ['$filter'];
export default function dateTime($filter) {
return function(input, format) {
let value = typeof input === 'string' ? new Date(input) : input;
let value;
if (input) {
value = new Date(input);
let offset = value.getTimezoneOffset() * 60000;
value.setTime(value.getTime() + offset);
}
return $filter('date')(value, format);
};

View File

@ -23,8 +23,8 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-pets:before {
content: "\e94e";
.icon-unavailable:before {
content: "\e94f";
}
.icon-100:before {
content: "\e940";
@ -134,12 +134,12 @@
.icon-info:before {
content: "\e949";
}
.icon-invoices1:before {
content: "\e94a";
}
.icon-invoices:before {
content: "\e91c";
}
.icon-invoices1:before {
content: "\e94a";
}
.icon-item:before {
content: "\e941";
}
@ -191,6 +191,9 @@
.icon-person:before {
content: "\e929";
}
.icon-pets:before {
content: "\e94e";
}
.icon-photo:before {
content: "\e92a";
}

Binary file not shown.

View File

@ -86,4 +86,5 @@
<glyph unicode="&#xe94c;" glyph-name="revision" d="M358.4 140.8h-102.4v102.4h81.067c0 0 0 4.267 0 4.267 0 34.133 8.533 68.267 21.333 98.133h-102.4v102.4h170.667c51.2 51.2 123.733 85.333 200.533 102.4h-371.2v102.4h512v-93.867c76.8-8.533 149.333-34.133 204.8-72.533v268.8c0 55.467-46.933 102.4-102.4 102.4h-213.333c-21.333 59.733-76.8 102.4-145.067 102.4s-123.733-42.667-145.067-102.4h-213.333c-55.467 0-102.4-46.933-102.4-102.4v-716.8c0-55.467 46.933-102.4 102.4-102.4h546.133c-157.867 8.533-290.133 89.6-341.333 204.8zM512 857.6c29.867 0 51.2-21.333 51.2-51.2s-21.333-51.2-51.2-51.2-51.2 21.333-51.2 51.2c0 29.867 21.333 51.2 51.2 51.2zM721.067 452.267c-136.533 0-251.733-85.333-302.933-204.8 46.933-119.467 162.133-204.8 302.933-204.8s251.733 85.333 302.933 204.8c-46.933 119.467-162.133 204.8-302.933 204.8zM721.067 110.933c-76.8 0-136.533 59.733-136.533 136.533s64 136.533 136.533 136.533 136.533-64 136.533-136.533-59.733-136.533-136.533-136.533zM721.067 328.533c-46.933 0-81.067-38.4-81.067-81.067s38.4-81.067 81.067-81.067c46.933 0 81.067 38.4 81.067 81.067s-34.133 81.067-81.067 81.067z" />
<glyph unicode="&#xe94d;" glyph-name="services" d="M951.467 217.6c0 8.533 0 21.333 0 29.867s0 21.333-4.267 29.867l64 51.2c4.267 4.267 8.533 12.8 4.267 21.333l-64 106.667c-4.267 8.533-12.8 8.533-17.067 8.533l-76.8-29.867c-17.067 12.8-34.133 21.333-51.2 29.867l-12.8 81.067c0 8.533-8.533 12.8-17.067 12.8h-123.733c-8.533 0-12.8-4.267-17.067-12.8l-12.8-81.067c-17.067-8.533-38.4-17.067-51.2-29.867l-76.8 29.867c-8.533 4.267-17.067 0-17.067-8.533l-64-106.667c-4.267-8.533-4.267-17.067 4.267-21.333l64-51.2c0-8.533-4.267-21.333-4.267-29.867s0-21.333 4.267-29.867l-55.467-51.2c-4.267-4.267-8.533-12.8-4.267-21.333l64-106.667c4.267-8.533 12.8-8.533 17.067-8.533l76.8 29.867c17.067-12.8 34.133-21.333 51.2-29.867l12.8-81.067c0-8.533 8.533-12.8 17.067-12.8h123.733c8.533 0 12.8 4.267 17.067 12.8l12.8 81.067c17.067 8.533 38.4 17.067 51.2 29.867l76.8-29.867c8.533-4.267 17.067 0 17.067 8.533l64 106.667c4.267 8.533 4.267 17.067-4.267 21.333 0 0-68.267 51.2-68.267 51.2zM721.067 132.267c-64 0-115.2 51.2-115.2 115.2s51.2 115.2 115.2 115.2 115.2-51.2 115.2-115.2c0-64-51.2-115.2-115.2-115.2zM345.6 174.933h-89.6v102.4h81.067c4.267 34.133 8.533 68.267 21.333 102.4h-102.4v102.4h162.133c34.133 42.667 72.533 76.8 119.467 102.4h-281.6v102.4h520.533v-59.733c51.2-8.533 102.4-25.6 145.067-51.2v281.6c0 55.467-46.933 102.4-102.4 102.4h-622.933c-55.467 0-102.4-46.933-102.4-102.4v-819.2c0-55.467 46.933-102.4 102.4-102.4h302.933c-81.067 55.467-136.533 140.8-153.6 238.933z" />
<glyph unicode="&#xe94e;" glyph-name="pets" d="M1024 571.733c-4.267 46.933-25.6 81.067-55.467 110.933-34.133 29.867-72.533 42.667-110.933 38.4 0 0-4.267 0-4.267 0 0 8.533 0 17.067-4.267 29.867-8.533 51.2-29.867 98.133-68.267 128-25.6 21.333-51.2 34.133-72.533 38.4-29.867 4.267-59.733 0-76.8-4.267-42.667-8.533-81.067-34.133-110.933-72.533-21.333 25.6-42.667 46.933-68.267 64-64 38.4-140.8 29.867-196.267-21.333-25.6-21.333-42.667-46.933-51.2-81.067-12.8-29.867-17.067-59.733-17.067-93.867-8.533 0-17.067 0-25.6 0-42.667 0-81.067-17.067-110.933-46.933-29.867-34.133-42.667-76.8-46.933-98.133-4.267-12.8-4.267-25.6-4.267-42.667 4.267-55.467 25.6-110.933 59.733-157.867 29.867-38.4 68.267-64 110.933-76.8-4.267-12.8-8.533-21.333-8.533-34.133 0-4.267-4.267-8.533-4.267-17.067-12.8-42.667-25.6-98.133 4.267-162.133 29.867-59.733 89.6-102.4 157.867-106.667 4.267 0 12.8 0 17.067 0 46.933 0 85.333 17.067 119.467 29.867 4.267 0 8.533 4.267 12.8 4.267 17.067 4.267 34.133 12.8 51.2 12.8 8.533 0 17.067-4.267 34.133-12.8s42.667-21.333 68.267-25.6c29.867-4.267 64-4.267 93.867 0 38.4 8.533 68.267 21.333 89.6 38.4 59.733 46.933 68.267 128 51.2 187.733-8.533 25.6-21.333 55.467-34.133 85.333 29.867 4.267 55.467 12.8 76.8 29.867 81.067 51.2 110.933 128 119.467 187.733 4.267 12.8 4.267 51.2 4.267 68.267zM541.867 674.133c4.267 42.667 21.333 81.067 42.667 115.2 34.133 42.667 93.867 68.267 136.533 25.6 0 0 0 0 0 0 21.333-21.333 34.133-51.2 34.133-81.067 4.267-38.4 0-72.533-17.067-106.667-17.067-38.4-38.4-68.267-76.8-89.6-46.933-25.6-102.4-8.533-119.467 42.667-4.267 29.867-4.267 68.267 0 93.867zM277.333 776.533c8.533 17.067 17.067 34.133 34.133 46.933 29.867 29.867 64 34.133 102.4 8.533 51.2-29.867 81.067-85.333 85.333-145.067 4.267-51.2-12.8-115.2-64-145.067-17.067-4.267-34.133-8.533-51.2-4.267-21.333 4.267-38.4 17.067-51.2 29.867-55.467 46.933-76.8 140.8-55.467 209.067zM123.733 413.867c-34.133 46.933-55.467 110.933-34.133 170.667 12.8 25.6 34.133 42.667 64 46.933 25.6 4.267 51.2-8.533 72.533-25.6 8.533-4.267 12.8-12.8 17.067-17.067 17.067-21.333 29.867-46.933 34.133-72.533 8.533-29.867 12.8-59.733 8.533-85.333-4.267-34.133-29.867-64-64-68.267-38.4-4.267-76.8 21.333-98.133 51.2zM755.2 76.8c-29.867-25.6-81.067-29.867-115.2-21.333-42.667 8.533-72.533 38.4-115.2 42.667-29.867 0-55.467-8.533-85.333-17.067-38.4-12.8-76.8-34.133-115.2-29.867-25.6 0-55.467 12.8-72.533 34.133-42.667 42.667-29.867 110.933-8.533 162.133 17.067 55.467 55.467 102.4 98.133 140.8 17.067 17.067 38.4 34.133 64 42.667 25.6 12.8 55.467 17.067 85.333 17.067 34.133 0 68.267 0 98.133-12.8s55.467-29.867 72.533-55.467c21.333-25.6 42.667-51.2 59.733-81.067 17.067-25.6 34.133-55.467 46.933-85.333 17.067-34.133 21.333-76.8 4.267-110.933 0-12.8-8.533-21.333-17.067-25.6zM942.933 516.267c-8.533-55.467-34.133-106.667-81.067-136.533-17.067-12.8-38.4-17.067-64-17.067-42.667 0-72.533 34.133-81.067 72.533-17.067 76.8 59.733 200.533 140.8 204.8 21.333 0 38.4-4.267 51.2-21.333 21.333-17.067 29.867-42.667 34.133-68.267 0 4.267 4.267-8.533 0-34.133z" />
<glyph unicode="&#xe94f;" glyph-name="unavailable" d="M469.333 524.8v366.933h-136.533v-499.2zM290.133 345.6v546.133h-42.667v-588.8zM776.533 832v59.733h-42.667v-102.4zM644.267 699.733v192h-89.6c0 0 0-145.067 0-277.333l89.6 85.333zM866.133 682.667v-42.667c34.133-17.067 64-42.667 89.6-68.267v200.533l-89.6-89.6zM776.533 593.067l-64-64c8.533 0 17.067 4.267 25.6 4.267 85.333 0 149.333-68.267 149.333-149.333 0-85.333-68.267-149.333-149.333-149.333s-149.333 68.267-149.333 149.333c0 8.533 0 17.067 0 25.6l-68.267-68.267c8.533-38.4 21.333-72.533 46.933-102.4l-12.8-12.8h-25.6l-166.4-170.667 51.2-51.2 166.4 170.667v25.6l8.533 12.8c38.4-34.133 89.6-51.2 145.067-51.2 123.733 0 217.6 98.133 217.6 217.6 0 106.667-76.8 192-174.933 213.333zM157.867 213.333v678.4h-89.6v-733.867h29.867zM460.8 273.067l-119.467-115.2h21.333l102.4 102.4c-4.267 4.267-4.267 8.533-4.267 12.8zM964.267 960l59.733-59.733-964.267-964.267-59.733 59.733 964.267 964.267z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Binary file not shown.

View File

@ -17,6 +17,11 @@ describe('Component vnLeftMenu', () => {
];
}));
it(`should set items in the controller for the left menu`, () => {
expect(controller.items.length).toEqual(3);
expect(controller.items[2].state).toEqual('client.card.summary');
});
describe('depth() setter', () => {
it(`should set depth property and call activateItem()`, () => {
spyOn(controller, 'activateItem');

View File

@ -1,9 +1,3 @@
<vn-crud-model
url="/api/Banks"
vn-id="banks"
data="banksData"
order="bank">
</vn-crud-model>
<vn-crud-model
url="/api/Warehouses"
vn-id="warehouses"
@ -33,11 +27,12 @@
label="Local bank"
id="localBank"
field="$ctrl.localBankFk"
data="banksData"
url="/api/Banks"
select-fields="['id','bank']"
show-field="bank"
order="id"
value-field="id">
value-field="id"
search-function="{or: [{id: $search}, {bank: {like: '%'+ $search +'%'}}]}">
<tpl-item>{{id}}: {{bank}}</tpl-item>
</vn-autocomplete>
<vn-autocomplete

View File

@ -31,6 +31,13 @@ class Controller {
}
}
$onInit() {
if (window.localStorage.localBankFk && window.localStorage.localBankFk !== 'null')
window.localStorage.defaultBankFk = window.localStorage.localBankFk;
else
localStorage.removeItem('defaultBankFk');
}
set lang(value) {
this._lang = value;
this.$translate.use(value);
@ -105,7 +112,6 @@ class Controller {
}
show(event) {
this.$scope.banks.refresh();
this.$scope.warehouses.refresh();
this.$scope.companies.refresh();
this.$scope.popover.parent = event.target;
@ -139,11 +145,8 @@ class Controller {
});
}
$onInit() {
if (window.localStorage.localBankFk && window.localStorage.localBankFk !== 'null')
window.localStorage.defaultBankFk = window.localStorage.localBankFk;
else
localStorage.removeItem('defaultBankFk');
searchLocalBank(a, b) {
return angular.equals(a.id, b.id);
}
}

View File

@ -355,7 +355,7 @@ async function docker() {
let d = new Date();
let pad = v => v < 10 ? '0' + v : v;
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./services/db`);
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`);
let dockerArgs = `--name ${containerId} -p 3306:${dbConf.port}`;

View File

@ -8,7 +8,7 @@ describe('Model crud()', () => {
expect(ItemBarcode.crud).toBeDefined();
});
it('should create a new instance', async () => {
it('should create a new instance', async() => {
let data = {code: '500', itemFk: '1'};
let creates = [data];
@ -20,7 +20,7 @@ describe('Model crud()', () => {
expect(instance.code).toEqual('500');
});
it('should update the instance', async () => {
it('should update the instance', async() => {
let updates = [{
where: {id: insertId},
data: {code: '501', itemFk: 1}
@ -32,7 +32,7 @@ describe('Model crud()', () => {
expect(instance.code).toEqual('501');
});
it('should delete the created instance', async () => {
it('should delete the created instance', async() => {
let deletes = [insertId];
await ItemBarcode.crud(deletes);
let instance = await ItemBarcode.findById(insertId);

View File

@ -12,6 +12,10 @@ module.exports = function(Self) {
});
Self.observe('before save', async function(ctx) {
let options = {};
if (ctx.options && ctx.options.transaction)
options.transaction = ctx.options.transaction;
let oldInstance;
let oldInstanceFk;
let newInstance;
@ -22,7 +26,7 @@ module.exports = function(Self) {
oldInstance = await fkToValue(oldInstanceFk, ctx);
if (ctx.where && !ctx.currentInstance) {
let fields = Object.keys(ctx.data);
ctx.oldInstances = await ctx.Model.app.models[ctx.Model.definition.name].find({where: ctx.where, fields: fields});
ctx.oldInstances = await ctx.Model.app.models[ctx.Model.definition.name].find({where: ctx.where, fields: fields}, options);
}
}
if (ctx.isNewInstance)
@ -33,10 +37,14 @@ module.exports = function(Self) {
});
Self.observe('before delete', async function(ctx) {
let options = {};
if (ctx.options && ctx.options.transaction)
options.transaction = ctx.options.transaction;
if (ctx.where) {
let affectedModel = ctx.Model.definition.name;
let definition = ctx.Model.definition;
let deletedInstances = await ctx.Model.app.models[affectedModel].find({where: ctx.where});
let deletedInstances = await ctx.Model.app.models[affectedModel].find({where: ctx.where}, options);
let relation = definition.settings.log.relation;
if (relation) {
@ -61,6 +69,10 @@ module.exports = function(Self) {
});
async function logDeletedInstances(ctx, loopBackContext) {
let options = {};
if (ctx.options && ctx.options.transaction)
options.transaction = ctx.options.transaction;
ctx.hookState.oldInstance.forEach(async instance => {
let userFk;
if (loopBackContext)
@ -80,16 +92,16 @@ module.exports = function(Self) {
newInstance: {}
};
let transaction = {};
if (ctx.options && ctx.options.transaction)
transaction = ctx.options.transaction;
let logModel = definition.settings.log.model;
await ctx.Model.app.models[logModel].create(logRecord, transaction);
await ctx.Model.app.models[logModel].create(logRecord, options);
});
}
async function fkToValue(instance, ctx) {
let options = {};
if (ctx.options && ctx.options.transaction)
options.transaction = ctx.options.transaction;
let cleanInstance = JSON.parse(JSON.stringify(instance));
let result = {};
for (let key in cleanInstance) {
@ -98,8 +110,11 @@ module.exports = function(Self) {
for (let key1 in ctx.Model.relations) {
let val1 = ctx.Model.relations[key1];
if (val1.keyFrom == key && key != 'id') {
let recordSet = await val1.modelTo.findById(val);
val = recordSet.name; // FIXME preparar todos los modelos con campo name
let recordSet = await ctx.Model.app.models[val1.modelTo.modelName].findById(val, options);
let definition = val1.modelTo.definition;
let changedModelValue = definition.settings.log && definition.settings.log.changedModelValue;
val = (changedModelValue && recordSet && recordSet[changedModelValue]) || (recordSet && recordSet.id) || val; // FIXME preparar todos los modelos con campo name
break;
}
}
@ -109,6 +124,10 @@ module.exports = function(Self) {
}
async function logInModel(ctx, loopBackContext) {
let options = {};
if (ctx.options && ctx.options.transaction)
options.transaction = ctx.options.transaction;
let definition = ctx.Model.definition;
let primaryKey;
for (let property in definition.properties) {
@ -143,10 +162,11 @@ module.exports = function(Self) {
// Sets the changedModelValue to save and the instances changed in case its an updateAll
let changedModelValue = definition.settings.log.changedModelValue;
let where;
if (changedModelValue && (!ctx.instance || !ctx.instance[changedModelValue])) {
var where = [];
changedModelId = [];
let changedInstances = await ctx.Model.app.models[definition.name].find({where: ctx.where, fields: ['id', changedModelValue]});
where = [];
let changedInstances = await ctx.Model.app.models[definition.name].find({where: ctx.where, fields: ['id', changedModelValue]}, options);
changedInstances.forEach(element => {
where.push(element[changedModelValue]);
changedModelId.push(element.id);
@ -185,11 +205,7 @@ module.exports = function(Self) {
let logModel = definition.settings.log.model;
let transaction = {};
if (ctx.options && ctx.options.transaction)
transaction = ctx.options.transaction;
await ctx.Model.app.models[logModel].create(logsToSave, transaction);
await ctx.Model.app.models[logModel].create(logsToSave, options);
}
// this function retuns all the instances changed in case this is an updateAll

View File

@ -18,7 +18,6 @@
"Package cannot be blank": "Package cannot be blank",
"The new quantity should be smaller than the old one": "The new quantity should be smaller than the old one",
"The sales of this ticket can't be modified": "The sales of this ticket can't be modified",
"Cannot check VIES and Equalization Tax": "Cannot check VIES and Equalization Tax",
"Cannot check Equalization Tax in this NIF/CIF": "Cannot check Equalization Tax in this NIF/CIF",
"You can't create an order for a frozen client": "You can't create an order for a frozen client",
"This address doesn't exist": "This address doesn't exist",
@ -37,5 +36,7 @@
"Barcode must be unique": "Barcode must be unique",
"You don't have enough privileges to do that": "You don't have enough privileges to do that",
"You can't create a ticket for a frozen client": "You can't create a ticket for a frozen client",
"can't be blank": "can't be blank"
"can't be blank": "can't be blank",
"Street cannot be empty": "Street cannot be empty",
"City cannot be empty": "City cannot be empty"
}

View File

@ -59,7 +59,6 @@
"You can't create an order for a client that doesn't has tax data verified": "You can't create an order for a client that doesn't has tax data verified",
"You must delete the claim id %d first": "Antes debes borrar la reclamacion %d",
"You don't have enough privileges": "No tienes suficientes permisos",
"Cannot check VIES and Equalization Tax": "No puedes marcar VIES y RE al mismo",
"Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",
"You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos basicos de una orden con artículos",
"INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no esta permitido el uso de la letra ñ",
@ -68,5 +67,10 @@
"Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
"ORDER_EMPTY": "Cesta vacía",
"You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
"You can't create a ticket for a client that has a debt": "No puedes crear un ticket para un client con deuda"
"You can't create a ticket for a client that has a debt": "No puedes crear un ticket para un client con deuda",
"NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT",
"Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido",
"Street cannot be empty": "Dirección no puede estar en blanco",
"City cannot be empty": "Cuidad no puede estar en blanco",
"Code cannot be blank": "Código no puede estar en blanco"
}

View File

@ -1,4 +1,3 @@
const mysql = require('mysql');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const MySQL = require('loopback-connector-mysql').MySQL;
@ -23,6 +22,19 @@ class VnMySQL extends MySQL {
return v < 10 ? '0' + v : v;
}
}
fromColumnValue(prop, val) {
if (val == null || !prop || prop.type !== Date)
return MySQL.prototype.fromColumnValue.call(this, prop, val);
let date = new Date(val);
return date;
}
isIsoDate(dateString) {
let isoRegexp = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/g;
return isoRegexp.test(dateString);
}
/**
* Promisified version of execute().
@ -230,11 +242,12 @@ exports.initialize = function initialize(dataSource, callback) {
dataSource.EnumFactory = EnumFactory;
if (callback)
if (callback) {
if (dataSource.settings.lazyConnect) {
process.nextTick(function() {
callback();
});
} else
dataSource.connector.connect(callback);
}
};

View File

@ -1,10 +1,10 @@
{
"db": {
"connector": "memory"
"connector": "memory",
"timezone": "local"
},
"vn": {
"connector": "vn-mysql",
"timezone": "CET",
"database": "vn",
"debug": false,
"host": "localhost",

View File

@ -37,7 +37,8 @@
min="0"
step="1"
label="Traveling days"
field="$ctrl.zone.travelingDays">
field="$ctrl.zone.travelingDays"
display-controls="false">
</vn-input-number>
<vn-input-time
vn-two
@ -50,13 +51,15 @@
label="Price"
field="$ctrl.zone.price"
min="0.00"
step="0.50">
step="0.10"
display-controls="false">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
field="$ctrl.zone.bonus"
min="0.00"
step="0.50">
step="0.10"
display-controls="false">
</vn-input-number>
</vn-horizontal>
</vn-card>

View File

@ -17,7 +17,9 @@ class Controller {
this.ndMonth = this.$scope.ndMonth;
}
get zone() {
// Disabled until implementation
// of holidays by node
/* get zone() {
return this._zone;
}
@ -41,7 +43,7 @@ class Controller {
this.events = this.events.concat(events);
});
}
} */
get data() {
return this._data;
@ -54,8 +56,11 @@ class Controller {
const events = [];
value.forEach(event => {
let date = new Date(event.delivered);
date.setHours(0, 0, 0, 0);
events.push({
date: event.delivered,
date: date,
color: 'green-circle',
title: 'Has delivery',
isRemovable: true
@ -114,10 +119,7 @@ class Controller {
if (event && !event.isRemovable)
return false;
// FIXME - Date offset
let date = new Date(day.date);
date.setHours(0, 0, 0, 0);
dates.push(date);
dates.push(day.date);
this.stMonth.removeEvent(day.date);
this.stMonth.repaint();

View File

@ -39,7 +39,8 @@
value="$ctrl.zone.travelingDays"
step="1"
label="Traveling days"
field="$ctrl.zone.travelingDays">
field="$ctrl.zone.travelingDays"
display-controls="false">
</vn-input-number>
<vn-input-time
vn-two
@ -52,13 +53,15 @@
label="Price"
field="$ctrl.zone.price"
min="0.00"
step="0.50">
step="0.10"
display-controls="false">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
field="$ctrl.zone.bonus"
min="0.00"
step="0.50">
step="0.10"
display-controls="false">
</vn-input-number>
</vn-horizontal>
</vn-card>

View File

@ -31,7 +31,7 @@
value="{{$ctrl.zone.agencyMode.name}}">
</vn-label-value>
<vn-label-value label="Estimated hour (ETD)"
value="{{$ctrl.zone.hour | date: 'HH:mm'}}">
value="{{$ctrl.zone.hour | dateTime: 'HH:mm'}}">
</vn-label-value>
<vn-label-value label="Traveling days"
value="{{$ctrl.zone.travelingDays}}">

View File

@ -36,7 +36,7 @@
<vn-td>{{::zone.name}}</vn-td>
<vn-td>{{::zone.agencyMode.name}}</vn-td>
<vn-td>{{::zone.warehouse.name}}</vn-td>
<vn-td>{{::zone.hour | date: 'HH:mm'}}</vn-td>
<vn-td>{{::zone.hour | dateTime: 'HH:mm'}}</vn-td>
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
<vn-td>
<vn-icon-button

View File

@ -23,12 +23,13 @@ class Controller {
}
onSelection(item, isIncluded) {
item.isIncluded = isIncluded;
const path = '/agency/api/ZoneIncludeds/toggleIsIncluded';
const params = {zoneFk: this.zone.id, item};
this.$http.post(path, params).then(() => {
let node = Object.assign({}, item);
node.isIncluded = isIncluded;
node.childs = []; // Data too large
});
const path = '/agency/api/ZoneIncludeds/toggleIsIncluded';
const params = {zoneFk: this.zone.id, item: node};
this.$http.post(path, params);
}
}

View File

@ -18,7 +18,7 @@
</vn-one>
<vn-one>
<vn-label-value label="Estimated hour (ETD)"
value="{{::$ctrl.summary.hour | date: 'HH:mm'}}">
value="{{::$ctrl.summary.hour | dateTime: 'HH:mm'}}">
</vn-label-value>
<vn-label-value label="Traveling days"
value="{{::$ctrl.summary.travelingDays}}">

View File

@ -6,7 +6,7 @@ xdescribe('claimBeginning', () => {
let refundTicketSales;
let salesInsertedInClaimEnd;
afterAll(async () => {
afterAll(async() => {
let promises = [];
promises.push(app.models.Ticket.destroyById(ticket.id));
@ -16,7 +16,7 @@ xdescribe('claimBeginning', () => {
});
describe('importToNewRefundTicket()', () => {
it('should create a new ticket with negative sales, save an observation, update the state and insert the negative sales into claimEnd', async () => {
it('should create a new ticket with negative sales, save an observation, update the state and insert the negative sales into claimEnd', async() => {
let ctxOfSalesAssistant = {req: {accessToken: {userId: 21}}};
let claimId = 1;
ticket = await app.models.ClaimBeginning.importToNewRefundTicket(ctxOfSalesAssistant, claimId);

View File

@ -3,13 +3,15 @@ const app = require('vn-loopback/server/server');
describe('Claim importTicketSales()', () => {
let claimEnds;
afterAll(async () => {
afterAll(async done => {
claimEnds.forEach(async line => {
await line.destroy();
});
done();
});
it('should import sales to a claim actions from an specific ticket', async () => {
it('should import sales to a claim actions from an specific ticket', async() => {
let ctx = {req: {accessToken: {userId: 5}}};
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
claimFk: 1,

View File

@ -17,7 +17,7 @@ module.exports = Self => {
}
});
Self.regularizeClaim = async (ctx, params) => {
Self.regularizeClaim = async(ctx, params) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const resolvedState = 3;

View File

@ -4,8 +4,10 @@ describe('Claim Create', () => {
let newDate = new Date();
let createdClaimFk;
afterAll(async () => {
afterAll(async done => {
await app.models.Claim.destroyById(createdClaimFk);
done();
});
let newClaim = {
@ -23,7 +25,7 @@ describe('Claim Create', () => {
let params = {claim: newClaim, sales: newSale};
it('should create a new claim', async () => {
it('should create a new claim', async() => {
let claim = await app.models.Claim.createFromSales(params);
expect(claim.ticketFk).toEqual(newClaim.ticketFk);
@ -39,7 +41,7 @@ describe('Claim Create', () => {
createdClaimFk = claim.id;
});
it('should not be able to create a claim if exists that sale', async () => {
it('should not be able to create a claim if exists that sale', async() => {
let error;
await app.models.Claim.createFromSales(params)

View File

@ -9,7 +9,7 @@ xdescribe('regularizeClaim()', () => {
let claimEnds = [];
let trashTicket;
afterAll(async () => {
afterAll(async done => {
let claim = await app.models.Claim.findById(claimFk);
await claim.updateAttributes({claimStateFk: pendentState});
await app.models.Ticket.destroyById(trashTicket.id);
@ -17,9 +17,11 @@ xdescribe('regularizeClaim()', () => {
claimEnds.forEach(async line => {
await line.destroy();
});
done();
});
it('should change claim state to resolved', async () => {
it('should change claim state to resolved', async() => {
let ctx = {req: {accessToken: {userId: 18}}};
let params = {claimFk: claimFk};

View File

@ -14,12 +14,16 @@ describe('Update Claim', () => {
observation: 'observation'
};
beforeAll(async() => {
beforeAll(async done => {
newInstance = await app.models.Claim.create(original);
done();
});
afterAll(async() => {
afterAll(async done => {
await app.models.Claim.destroyById(newInstance.id);
done();
});
it('should throw error if isSaleAssistant is false and try to modify a forbidden field', async() => {

View File

@ -177,7 +177,7 @@
ng-repeat="ticket in lastTickets"
ng-click="$ctrl.importTicketLines(ticket.id)">
<vn-td number>{{::ticket.id}}</vn-td>
<vn-td>{{::ticket.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td>{{::ticket.shipped | dateTime: 'dd/MM/yyyy'}}</vn-td>
<vn-td>{{::ticket.agencyMode.name}}</vn-td>
<vn-td>{{::ticket.warehouse.name}}</vn-td>
</vn-tr>

View File

@ -41,7 +41,7 @@
{{::claim.client.name}}
</span>
</vn-td>
<vn-td center>{{::claim.created | date:'dd/MM/yyyy'}}</vn-td>
<vn-td center>{{::claim.created | dateTime:'dd/MM/yyyy'}}</vn-td>
<vn-td expand>
<span
class="link"

View File

@ -0,0 +1,42 @@
module.exports = function(Self) {
Self.remoteMethod('createDefaultAddress', {
description: 'Creates both client and its web account',
accepts: {
arg: 'data',
type: 'object',
http: {source: 'body'}
},
returns: {
root: true,
type: 'Object'
},
http: {
verb: 'post',
path: '/createDefaultAddress'
}
});
Self.createDefaultAddress = async data => {
const Address = Self.app.models.Address;
const Client = Self.app.models.Client;
const transaction = await Address.beginTransaction({});
try {
let address = data.address;
let newAddress = await Address.create(address, {transaction});
let client = await Client.findById(address.clientFk, {transaction});
if (data.isDefaultAddress) {
await client.updateAttributes({
defaultAddressFk: newAddress.id
}, {transaction});
}
await transaction.commit();
return newAddress;
} catch (e) {
await transaction.rollback();
throw e;
}
};
};

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