Merge branch 'dev' of verdnatura/salix into test
gitea/salix/test This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-12-13 14:26:32 +00:00 committed by Gitea
commit 29f437d716
171 changed files with 10140 additions and 51173 deletions

View File

@ -63,7 +63,7 @@ module.exports = Self => {
}
try {
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId);
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId, myOptions);
if (!hasWriteRole)
throw new UserError(`You don't have enough privileges`);
@ -83,7 +83,7 @@ module.exports = Self => {
const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`;
const destinationPath = `${container.client.root}/${pathHash}/${newDms.file}`;
fs.rename(originPath, destinationPath);
await fs.rename(originPath, destinationPath);
addedDms.push(newDms);
}

View File

@ -58,10 +58,11 @@ module.exports = Self => {
*
* @param {Integer} userId The user id
* @param {String} name The role name
* @param {Object} options Options
* @return {Boolean} %true if user has the role, %false otherwise
*/
Self.hasRole = async function(userId, name) {
let roles = await Self.getRoles(userId);
Self.hasRole = async function(userId, name, options) {
let roles = await Self.getRoles(userId, options);
return roles.some(role => role == name);
};
@ -69,15 +70,16 @@ module.exports = Self => {
* Get all user roles.
*
* @param {Integer} userId The user id
* @param {Object} options Options
* @return {Object} User role list
*/
Self.getRoles = async userId => {
Self.getRoles = async(userId, options) => {
let result = await Self.rawSql(
`SELECT r.name
FROM account.user u
JOIN account.roleRole rr ON rr.role = u.role
JOIN account.role r ON r.id = rr.inheritsFrom
WHERE u.id = ?`, [userId]);
WHERE u.id = ?`, [userId], options);
let roles = [];
for (role of result)

View File

@ -5,17 +5,18 @@ module.exports = Self => {
*
* @param {Object} ctx - Request context
* @param {Interger} id - DmsType id
* @param {Object} options - Query options
* @return {Boolean} True for user with read privileges
*/
Self.hasReadRole = async(ctx, id) => {
Self.hasReadRole = async(ctx, id, options) => {
const models = Self.app.models;
const dmsType = await models.DmsType.findById(id, {
include: {
relation: 'readRole'
}
});
}, options);
return await hasRole(ctx, dmsType);
return await hasRole(ctx, dmsType, options);
};
/**
@ -24,17 +25,18 @@ module.exports = Self => {
*
* @param {Object} ctx - Request context
* @param {Interger} id - DmsType id
* @param {Object} options - Query options
* @return {Boolean} True for user with write privileges
*/
Self.hasWriteRole = async(ctx, id) => {
Self.hasWriteRole = async(ctx, id, options) => {
const models = Self.app.models;
const dmsType = await models.DmsType.findById(id, {
include: {
relation: 'writeRole'
}
});
}, options);
return await hasRole(ctx, dmsType);
return await hasRole(ctx, dmsType, options);
};
/**
@ -42,8 +44,9 @@ module.exports = Self => {
* read or write privileges
* @param {Object} ctx - Context
* @param {Object} dmsType - Dms type [read/write]
* @param {Object} options - Query options
*/
async function hasRole(ctx, dmsType) {
async function hasRole(ctx, dmsType, options) {
const models = Self.app.models;
const myUserId = ctx.req.accessToken.userId;
@ -51,8 +54,8 @@ module.exports = Self => {
const writeRole = dmsType.writeRole() && dmsType.writeRole().name;
const requiredRole = readRole || writeRole;
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole);
const isRoot = await models.Account.hasRole(myUserId, 'root');
const hasRequiredRole = await models.Account.hasRole(myUserId, requiredRole, options);
const isRoot = await models.Account.hasRole(myUserId, 'root', options);
if (isRoot || hasRequiredRole)
return true;

View File

@ -1,4 +1,4 @@
FROM mysql:5.6.42
FROM mysql:8.0.18
ENV MYSQL_ROOT_PASSWORD root
ENV TZ Europe/Madrid
@ -7,36 +7,33 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& curl -sL https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \
&& echo "deb http://apt.verdnatura.es/ jessie main" > /etc/apt/sources.list.d/vn.list \
&& echo "deb http://apt.verdnatura.es/ stretch main" > /etc/apt/sources.list.d/vn.list \
&& apt-get update \
&& apt-get install -y --allow-unauthenticated vn-mysql \
&& apt-get install -y vn-mysql libmysqlclient21 \
&& apt-get purge -y --auto-remove curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# XXX: Removes the last script line to avoid daemon to be started
RUN cp /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-init.sh \
&& sed -i '$ d' /usr/local/bin/docker-init.sh
WORKDIR /docker-entrypoint-initdb.d
ARG STAMP=unknown
COPY import-changes.sh config.ini /docker-entrypoint-initdb.d/import/
COPY docker.cnf /etc/mysql/mysql.conf.d/
COPY changes /docker-entrypoint-initdb.d/import/changes
COPY docker-boot.sh /docker-entrypoint-initdb.d/
COPY dump /docker-entrypoint-initdb.d/dump
COPY docker/docker.cnf /etc/mysql/conf.d/
COPY docker/docker-init.sh docker/docker-start.sh /usr/local/bin/
RUN mkdir /mysql-data \
&& /usr/local/bin/docker-init.sh mysqld --datadir /mysql-data \
&& chown -R mysql:mysql /mysql-data \
&& chown -R mysql:mysql /mysql-data
WORKDIR /docker-entrypoint-initdb.d
COPY dump dump
COPY docker/docker-boot.sh /docker-entrypoint-initdb.d/
COPY changes import/changes
COPY import-changes.sh config.ini import/
ARG STAMP=unknown
RUN gosu mysql docker-init.sh mysqld \
&& rm -rf /docker-entrypoint-initdb.d/*
COPY docker-start.sh /usr/local/bin/
USER mysql
ENTRYPOINT ["docker-start.sh"]
USER mysql
CMD ["mysqld", "--datadir", "/mysql-data"]
CMD ["mysqld"]
#HEALTHCHECK --interval=5s --timeout=10s --retries=200 \
# CMD mysqladmin ping -h 127.0.0.1 -u root || exit 1

View File

@ -6,8 +6,8 @@ USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getWarehouse`(vAddress INT, vLanded DATE, vWarehouse INT)
BEGIN
/**
* Devuelve el listado de agencias disponibles para la fecha,
* dirección y warehouse pasadas
* Devuelve el listado de agencias disponibles para la fecha,
* dirección y almacén pasados.
*
* @param vAddress
* @param vWarehouse warehouse
@ -30,7 +30,8 @@ BEGIN
JOIN agencyMode am ON am.id = z.agencyModeFk
JOIN zoneWarehouse zw ON zw.zoneFk = zo.zoneFk
WHERE zw.warehouseFk
GROUP BY z.agencyModeFk;
GROUP BY z.agencyModeFk
ORDER BY agencyMode;
DROP TEMPORARY TABLE
tmp.zone,

View File

@ -1,83 +1,2 @@
ALTER TABLE `vn2008`.`department`
ADD COLUMN `parentFk` INT UNSIGNED NULL AFTER `sons`,
ADD COLUMN `path` VARCHAR(255) NULL AFTER `parentFk`,
CHANGE COLUMN `sons` `sons` DECIMAL(10,0) NOT NULL DEFAULT '0' ;
USE `vn`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `department` AS
SELECT
`b`.`department_id` AS `id`,
`b`.`name` AS `name`,
`b`.`production` AS `isProduction`,
`b`.`parentFk` AS `parentFk`,
`b`.`path` AS `path`,
`b`.`lft` AS `lft`,
`b`.`rgt` AS `rgt`,
`b`.`isSelected` AS `isSelected`,
`b`.`depth` AS `depth`,
`b`.`sons` AS `sons`
FROM
`vn2008`.`department` `b`;
DROP TRIGGER IF EXISTS `vn2008`.`department_AFTER_DELETE`;
DELIMITER $$
USE `vn2008`$$
CREATE DEFINER = CURRENT_USER TRIGGER `vn2008`.`department_AFTER_DELETE`
AFTER DELETE ON `department` FOR EACH ROW
BEGIN
UPDATE vn.department_recalc SET isChanged = TRUE;
END$$
DELIMITER ;
DROP TRIGGER IF EXISTS `vn2008`.`department_BEFORE_INSERT`;
DELIMITER $$
USE `vn2008`$$
CREATE DEFINER = CURRENT_USER TRIGGER `vn2008`.`department_BEFORE_INSERT`
BEFORE INSERT ON `department` FOR EACH ROW
BEGIN
UPDATE vn.department_recalc SET isChanged = TRUE;
END$$
DELIMITER ;
DROP TRIGGER IF EXISTS `vn2008`.`department_AFTER_UPDATE`;
DELIMITER $$
USE `vn2008`$$
CREATE DEFINER = CURRENT_USER TRIGGER `vn2008`.`department_AFTER_UPDATE`
AFTER UPDATE ON `department` FOR EACH ROW
BEGIN
IF !(OLD.parentFk <=> NEW.parentFk) THEN
UPDATE vn.department_recalc SET isChanged = TRUE;
END IF;
END$$
DELIMITER ;
CREATE TABLE `vn`.`department_recalc` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`isChanged` TINYINT(4) NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO `vn`.`department_recalc` (`id`, `isChanged`) VALUES ('1', '0');
ALTER TABLE `vn2008`.`department`
CHANGE COLUMN `lft` `lft` INT(11) NULL ,
CHANGE COLUMN `rgt` `rgt` INT(11) NULL ;
ALTER TABLE `vn2008`.`department`
DROP INDEX `rgt_UNIQUE` ,
DROP INDEX `lft_UNIQUE` ;
;
ALTER TABLE `vn2008`.`department`
ADD INDEX `lft_rgt_depth_idx` (`lft` ASC, `rgt` ASC, `depth` ASC);
;
UPDATE vn.department SET lft = NULL, rgt = NULL;

View File

@ -1,5 +1,5 @@
CREATE TABLE `vn`.`travelLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`originFk` int(10) unsigned NOT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL,
@ -13,6 +13,6 @@ CREATE TABLE `vn`.`travelLog` (
PRIMARY KEY (`id`),
KEY `originFk` (`originFk`),
KEY `userFk` (`userFk`),
CONSTRAINT `travelLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `vn`.`travel` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `travelLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

View File

@ -33,7 +33,6 @@ BEGIN
DECLARE vAgencyModeId INT;
DECLARE TICKET_FREE INT DEFAULT 2;
DECLARE SYSTEM_WORKER INT DEFAULT 20;
DECLARE cDates CURSOR FOR
SELECT zgs.shipped, r.warehouse_id
@ -44,9 +43,9 @@ BEGIN
GROUP BY r.warehouse_id;
DECLARE cRows CURSOR FOR
SELECT r.id, r.item_id, a.Article, r.amount, r.price, r.rate
SELECT r.id, r.item_id, i.name, r.amount, r.price, r.rate
FROM order_row r
JOIN vn2008.Articles a ON a.Id_Article = r.item_id
JOIN vn.item i ON i.id = r.item_id
WHERE r.amount != 0
AND r.warehouse_id = vWarehouse
AND r.order_id = vOrder
@ -64,12 +63,12 @@ BEGIN
-- Carga los datos del pedido
SELECT o.date_send, o.address_id, o.note,
o.confirmed, cs.Id_Cliente, o.company_id, o.agency_id
o.confirmed, a.clientFk, o.company_id, o.agency_id
INTO vDelivery, vAddress, vNotes,
vIsConfirmed, vClientId, vCompanyId, vAgencyModeId
FROM hedera.`order` o
JOIN vn2008.Consignatarios cs ON cs.Id_Consigna = o.address_id
WHERE id = vOrder;
JOIN vn.address a ON a.id = o.address_id
WHERE o.id = vOrder;
-- Comprueba que el pedido no está confirmado
@ -114,19 +113,18 @@ BEGIN
-- Busca un ticket existente que coincida con los parametros
SELECT Id_Ticket INTO vTicket
FROM vn2008.Tickets t
LEFT JOIN vn.ticketState tls on tls.ticket = t.Id_Ticket
SELECT t.id INTO vTicket
FROM vn.ticket t
LEFT JOIN vn.ticketState tls on tls.ticket = t.id
JOIN `order` o
ON o.address_id = t.Id_Consigna
AND vWarehouse = t.warehouse_id
AND o.agency_id = t.Id_Agencia
AND t.landing = o.date_send
AND vShipment = DATE(t.Fecha)
ON o.address_id = t.addressFk
AND vWarehouse = t.warehouseFk
AND o.agency_id = t.agencyModeFk
AND o.date_send = t.landed
AND vShipment = DATE(t.shipped)
WHERE o.id = vOrder
AND t.Factura IS NULL
AND t.invoiceOutFk IS NULL
AND IFNULL(tls.alertLevel,0) = 0
AND t.Id_Cliente <> 1118
LIMIT 1;
-- Crea el ticket en el caso de no existir uno adecuado
@ -148,24 +146,24 @@ BEGIN
ELSE
INSERT INTO vncontrol.inter
SET Id_Ticket = vTicket,
Id_Trabajador = SYSTEM_WORKER,
Id_Trabajador = vUserId,
state_id = TICKET_FREE;
END IF;
INSERT IGNORE INTO vn2008.order_Tickets
SET order_id = vOrder,
Id_Ticket = vTicket;
INSERT IGNORE INTO vn.orderTicket
SET orderFk = vOrder,
ticketFk = vTicket;
-- Añade las notas
IF vNotes IS NOT NULL AND vNotes != ''
THEN
INSERT INTO vn2008.ticket_observation SET
Id_Ticket = vTicket,
observation_type_id = 4 /* salesperson */ ,
`text` = vNotes
INSERT INTO vn.ticketObservation SET
ticketFk = vTicket,
observationTypeFk = 4 /* salesperson */ ,
`description` = vNotes
ON DUPLICATE KEY UPDATE
`text` = CONCAT(VALUES(`text`),'. ', `text`);
`description` = CONCAT(VALUES(`description`),'. ', `description`);
END IF;
-- Añade los movimientos y sus componentes
@ -181,20 +179,20 @@ BEGIN
LEAVE lRows;
END IF;
INSERT INTO vn2008.Movimientos
INSERT INTO vn.sale
SET
Id_Article = vItem,
Id_Ticket = vTicket,
Concepte = vConcept,
Cantidad = vAmount,
Preu = vPrice,
CostFixat = 0,
PrecioFijado = TRUE;
itemFk = vItem,
ticketFk = vTicket,
concept = vConcept,
quantity = vAmount,
price = vPrice,
priceFixed = 0,
isPriceFixed = TRUE;
SET vSale = LAST_INSERT_ID();
INSERT INTO vn2008.Movimientos_componentes
(Id_Movimiento, Id_Componente, Valor)
INSERT INTO vn.saleComponent
(saleFk, componentFk, `value`)
SELECT vSale, cm.component_id, cm.price
FROM order_component cm
JOIN bi.tarifa_componentes tc
@ -215,20 +213,20 @@ BEGIN
CREATE TEMPORARY TABLE tComponents
(INDEX (saleFk))
ENGINE = MEMORY
SELECT SUM(mc.Valor) valueSum, mc.Id_Movimiento saleFk
FROM vn2008.Movimientos_componentes mc
JOIN bi.tarifa_componentes tc USING(Id_Componente)
SELECT SUM(sc.`value`) valueSum, sc.saleFk
FROM vn.saleComponent sc
JOIN bi.tarifa_componentes tc ON tc.Id_Componente = sc.componentFk
JOIN bi.tarifa_componentes_series tcs
ON tcs.tarifa_componentes_series_id = tc.tarifa_componentes_series_id
AND tcs.base
JOIN vn2008.Movimientos m
ON m.Id_Movimiento = mc.Id_Movimiento
WHERE m.Id_Ticket = vTicket
GROUP BY mc.Id_Movimiento;
JOIN vn.sale s
ON s.id = sc.saleFk
WHERE s.ticketFk = vTicket
GROUP BY sc.saleFk;
UPDATE vn2008.Movimientos m
JOIN tComponents mc ON mc.saleFk = m.Id_Movimiento
SET m.CostFixat = valueSum;
UPDATE vn.sale s
JOIN tComponents mc ON mc.saleFk = s.id
SET s.priceFixed = valueSum;
DROP TEMPORARY TABLE tComponents;
END LOOP;

View File

@ -39,16 +39,16 @@ BEGIN
CALL util.throw ('NOT_ZONE_WITH_THIS_PARAMETERS');
END IF;
END IF;
INSERT INTO vn2008.Tickets (
Id_Cliente,
Fecha,
Id_Consigna,
Id_Agencia,
Alias,
warehouse_id,
Id_Ruta,
empresa_id,
landing,
INSERT INTO ticket (
clientFk,
shipped,
addressFk,
agencyModeFk,
nickname,
warehouseFk,
routeFk,
companyFk,
landed,
zoneFk
)
SELECT

View File

@ -36,7 +36,7 @@ BEGIN
CALL vn.zone_getShippedWarehouse(vlanded, vAddressFk, vAgencyModeFk);
SELECT id INTO vZoneFk FROM tmp.zoneGetShipped
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetShipped
WHERE shipped = vShipped AND warehouseFk = vWarehouseFk LIMIT 1;
INSERT INTO vn2008.Tickets (

View File

@ -1,34 +0,0 @@
DROP procedure IF EXISTS `vn`.`buy_notifyPassport`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`buy_notifyPassport`(
IN vBuyFk INT,
IN vItemFk INT,
IN vStickers SMALLINT,
IN vPacking SMALLINT
)
BEGIN
INSERT INTO vn.mail(`subject`,`body`,`sender`)
SELECT 'Solicitar pasaporte',
CONCAT(
'Etiquetas: ', IFNULL(vStickers, 0),
', Packing: ', IFNULL(vPacking, 0),
', Nombre: ', IFNULL(i.`name`, 0),
', buy_edi: ', IFNULL(e.id, 0),
', Nombre botánico: ', IFNULL(g.latin_genus_name, ''), ' ', IFNULL(s.latin_species_name, ''),
', Productor: ',IFNULL(es.company_name, IFNULL(p.`name`, ''))
)
,'ekt@verdnatura.es'
FROM item i
LEFT JOIN itemBotanical ib ON ib.itemFk = i.id
LEFT JOIN edi.genus g ON g.genus_id = ib.genusFk
LEFT JOIN edi.specie s ON IFNULL(s.specie_id, ib.specieFk) = ib.specieFk
LEFT JOIN producer p ON p.id = i.producerFk
LEFT JOIN buy b ON b.id = vBuyFk
LEFT JOIN edi.ekt e ON b.ektFk = e.id
LEFT JOIN edi.supplier es ON es.supplier_id = e.pro
WHERE i.id = vItemFk;
END$$
DELIMITER ;

View File

@ -0,0 +1,51 @@
DROP TRIGGER IF EXISTS `vn`.`client_beforeUpdate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`client_beforeUpdate`
BEFORE UPDATE ON `client`
FOR EACH ROW
BEGIN
DECLARE vText VARCHAR(255) DEFAULT NULL;
-- Comprueba que el formato de los teléfonos es válido
IF !(NEW.phone <=> OLD.phone) THEN
CALL pbx.phone_isValid(NEW.phone);
END IF;
IF !(NEW.mobile <=> OLD.mobile) THEN
CALL pbx.phone_isValid(NEW.mobile);
END IF;
IF !(NEW.fax <=> OLD.fax) THEN
CALL pbx.phone_isValid(NEW.fax);
END IF;
IF NEW.payMethodFk = 4 AND NEW.dueDay = 0 THEN
SET NEW.dueDay = 5;
END IF;
-- Avisar al comercial si ha llegado la documentación sepa/core
IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN
SET vText = 'Sepa de VNL';
END IF;
IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN
SET vText = 'Core de VNL';
END IF;
IF vText IS NOT NULL
THEN
INSERT INTO mail(sender, replyTo, `subject`, body)
SELECT
CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'),
'administracion@verdnatura.es',
CONCAT('Cliente ', NEW.id),
CONCAT('Recibida la documentación: ', vText)
FROM worker w
LEFT JOIN account.user u ON w.userFk = u.id AND u.active
LEFT JOIN account.account ac ON ac.id = u.id
WHERE w.id = NEW.salesPersonFk;
END IF;
END$$
DELIMITER ;

View File

@ -62,7 +62,7 @@ BEGIN
UNION ALL
SELECT g.amount
FROM greuge g
JOIN client c ON c.id = g.clientFk
JOIN `client` c ON c.id = g.clientFk
WHERE g.greugeTypeFk = vManaGreugeType
AND g.shipped > vFromDated
AND g.shipped <= CURDATE()

View File

@ -0,0 +1,97 @@
DROP procedure IF EXISTS `vn`.`clientPackagingOverstock`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`clientPackagingOverstock`(vClientFk INT, vGraceDays INT )
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp.clientPackagingOverstock;
CREATE TEMPORARY TABLE tmp.clientPackagingOverstock
ENGINE = MEMORY
SELECT itemFk,
sum(GotfromClient) - sum(SenttoClient) as devueltos,
sum(InvoicedtoClient) - sum(InvoicedfromClient) as facturados,
LEAST(
sum(GotfromClient) - sum(SenttoClient),
sum(InvoicedtoClient) - sum(InvoicedfromClient)
) as abonables
FROM
(
SELECT t.*,
IF(@month = month, 0, 1) monthEnd,
@month := month
FROM
(
SELECT x.id as ticketFk,
date(x.shipped) as shipped,
x.itemFk,
IFNULL(cast(sum(x.InvoicedtoClient) as DECIMAL(10,0)),0) InvoicedtoClient,
IFNULL(cast(sum(x.InvoicedfromClient) as DECIMAL(10,0)),0) InvoicedfromClient,
IFNULL(cast(sum(x.SenttoClient) as DECIMAL(10,0)),0) SenttoClient,
IFNULL(cast(sum(x.GotfromClient) as DECIMAL(10,0)),0) GotfromClient,
i.name as concept,
x.refFk as invoice,
month(shipped) month,
x.companyFk
FROM
(
SELECT t.id,
t.shipped,
IFNULL(pe.equivalentFk, s.itemFk) itemFk,
IF(s.quantity > 0, s.quantity, NULL) InvoicedtoClient,
IF(s.quantity < 0, -s.quantity, NULL) InvoicedfromClient,
NULL SenttoClient,
NULL GotfromClient,
t.refFk,
@month := 0 month,
t.companyFk
FROM sale s
JOIN ticket t on t.id = s.ticketFk
JOIN packaging p ON p.itemFk = s.itemFk
LEFT JOIN packageEquivalentItem pe ON pe.itemFk = s.itemFk
WHERE t.clientFk = vClientFk
AND t.shipped > '2017-11-30'
AND p.isPackageReturnable
UNION ALL
SELECT NULL,
'2017-11-30',
IFNULL(pe.equivalentFk, tps.itemFk) itemFk,
tps.sent InvoicedtoClient,
tps.returned InvoicedfromClient,
NULL SenttoClient,
NULL GotfromClient,
'Histórico',
NULL,
NULL
FROM ticketPackagingStartingStock tps
LEFT JOIN packageEquivalentItem pe ON pe.itemFk = tps.itemFk
WHERE tps.clientFk = vClientFk
AND tps.isForgetable = FALSE
UNION ALL
SELECT t.id,
t.shipped,
IFNULL(pe.equivalentFk, p.itemFk) itemFk,
NULL,
NULL,
IF(tp.quantity > 0 AND t.shipped <= TIMESTAMPADD(DAY, - vGraceDays, CURDATE()), tp.quantity, NULL) SenttoClient,
IF(tp.quantity < 0, -tp.quantity, NULL) GotfromClient,
NULL AS refFk,
NULL,
t.companyFk
FROM ticketPackaging tp
JOIN ticket t on t.id = tp.ticketFk
JOIN packaging p ON p.id = tp.packagingFk
LEFT JOIN packageEquivalentItem pe ON pe.itemFk = p.itemFk
WHERE t.clientFk = vClientFk
AND t.shipped > '2017-11-21' ) x
JOIN item i ON x.itemFk = i.id
GROUP BY x.id, x.itemFk
) t
ORDER BY itemFk, shipped DESC
) t2
GROUP BY itemFk;
END$$
DELIMITER ;

View File

@ -0,0 +1,132 @@
DROP procedure IF EXISTS `vn`.`clonTravelComplete`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`clonTravelComplete`(IN `vTravelFk` INT, IN `vDateStart` DATE, IN `vDateEnd` DATE, IN `vRef` VARCHAR(255))
BEGIN
DECLARE vTravelNew INT;
DECLARE vEntryNew INT;
DECLARE vDone BIT DEFAULT 0;
DECLARE vAuxEntryFk INT;
DECLARE vRsEntry CURSOR FOR
SELECT e.id
FROM entry e
JOIN travel t
ON t.id = e.travelFk
WHERE e.travelFk = vTravelFk;
DECLARE vRsBuy CURSOR FOR
SELECT b.*
FROM buy b
JOIN entry e
ON b.entryFk = e.id
WHERE e.travelFk = vTravelNew and b.entryFk=entryNew
ORDER BY e.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
INSERT INTO travel (shipped,landed, warehouseInFk, warehouseOutFk, agencyFk, ref, isDelivered, isReceived, m3, kg)
SELECT vDateStart, vDateEnd,warehouseInFk, warehouseOutFk, agencyFk, vRef, isDelivered, isReceived, m3, kg
FROM travel
WHERE id = vTravelFk;
SET vTravelNew = LAST_INSERT_ID();
SET vDone = 0;
OPEN vRsEntry ;
FETCH vRsEntry INTO vAuxEntryFk;
WHILE NOT vDone DO
INSERT INTO entry (supplierFk,
ref,
isInventory,
isConfirmed,
isOrdered,
isRaid,
commission,
created,
evaNotes,
travelFk,
currencyFk,
companyFk,
gestDocFk,
invoiceInFk)
SELECT supplierFk,
ref,
isInventory,
isConfirmed,
isOrdered,
isRaid,
commission,
created,
evaNotes,
vTravelNew,
currencyFk,
companyFk,
gestDocFk,
invoiceInFk
FROM entry
WHERE id = vAuxEntryFk;
SET vEntryNew = LAST_INSERT_ID();
INSERT INTO buy (entryFk,
itemFk,
quantity,
buyingValue,
packageFk,
stickers,
freightValue,
packageValue,
comissionValue,
packing,
`grouping`,
groupingMode,
location,
price1,
price2,
price3,
minPrice,
producer,
printedStickers,
isChecked)
SELECT vEntryNew,
itemFk,
quantity,
buyingValue,
packageFk,
stickers,
freightValue,
packageValue,
comissionValue,
packing,
`grouping`,
groupingMode,
location,
price1,
price2,
price3,
minPrice,
producer,
printedStickers,
isChecked
FROM buy
WHERE entryFk = vAuxEntryFk;
FETCH vRsEntry INTO vAuxEntryFk;
END WHILE;
CLOSE vRsEntry;
COMMIT;
END$$
DELIMITER ;

View File

@ -0,0 +1,16 @@
DELIMITER $$
DROP TRIGGER IF EXISTS `vn`.`creditClassification_BEFORE_UPDATE` $$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`creditClassification_beforeUpdate` BEFORE UPDATE ON `creditClassification` FOR EACH ROW
BEGIN
IF NEW.client <> OLD.client THEN
CALL util.throw('NOT_ALLOWED_CHANGE_CLIENT');
END IF;
IF NEW.dateEnd IS NOT NULL AND OLD.dateEnd IS NULL THEN
UPDATE `client` c
SET creditInsurance = 0 WHERE c.id = NEW.client;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,13 @@
DELIMITER $$
DROP TRIGGER IF EXISTS `vn`.`creditInsurance_AFTER_INSERT` $$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`creditInsurance_afterInsert` AFTER INSERT ON `creditInsurance` FOR EACH ROW
BEGIN
UPDATE `client` c
JOIN vn.creditClassification cc ON cc.client = c.id
SET creditInsurance = NEW.credit WHERE cc.id = NEW.creditClassification;
END$$
DELIMITER ;

View File

@ -0,0 +1,74 @@
DROP procedure IF EXISTS `vn`.`duaInvoiceInBooking`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`duaInvoiceInBooking`(vDuaFk INT)
BEGIN
DECLARE done BOOL DEFAULT FALSE;
DECLARE vInvoiceFk INT;
DECLARE vASIEN BIGINT DEFAULT 0;
DECLARE vCounter INT DEFAULT 0;
DECLARE rs CURSOR FOR
SELECT e.invoiceInFk
FROM entry e
JOIN duaEntry de ON de.entryFk = e.id
JOIN invoiceIn ii ON ii.id = e.invoiceInFk
WHERE de.duaFk = vDuaFk
AND de.customsValue
AND ii.isBooked = FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN rs;
UPDATE invoiceIn ii
JOIN entry e ON e.invoiceInFk = ii.id
JOIN duaEntry de ON de.entryFk = e.id
JOIN dua d ON d.id = de.duaFk
SET ii.isBooked = TRUE,
ii.booked = IFNULL(ii.booked,d.booked),
ii.operated = IFNULL(ii.operated,d.operated),
ii.issued = IFNULL(ii.issued,d.issued),
ii.bookEntried = IFNULL(ii.bookEntried,d.bookEntried),
e.isConfirmed = TRUE
WHERE d.id = vDuaFk;
SELECT IFNULL(ASIEN,0) INTO vASIEN
FROM dua
WHERE id = vDuaFk;
FETCH rs INTO vInvoiceFk;
WHILE NOT done DO
CALL invoiceInBookingMain(vInvoiceFk);
IF vCounter > 0 OR vASIEN > 0 THEN
UPDATE XDiario x
JOIN config c ON c.ASIEN = x.ASIEN
SET x.ASIEN = vASIEN;
ELSE
SELECT ASIEN INTO vASIEN FROM config;
END IF;
SET vCounter = vCounter + 1;
FETCH rs INTO vInvoiceFk;
END WHILE;
CLOSE rs;
UPDATE dua
SET ASIEN = vASIEN
WHERE id = vDuaFk;
END$$
DELIMITER ;

View File

@ -1,119 +0,0 @@
USE `vn`;
DROP procedure IF EXISTS `itemDiary`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `itemDiary`(IN vItemId INT, IN vWarehouse INT)
BEGIN
DECLARE vDateInventory DATETIME;
DECLARE vCurdate DATE DEFAULT CURDATE();
DECLARE vDayEnd DATETIME DEFAULT util.dayEnd(vCurdate);
-- traduccion: date, alertLevel, origin, reference, name, In, Out, Balance
SELECT Fechainventario INTO vDateInventory FROM vn2008.tblContadores;
SET @a = 0;
SELECT DATE(date) AS date,
alertLevel,
stateName,
origin,
reference,
clientFk,
name,
`in`,
`out`,
@a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance,
isPicked,
isTicket
FROM
( SELECT tr.landed as date,
b.quantity as `in`,
NULL as `out`,
IF(tr.isReceived != FALSE,3, IF(tr.isDelivered,1,0)) as alertLevel,
st.name AS stateName,
s.name as name,
e.ref as reference,
e.id as origin,
s.id as clientFk,
TRUE isPicked,
FALSE AS isTicket
FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.supplier s ON s.id = e.supplierFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN tr.isReceived != FALSE THEN 3
WHEN tr.isDelivered THEN 1
ELSE 0
END
JOIN vn.state st ON st.code = al.code
WHERE tr.landed >= vDateInventory
AND vWarehouse = tr.warehouseInFk
AND b.itemFk = vItemId
AND e.isInventory = 0
AND e.isRaid = 0
UNION ALL
SELECT tr.shipped as date,
NULL as `in`,
b.quantity as `out`,
IF(tr.isReceived != FALSE,3, IF(tr.isDelivered,1,0)) as alertLevel,
st.name AS stateName,
s.name as name,
e.ref as reference,
e.id as origin,
s.id as clientFk,
TRUE isPicked,
FALSE AS isTicket
FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.warehouse w ON w.id = tr.warehouseOutFk
JOIN vn.supplier s ON s.id = e.supplierFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN tr.isReceived != FALSE THEN 3
WHEN tr.isDelivered THEN 1
ELSE 0
END
JOIN vn.state st ON st.code = al.code
WHERE tr.shipped >= vDateInventory
AND vWarehouse =tr.warehouseOutFk
AND s.id <> 4
AND b.itemFk = vItemId
AND e.isInventory = 0
AND w.isFeedStock = 0
AND e.isRaid = 0
UNION ALL
SELECT t.shipped as date,
NULL as `in`,
s.quantity as `out`,
al.alertLevel as alertLevel,
st.name AS stateName,
t.nickname as name,
t.refFk as reference,
t.id as origin,
t.clientFk,
stk.id as isPicked, -- TRUE as isPicked
TRUE as isTicket
FROM vn.sale s
JOIN vn.ticket t ON t.id = s.ticketFk
LEFT JOIN vn.ticketState ts ON ts.ticket = t.id
LEFT JOIN vn.state st ON st.code = ts.code
JOIN vn.client c ON c.id = t.clientFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN t.shipped < vCurdate THEN 3
WHEN t.shipped > vDayEnd THEN 0
ELSE IFNULL(ts.alertLevel, 0)
END
LEFT JOIN vn.saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = 14 -- comentar
WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemId
AND vWarehouse =t.warehouseFk
) AS itemDiary
ORDER BY date, isTicket, alertLevel DESC, isPicked DESC, `in` DESC, `out` DESC;
END$$
DELIMITER ;

View File

@ -0,0 +1,41 @@
DROP procedure IF EXISTS `vn`.`rangeDateInfo`;
DELIMITER $$
CREATE PROCEDURE `vn`.`rangeDateInfo` (vStarted DATE, vEnded DATE)
BEGIN
/**
* Crea una tabla temporal con las fechas
* desde una fecha inicial a una final
* @param vStarted fecha inicial
* @param vEnded fecha final
*/
DECLARE vDated DATE DEFAULT vStarted;
DROP TEMPORARY TABLE IF EXISTS tmp.rangeDate;
CREATE TEMPORARY TABLE tmp.rangeDate(
`dated` DATE,
`period` INT,
`month` INT,
`year` INT,
`day` INT,
`week` INT,
`yearMonth` INT
)
ENGINE = MEMORY;
WHILE vDated <= vEnded DO
INSERT INTO tmp.rangeDate
SET `dated` = vDated,
`period` = YEAR(vDated) * 100 + WEEK(vDated, 1),
`month` = MONTH(vDated),
`year` = YEAR(vDated),
`day` = DAY(vDated),
`week` = WEEK(vDated, 1),
`yearMonth` = YEAR(vDated) * 100 + MONTH(vDated);
SET vDated = DATE_ADD(vDated, INTERVAL 1 DAY);
END WHILE;
END$$
DELIMITER ;

View File

@ -1,4 +1,3 @@
USE `vn`;
ALTER TABLE `vn`.`ticketRequest`
DROP FOREIGN KEY `fgnAtender`;
@ -10,44 +9,12 @@ ADD CONSTRAINT `fgnAtender`
REFERENCES `vn`.`worker` (`id`)
ON UPDATE CASCADE;
USE `vn2008`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn2008`.`Ordenes` AS
SELECT
`tr`.`id` AS `Id_ORDEN`,
`tr`.`description` AS `ORDEN`,
`tr`.`requesterFk` AS `requesterFk`,
`tr`.`attenderFk` AS `attenderFk`,
`tr`.`quantity` AS `CANTIDAD`,
`tr`.`itemFk` AS `Id_ARTICLE`,
`tr`.`price` AS `PRECIOMAX`,
`tr`.`isOk` AS `isOk`,
`tr`.`saleFk` AS `Id_Movimiento`,
`tr`.`ticketFk` AS `ticketFk`,
`tr`.`response` AS `COMENTARIO`,
`tr`.`created` AS `odbc_date`,
`tr`.`ordered` AS `datORDEN`,
`tr`.`shipped` AS `datTICKET`,
`tr`.`salesPersonCode` AS `CodVENDEDOR`,
`tr`.`buyerCode` AS `CodCOMPRADOR`,
`tr`.`price__` AS `PREU`,
`tr`.`clientFk` AS `Id_CLIENTE`,
`tr`.`ok__` AS `OK`,
`tr`.`total` AS `TOTAL`,
`tr`.`buyed` AS `datCOMPRA`,
`tr`.`ko__` AS `KO`
FROM
`vn`.`ticketRequest` `tr`;
USE `vn`;
DROP TRIGGER IF EXISTS `vn`.`ticketRequest_beforeInsert`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`ticketRequest_beforeInsert` BEFORE INSERT ON `ticketRequest` FOR EACH ROW
BEGIN
IF NEW.ticketFk IS NULL THEN
@ -68,7 +35,6 @@ DELIMITER ;
DROP TRIGGER IF EXISTS `vn`.`ticketRequest_beforeUpdate`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`ticketRequest_beforeUpdate` BEFORE UPDATE ON `ticketRequest` FOR EACH ROW
BEGIN
IF NEW.saleFk <> OLD.saleFk THEN
@ -85,24 +51,4 @@ BEGIN
END$$
DELIMITER ;
USE `vn`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`ticketRequest__` AS
SELECT
`t`.`Id_ORDEN` AS `id`,
`t`.`ORDEN` AS `description`,
`t`.`requesterFk` AS `requesterFk`,
`t`.`attenderFk` AS `attenderFk`,
`t`.`CANTIDAD` AS `quantity`,
`t`.`Id_ARTICLE` AS `itemFk`,
`t`.`PRECIOMAX` AS `price`,
`t`.`isOk` AS `isOk`,
`t`.`Id_Movimiento` AS `saleFk`,
`t`.`ticketFk` AS `ticketFk`,
`t`.`COMENTARIO` AS `response`,
`t`.`odbc_date` AS `created`
FROM
`vn2008`.`Ordenes` `t`;

View File

@ -0,0 +1,41 @@
DROP procedure IF EXISTS `vn`.`timeControl_calculate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`timeControl_calculate`(vDatedFrom DATETIME, vDatedTo DATETIME)
BEGIN
SET @vIsOdd := TRUE;
SET @vUser := NULL;
SET @vDated := NULL;
DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate;
CREATE TEMPORARY TABLE tmp.timeControlCalculate
SELECT userFk,
dated,
IF( timeWork >= 18000, @timeWork:=timeWork + 1200, @timeWork:=timeWork) timeWorkSeconds,
SEC_TO_TIME(@timeWork ) timeWorkSexagesimal,
@timeWork / 3600 timeWorkDecimal
FROM (SELECT SUM(timeWork) timeWork,
userFk,
dated
FROM (SELECT IF(@vUser = wtc.userFk, @vUser :=@vUser, @vUser := wtc.userFk ),
IF(@vIsOdd, @vIsOdd := FALSE, @vIsOdd := TRUE ),
IF(direction='in', @vIsOdd := TRUE, @vIsOdd := @vIsOdd ),
IF(@vIsOdd, @vLastTimed:=UNIX_TIMESTAMP(timed),@vLastTimed:=@vLastTimed),
IF(@vIsOdd, 0, UNIX_TIMESTAMP(timed)-@vLastTimed) timeWork,
IF(direction='in', @vDated := DATE(wtc.timed), @vDated :=@vDated) dated,
wtc.userFk,
wtc.timed timed,
direction
FROM workerTimeControl wtc
JOIN tmp.`user` w ON w.userFk = wtc.userFk
WHERE wtc.timed BETWEEN vDatedFrom AND vDatedTo
ORDER BY userFk, timed
) sub
GROUP BY userFk, dated
ORDER BY userFk, dated
)sub2;
END$$
DELIMITER ;

View File

@ -0,0 +1,53 @@
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn2008`.`Ordenes` AS
SELECT
`tr`.`id` AS `Id_ORDEN`,
`tr`.`description` AS `ORDEN`,
`tr`.`requesterFk` AS `requesterFk`,
`tr`.`attenderFk` AS `attenderFk`,
`tr`.`quantity` AS `CANTIDAD`,
`tr`.`itemFk` AS `Id_ARTICLE`,
`tr`.`price` AS `PRECIOMAX`,
`tr`.`isOk` AS `isOk`,
`tr`.`saleFk` AS `Id_Movimiento`,
`tr`.`ticketFk` AS `ticketFk`,
`tr`.`response` AS `COMENTARIO`,
`tr`.`created` AS `odbc_date`,
`tr`.`ordered` AS `datORDEN`,
`tr`.`shipped` AS `datTICKET`,
`tr`.`salesPersonCode` AS `CodVENDEDOR`,
`tr`.`buyerCode` AS `CodCOMPRADOR`,
`tr`.`price__` AS `PREU`,
`tr`.`clientFk` AS `Id_CLIENTE`,
`tr`.`ok__` AS `OK`,
`tr`.`total` AS `TOTAL`,
`tr`.`buyed` AS `datCOMPRA`,
`tr`.`ko__` AS `KO`
FROM
`vn`.`ticketRequest` `tr`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`ticketRequest__` AS
SELECT
`t`.`Id_ORDEN` AS `id`,
`t`.`ORDEN` AS `description`,
`t`.`requesterFk` AS `requesterFk`,
`t`.`attenderFk` AS `attenderFk`,
`t`.`CANTIDAD` AS `quantity`,
`t`.`Id_ARTICLE` AS `itemFk`,
`t`.`PRECIOMAX` AS `price`,
`t`.`isOk` AS `isOk`,
`t`.`Id_Movimiento` AS `saleFk`,
`t`.`ticketFk` AS `ticketFk`,
`t`.`COMENTARIO` AS `response`,
`t`.`odbc_date` AS `created`
FROM
`vn2008`.`Ordenes` `t`;

View File

@ -1,59 +0,0 @@
DROP procedure IF EXISTS `vn`.`buy_afterUpsert`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`buy_afterUpsert`(vSelf INT)
BEGIN
/**
* Triggered actions when a buy is updated or inserted.
*
* @param vSelf The buy reference
*/
DECLARE vEntryFk INT;
DECLARE vItemFk INT;
DECLARE vStickers INT;
DECLARE vPacking INT;
DECLARE vWarehouse INT;
DECLARE vWarehouseOut INT;
DECLARE vIsMerchandise BOOL;
DECLARE vIsFeedStock BOOL;
SELECT entryFk, itemFk, stickers, packing
INTO vEntryFk, vItemFk, vStickers, vPacking
FROM buy
WHERE id = vSelf;
SELECT t.warehouseInFk, t.warehouseOutFk
INTO vWarehouse, vWarehouseOut
FROM entry e
JOIN travel t ON t.id = e.travelFk
WHERE e.id = vEntryFk;
SELECT k.merchandise INTO vIsMerchandise
FROM itemCategory k
JOIN itemType it ON it.categoryFk = k.id
JOIN item i ON i.typeFk = it.id
WHERE i.id = vItemFk;
IF vIsMerchandise THEN
REPLACE bi.rotacion SET
Id_Article = vItemFk,
warehouse_id = vWarehouse,
cm3 = buy_getUnitVolume(vSelf);
END IF;
SELECT isFeedStock INTO vIsFeedStock
FROM warehouse WHERE id = vWarehouseOut AND id <> 13;
IF vIsFeedStock AND vn2008.has_notify_passport(vItemFk, vSelf) THEN
CALL vn.buy_notifyPassport(vSelf, vItemFk, vStickers, vPacking);
INSERT IGNORE INTO producer(`name`)
SELECT es.company_name
FROM buy b
JOIN edi.ekt be ON be.id = b.ektFk
JOIN edi.supplier es ON es.supplier_id = be.pro
WHERE b.id = 1;
END IF;
END$$
DELIMITER ;

View File

@ -1,16 +0,0 @@
DROP procedure IF EXISTS `vn2008`.`notify_passport`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn2008`.`notify_passport`(
IN vItemFk INT,
IN vStickers SMALLINT,
IN vPacking SMALLINT,
IN vBuyFk INT
)
BEGIN
-- DPRECATED use vn.buy_notifyPassport
CALL vn.buy_notifyPassport(vBuyFk, vItemFk, vStickers, vPacking);
END$$
DELIMITER ;

View File

@ -0,0 +1,96 @@
DROP procedure IF EXISTS `vn`.`timeBusiness_calculate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`timeBusiness_calculate`(vDatedFrom DATETIME, vDatedTo DATETIME)
BEGIN
/**
* Horas que debe trabajar un empleado según contrato y día.
* @param vDatedFrom workerTimeControl
* @param vDatedTo workerTimeControl
* @table tmp.user(userFk)
* @return tmp.timeBusinessCalculate
*/
DECLARE vHoursFullTime INT DEFAULT 40;
DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate;
DROP TEMPORARY TABLE IF EXISTS tmp.businessFullTime;
CALL rangeDateInfo(vDatedFrom, vDatedTo);
CREATE TEMPORARY TABLE tmp.timeBusinessCalculate
SELECT dated,
businessFk,
userFk,
departmentFk,
hourStart,
hourEnd,
timeWorkSeconds,
SEC_TO_TIME(timeWorkSeconds) timeWorkSexagesimal,
timeWorkSeconds / 3600 timeWorkDecimal,
timeWorkSeconds timeBusinessSeconds,
SEC_TO_TIME(timeWorkSeconds) timeBusinessSexagesimal,
timeWorkSeconds / 3600 timeBusinessDecimal,
type,
permissionrate,
hoursWeek
FROM(SELECT rd.dated,
b.business_id businessFk,
w.userFk,
bl.department_id departmentFk,
IF(cl.hours_week = vHoursFullTime, NULL, GROUP_CONCAT(DISTINCT LEFT(j.start,2) ORDER BY j.start ASC SEPARATOR '-')) hourStart ,
IF(cl.hours_week = vHoursFullTime, NULL, GROUP_CONCAT(DISTINCT LEFT(j.end,2) ORDER BY j.end ASC SEPARATOR '-')) hourEnd,
IF(cl.hours_week = vHoursFullTime, 0, IFNULL(SUM(TIME_TO_SEC(j.end)) - SUM(TIME_TO_SEC(j.start)),0)) timeWorkSeconds,
cs.type,
cs.permissionRate,
cl.hours_week hoursWeek
FROM tmp.rangeDate rd
LEFT JOIN postgresql.business b ON rd.dated BETWEEN b.date_start AND ifnull(b.date_end, vDatedTo )
LEFT JOIN postgresql.profile AS pr ON b.client_id = pr.profile_id
LEFT JOIN postgresql.person AS p ON pr.person_id = p.person_id
LEFT JOIN vn.worker AS w ON p.id_trabajador = w.id
JOIN tmp.`user` u ON u.userFK = w.userFK
JOIN postgresql.business_labour AS bl ON b.business_id = bl.business_id
LEFT JOIN postgresql.business_labour_payroll AS bp ON bl.business_id = bp.business_id
LEFT JOIN postgresql.professional_category AS pc ON bl.professional_category_id = pc.professional_category_id
LEFT JOIN postgresql.workcenter AS wc ON bl.workcenter_id = wc.workcenter_id
LEFT JOIN postgresql.calendar_labour_type AS cl ON bl.calendar_labour_type_id = cl.calendar_labour_type_id
LEFT JOIN postgresql.journey AS j ON j.business_id = b.business_id and j.day_id=WEEKDAY(rd.dated)+1
LEFT JOIN postgresql.calendar_employee ce ON ce.business_id=b.business_id and ce.date = rd.dated
LEFT JOIN postgresql.calendar_state cs ON cs.calendar_state_id = ce.calendar_state_id
WHERE rd.dated BETWEEN vDatedFrom AND vDatedTo
GROUP BY w.userFk,dated
)sub;
UPDATE tmp.timeBusinessCalculate t
SET t.timeWorkSeconds = vHoursFullTime / 5 * 3600,
t.timeWorkSexagesimal = SEC_TO_TIME( vHoursFullTime / 5 * 3600),
t.timeWorkDecimal = vHoursFullTime / 5,
t.timeBusinessSeconds = vHoursFullTime / 5 * 3600,
t.timeBusinessSexagesimal = SEC_TO_TIME( vHoursFullTime / 5 * 3600),
t.timeBusinessDecimal = vHoursFullTime / 5
WHERE DAYOFWEEK(t.dated) IN(2,3,4,5,6) AND hoursWeek = vHoursFullTime ;
UPDATE tmp.timeBusinessCalculate t
SET t.timeWorkSeconds = t.timeWorkSeconds - (t.timeWorkSeconds * permissionrate) ,
t.timeWorkSexagesimal = SEC_TO_TIME(t.timeWorkSeconds - (t.timeWorkSeconds * permissionrate)),
t.timeWorkDecimal = t.timeWorkDecimal - (t.timeWorkDecimal * permissionrate)
WHERE permissionrate <> 0;
UPDATE tmp.timeBusinessCalculate t
JOIN postgresql.calendar_labour cl ON cl.day = t.dated
JOIN postgresql.business_labour bl ON bl.business_id = t.businessFk AND bl.workcenter_id = cl.workcenter_id
SET t.timeWorkSeconds = 0,
t.timeWorkSexagesimal = 0,
t.timeWorkDecimal = 0,
t.permissionrate = 1,
t.type = 'Festivo'
WHERE t.type IS NULL;
DROP TEMPORARY TABLE IF EXISTS tmp.rangeDate;
END$$
DELIMITER ;

View File

@ -0,0 +1,58 @@
DROP TRIGGER IF EXISTS `vn`.`entry_beforeUpdate`;
DELIMITER $$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`entry_beforeUpdate`
BEFORE UPDATE ON `entry`
FOR EACH ROW
BEGIN
DECLARE vIsVirtual BOOL;
DECLARE vPrintedCount INT;
DECLARE vHasDistinctWarehouses BOOL;
IF !(NEW.travelFk <=> OLD.travelFk) THEN
SELECT COUNT(*) > 0 INTO vIsVirtual
FROM entryVirtual WHERE entryFk = NEW.id;
SELECT !(o.warehouseInFk <=> n.warehouseInFk)
OR !(o.warehouseOutFk <=> n.warehouseOutFk)
INTO vHasDistinctWarehouses
FROM travel o, travel n
WHERE o.id = OLD.travelFk
AND n.id = NEW.travelFk;
IF vIsVirtual AND vHasDistinctWarehouses THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'A cloned entry cannot be moved to a travel with different warehouses';
END IF;
IF NEW.travelFk IS NULL THEN
SELECT COUNT(*) INTO vPrintedCount
FROM buy
WHERE entryFk = OLD.id
AND printedStickers > 0;
IF vPrintedCount > 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An entry that contains lines with printed labels cannot be deleted';
END IF;
END IF;
END IF;
IF !(NEW.supplierFk <=> OLD.supplierFk) THEN
SET NEW.currencyFk = entry_getCurrency(NEW.currencyFk, NEW.supplierFk);
END IF;
IF !(NEW.travelFk <=> OLD.travelFk)
OR !(NEW.currencyFk <=> OLD.currencyFk) THEN
SET NEW.commission = entry_getCommission(NEW.travelFk, NEW.currencyFk,NEW.supplierFk);
END IF;
IF !(ABS(NEW.isBooked) <=> ABS(OLD.isBooked)) THEN
INSERT INTO entryLog SET
action = 'update',
description = 'Cambia a Contabilizada',
userFk = myWorker_getId(),
originFk = NEW.id;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,120 @@
DROP procedure IF EXISTS `hedera`.`tpvTransaction_confirm`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`tpvTransaction_confirm`(
vAmount INT
,vOrder INT
,vMerchant INT
,vCurrency INT
,vResponse INT
,vErrorCode VARCHAR(10)
)
BEGIN
/**
* Confirma una transacción previamente iniciada, reescribiendo
* sus datos por los confirmados por el banco (solo si estos difieren).
* Genera el recibo y su correspondiente entrada en caja.
*
* @param vAmount Cantidad confirmada
* @param vOrder Identificador de transacción
* @param vMerchant Identificador de comercio
* @param vCurrency Identificador de moneda
* @param vResponse Identificador de respuesta del banco
* @param vErrorCode Código de error del banco, si lo hubiera
*/
DECLARE vReceipt INT;
DECLARE vStatus VARCHAR(10);
DECLARE vCustomer INT;
DECLARE vBank INT;
DECLARE vCompany INT;
DECLARE vEmployee INT;
DECLARE vIsDuplicated BOOLEAN;
DECLARE vDate DATE;
DECLARE vConcept VARCHAR(25) DEFAULT 'Cobro Web';
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
SELECT COUNT(*) > 0 INTO vIsDuplicated
FROM tpvTransaction
WHERE id = vOrder AND response IS NOT NULL
FOR UPDATE;
IF vIsDuplicated
THEN
CALL util.throw ('TRANSACTION_DUPLICATED');
END IF;
IF vResponse BETWEEN 0 AND 99
THEN
SELECT
t.clientFk
,m.bankFk
,m.companyFk
,c.employeeFk
,DATE(t.created)
INTO
vCustomer
,vBank
,vCompany
,vEmployee
,vDate
FROM tpvMerchant m
JOIN tpvConfig c
LEFT JOIN tpvTransaction t ON t.id = vOrder
WHERE m.id = vMerchant;
INSERT INTO vn.receipt
SET
amountPaid = vAmount / 100
,payed = vDate
,workerFk = vEmployee
,bankFk = vBank
,clientFk = vCustomer
,companyFk = vCompany
,invoiceFk = vConcept
,isConciliate = TRUE;
SET vReceipt = LAST_INSERT_ID();
SET vStatus = 'ok';
-- Código redundante
DO vn.till_new
(
vCustomer
,vBank
,vAmount / 100
,vConcept
,vDate
,'A'
,TRUE
,vCustomer
,vCompany
,vEmployee
);
ELSE
SET vReceipt = NULL;
SET vStatus = 'ko';
END IF;
UPDATE tpvTransaction
SET
merchantFk = vMerchant
,receiptFk = vReceipt
,amount = vAmount
,response = vResponse
,errorCode = vErrorCode
,status = vStatus
WHERE id = vOrder;
COMMIT;
END$$
DELIMITER ;

View File

@ -0,0 +1,86 @@
DROP procedure IF EXISTS `hedera`.`tpvTransaction_undo`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`tpvTransaction_undo`(vSelf INT)
BEGIN
DECLARE vCustomer INT;
DECLARE vAmount DOUBLE;
DECLARE vReceipt INT;
DECLARE vDate DATE;
DECLARE vBank INT;
DECLARE vAccount VARCHAR(12);
DECLARE vSubaccount VARCHAR(12);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
SELECT
t.clientFk
,t.amount / 100
,t.receiptFk
,DATE(t.created)
,m.bankFk
INTO
vCustomer
,vAmount
,vReceipt
,vDate
,vBank
FROM tpvTransaction t
JOIN tpvMerchant m ON m.id = t.merchantFk
JOIN tpvConfig c
WHERE t.id = vSelf
FOR UPDATE;
-- Elimina el recibo
DELETE FROM vn.receipt
WHERE id = vReceipt LIMIT 1;
-- Elimina la entrada de cajas
DELETE FROM vn.till
WHERE bankFk = vBank
AND DATE(dated) = vDate
AND `in` = vAmount
LIMIT 1;
-- Elimina los asientos contables
SELECT accountingAccount INTO vSubaccount
FROM vn.`client` WHERE id = vCustomer;
SELECT account INTO vAccount
FROM vn.bank WHERE id = vBank;
DELETE FROM vn.XDiario
WHERE SUBCTA = vSubaccount
AND CONTRA = vAccount
AND DATE(FECHA) = vDate
AND EUROHABER = vAmount
LIMIT 1;
DELETE FROM vn.XDiario
WHERE CONTRA = vSubaccount
AND SUBCTA = vAccount
AND DATE(FECHA) = vDate
AND EURODEBE = vAmount
LIMIT 1;
-- Actualiza la transaccion
UPDATE tpvTransaction
SET response = NULL, status = 'started'
WHERE id = vSelf;
COMMIT;
END$$
DELIMITER ;

View File

@ -1,3 +0,0 @@
[mysqld]
innodb_log_file_size = 4M
innodb_autoextend_increment = 4

17
db/docker/docker-init.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
. /usr/local/bin/docker-entrypoint.sh
mysql_check_config "$@"
docker_setup_env "$@"
docker_create_db_directories
docker_verify_minimum_env
docker_init_database_dir "$@"
docker_temp_server_start "$@"
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
mysql_expire_root_user
docker_temp_server_stop

10
db/docker/docker.cnf Normal file
View File

@ -0,0 +1,10 @@
[mysqld]
innodb_log_file_size = 4M
innodb_autoextend_increment = 4
innodb_page_size = 8K
innodb_default_row_format = COMPACT
log_bin_trust_function_creators = ON
datadir = /mysql-data
sql_mode = NO_ENGINE_SUBSTITUTION
innodb_temp_data_file_path = /tmp/ibtmp1:12M:autoextend
skip-log-bin

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,13 @@
-- FIXME: cuando se eliminen los procedimientos de la cache, se podra eliminar esta linea
CREATE SCHEMA IF NOT EXISTS `vn2008`;
CREATE SCHEMA IF NOT EXISTS `tmp`;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
ALTER TABLE `vn`.`itemTaxCountry` AUTO_INCREMENT = 1;
ALTER TABLE `vn`.`address` AUTO_INCREMENT = 1;
ALTER TABLE `vn`.`zoneGeo` AUTO_INCREMENT = 1;
ALTER TABLE `vn`.`ticket` AUTO_INCREMENT = 1;
INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`)
VALUES
@ -14,10 +21,9 @@ INSERT INTO `vn`.`bionicConfig` (`generalInflationCoeficient`, `minimumDensityVo
VALUES
(1.30, 167.00, 138000, 71);
INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`,`email`, `lang`)
SELECT id, name, CONCAT(name, 'Nick'),MD5('nightmare'), id, 1, CONCAT(name, '@mydomain.com'), 'es'
FROM `account`.`role`;
FROM `account`.`role` WHERE id <> 20;
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
@ -261,7 +267,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(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),
(124, 'address 24', 'Stark tower Silla', '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),
@ -331,8 +337,8 @@ INSERT INTO `vn`.`clientObservation`(`id`, `clientFk`, `workerFk`, `text`, `crea
(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());
(9, 109, 18, 'HULK SMASH! ...', CURDATE()),
(10, 110, 18, '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`)
VALUES
@ -361,7 +367,7 @@ INSERT INTO `vn`.`creditInsurance`(`id`, `creditClassification`, `credit`, `crea
(2, 2, 6000, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL),
(3, 3, 10000, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL);
INSERT INTO `vn2008`.`empresa_grupo`(`empresa_grupo_id`, `grupo`)
INSERT INTO `vn`.`companyGroup`(`id`, `code`)
VALUES
(1, 'Wayne Industries');
@ -554,14 +560,18 @@ INSERT INTO `vn`.`stowaway`(`id`, `shipFk`, `created`)
VALUES
(12, 13, CURDATE());
INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`)
INSERT INTO `vn`.`deliveryPoint` (`id`, `name`, `ubication`)
VALUES
(1, '3333-BAT', 'WAYNE INDUSTRIES', 'BATMOBILE', 442, 1, 'The ultimate war machine', 50, 1),
(2, '1111-IMK', 'STARK INDUSTRIES', 'MARK-III', 442, 1, 'Iron-Man Heavy Armor MARK-III', 18, 1),
(3, '2222-IMK', 'STARK INDUSTRIES', 'MARK-VI', 442, 1, 'Iron-Man Heavy Armor MARK-VI', 16, 1),
(4, '3333-IMK', 'STARK INDUSTRIES', 'MARK-VII', 442, 1, 'Iron-Man Heavy Armor MARK-VII', 14, 1),
(5, '4444-IMK', 'STARK INDUSTRIES', 'MARK-XLII', 442, 1, 'Iron-Man Heavy Armor MARK-XLII', 13, 1),
(6, '5555-IMK', 'STARK INDUSTRIES', 'MARK-XLV', 442, 1, 'Iron-Man Heavy Armor MARK-XLV', 12, 0);
(1, 'Silla','46460 Av Espioca 100-Silla');
INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`, `deliveryPointFk`)
VALUES
(1, '3333-BAT', 'WAYNE INDUSTRIES', 'BATMOBILE', 442, 1, 'The ultimate war machine', 50, 1, 1),
(2, '1111-IMK', 'STARK INDUSTRIES', 'MARK-III', 442, 1, 'Iron-Man Heavy Armor MARK-III', 18, 1, 1),
(3, '2222-IMK', 'STARK INDUSTRIES', 'MARK-VI', 442, 1, 'Iron-Man Heavy Armor MARK-VI', 16, 1, 1),
(4, '3333-IMK', 'STARK INDUSTRIES', 'MARK-VII', 442, 1, 'Iron-Man Heavy Armor MARK-VII', 14, 1, 1),
(5, '4444-IMK', 'STARK INDUSTRIES', 'MARK-XLII', 442, 1, 'Iron-Man Heavy Armor MARK-XLII', 13, 1, 1),
(6, '5555-IMK', 'STARK INDUSTRIES', 'MARK-XLV', 442, 1, 'Iron-Man Heavy Armor MARK-XLV', 12, 0, 1);
INSERT INTO `vn`.`config`(`id`, `mdbServer`, `fakeEmail`, `defaultersMaxAmount`, `inventoried`)
VALUES
@ -601,16 +611,16 @@ INSERT INTO `vn`.`mandate`(`id`, `clientFk`, `companyFk`, `code`, `created`, `ma
VALUES
(1, 102, 442, '1-1', CURDATE(), 2);
INSERT INTO `vn`.`itemCategory`(`id`, `name`, `display`, `color`, `icon`)
INSERT INTO `vn`.`itemCategory`(`id`, `name`, `display`, `color`, `icon`, `code`)
VALUES
(1, 'Plant', 1, 'B92A26', 'icon-plant'),
(2, 'Flower', 2, 'dcf711', 'icon-flower'),
(3, 'Logistic', 0, 'b9f711', NULL),
(4, 'Handmade', 1, NULL, 'icon-handmade'),
(5, 'Artificial', 1, NULL, 'icon-artificial'),
(6, 'Green', 1, NULL, 'icon-greenery'),
(7, 'Accessories', 1, NULL, 'icon-accessory'),
(8, 'Fruit', 1, NULL, 'icon-fruit');
(1, 'Plant', 1, 'B92A26', 'icon-plant', 'plant'),
(2, 'Flower', 2, 'dcf711', 'icon-flower', 'flower'),
(3, 'Logistic', 0, 'b9f711', NULL, 'logistical'),
(4, 'Handmade', 1, NULL, 'icon-handmade', 'handmade'),
(5, 'Artificial', 1, NULL, 'icon-artificial', 'artificial'),
(6, 'Green', 1, NULL, 'icon-greenery', 'greenery'),
(7, 'Accessories', 1, NULL, 'icon-accessory', 'accessory'),
(8, 'Fruit', 1, NULL, 'icon-fruit', 'fruit');
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk`, `isPackaging`)
VALUES
@ -885,6 +895,11 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
(32, 36, -92.324),
(32, 39, 0.994);
INSERT INTO `vncontrol`.`accion`(`accion_id`, `accion`)
VALUES
(3, 'ACTION ONE'),
(4, 'ACTIOn TWO');
INSERT INTO `vn`.`saleTracking`(`saleFk`, `isChecked`, `created`, `originalQuantity`, `workerFk`, `actionFk`, `id`, `stateFk`)
VALUES
(1, 0, CURDATE(), 5, 55, 3, 1, 14),
@ -1356,6 +1371,7 @@ INSERT INTO `vn`.`clientContact`(`id`, `clientFk`, `name`, `phone`)
La otra manera es poner el calculo con los 2 trabajadores que utilizamos ahora mismo para los tickets
*/
call vn.manaSpellersRequery(19);
call vn.manaSpellersRequery(18);
@ -1464,7 +1480,7 @@ INSERT INTO `vn`.`receipt`(`id`, `invoiceFk`, `amountPaid`, `amountUnpaid`, `pay
(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`)
INSERT INTO `vn`.`workerTeam`(`id`, `team`, `workerFk`)
VALUES
(1, 1, 9),
(2, 1, 18),
@ -1489,13 +1505,13 @@ INSERT INTO `vn`.`ticketServiceType`(`id`, `name`)
(4, 'Cargo FITOSANITARIO'),
(5, 'Documentos');
INSERT INTO `vn`.`ticketService`(`id`, `description`, `quantity`, `price`, `taxClassFk`, `ticketFk`)
INSERT INTO `vn`.`ticketService`(`id`, `description`, `quantity`, `price`, `taxClassFk`, `ticketFk`, `ticketServiceTypeFk`)
VALUES
(1, 'Documentos', 1, 2.00, 1, 1),
(2, 'Porte Agencia', 1, 10.00, 1, 2),
(3, 'Documentos', 1, 5.50, 1, 11),
(4, 'Documentos', 1, 2.00, 1, 9),
(5, 'Documentos', 1, 2.00, 1, 8);
(1, 'Documentos', 1, 2.00, 1, 1, 1),
(2, 'Porte Agencia', 1, 10.00, 1, 2, 1),
(3, 'Documentos', 1, 5.50, 1, 11, 1),
(4, 'Documentos', 1, 2.00, 1, 9, 1),
(5, 'Documentos', 1, 2.00, 1, 8, 1);
INSERT INTO `pbx`.`sip`(`user_id`, `extension`)
VALUES
@ -1570,9 +1586,9 @@ INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`
(107, 1, DATE_ADD(CURDATE(), INTERVAL -12 DAY)),
(107, 2, DATE_ADD(CURDATE(), INTERVAL -20 DAY));
INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `user`, `password`, `title`)
INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`)
VALUES
('1', 'https://websms.xtratelecom.es/api_php/server.wsdl', 'VERDINATURA', '182wbOKu', 'Verdnatura');
('1', 'https://websms.xtratelecom.es/api_php/server.wsdl', 'Verdnatura');
INSERT INTO `vn`.`sharingClient`(`id`, `workerFk`, `started`, `ended`, `clientFk`)
VALUES
@ -1869,7 +1885,8 @@ INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `wa
VALUES
(1, 14, '1.txt', 'text/plain', 5, 1, 442, NULL, FALSE, 'Ticket:11', 'Ticket:11 dms for the ticket', CURDATE()),
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', CURDATE()),
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE());
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', CURDATE()),
(4, 3, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', CURDATE());
INSERT INTO `vn`.`ticketDms`(`ticketFk`, `dmsFk`)
VALUES
@ -1880,6 +1897,10 @@ INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`)
(104, 2),
(104, 3);
INSERT INTO `vn`.`workerDocument`(`id`, `worker`, `document`)
VALUES
(1, 106, 4);
INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`)
VALUES
('aaa', 'android', '9');
@ -1916,7 +1937,6 @@ INSERT INTO `vn`.`userPhone`(`id`, `userFk`, `typeFk`, `phone`)
(22, 17, 'personalPhone', 623111111),
(23, 18, 'personalPhone', 623111111),
(24, 19, 'personalPhone', 623111111),
(25, 20, 'personalPhone', 623111111),
(26, 21, 'personalPhone', 623111111),
(27, 22, 'personalPhone', 623111111),
(28, 30, 'personalPhone', 623111111),

View File

@ -1,4 +1,3 @@
USE `vn2008`;
-- Import compiled functions
CREATE AGGREGATE FUNCTION minacum RETURNS INT SONAME 'minacum.so';

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ INI_FILE="config.production.ini"
dump_tables() {
SCHEMA=$1
echo "USE \`$SCHEMA\`;" >> "$DUMPED_FILE"
mysqldump --defaults-file="$INI_FILE" --no-create-info $@ >> "$DUMPED_FILE"
mysqldump --defaults-file="$INI_FILE" --no-create-info --skip-triggers $@ >> "$DUMPED_FILE"
}
echo "" > "$DUMPED_FILE"
@ -48,22 +48,11 @@ TABLES=(
ticketUpdateAction
state
sample
department
)
dump_tables ${TABLES[@]}
TABLES=(
vn2008
time
accion_dits
businessReasonEnd
container
department
Grupos
iva_group_codigo
tarifa_componentes
tarifa_componentes_series
)
dump_tables ${TABLES[@]}
TABLES=(
bi

View File

@ -14,15 +14,93 @@ SCHEMAS=(
stock
util
vn
vn2008
vncontrol
)
IGNORETABLES=(
--ignore-table=bi.last_Id_Cubo
--ignore-table=bi.v_clientes_jerarquia
--ignore-table=bi.v_ventas_contables
--ignore-table=bs.horasSilla
--ignore-table=bs.productionIndicators
--ignore-table=bs.VentasPorCliente
--ignore-table=bs.v_ventas
--ignore-table=edi.supplyOffer
--ignore-table=postgresql.currentWorkersStats
--ignore-table=vn.accounting__
--ignore-table=vn.agencyModeZone
--ignore-table=vn.agencyProvince
--ignore-table=vn.agencyWarehouse
--ignore-table=vn.awb
--ignore-table=vn.botanicExport__
--ignore-table=vn.clientDefaultCompany
--ignore-table=vn.color
--ignore-table=vn.comparative
--ignore-table=vn.comparativeFilter
--ignore-table=vn.coolerPath
--ignore-table=vn.coolerPathDetail
--ignore-table=vn.department__
--ignore-table=vn.doc
--ignore-table=vn.entity
--ignore-table=vn.especialPrice
--ignore-table=vn.exchangeInsurance
--ignore-table=vn.exchangeInsuranceInPrevious
--ignore-table=vn.exchangeReportSource
--ignore-table=vn.grant
--ignore-table=vn.grantGroup
--ignore-table=vn.invoiceCorrection__
--ignore-table=vn.invoiceIn
--ignore-table=vn.invoiceInAwb
--ignore-table=vn.invoiceInDueDay
--ignore-table=vn.invoiceInEntry
--ignore-table=vn.invoiceInIntrastat
--ignore-table=vn.invoiceInTax
--ignore-table=vn.itemTaxCountrySpain
--ignore-table=vn.mail__
--ignore-table=vn.manaSpellers
--ignore-table=vn.outgoingInvoiceKk
--ignore-table=vn.payment
--ignore-table=vn.paymentExchangeInsurance
--ignore-table=vn.payrollCenter
--ignore-table=vn.plantpassport
--ignore-table=vn.plantpassportAuthority
--ignore-table=vn.preparationException
--ignore-table=vn.priceFixed__
--ignore-table=vn.printer
--ignore-table=vn.printingQueue
--ignore-table=vn.printServerQueue__
--ignore-table=vn.promissoryNote
--ignore-table=vn.rate
--ignore-table=vn.referenceRate__
--ignore-table=vn.routesControl
--ignore-table=vn.salesToPrePrepare
--ignore-table=vn.specialPrice__
--ignore-table=vn.ticketDownBuffer
--ignore-table=vn.ticketeToPreparePrepared
--ignore-table=vn.ticketObservation__
--ignore-table=vn.ticketRequest__
--ignore-table=vn.ticketToPrepare
--ignore-table=vn.till__
--ignore-table=vn.time
--ignore-table=vn.travelThermograph__
--ignore-table=vn.travel_cloneWeekly
--ignore-table=vn.unary
--ignore-table=vn.unaryScan
--ignore-table=vn.unaryScanLine
--ignore-table=vn.unaryScanLineBuy
--ignore-table=vn.unaryScanLineExpedition
--ignore-table=vn.warehouseAlias__
--ignore-table=vn.warehouseJoined
--ignore-table=vn.workerTeam__
--ignore-table=vn.XDiario__
)
mysqldump \
--defaults-file=config.production.ini \
--default-character-set=utf8 \
--column-statistics=0 \
--no-data --comments \
--triggers --routines --events \
--databases \
${SCHEMAS[@]} \
${IGNORETABLES[@]} \
> dump/structure.sql

View File

@ -336,6 +336,7 @@ let actions = {
waitForLastSnackbar: function() {
return this.wait(500)
.waitForSpinnerLoad()
.waitForLastShape('vn-snackbar .shape .text');
},

View File

@ -3,7 +3,7 @@ const config = require('./config.js');
let nightmare;
module.exports = function createNightmare(width = 1280, height = 720) {
module.exports = function createNightmare(width = 1280, height = 800) {
if (nightmare)
return nightmare;

View File

@ -44,7 +44,7 @@ export default {
},
clientDescriptor: {
moreMenu: 'vn-client-descriptor vn-icon-menu[icon=more_vert]',
simpleTicketButton: '.vn-drop-down.shown li'
simpleTicketButton: '.vn-drop-down.shown li[name="Simple ticket"]'
},
clientBasicData: {
basicDataButton: 'vn-left-menu a[ui-sref="client.card.basicData"]',
@ -75,7 +75,8 @@ export default {
hasToInvoiceCheckbox: 'vn-check[label="Has to invoice"]',
invoiceByMailCheckbox: 'vn-check[label="Invoice by mail"]',
viesCheckbox: 'vn-check[label="Vies"]',
saveButton: `button[type=submit]`
saveButton: `button[type=submit]`,
watcher: 'vn-client-fiscal-data vn-watcher'
},
clientBillingData: {
payMethodAutocomplete: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]',
@ -91,7 +92,8 @@ export default {
newBankEntityBIC: '.vn-dialog.shown vn-textfield[label="Swift / BIC"] input',
newBankEntityCode: '.vn-dialog.shown vn-textfield[label="Entity Code"] input',
acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]',
saveButton: `button[type=submit]`
saveButton: `button[type=submit]`,
watcher: 'vn-client-billing-data vn-watcher'
},
clientAddresses: {
addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]',
@ -235,7 +237,7 @@ export default {
nameInput: 'vn-textfield[label="Name"] input',
relevancyInput: 'vn-input-number[ng-model="$ctrl.item.relevancy"] input',
originAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
expenceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.expenceFk"]',
expenseAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.expenseFk"]',
longNameInput: 'vn-textfield[ng-model="$ctrl.item.longName"] input',
isActiveCheckbox: 'vn-check[label="Active"]',
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
@ -499,16 +501,17 @@ export default {
},
ticketService: {
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]',
firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.description"]',
firstAddServiceTypeButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]',
firstServiceTypeAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]',
firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input',
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
newDescriptionInput: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
newServiceTypeNameInput: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
newServiceTypeExpenseAutocomplete: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.newServiceType.expenseFk"]',
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
saveServiceButton: `button[type=submit]`,
saveDescriptionButton: '.vn-dialog.shown tpl-buttons > button'
saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button'
},
createStateView: {
stateAutocomplete: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',

View File

@ -307,6 +307,7 @@ describe('Client Edit fiscalData path', () => {
it('should navigate back to fiscal data to confirm invoice by address is now checked', async() => {
const result = await nightmare
.waitToClick(selectors.clientFiscalData.fiscalDataButton)
.waitForWatcherData(selectors.clientFiscalData.watcher)
.checkboxState(selectors.clientFiscalData.invoiceByAddressCheckbox);
expect(result).toBe('checked');

View File

@ -62,8 +62,8 @@ describe('Client Edit billing data path', () => {
it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => {
const AutomaticCode = await nightmare
.clearInput(selectors.clientBillingData.IBANInput)
.waitToClick(selectors.clientBillingData.clearswiftBicButton)
.write(selectors.clientBillingData.IBANInput, 'ES9121000418450200051332')
.waitForTextInInput(`${selectors.clientBillingData.swiftBicAutocomplete} input`, 'caixesbb')
.waitToGetProperty(`${selectors.clientBillingData.swiftBicAutocomplete} input`, 'value');
expect(AutomaticCode).toEqual('CAIXESBB Caixa Bank');
@ -71,6 +71,7 @@ describe('Client Edit billing data path', () => {
it(`should save the form with all its new data`, async() => {
const snackbarMessages = await nightmare
.waitForWatcherData(selectors.clientBillingData.watcher)
.waitToClick(selectors.clientBillingData.saveButton)
.waitForSnackbar();

View File

@ -99,6 +99,7 @@ describe('Client Add address path', () => {
it(`should click on the active checkbox and receive an error to save it because it is the default address`, async() => {
const result = await nightmare
.waitForWatcherData(selectors.clientAddresses.watcher)
.waitToClick(selectors.clientAddresses.activeCheckbox)
.waitToClick(selectors.clientAddresses.saveButton)
.waitForLastSnackbar();

View File

@ -57,6 +57,7 @@ describe('Client balance path', () => {
it('should check balance is now 0 and the company is now VNL becouse the user local settings were removed', async() => {
let company = await nightmare
.waitForSpinnerLoad()
.waitToGetProperty(`${selectors.clientBalance.companyAutocomplete} input`, 'value');
let firstBalanceLine = await nightmare

View File

@ -27,7 +27,7 @@ describe('Item Edit basic data path', () => {
.clearInput(selectors.itemBasicData.relevancyInput)
.write(selectors.itemBasicData.relevancyInput, '1')
.autocompleteSearch(selectors.itemBasicData.originAutocomplete, 'Spain')
.autocompleteSearch(selectors.itemBasicData.expenceAutocomplete, 'Alquiler VNH')
.autocompleteSearch(selectors.itemBasicData.expenseAutocomplete, 'Alquiler VNH')
.clearInput(selectors.itemBasicData.longNameInput)
.write(selectors.itemBasicData.longNameInput, 'RS Rose of Purity')
.waitToClick(selectors.itemBasicData.isActiveCheckbox)
@ -76,7 +76,7 @@ describe('Item Edit basic data path', () => {
it(`should confirm the item expence was edited`, async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.itemBasicData.expenceAutocomplete} input`, 'value');
.waitToGetProperty(`${selectors.itemBasicData.expenseAutocomplete} input`, 'value');
expect(result).toEqual('Alquiler VNH');
});

View File

@ -33,6 +33,7 @@ describe('Ticket diary path', () => {
const url = await nightmare
.waitToClick(selectors.ticketSummary.firstSaleItemId)
.waitToClick(selectors.ticketSummary.popoverDiaryButton)
.waitForURL('/diary')
.parsedUrl();
expect(url.hash).toContain('/diary');

View File

@ -15,10 +15,10 @@ describe('Ticket services path', () => {
it('should find the add descripton button disabled for this user role', async() => {
const result = await nightmare
.waitForClassPresent(selectors.ticketService.firstAddDescriptionButton, 'disabled')
.waitForClassPresent(selectors.ticketService.firstAddServiceTypeButton, 'disabled')
.waitToClick(selectors.ticketService.addServiceButton)
.wait(selectors.ticketService.firstAddDescriptionButton)
.isDisabled(selectors.ticketService.firstAddDescriptionButton);
.wait(selectors.ticketService.firstAddServiceTypeButton)
.isDisabled(selectors.ticketService.firstAddServiceTypeButton);
expect(result).toBeTruthy();
}, 100000);
@ -50,7 +50,7 @@ describe('Ticket services path', () => {
it('should click on the add button to prepare the form to create a new service', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.addServiceButton)
.isVisible(selectors.ticketService.firstDescriptionAutocomplete);
.isVisible(selectors.ticketService.firstServiceTypeAutocomplete);
expect(result).toBeTruthy();
});
@ -63,27 +63,28 @@ describe('Ticket services path', () => {
expect(result).toEqual(`can't be blank`);
});
it('should click on the add new description to open the dialog', async() => {
it('should click on the add new service type to open the dialog', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.firstAddDescriptionButton)
.waitToClick(selectors.ticketService.firstAddServiceTypeButton)
.wait('.vn-dialog.shown')
.isVisible(selectors.ticketService.newDescriptionInput);
.isVisible(selectors.ticketService.newServiceTypeNameInput);
expect(result).toBeTruthy();
});
it('should receive an error if description is empty on submit', async() => {
it('should receive an error if service type is empty on submit', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.saveDescriptionButton)
.waitToClick(selectors.ticketService.saveServiceTypeButton)
.waitForLastSnackbar();
expect(result).toEqual(`Name can't be empty`);
});
it('should create a new description then add price then create the service', async() => {
it('should create a new service type then add price then create the service', async() => {
const result = await nightmare
.write(selectors.ticketService.newDescriptionInput, 'accurate description')
.waitToClick(selectors.ticketService.saveDescriptionButton)
.write(selectors.ticketService.newServiceTypeNameInput, 'Documentos')
.autocompleteSearch(selectors.ticketService.newServiceTypeExpenseAutocomplete, 'Retencion')
.waitToClick(selectors.ticketService.saveServiceTypeButton)
.write(selectors.ticketService.firstPriceInput, 999)
.waitToClick(selectors.ticketService.saveServiceButton)
.waitForLastSnackbar();
@ -94,9 +95,9 @@ describe('Ticket services path', () => {
it('should confirm the service description was created correctly', async() => {
const result = await nightmare
.reloadSection('ticket.card.service')
.waitToGetProperty(`${selectors.ticketService.firstDescriptionAutocomplete} input`, 'value');
.waitToGetProperty(`${selectors.ticketService.firstServiceTypeAutocomplete} input`, 'value');
expect(result).toEqual('accurate description');
expect(result).toEqual('Documentos');
});
it('should confirm the service quantity was created correctly', async() => {

View File

@ -18,24 +18,11 @@ describe('Ticket create path', () => {
expect(url.hash).toEqual('#!/ticket/create');
});
it('should attempt to create a ticket for a frozen client but fail', async() => {
const result = await nightmare
.autocompleteSearch(selectors.createTicketView.clientAutocomplete, 'Bruce Banner')
.autocompleteSearch(selectors.createTicketView.addressAutocomplete, 'Bruce Banner')
.datePicker(selectors.createTicketView.deliveryDateInput, 1, null)
.autocompleteSearch(selectors.createTicketView.warehouseAutocomplete, 'Warehouse One')
.autocompleteSearch(selectors.createTicketView.agencyAutocomplete, 'Silla247')
.wait(1999)
.waitToClick(selectors.createTicketView.createButton)
.waitForLastSnackbar();
expect(result).toMatch(/You can't create a ticket for a inactive|frozen client/);
});
it('should succeed to create a ticket for a valid client', async() => {
it('should succeed to create a ticket', async() => {
const result = await nightmare
.autocompleteSearch(selectors.createTicketView.clientAutocomplete, 'Tony Stark')
.autocompleteSearch(selectors.createTicketView.addressAutocomplete, 'Tony Stark')
.datePicker(selectors.createTicketView.deliveryDateInput, 1, null)
.autocompleteSearch(selectors.createTicketView.warehouseAutocomplete, 'Warehouse One')
.autocompleteSearch(selectors.createTicketView.agencyAutocomplete, 'Silla247')
.waitToClick(selectors.createTicketView.createButton)

View File

@ -94,38 +94,4 @@ describe('Claim development', () => {
expect(worker).toEqual('deliveryNick');
expect(redelivery).toEqual('Reparto');
});
it('should delete the first development, add an empty one and save it', async() => {
const result = await nightmare
.waitToClick(selectors.claimDevelopment.firstDeleteDevelopmentButton)
.waitToClick(selectors.claimDevelopment.addDevelopmentButton)
.waitToClick(selectors.claimDevelopment.saveDevelopmentButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should confirm the second development was auto filled', async() => {
const reason = await nightmare
.reloadSection('claim.card.development')
.waitToGetProperty(`${selectors.claimDevelopment.secondClaimReasonAutocomplete} input`, 'value');
const result = await nightmare
.waitToGetProperty(`${selectors.claimDevelopment.secondClaimResultAutocomplete} input`, 'value');
const responsible = await nightmare
.waitToGetProperty(`${selectors.claimDevelopment.secondClaimResponsibleAutocomplete} input`, 'value');
const worker = await nightmare
.waitToGetProperty(`${selectors.claimDevelopment.secondClaimWorkerAutocomplete} input`, 'value');
const redelivery = await nightmare
.waitToGetProperty(`${selectors.claimDevelopment.secondClaimRedeliveryAutocomplete} input`, 'value');
expect(reason).toEqual('Prisas');
expect(result).toEqual('Otros daños');
expect(responsible).toEqual('Compradores');
expect(worker).toEqual('managerNick');
expect(redelivery).toEqual('Cliente');
});
});

View File

@ -1,3 +1,5 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
/**
* Returns a set of allowed values defined on table scheme
@ -7,7 +9,6 @@ module.exports = Self => {
Self.getSetValues = async function(column) {
let model = this.app.models[this.modelName].definition;
let properties = model.properties;
let columnName;
let tableName = this.modelName;
let schema = null;
@ -17,35 +18,32 @@ module.exports = Self => {
schema = tableSplit.pop() || null;
}
if (properties[column]) {
columnName = column;
let property = properties[column];
if (properties[column].mysql)
columnName = properties[column].mysql.columnName;
}
if (!property)
throw new UserError(`Column does not exist`);
let findColumn = Object.keys(properties).find(prop => {
return properties[prop].mysql && properties[prop].mysql.columnName === column;
});
let columnName = property.mysql
? property.mysql.columnName
: column;
if (findColumn)
columnName = properties[findColumn].mysql.columnName;
let type = await this.rawSql(
`SELECT DISTINCT column_type FROM information_schema.columns
let columnInfo = await this.rawSql(
`SELECT column_type columnType
FROM information_schema.columns
WHERE table_name = ?
AND table_schema = IFNULL(?, DATABASE())
AND column_name = ?`,
[tableName, schema, columnName]
);
if (!type) return;
if (!columnInfo || !columnInfo[0])
throw new UserError(`Cannot fetch column values`);
let setValues;
setValues = type[0].column_type;
setValues = setValues.replace(/set\((.*)\)/i, '$1');
setValues = setValues.replace(/'/g, '');
setValues = setValues.match(new RegExp(/(\w+)+/, 'ig'));
setValues = columnInfo[0].columnType
.replace(/^set\((.*)\)$/i, '$1')
.replace(/'/g, '')
.match(new RegExp(/(\w+)+/, 'ig'));
let values = [];
setValues.forEach(setValue => {

View File

@ -13,11 +13,4 @@ describe('Model getSetValues()', () => {
expect(result.length).toEqual(6);
expect(result[5].value).toEqual('TABLET_VN');
});
it('should return an array of set values from table column source_app', async() => {
let result = await app.models.Order.getSetValues('source_app');
expect(result.length).toEqual(6);
expect(result[5].value).toEqual('TABLET_VN');
});
});

View File

@ -56,5 +56,6 @@
"Value has an invalid format": "Value has an invalid format",
"The postcode doesn't exists. Ensure you put the correct format": "The postcode doesn't exists. Ensure you put the correct format",
"Can't create stowaway for this ticket": "Can't create stowaway for this ticket",
"Has deleted the ticket id": "Has deleted the ticket id [#{{id}}]({{{url}}})"
"Has deleted the ticket id": "Has deleted the ticket id [#{{id}}]({{{url}}})",
"Swift / BIC can't be empty": "Swift / BIC can't be empty"
}

View File

@ -117,5 +117,6 @@
"You should specify a date": "Debes especificar una fecha",
"You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fín",
"Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fín",
"You should mark at least one week day": "Debes marcar al menos un día de la semana"
"You should mark at least one week day": "Debes marcar al menos un día de la semana",
"Swift / BIC can't be empty": "Swift / BIC no puede estar vacío"
}

View File

@ -1,8 +1,3 @@
<vn-crud-model auto-load="true"
url="Zones/{{$ctrl.$params.id}}/warehouses"
include="{relation: 'warehouse'}"
data="zoneWarehouses">
</vn-crud-model>
<vn-card class="summary">
<h5>#{{$ctrl.summary.id}} - {{$ctrl.summary.name}}</h5>
<vn-horizontal class="vn-pa-md">
@ -34,14 +29,14 @@
<vn-horizontal class="vn-pa-md">
<vn-auto>
<h4 translate>Warehouses</h4>
<vn-table model="model">
<vn-table model="model" auto-load="false">
<vn-thead>
<vn-tr>
<vn-th>Name</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="zoneWarehouse in zoneWarehouses">
<vn-tr ng-repeat="zoneWarehouse in $ctrl.zoneWarehouses">
<vn-td>{{zoneWarehouse.warehouse.name}}</vn-td>
</vn-tr>
</vn-tbody>

View File

@ -2,6 +2,11 @@ import ngModule from '../module';
import Component from 'core/lib/component';
class Controller extends Component {
constructor($element, $, $httpParamSerializer) {
super($element, $);
this.$httpParamSerializer = $httpParamSerializer;
}
get zone() {
return this._zone;
}
@ -12,21 +17,45 @@ class Controller extends Component {
if (!value) return;
this.getSummary();
this.getWarehouses();
}
getSummary() {
let filter = {
include: {relation: 'agencyMode', fields: ['name']},
where: {id: this.zone.id}
const params = {
filter: {
include: {
relation: 'agencyMode',
fields: ['name']
},
where: {
id: this.zone.id
}
}
};
filter = encodeURIComponent(JSON.stringify((filter)));
this.$http.get(`Zones/findOne?filter=${filter}`).then(res => {
if (res && res.data)
const serializedParams = this.$httpParamSerializer(params);
this.$http.get(`Zones/findOne?${serializedParams}`).then(res => {
this.summary = res.data;
});
}
getWarehouses() {
const params = {
filter: {
include: {
relation: 'warehouse',
fields: ['name']
}
}
};
const serializedParams = this.$httpParamSerializer(params);
this.$http.get(`Zones/${this.zone.id}/warehouses?${serializedParams}`).then(res => {
this.zoneWarehouses = res.data;
});
}
}
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnZoneSummary', {
template: require('./index.html'),
controller: Controller,

View File

@ -0,0 +1,68 @@
import './index';
describe('component vnZoneSummary', () => {
let $element;
let $scope;
let controller;
let $httpBackend;
let $httpParamSerializer;
beforeEach(ngModule('agency'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new();
$element = angular.element(`<vn-zone-summary></vn-zone-summary>`);
controller = $componentController('vnZoneSummary', {$element, $scope});
}));
describe('zone setter', () => {
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
spyOn(controller, 'getSummary');
spyOn(controller, 'getWarehouses');
controller.zone = {id: 1};
expect(controller.getSummary).toHaveBeenCalledWith();
expect(controller.getWarehouses).toHaveBeenCalledWith();
});
});
describe('getSummary()', () => {
it('should perform a get and then store data on the controller', () => {
controller._zone = {id: 1};
let params = {
filter: {
include: {
relation: 'agencyMode',
fields: ['name']
},
where: {
id: controller._zone.id
}
}
};
const serializedParams = $httpParamSerializer(params);
const query = `Zones/findOne?${serializedParams}`;
$httpBackend.expectGET(query).respond({id: 1});
controller.getSummary();
$httpBackend.flush();
expect(controller.summary).toBeDefined();
});
});
xdescribe('getEntries()', () => {
it('should call the getEntries method to get the entries data', () => {
controller._travel = {id: 999};
const query = `/api/Travels/${controller._travel.id}/getEntries`;
$httpBackend.expectGET(query).respond('I am the entries');
controller.getEntries();
$httpBackend.flush();
expect(controller.entries).toEqual('I am the entries');
});
});
});

View File

@ -1,6 +1,6 @@
module.exports = Self => {
Self.remoteMethodCtx('removeFile', {
description: 'Removes a ticket document',
description: 'Removes a claim document',
accessType: 'WRITE',
accepts: {
arg: 'id',

View File

@ -104,9 +104,6 @@ module.exports = Self => {
}
}
},
{
relation: 'claimDestination'
},
{
relation: 'claimReason'
},

View File

@ -11,6 +11,21 @@
"type": "Number",
"id": true,
"description": "Identifier"
},
"claimFk": {
"required": true
},
"claimResponsibleFk": {
"required": true
},
"claimReasonFk": {
"required": true
},
"claimResultFk": {
"required": true
},
"claimRedeliveryFk": {
"required": true
}
},
"relations": {
@ -29,11 +44,6 @@
"model": "Worker",
"foreignKey": "workerFk"
},
"claimDestination": {
"type": "belongsTo",
"model": "ClaimDestination",
"foreignKey": "claimDestinationFk"
},
"claimReason": {
"type": "belongsTo",
"model": "ClaimReason",

View File

@ -57,11 +57,11 @@
<span class="link"
vn-tooltip="Edit discount"
ng-click="$ctrl.showEditPopover($event, saleClaimed)">
{{::saleClaimed.sale.discount}} %
{{saleClaimed.sale.discount}} %
</span>
</vn-td>
<vn-td number>
{{::$ctrl.getSaleTotal(saleClaimed.sale) | currency: 'EUR':2}}
{{$ctrl.getSaleTotal(saleClaimed.sale) | currency: 'EUR':2}}
</vn-td>
<vn-td shrink>
<vn-icon-button
@ -125,8 +125,9 @@
<vn-popover
class="edit"
vn-id="edit-popover"
on-open="$ctrl.getManaSalespersonMana()"
on-open="$ctrl.getSalespersonMana()"
on-close="$ctrl.mana = null">
<div class="discount-popover">
<vn-spinner
ng-if="$ctrl.mana == null"
style="padding: 1em;"
@ -147,10 +148,11 @@
suffix="€">
</vn-input-number>
<div class="simulator">
<p class="simulatorTitle" translate>New price</p>
<p class="simulatorTitle" translate>Total claimed price</p>
<p>{{$ctrl.newPrice | currency: 'EUR':2}}
</p>
</div>
</div>
</div>
</div>
</vn-popover>

View File

@ -128,25 +128,30 @@ class Controller {
this.$.editPopover.show();
}
getManaSalespersonMana() {
getSalespersonMana() {
this.$http.get(`Tickets/${this.claim.ticketFk}/getSalesPersonMana`).then(res => {
this.mana = res.data;
});
}
updateDiscount() {
if (this.newDiscount != this.saleClaimed.sale.discount) {
const params = {salesIds: [this.saleClaimed.sale.id], newDiscount: this.newDiscount};
const query = `Tickets/${this.saleClaimed.sale.ticketFk}/updateDiscount`;
const claimedSale = this.saleClaimed.sale;
if (this.newDiscount != claimedSale.discount) {
const params = {salesIds: [claimedSale.id], newDiscount: this.newDiscount};
const query = `Tickets/${claimedSale.ticketFk}/updateDiscount`;
this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
claimedSale.discount = this.newDiscount;
this.calculateTotals();
this.clearDiscount();
this.$.model.refresh();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).catch(err => {
this.vnApp.showError(err.message);
});
}
this.$.editPopover.hide();
}
updateNewPrice() {

View File

@ -29,6 +29,9 @@ describe('claim', () => {
hide: () => {},
show: () => {}
};
controller.$.editPopover = {
hide: () => {}
};
}));
describe('openAddSalesDialog()', () => {
@ -110,16 +113,18 @@ describe('claim', () => {
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller, 'calculateTotals');
spyOn(controller, 'clearDiscount');
spyOn(controller.$.model, 'refresh');
spyOn(controller.$.editPopover, 'hide');
$httpBackend.when('POST', 'Tickets/1/updateDiscount').respond({});
controller.updateDiscount();
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.calculateTotals).toHaveBeenCalledWith();
expect(controller.clearDiscount).toHaveBeenCalledWith();
expect(controller.$.model.refresh).toHaveBeenCalledWith();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
expect(controller.$.editPopover.hide).toHaveBeenCalledWith();
});
});

View File

@ -7,3 +7,4 @@ Claimable sales from ticket: Lineas reclamables del ticket
Detail: Detalles
Add sale item: Añadir artículo
Insuficient permisos: Permisos insuficientes
Total claimed price: Precio total reclamado

View File

@ -1,28 +1,9 @@
@import "variables";
vn-claim-detail {
.vn-textfield {
margin: 0!important;
max-width: 100px;
}
vn-dialog[vn-id=addSales] {
tpl-body {
width: 950px;
div {
div.buttons {
display: none;
}
vn-table{
min-width: 950px;
}
}
}
}
vn-popover.edit {
div.popover {
width: 200px;
}
vn-horizontal.header {
.vn-popover .discount-popover {
width: 16em;
.header {
background-color: $color-main;
color: $color-font-dark;
@ -31,7 +12,7 @@ vn-claim-detail {
margin: 0 auto;
}
}
p.simulatorTitle {
.simulatorTitle {
margin-bottom: 0px;
font-size: 12px;
color: $color-main;
@ -39,9 +20,8 @@ vn-claim-detail {
vn-label-value {
padding-bottom: 20px;
}
div.simulator{
.simulator{
text-align: center;
}
}
}

View File

@ -49,7 +49,7 @@
data="claimReasons"
fields="['id', 'description']"
show-field="description"
vn-acl="salesAssistant">
rule>
</vn-autocomplete>
<vn-autocomplete
vn-one
@ -58,7 +58,7 @@
data="claimResults"
fields="['id', 'description']"
show-field="description"
vn-acl="salesAssistant">
rule>
</vn-autocomplete>
<vn-autocomplete
vn-one
@ -67,7 +67,7 @@
data="claimResponsibles"
fields="['id', 'description']"
show-field="description"
vn-acl="salesAssistant">
rule>
</vn-autocomplete>
<vn-autocomplete
vn-one
@ -78,7 +78,7 @@
value-field="id"
where="{role: 'employee'}"
label="Worker"
vn-acl="salesAssistant">
rule>
</vn-autocomplete>
<vn-autocomplete
vn-one
@ -87,15 +87,14 @@
data="claimRedeliveries"
fields="['id', 'description']"
show-field="description"
vn-acl="salesAssistant">
rule>
</vn-autocomplete>
<vn-icon-button
class="vn-my-md"
vn-tooltip="Remove sale"
icon="delete"
ng-click="model.remove($index)"
tabindex="-1"
vn-acl="salesAssistant">
tabindex="-1">
</vn-icon-button>
</vn-horizontal>
</form>
@ -104,8 +103,7 @@
vn-bind="+"
vn-tooltip="Add sale"
icon="add_circle"
ng-click="model.insert()"
vn-acl="salesAssistant">
ng-click="model.insert()">
</vn-icon-button>
</vn-one>
</vn-vertical>
@ -113,8 +111,7 @@
<vn-button-bar>
<vn-submit
label="Save"
ng-click="$ctrl.onSubmit()"
vn-acl="salesAssistant">
ng-click="$ctrl.onSubmit()">
</vn-submit>
</vn-button-bar>
</vn-vertical>

View File

@ -18,8 +18,8 @@ class Controller {
this._claim = value;
// Get DMS on summary load
/* if (value)
this.$.$applyAsync(() => this.loadDms()); */
if (value)
this.$.$applyAsync(() => this.loadDms());
}
loadDms() {

View File

@ -20,7 +20,7 @@ module.exports = Self => {
Self.removeFile = async(ctx, id) => {
const models = Self.app.models;
const clientDms = await models.ClientDms.findById(id);
const clientDms = await Self.findById(id);
await models.Dms.removeFile(ctx, clientDms.dmsFk);

View File

@ -7,7 +7,7 @@ describe('Client activeWorkersWithRole', () => {
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
expect(result.length).toEqual(15);
expect(result.length).toEqual(14);
expect(isSalesPerson).toBeTruthy();
});
@ -17,7 +17,7 @@ describe('Client activeWorkersWithRole', () => {
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
expect(result.length).toEqual(12);
expect(result.length).toEqual(11);
expect(isBuyer).toBeTruthy();
});
});

View File

@ -6,7 +6,7 @@ describe('Client listWorkers', () => {
.then(result => {
let amountOfEmployees = Object.keys(result).length;
expect(amountOfEmployees).toEqual(50);
expect(amountOfEmployees).toEqual(49);
done();
})
.catch(done.fail);

View File

@ -47,7 +47,14 @@ module.exports = Self => {
let xmlParsed;
let status;
try {
if (process.env.NODE_ENV !== 'production') {
status = {
codigo: [200],
descripcion: ['Fake response']
};
} else {
[xmlResponse] = await soapClient.sendSMSAsync(params);
xmlResult = xmlResponse.result.$value;
xmlParsed = await new Promise((resolve, reject) => {
@ -58,6 +65,7 @@ module.exports = Self => {
});
});
[status] = xmlParsed['xtratelecom-sms-response'].sms;
}
} catch (e) {
console.error(e);
}

View File

@ -32,43 +32,6 @@ describe('sms send()', () => {
let result = await app.models.Sms.send(ctx, 105, 'destination', 'My SMS Body');
expect(result.statusCode).toEqual(200);
expect(result.status).toContain('Envio en procesamiento');
});
it(`should throw if the response code isn't 200`, async() => {
let error;
const code = 400;
const smsConfig = await app.models.SmsConfig.findOne();
const soapClient = await soap.createClientAsync(smsConfig.uri);
spyOn(soap, 'createClientAsync').and.returnValue(soapClient);
spyOn(soapClient, 'sendSMSAsync').and.returnValue([{
result: {
$value:
`<xtratelecom-sms-response>
<sms>
<codigo>
${code}
</codigo>
<descripcion>
Envio en procesamiento
</descripcion>
<messageId>
1
</messageId>
</sms>
<procesoId>
444328681
</procesoId>
</xtratelecom-sms-response>`
}
}]);
let ctx = {req: {accessToken: {userId: 1}}};
try {
await app.models.Sms.send(ctx, 105, 'destination', 'My SMS Body');
} catch (err) {
error = err;
}
expect(error.message).toEqual(`We weren't able to send this SMS`);
expect(result.status).toContain('Fake response');
});
});

View File

@ -1,5 +1,8 @@
module.exports = Self => {
Self.validatesPresenceOf('name', {
message: 'Name cannot be blank'
message: `Name cannot be blank`
});
Self.validatesPresenceOf('bic', {
message: `Swift / BIC can't be empty`
});
};

View File

@ -61,8 +61,8 @@
<vn-icon-button
vn-auto
icon="add_circle"
ng-click="$ctrl.onAddEntityClick($event)"
vn-tooltip="New bank entity"
vn-dialog="bankEntityDialog"
vn-acl="salesAssistant">
</vn-icon-button>
</append>
@ -98,8 +98,7 @@
<!-- Create bank entity dialog -->
<vn-dialog class="edit"
vn-id="bankEntityDialog"
on-open="$ctrl.onBankEntityOpen()"
on-response="$ctrl.onBankEntityResponse($response)">
on-accept="$ctrl.onBankEntityAccept()">
<tpl-body>
<h5 class="vn-py-sm" translate>New bank entity</h5>
<vn-horizontal>

View File

@ -1,13 +1,7 @@
import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller {
constructor($scope, $http, vnApp, $translate) {
this.$scope = $scope;
this.$http = $http;
this.vnApp = vnApp;
this.$translate = $translate;
}
export default class Controller extends Section {
get client() {
return this._client;
}
@ -19,10 +13,6 @@ export default class Controller {
if (!value.bankEntityFk)
this.autofillBic();
this.newBankEntity = {
countryFk: Number.parseInt(value.countryFk)
};
}
onSubmit() {
@ -31,14 +21,14 @@ export default class Controller {
if (this.hasPaymethodChanges())
shouldNotify = true;
this.$scope.watcher.submit().then(() => {
this.$.watcher.submit().then(() => {
if (shouldNotify)
this.vnApp.showMessage(this.$translate.instant('Notification sent!'));
this.vnApp.showMessage(this.$t('Notification sent!'));
});
}
hasPaymethodChanges() {
let orgData = this.$scope.watcher.orgData;
let orgData = this.$.watcher.orgData;
let payMethod = orgData.payMethodFk != this.client.payMethodFk;
let iban = orgData.iban != this.client.iban;
@ -47,31 +37,17 @@ export default class Controller {
return payMethod || iban || dueDay;
}
onBankEntityOpen() {
this.newBankEntity.name = '';
this.newBankEntity.id = '';
this.newBankEntity.bic = '';
this.$scope.$apply();
onAddEntityClick(event) {
event.preventDefault();
this.newBankEntity = {
countryFk: Number.parseInt(this.client.countryFk)
};
this.$.bankEntityDialog.show();
}
onBankEntityResponse(response) {
if (response == 'accept') {
try {
if (!this.newBankEntity.name)
throw new Error(`Name can't be empty`);
if (!this.newBankEntity.bic)
throw new Error(`Swift / BIC can't be empty`);
this.$http.post(`BankEntities`, this.newBankEntity).then(response => {
if (response.data)
this.client.bankEntityFk = response.data.id;
});
} catch (e) {
this.vnApp.showError(this.$translate.instant(e.message));
return false;
}
}
return true;
onBankEntityAccept() {
return this.$http.post(`BankEntities`, this.newBankEntity)
.then(res => this.client.bankEntityFk = res.data.id);
}
get ibanCountry() {
@ -90,8 +66,7 @@ export default class Controller {
if (this.ibanCountry != 'ES') return;
let json = encodeURIComponent(JSON.stringify(filter));
this.$http.get(`BankEntities?filter=${json}`).then(response => {
this.$http.get(`BankEntities`, {filter}).then(response => {
const hasData = response.data && response.data[0];
if (hasData)
@ -101,7 +76,6 @@ export default class Controller {
});
}
}
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate'];
ngModule.component('vnClientBillingData', {
template: require('./index.html'),

View File

@ -10,12 +10,13 @@ describe('Client', () => {
beforeEach(ngModule('client'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => {
let $element = angular.element('<vn-client-billing-data></vn-client-billing-data>');
$httpBackend = _$httpBackend_;
vnApp = _vnApp_;
$scope = $rootScope.$new();
$scope.watcher = {};
spyOn(vnApp, 'showError');
controller = $componentController('vnClientBillingData', {$scope});
controller = $componentController('vnClientBillingData', {$element, $scope});
controller.client = {id: 101, name: 'Client name', payMethodFk: 4};
$scope.watcher.orgData = {id: 101, name: 'Client name', payMethodFk: 4};
}));
@ -34,42 +35,7 @@ describe('Client', () => {
});
});
describe('onBankEntityOpen()', () => {
it('should set reset the new bank entity properties', () => {
controller.newBankEntity.name = 'My new bank entity';
controller.newBankEntity.bic = 'ES123';
controller.onBankEntityOpen();
expect(controller.newBankEntity.name).toBe('');
expect(controller.newBankEntity.bic).toBe('');
});
});
describe('onBankEntityResponse()', () => {
it(`should throw an error if name property is empty`, () => {
controller.newBankEntity = {
name: '',
bic: 'ES123',
countryFk: 1,
id: 999
};
controller.onBankEntityResponse('accept');
expect(vnApp.showError).toHaveBeenCalledWith(`Name can't be empty`);
});
it(`should throw an error if bic property is empty`, () => {
controller.newBankEntity = {
name: 'My new bank entity',
bic: '',
countryFk: 1,
id: 999
};
controller.onBankEntityResponse('accept');
expect(vnApp.showError).toHaveBeenCalledWith(`Swift / BIC can't be empty`);
});
describe('onBankEntityAccept()', () => {
it('should request to create a new bank entity', () => {
let newBankEntity = {
name: 'My new bank entity',
@ -78,40 +44,49 @@ describe('Client', () => {
id: 999
};
controller.newBankEntity = newBankEntity;
$httpBackend.when('POST', 'BankEntities').respond('done');
$httpBackend.expectPOST('BankEntities', newBankEntity);
controller.onBankEntityResponse('accept');
$httpBackend.expectPOST('BankEntities', newBankEntity).respond({id: 999});
controller.onBankEntityAccept();
$httpBackend.flush();
expect(controller.client.bankEntityFk).toEqual(newBankEntity.id);
});
});
describe('autofillBic() should perform a GET query if client iban is specified and country code is "ES".', () => {
it(`Should not define bankEntityFk property`, () => {
controller.client.payMethodFk = 5;
controller.client.iban = 'ES9121000418450200051332';
let expectedFilter = {where: {id: 2100}};
let json = encodeURIComponent(JSON.stringify(expectedFilter));
describe('autofillBic()', () => {
it(`Should do nothing if there is not client`, () => {
controller.client = undefined;
controller.autofillBic();
expect(controller.client).toBeUndefined();
});
it(`Should do nothing if the iban is not spanish`, () => {
controller.client.iban = 'FR9121000418450200051332';
$httpBackend.when('GET', `BankEntities?filter=${json}`).respond('done');
$httpBackend.expect('GET', `BankEntities?filter=${json}`);
controller.autofillBic();
$httpBackend.flush();
expect(controller.client.bankEntityFk).toBeUndefined();
});
it(`Should define bankEntityFk property`, () => {
controller.client.payMethodFk = 5;
controller.client.iban = 'ES1501280010120123456789';
let expectedFilter = {where: {id: 128}};
let json = encodeURIComponent(JSON.stringify(expectedFilter));
it(`Should set the bankEntityId in the client`, () => {
controller.client.iban = 'ES9121000418450200051332';
$httpBackend.when('GET', `BankEntities?filter=${json}`).respond([{id: 128}]);
$httpBackend.expect('GET', `BankEntities?filter=${json}`);
$httpBackend.whenRoute('GET', `BankEntities`).respond([{id: 123}]);
controller.autofillBic();
$httpBackend.flush();
expect(controller.client.bankEntityFk).toEqual(128);
expect(controller.client.bankEntityFk).toEqual(123);
});
it(`Should set clients bankEntityFk to null if no bank entity founds`, () => {
controller.client.iban = 'ES9121000418450200051332';
$httpBackend.whenRoute('GET', `BankEntities`).respond([]);
controller.autofillBic();
$httpBackend.flush();
expect(controller.client.bankEntityFk).toBeNull();
});
});

View File

@ -15,5 +15,4 @@ Received B2B VNL: Recibido B2B VNL
Save: Guardar
New bank entity: Nueva entidad bancaria
Name can't be empty: El nombre no puede quedar vacío
Swift / BIC can't be empty: El Swift / BIC no puede quedar vacío
Entity Code: Código

View File

@ -68,3 +68,6 @@
</vn-quick-links>
</div>
</div>
<!-- SMS Dialog -->
<vn-client-sms vn-id="sms" sms="$ctrl.newSMS"></vn-client-sms>
<!-- SMS Dialog -->

View File

@ -1,11 +1,13 @@
import ngModule from '../module';
import Component from 'core/lib/component';
class Controller extends Component {
constructor($element, $) {
super($element, $);
class Controller {
constructor($http, $state) {
this.$state = $state;
this.$http = $http;
this.moreOptions = [
{callback: this.newTicket, name: 'Simple ticket'}
{name: 'Simple ticket', callback: this.newTicket},
{name: 'Send SMS', callback: this.showSMSDialog},
];
}
@ -22,6 +24,9 @@ class Controller {
if (!value) return;
if (this.$params.sendSMS)
this.showSMSDialog();
this._quicklinks = {
btnOne: {
icon: 'icon-ticket',
@ -47,9 +52,20 @@ class Controller {
newTicket() {
this.$state.go('ticket.create', {clientFk: this.client.id});
}
showSMSDialog() {
const phone = this.$params.phone || this.client.phone;
const message = this.$params.message || '';
this.newSMS = {
destinationFk: this.client.id,
destination: phone,
message: message
};
this.$.sms.open();
}
}
Controller.$inject = ['$http', '$state'];
Controller.$inject = ['$element', '$scope'];
ngModule.component('vnClientDescriptor', {
template: require('./index.html'),

View File

@ -56,7 +56,7 @@
"component": "vn-client-create",
"description": "New client"
}, {
"url": "/:id",
"url": "/:id?sendSMS&phone&message",
"state": "client.card",
"abstract": true,
"component": "vn-client-card"

View File

@ -56,7 +56,7 @@
<span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)"
class="link">
{{ticket.id | zeroFill:6}}
{{ticket.id}}
</span>
</vn-td>
<vn-td>

View File

@ -46,7 +46,7 @@ module.exports = Self => {
},
{relation: 'intrastat'},
{relation: 'itemBarcode'},
{relation: 'expence'},
{relation: 'expense'},
{relation: 'origin'},
{relation: 'taxes',
scope: {

View File

@ -1,5 +1,5 @@
{
"Expence": {
"Expense": {
"dataSource": "vn"
},
"Genus": {

View File

@ -1,5 +1,5 @@
{
"name": "Expence",
"name": "Expense",
"base": "VnModel",
"options": {
"mysql": {

View File

@ -116,6 +116,12 @@
"hasKgPrice": {
"type": "Boolean",
"description": "Price per Kg"
},
"expenseFk": {
"type": "Number",
"mysql": {
"columnName": "expenceFk"
}
}
},
"relations": {
@ -144,10 +150,10 @@
"model": "Intrastat",
"foreignKey": "intrastatFk"
},
"expence": {
"expense": {
"type": "belongsTo",
"model": "Expence",
"foreignKey": "expenceFk"
"model": "Expense",
"foreignKey": "expenseFk"
},
"tags": {
"type": "hasMany",

View File

@ -1,7 +1,7 @@
<mg-ajax
path="Items/{{patch.params.id}}"
options="vnPatch"
override="{filter: {include: [{relation: 'itemType'}, {relation: 'origin'}, {relation: 'ink'}, {relation: 'producer'}, {relation: 'expence'}]}}">
override="{filter: {include: [{relation: 'itemType'}, {relation: 'origin'}, {relation: 'ink'}, {relation: 'producer'}, {relation: 'expense'}]}}">
</mg-ajax>
<vn-watcher
vn-id="watcher"
@ -49,10 +49,10 @@
</tpl-item>
</vn-autocomplete>
<vn-autocomplete vn-one
url="Expences"
label="Expence"
ng-model="$ctrl.item.expenceFk"
initial-data="$ctrl.item.expence">
url="Expenses"
label="Expense"
ng-model="$ctrl.item.expenseFk"
initial-data="$ctrl.item.expense">
</vn-autocomplete>
<vn-autocomplete vn-one
url="Origins"

View File

@ -4,5 +4,5 @@ Full name calculates based on tags 1-3. Is not recommended to change it manually
basado en los tags 1-3.
No se recomienda cambiarlo manualmente
Is active: Activo
Expence: Gasto
Expense: Gasto
Price in kg: Precio en kg

View File

@ -60,8 +60,8 @@
<vn-label-value label="Compression"
value="{{$ctrl.summary.item.compression}}">
</vn-label-value>
<vn-label-value label="Expence"
value="{{$ctrl.summary.item.expence.name}}">
<vn-label-value label="Expense"
value="{{$ctrl.summary.item.expense.name}}">
</vn-label-value>
</vn-one>
<vn-one name="tags">

View File

@ -0,0 +1,29 @@
module.exports = Self => {
Self.remoteMethod('getDeliveryPoint', {
description: 'get the deliveryPoint address ',
accessType: 'WRITE',
accepts: {
arg: 'vehicleId',
type: 'number',
required: true,
description: 'vehicle id asigned in the route',
http: {source: 'path'}
},
returns: {
type: 'String',
root: true
},
http: {
path: `/:vehicleId/getDeliveryPoint`
}
});
Self.getDeliveryPoint = async vehicleId => {
let vehicle = await Self.app.models.Vehicle.findById(vehicleId);
let deliveryPoint = await Self.app.models.DeliveryPoint.findById(vehicle.deliveryPointFk);
return deliveryPoint.ubication;
};
};

View File

@ -0,0 +1,13 @@
const app = require('vn-loopback/server/server');
describe('route getDeliveryPoint()', () => {
const routeId = 1;
const deliveryPointAddress = '46460 Av Espioca 100-Silla';
it('should get the delivery point addres of a route with assigned vehicle', async() => {
let route = await app.models.Route.findById(routeId);
let address = await app.models.Route.getDeliveryPoint(route.vehicleFk);
expect(address).toEqual(deliveryPointAddress);
});
});

View File

@ -7,5 +7,10 @@
},
"RouteLog": {
"dataSource": "vn"
},
"DeliveryPoint": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,22 @@
{
"name": "DeliveryPoint",
"base": "VnModel",
"options": {
"mysql": {
"table": "deliveryPoint"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "String"
},
"ubication": {
"type": "String"
}
}
}

View File

@ -4,4 +4,5 @@ module.exports = Self => {
require('../methods/route/getTickets')(Self);
require('../methods/route/guessPriority')(Self);
require('../methods/route/updateVolume')(Self);
require('../methods/route/getDeliveryPoint')(Self);
};

View File

@ -41,6 +41,11 @@
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
},
"deliveryPoint": {
"type": "belongsTo",
"model": "DeliveryPoint",
"foreignKey": "deliveryPointFk"
}
},
"scope": {

View File

@ -7,8 +7,8 @@
</vn-crud-model>
<vn-data-viewer model="model">
<form name="form">
<vn-card class="vn-pa-lg">
<vn-tool-bar class="vn-mb-sm">
<vn-card class="vn-pa-md">
<vn-tool-bar>
<vn-button
icon="icon-wand"
ng-click="$ctrl.guessPriority()"
@ -18,14 +18,11 @@
disabled="!$ctrl.isChecked"
ng-click="$ctrl.goToBuscaman()"
vn-tooltip="Open buscaman"
tooltip-position="up"
icon="icon-buscaman">
</vn-button>
</vn-tool-bar>
<vn-icon-button
vn-tooltip="Load more"
ng-click="$ctrl.goToBuscaman()">
</vn-icon-button>
</vn-card>
<vn-card class="vn-mt-md">
<vn-table model="model" auto-load="false">
<vn-thead>
<vn-tr>
@ -36,12 +33,12 @@
</vn-th>
<vn-th>Order</vn-th>
<vn-th number>Ticket</vn-th>
<vn-th>Client</vn-th>
<vn-th number shrink>Packages</vn-th>
<vn-th shrink></vn-th>
<vn-th shrink>Warehouse</vn-th>
<vn-th expand>Postcode</vn-th>
<vn-th>Street</vn-th>
<vn-th expand>Client</vn-th>
<vn-th number>Packages</vn-th>
<vn-th number></vn-th>
<vn-th>Warehouse</vn-th>
<vn-th>Postcode</vn-th>
<vn-th expand>Street</vn-th>
<vn-th shrink></vn-th>
<vn-th shrink></vn-th>
</vn-tr>
@ -53,11 +50,12 @@
ng-model="ticket.checked">
</vn-check>
</vn-td>
<vn-td>
<vn-td number>
<vn-input-number
on-change="$ctrl.setPriority(ticket.id, ticket.priority)"
ng-model="ticket.priority"
rule="Ticket">
rule="Ticket"
class="dense">
</vn-input-number>
</vn-td>
<vn-td number>
@ -74,10 +72,10 @@
{{ticket.nickname}}
</span>
</vn-td>
<vn-td number shrink>{{ticket.packages}}</vn-td>
<vn-td shrink>{{ticket.volume}}</vn-td>
<vn-td shrink>{{ticket.warehouse.name}}</vn-td>
<vn-td number shrink>{{ticket.address.postalCode}}</vn-td>
<vn-td number>{{ticket.packages}}</vn-td>
<vn-td number>{{ticket.volume}}</vn-td>
<vn-td expand>{{ticket.warehouse.name}}</vn-td>
<vn-td>{{ticket.address.postalCode}}</vn-td>
<vn-td expand title="{{ticket.address.street}}">{{ticket.address.street}}</vn-td>
<vn-td shrink>
<vn-icon-button

View File

@ -85,20 +85,26 @@ class Controller {
}
goToBuscaman() {
// firstAddress is a temporal variable, will be replaced with #1298
let firstAddress = `46460 Av Espioca 100-46460 Silla`;
let addresses = firstAddress;
let query = `Routes/${this.route.vehicleFk}/getDeliveryPoint`;
let deliveryPointAddress;
let addresses;
this.$http.get(query).then(response => {
deliveryPointAddress = response.data;
}).then(() => {
addresses = deliveryPointAddress;
let lines = this.getSelectedItems(this.tickets);
let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
lines.forEach(line => {
addresses = addresses + '+to:' + line.address.postalCode + ' ' + line.address.street + '-' + line.address.postalCode + ' ' + line.address.city;
addresses = addresses + '+to:' + line.address.postalCode + ' ' + line.address.city + ' ' + line.address.street;
});
window.open(url + addresses, '_blank');
});
}
showDeleteConfirm(id) {
this.selectedTicket = id;
this.$.confirm.show();

View File

@ -120,7 +120,11 @@ describe('Route', () => {
describe('goToBuscaman()', () => {
it('should open buscaman with the given arguments', () => {
spyOn(window, 'open');
const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460 Av Espioca 100-46460 Silla+to:n19 my street-n19 London';
const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460 Av Espioca 100+to:n19 London my street';
controller.route = {vehicleFk: 1};
const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`;
$httpBackend.expectGET(url).respond('46460 Av Espioca 100');
controller.tickets = [
{
id: 1,
@ -134,6 +138,7 @@ describe('Route', () => {
];
controller.goToBuscaman();
$httpBackend.flush();
expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank');
});

View File

@ -49,7 +49,6 @@ module.exports = function(Self) {
let query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`;
let [result] = await Self.rawSql(query, [ticket.clientFk, ticket.companyFk, 'R'], options);
let serial = result.serial;
let stmts = [];
stmt = new ParameterizedSQL('CALL vn.invoiceOut_newFromTicket(?, ?, ?, @invoiceId)', [

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