This commit is contained in:
Carlos Jimenez Ruiz 2019-06-26 15:02:22 +02:00
commit c352a12d49
73 changed files with 1001 additions and 4212 deletions

View File

@ -1,5 +1,4 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
const fs = require('fs-extra');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('downloadFile', { Self.remoteMethodCtx('downloadFile', {
@ -8,7 +7,7 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'id', arg: 'id',
type: 'String', type: 'Number',
description: 'The document id', description: 'The document id',
http: {source: 'path'} http: {source: 'path'}
} }

View File

@ -1,6 +1,5 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
const fs = require('fs-extra'); const fs = require('fs-extra');
const md5 = require('md5');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('uploadFile', { Self.remoteMethodCtx('uploadFile', {

View File

@ -1,15 +0,0 @@
CREATE TABLE `vn`.`device` (
`id` INT NOT NULL,
`sn` VARCHAR(50) NULL,
`model` VARCHAR(50) NULL,
`userFk` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `device_fk1_idx` (`userFk` ASC),
CONSTRAINT `device_fk1`
FOREIGN KEY (`userFk`)
REFERENCES `account`.`user` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
ALTER TABLE `vn`.`device`
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT ;

View File

@ -1,74 +0,0 @@
USE `nst`;
DROP procedure IF EXISTS `nodeAdd`;
DELIMITER $$
USE `nst`$$
CREATE DEFINER=`root`@`%` PROCEDURE `nodeAdd`(IN `vScheme` VARCHAR(45), IN `vTable` VARCHAR(45), IN `vParentFk` INT, IN `vChild` VARCHAR(100))
BEGIN
DECLARE vSql TEXT;
DECLARE vTableClone VARCHAR(45);
SET vTableClone = CONCAT(vTable, 'Clone');
CALL util.exec(CONCAT('DROP TEMPORARY TABLE IF EXISTS tmp.', vTableClone));
CALL util.exec(CONCAT(
'CREATE TEMPORARY TABLE tmp.', vTableClone,
' ENGINE = MEMORY',
' SELECT * FROM ', vScheme, '.', vTable
));
CALL util.exec(CONCAT(
'SELECT COUNT(c.id) INTO @childs',
' FROM ', vScheme, '.', vTable, ' p',
' LEFT JOIN tmp.', vTableClone, ' c ON c.lft',
' BETWEEN p.lft AND p.rgt AND c.id != ', vParentFk,
' WHERE p.id = ', vParentFk
));
IF @childs = 0 THEN
CALL util.exec(CONCAT(
'SELECT lft INTO @vLeft',
' FROM ', vScheme, '.', vTable,
' WHERE id = ', vParentFk
));
ELSE
CALL util.exec(CONCAT(
'SELECT c.rgt INTO @vLeft',
' FROM ', vScheme, '.', vTable, ' p',
' JOIN tmp.', vTableClone, ' c ON c.depth = p.depth + 1'
' AND c.lft BETWEEN p.lft AND p.rgt',
' WHERE p.id = ', vParentFk,
' ORDER BY c.lft',
' DESC LIMIT 1'
));
END IF;
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET rgt = rgt + 2',
' WHERE rgt > @vLeft',
' ORDER BY rgt DESC'
));
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET lft = lft + 2',
' WHERE lft > @vLeft',
' ORDER BY lft DESC'
));
SET vChild = REPLACE(vChild, "'", "\\'");
CALL util.exec(CONCAT(
'INSERT INTO ', vScheme, '.', vTable, ' (name, lft, rgt)',
' VALUES ("', vChild, '", @vLeft + 1, @vLeft + 2)'
));
-- CALL util.exec(CONCAT(
-- 'SELECT id, name, lft, rgt, depth, sons',
-- ' FROM ', vScheme, '.', vTable,
-- ' WHERE id = LAST_INSERT_ID()'
-- ));
CALL util.exec(CONCAT('DROP TEMPORARY TABLE tmp.', vTableClone));
END$$
DELIMITER ;

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneNest`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneNest`()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp.zoneGeo;
CREATE TEMPORARY TABLE tmp.zoneGeo
(id INT AUTO_INCREMENT PRIMARY KEY)
ENGINE = MEMORY
SELECT * FROM vn.zoneGeo;
DROP TEMPORARY TABLE IF EXISTS tmp.country;
CREATE TEMPORARY TABLE tmp.country
SELECT id FROM country
WHERE country IN('España exento');
CALL vn.zoneNestCountry();
CALL vn.zoneNestProvince();
CALL vn.zoneNestTown();
CALL vn.zoneNestPostcode();
CALL vn.nestTree('tmp', 'zoneGeo', 'vn', 'zoneGeo');
DROP TEMPORARY TABLE
tmp.zoneGeo,
tmp.country;
END$$
DELIMITER ;

View File

@ -1,55 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneNestCountry`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneNestCountry`()
BEGIN
DECLARE vDone BOOL;
DECLARE vParent INT DEFAULT 1;
DECLARE vGeoFk INT;
DECLARE vChildFk INT;
DECLARE vChildName VARCHAR(100);
DECLARE countryCur CURSOR FOR
SELECT 1, c.id, c.`country`
FROM vn.country c
JOIN tmp.country tc ON tc.id = c.id
ORDER BY c.`country`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Remove existing countries
DELETE zg FROM vn.country c
JOIN tmp.country tc ON tc.id = c.id
JOIN tmp.zoneGeo zg ON zg.id = c.geoFk;
-- Reset country geoFk
UPDATE vn.country c
JOIN tmp.country tc ON tc.id = c.id
SET c.geoFk = NULL
WHERE c.geoFk IS NOT NULL;
-- > Country cursor start
OPEN countryCur;
countryLoop: LOOP
SET vDone = FALSE;
FETCH countryCur INTO vParent, vChildFk, vChildName;
IF vDone THEN
LEAVE countryLoop;
END IF;
CALL nst.nodeAdd('tmp', 'zoneGeo', vParent, vChildName);
END LOOP;
CLOSE countryCur;
-- < Country cursor end
UPDATE country c
JOIN tmp.zoneGeo z ON z.name = c.country
SET c.geoFk = z.id
WHERE c.geoFk IS NULL;
END$$
DELIMITER ;

View File

@ -1,61 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneNestPostcode`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneNestPostcode`()
BEGIN
DECLARE vDone BOOL;
DECLARE vParent INT DEFAULT 1;
DECLARE vGeoFk INT;
DECLARE vChildFk INT;
DECLARE vChildName VARCHAR(100);
DECLARE postcodeCur CURSOR FOR
SELECT t.geoFk, pc.`code`, pc.`code`
FROM vn.postCode pc
JOIN vn.town t ON t.id = pc.townFk
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
ORDER BY t.geoFk, pc.`code`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Remove existing postCodes from zoneGeo
DELETE zg FROM vn.postCode pc
JOIN vn.town t ON t.id = pc.townFk
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
JOIN tmp.zoneGeo zg ON zg.id = pc.geoFk;
-- Reset town geoFk
UPDATE vn.postCode pc
JOIN vn.town t ON t.id = pc.townFk
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
SET pc.geoFk = NULL
WHERE pc.geoFk IS NOT NULL;
-- > Postcode cursor start
OPEN postcodeCur;
postcodeLoop: LOOP
SET vDone = FALSE;
FETCH postcodeCur INTO vParent, vChildFk, vChildName;
IF vDone THEN
LEAVE postcodeLoop;
END IF;
CALL nst.nodeAdd('tmp', 'zoneGeo', vParent, vChildName);
END LOOP;
CLOSE postcodeCur;
-- < Postcode cursor end
UPDATE postCode p
JOIN tmp.zoneGeo z ON z.name = p.code
SET p.geoFk = z.id
WHERE p.geoFk IS NULL;
END$$
DELIMITER ;

View File

@ -1,56 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneNestProvince`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneNestProvince`()
BEGIN
DECLARE vDone BOOL;
DECLARE vParent INT DEFAULT 1;
DECLARE vGeoFk INT;
DECLARE vChildFk INT;
DECLARE vChildName VARCHAR(100);
DECLARE provinceCur CURSOR FOR
SELECT c.geoFk, p.id, p.`name`
FROM province p
JOIN tmp.country tc ON tc.id = p.countryFk
JOIN vn.country c ON c.id = tc.id
ORDER BY c.geoFk, p.`name`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Remove existing provinces from zoneGeo
DELETE zg FROM vn.province p
JOIN tmp.country tc ON tc.id = p.countryFk
JOIN tmp.zoneGeo zg ON zg.id = p.geoFk;
-- Reset country geoFk
UPDATE vn.province p
JOIN tmp.country tc ON tc.id = p.countryFk
SET p.geoFk = NULL
WHERE p.geoFk IS NOT NULL;
-- > Province cursor start
OPEN provinceCur;
provinceLoop: LOOP
SET vDone = FALSE;
FETCH provinceCur INTO vParent, vChildFk, vChildName;
IF vDone THEN
LEAVE provinceLoop;
END IF;
CALL nst.nodeAdd('tmp', 'zoneGeo', vParent, vChildName);
END LOOP;
CLOSE provinceCur;
-- < Province cursor end
UPDATE province p
JOIN tmp.zoneGeo z ON z.name = p.name
SET p.geoFk = z.id
WHERE p.geoFk IS NULL;
END$$
DELIMITER ;

View File

@ -1,59 +0,0 @@
DROP procedure IF EXISTS `vn`.`zoneNestTown`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`zoneNestTown`()
BEGIN
DECLARE vDone BOOL;
DECLARE vParent INT DEFAULT 1;
DECLARE vGeoFk INT;
DECLARE vChildFk INT;
DECLARE vChildName VARCHAR(100);
DECLARE townCur CURSOR FOR
SELECT p.geoFk, t.id, t.`name`
FROM vn.town t
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
ORDER BY p.geoFk, t.`name`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Remove existing towns from zoneGeo
DELETE zg FROM vn.town t
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
JOIN tmp.zoneGeo zg ON zg.id = t.geoFk;
-- Reset town geoFk
UPDATE vn.town t
JOIN vn.province p ON p.id = t.provinceFk
JOIN tmp.country tc ON tc.id = p.countryFk
SET t.geoFk = NULL
WHERE t.geoFk IS NOT NULL;
-- > Town cursor start
OPEN townCur;
townLoop: LOOP
SET vDone = FALSE;
FETCH townCur INTO vParent, vChildFk, vChildName;
IF vDone THEN
LEAVE townLoop;
END IF;
CALL nst.nodeAdd('tmp', 'zoneGeo', vParent, vChildName);
END LOOP;
CLOSE townCur;
-- < Town cursor end
UPDATE town t
JOIN tmp.zoneGeo z ON z.name = t.name
LEFT JOIN province p ON p.geoFk = z.id
SET t.geoFk = z.id
WHERE p.geoFk IS NULL;
END$$
DELIMITER ;

View File

@ -1,19 +0,0 @@
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`ticketGetVolume` AS
SELECT
`s`.`ticketFk` AS `ticketFk`,
`t`.`routeFk` AS `routeFk`,
`s`.`id` AS `saleFk`,
`t`.`shipped` AS `Fecha`,
(((`s`.`quantity` * `r`.`cm3`) * `i`.`compression`) / 1000000) AS `volume`
FROM
(((`vn`.`sale` `s`
JOIN `vn`.`item` `i` ON ((`i`.`id` = `s`.`itemFk`)))
JOIN `vn`.`ticket` `t` ON ((`t`.`id` = `s`.`ticketFk`)))
JOIN `bi`.`rotacion` `r` ON (((`r`.`Id_Article` = `s`.`itemFk`)
AND (`r`.`warehouse_id` = `t`.`warehouseFk`))));

View File

@ -1,30 +0,0 @@
DROP function IF EXISTS `vn`.`ticketTotalVolume`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` FUNCTION `ticketTotalVolume`(vTicketId INT) RETURNS decimal(10,3)
READS SQL DATA
BEGIN
-- Devuelte el volumen total del ticket sumado
-- DECLARE vWarehouseId INTEGER;
-- DECLARE vShippedDate DATE;
DECLARE vVolume DECIMAL(10,3);
/*
SELECT warehouseFk, shipped INTO vWarehouseId,vShippedDate FROM vn.ticket WHERE id = vTicketId;
SELECT IFNULL(SUM(s.quantity * i.compression * r.cm3)/1000000,0) INTO vVolume
FROM sale s
JOIN vn.item i ON i.id = s.itemFk
JOIN bi.rotacion r on r.Id_Article = s.itemFk AND r.warehouse_id = vWarehouseId
WHERE s.ticketFk = vTicketId;
*/
SELECT sum(volume) INTO vVolume
FROM ticketGetVolume
WHERE ticketFk = vTicketId;
RETURN vVolume;
END$$
DELIMITER ;

View File

@ -1,61 +0,0 @@
DROP procedure IF EXISTS `vn`.`available_calc`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`available_calc`(
vDate DATE,
vAddress INT,
vAgencyMode INT)
BEGIN
/**
* Calculates the available for all available stores
* according to the given parameters.
*
* @param vDate The delivery date
* @param vAddress The delivery address id
* @param vAgencyMode The shipping agency
* @return tmp.availableCalc(calcFk) The available cache ids
*/
DECLARE vCalcFk INT;
DECLARE vShipment DATE;
DECLARE vWarehouse INT;
DECLARE vDone BOOL;
DECLARE cWarehouses CURSOR FOR
SELECT warehouseFk, shipped FROM tmp.zoneGetShipped;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET vDone = TRUE;
-- Establecemos los almacenes y las fechas que van a entrar al disponible
CALL vn.zoneGetShippedWarehouse(vDate, vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.availableCalc;
CREATE TEMPORARY TABLE tmp.availableCalc(
calcFk INT UNSIGNED,
PRIMARY KEY (calcFk)
)
ENGINE = MEMORY;
OPEN cWarehouses;
l: LOOP
SET vDone = FALSE;
FETCH cWarehouses INTO vWarehouse, vShipment;
IF vDone THEN
LEAVE l;
END IF;
CALL `cache`.available_refresh(vCalcFk, FALSE, vWarehouse, vShipment);
INSERT IGNORE INTO tmp.availableCalc
SET calcFk = vCalcFk;
END LOOP;
CLOSE cWarehouses;
DROP TEMPORARY TABLE tmp.zoneGetShipped;
END$$
DELIMITER ;

View File

@ -1,28 +0,0 @@
DROP procedure IF EXISTS `vn`.`catalog_calcFromItem`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`catalog_calcFromItem`(
vLanded DATE,
vAddressFk INT,
vAgencyModeFk INT,
vItemFk INT)
BEGIN
/**
* Calculates available and price for a single item.
*
* @param vItemFk The item id
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
ENGINE = MEMORY
SELECT vItemFk itemFk;
CALL ticketCalculate(vLanded, vAddressFk, vAgencyModeFk);
DROP TEMPORARY TABLE tmp.item;
END$$
DELIMITER ;

View File

@ -1,41 +0,0 @@
DROP procedure IF EXISTS `hedera`.`catalog_calcFromMyAddress`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`catalog_calcFromMyAddress`(vDelivery DATE, vAddress INT)
BEGIN
/**
* Gets the available items list.
*
* @param vDelivery Delivery date
* @param vAddress Address id
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
DECLARE vAgencyMode INT;
SELECT a.agencyModeFk
INTO vAgencyMode
FROM myClient c
JOIN vn.address a ON a.clientFk = c.id
WHERE a.id = vAddress;
CALL vn.available_calc(vDelivery, vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
(INDEX (itemFk))
ENGINE = MEMORY
SELECT c.item_id itemFk
FROM `cache`.available c
JOIN tmp.availableCalc a ON a.calcFk = c.calc_id
WHERE c.available > 0
GROUP BY c.item_id;
CALL vn.ticketCalculate(vDelivery, vAddress, vAgencyMode);
DROP TEMPORARY TABLE tmp.item;
END$$
DELIMITER ;

View File

@ -1,398 +0,0 @@
USE `vn2008`;
DROP procedure IF EXISTS `vn2008`.`bionic_available_`;
DELIMITER $$
USE `vn2008`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__bionic_available_`(
vDate DATE,
vAddress INT,
vAgency INT)
BEGIN
/**
* Calcula el disponible para un conjunto de almacenes y fechas
* devueltos por el procedimiento agencyHourGetShipped()
*
* @deprecated Use vn.available_calc()
* @table t_bionic_available Tabla con los ids de cache
*/
DECLARE vAvailableCalc INT;
DECLARE vShipment DATE;
DECLARE vAgencyId INT;
DECLARE vWh INT;
DECLARE vDone BOOL;
DECLARE cTravelTree CURSOR FOR
SELECT warehouseFk, shipped FROM tmp.agencyHourGetShipped;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Establecemos los almacenes y las fechas que van a entrar al disponible
SELECT agency_id INTO vAgencyId
FROM Agencias WHERE Id_Agencia = vAgency;
CALL vn.agencyHourGetShipped (vDate, vAddress, vAgencyId);
DROP TEMPORARY TABLE IF EXISTS t_bionic_available;
CREATE TEMPORARY TABLE t_bionic_available(
calc_id INT UNSIGNED,
PRIMARY KEY (calc_id)
)
ENGINE = MEMORY;
OPEN cTravelTree;
l: LOOP
SET vDone = FALSE;
FETCH cTravelTree INTO vWh, vShipment;
IF vDone THEN
LEAVE l;
END IF;
CALL `cache`.available_refresh (vAvailableCalc, FALSE, vWh, vShipment);
INSERT IGNORE INTO t_bionic_available
SET calc_id = vAvailableCalc;
END LOOP;
CLOSE cTravelTree;
DROP TEMPORARY TABLE tmp.agencyHourGetShipped;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`bionic_from_item`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__bionic_from_item`(vItem INT)
BEGIN
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT sent, addressFk, agencyModeFk
INTO vDate, vAddress, vAgencyMode
FROM myBasket;
CALL vn2008.bionic_from_item(vDate, vAddress, vAgencyMode, vItem);
END$$
DELIMITER ;
;
USE `vn2008`;
DROP procedure IF EXISTS `vn2008`.`bionic_from_order`;
DELIMITER $$
USE `vn2008`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__bionic_from_order`(
v_date DATE, -- fecha de recepcion de mercancia
v_consigna INT,
v_agencia INT,
v_order INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp.bionic_calc;
CREATE TEMPORARY TABLE tmp.bionic_calc
(PRIMARY KEY (item_id))
ENGINE = MEMORY
SELECT item_id FROM order_row
WHERE order_id = v_order GROUP BY item_id;
CALL bionic_calc (v_date, v_consigna, v_agencia);
DROP TEMPORARY TABLE tmp.bionic_calc;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`bionicCalcWithDate`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__bionicCalcWithDate`(vDate DATE)
BEGIN
DECLARE vMyAddressFk INTEGER;
DECLARE vMyAgencyModeFk INTEGER;
SELECT id, agencyModeFk INTO vMyAddressFk, vMyAgencyModeFk
FROM myAddress
WHERE isDefaultAddress;
CALL vn2008.bionic_calc(vDate, vMyAddressFk, vMyAgencyModeFk);
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`bionic_calc`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__bionic_calc`()
BEGIN
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT sent, addressFk, agencyModeFk
INTO vDate, vAddress, vAgencyMode
FROM myBasket;
CALL vn2008.bionic_calc(vDate, vAddress, vAgencyMode);
IF account.myUserGetName() = 'visitor'
THEN
DROP TEMPORARY TABLE tmp.bionic_component;
UPDATE tmp.bionic_item SET price = NULL;
END IF;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`itemGetAvailableOrder`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__itemGetAvailableOrder`(vOrder INT)
BEGIN
/**
* Gets the available items list with an order params.
*
* @table tmp.itemAvailable
*/
DECLARE vDelivery DATE;
DECLARE vAddress INT;
DECLARE vAgency INT;
SELECT landed, addressFk, agencyModeFk
INTO vDelivery, vAddress, vAgency
FROM myOrder
WHERE id = vOrder;
CALL vn2008.bionic_available_ (vDelivery, vAddress, vAgency);
DROP TEMPORARY TABLE IF EXISTS tmp.itemAvailable;
CREATE TEMPORARY TABLE tmp.itemAvailable
(INDEX (id))
ENGINE = MEMORY
SELECT c.item_id id
FROM cache.available c
JOIN vn2008.t_bionic_available a ON c.calc_id = a.calc_id
WHERE c.available > 0
GROUP BY c.item_id;
DROP TEMPORARY TABLE vn2008.t_bionic_available;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`itemGetAvailable`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__itemGetAvailable`()
BEGIN
/**
* Gets the available items list.
*
* @table tmp.itemAvailable
*/
DECLARE vDelivery DATE;
DECLARE vAddress INT;
DECLARE vAgency INT;
SELECT sent, addressFk, agencyModeFk
INTO vDelivery, vAddress, vAgency
FROM myBasket;
CALL vn2008.bionic_available_ (vDelivery, vAddress, vAgency);
DROP TEMPORARY TABLE IF EXISTS tmp.itemAvailable;
CREATE TEMPORARY TABLE tmp.itemAvailable
(INDEX (id))
ENGINE = MEMORY
SELECT c.item_id id
FROM cache.available c
JOIN vn2008.t_bionic_available a ON c.calc_id = a.calc_id
WHERE c.available > 0
GROUP BY c.item_id;
DROP TEMPORARY TABLE vn2008.t_bionic_available;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`myItemGetAvailableFromDate`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__myItemGetAvailableFromDate`(vDelivery DATE)
BEGIN
/**
* Gets the available items list.
*
* @deprecated Use item_calcCatalogFromMyAddress()
* @param vDelivery Delivery date
*/
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT a.agencyModeFk, a.id
INTO vAgencyMode, vAddress
FROM myClient c
JOIN vn.address a ON a.id = c.defaultAddressFk;
CALL vn2008.bionic_available_ (vDelivery, vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
(INDEX (itemFk))
ENGINE = MEMORY
SELECT c.item_id itemFk
FROM cache.available c
JOIN vn2008.t_bionic_available a ON c.calc_id = a.calc_id
WHERE c.available > 0
GROUP BY c.item_id;
CALL vn.ticketCalculate(vDelivery, vAddress, vAgencyMode);
-- -------------------
/*SELECT b.itemFk, b.item, b.available, b.price
FROM tmp.ticketCalculateItem b
JOIN vn.item i ON i.id = b.itemFk
WHERE b.available > 0
ORDER BY i.relevancy DESC, i.name, i.size;
select * from tmp.ticketComponentPrice;*/
-- -------------------
DROP TEMPORARY TABLE vn2008.t_bionic_available;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`myItemGetAvailable`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__myItemGetAvailable`(vDelivery DATE, vAddress INT)
BEGIN
/**
* Gets the available items list.
*
* @deprecated Use item_calcCatalogFromMyAddress()
* @param vDelivery Delivery date
* @param vAddress Id Address
*/
DECLARE vAgencyMode INT;
SELECT a.agencyModeFk
INTO vAgencyMode
FROM myClient c
JOIN vn.address a ON a.clientFk = c.id
WHERE a.id = vAddress;
CALL vn2008.bionic_available_ (vDelivery, vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
(INDEX (itemFk))
ENGINE = MEMORY
SELECT c.item_id itemFk
FROM cache.available c
JOIN vn2008.t_bionic_available a ON c.calc_id = a.calc_id
WHERE c.available > 0
GROUP BY c.item_id;
CALL vn.ticketCalculate(vDelivery, vAddress, vAgencyMode);
-- -------------------
/*SELECT b.itemFk, b.item, b.available, b.price
FROM tmp.ticketCalculateItem b
JOIN vn.item i ON i.id = b.itemFk
WHERE b.available > 0
ORDER BY i.relevancy DESC, i.name, i.size;
select * from tmp.ticketComponentPrice;*/
-- -------------------
DROP TEMPORARY TABLE vn2008.t_bionic_available;
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`myOrderAddItem`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__myOrderAddItem`(
vSelf INT,
vWarehouse INT,
vItem INT,
vAmount INT)
BEGIN
/**
* @deprecated Use myOrder_addItem()
*/
CALL myOrder_addItem(vSelf, vWarehouse, vItem, vAmount);
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`myOrderConfirm`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__myOrderConfirm`(vSelf INT)
BEGIN
/**
* @deprecated Use myOrder_confirm()
*/
CALL myOrder_confirm(vSelf);
END$$
DELIMITER ;
;
USE `hedera`;
DROP procedure IF EXISTS `hedera`.`myOrderNewFromDate`;
DELIMITER $$
USE `hedera`$$
CREATE DEFINER=`root`@`%` PROCEDURE `__myOrderNewFromDate`(
OUT vSelf INT,
vLandingDate DATE)
BEGIN
/**
* @deprecated Use myOrder_newWithDate()
*/
CALL myOrder_newWithDate(vSelf, vLandingDate);
END$$
DELIMITER ;
;

View File

@ -1,19 +0,0 @@
DROP procedure IF EXISTS `hedera`.`myBasket_calcCatalogFromItem`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`myBasket_calcCatalogFromItem`(vItem INT)
BEGIN
/**
* Gets the availability and prices for the given item
* using current user basket parameters.
*
* @table tmp.item(itemFk)
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
CALL order_calcCatalogFromItem(myBasket_getId(), vItem);
END$$
DELIMITER ;

View File

@ -1,19 +0,0 @@
DROP procedure IF EXISTS `hedera`.`myBasket_calcCatalogFull`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`myBasket_calcCatalogFull`()
BEGIN
/**
* Gets the availability and prices for the given items
* using current user basket parameters.
*
* @table tmp.item(itemFk)
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
CALL order_calcCatalogFull(myBasket_getId());
END$$
DELIMITER ;

View File

@ -1,14 +0,0 @@
DROP procedure IF EXISTS `hedera`.`myBasket_getAvailable`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`myBasket_getAvailable`()
BEGIN
/**
* Gets the available items list.
*
* @table tmp.itemAvailable
*/
CALL order_getAvailable(myBasket_getId());
END$$
DELIMITER ;

View File

@ -1,22 +0,0 @@
DROP procedure IF EXISTS `hedera`.`myOrder_getAvailable`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`myOrder_getAvailable`(vSelf INT)
BEGIN
/**
* Gets the available items list.
*
* @param vSelf The order id
* @table tmp.itemAvailable
*/
DECLARE isMine BOOL;
SELECT COUNT(*) INTO isMine
FROM myOrder
WHERE id = vSelf;
IF isMine THEN
CALL order_getAvailable(vSelf);
END IF;
END$$
DELIMITER ;

View File

@ -1,105 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_addItem`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_addItem`(
vSelf INT,
vWarehouse INT,
vItem INT,
vAmount INT)
BEGIN
/**
* Adds an item to the order, checking availability and grouping.
*
* @param vSelf The order id
* @param vWarehouse The warehouse id
* @param vItem The item id
* @param vAmount The amount to add
*/
DECLARE vRow INT;
DECLARE vAdd INT;
DECLARE vAvailable INT;
DECLARE vDone BOOL;
DECLARE vGrouping INT;
DECLARE vRate INT;
DECLARE vShipment DATE;
DECLARE vPrice DECIMAL(10,2);
DECLARE cur CURSOR FOR
SELECT `grouping`, price, rate
FROM tmp.ticketComponentPrice
WHERE warehouseFk = vWarehouse
AND itemFk = vItem
ORDER BY `grouping` DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
CALL order_calcCatalogFromItem(vSelf, vItem);
START TRANSACTION;
SELECT shipped INTO vShipment
FROM tmp.zoneGetShipped
WHERE warehouseFk = vWarehouse;
SELECT available INTO vAvailable
FROM tmp.ticketLot
WHERE warehouseFk = vWarehouse
AND itemFk = vItem;
IF vAmount > IFNULL(vAvailable, 0) THEN
CALL util.throw ('ORDER_ROW_UNAVAILABLE');
END IF;
OPEN cur;
l: LOOP
SET vDone = FALSE;
FETCH cur INTO vGrouping, vPrice, vRate;
IF vDone THEN
LEAVE l;
END IF;
SET vAdd = vAmount - MOD(vAmount, vGrouping);
SET vAmount = vAmount - vAdd;
IF vAdd = 0 THEN
ITERATE l;
END IF;
INSERT INTO orderRow SET
orderFk = vSelf,
itemFk = vItem,
warehouseFk = vWarehouse,
shipment = vShipment,
rate = vRate,
amount = vAdd,
price = vPrice;
SET vRow = LAST_INSERT_ID();
INSERT INTO orderRowComponent (rowFk, componentFk, price)
SELECT vRow, c.componentFk, c.cost
FROM tmp.ticketComponent c
JOIN vn.component t
ON t.id = c.componentFk
AND (t.classRate IS NULL OR t.classRate = vRate)
WHERE c.warehouseFk = vWarehouse
AND c.itemFk = vItem;
END LOOP;
CLOSE cur;
IF vAmount > 0 THEN
CALL util.throw ('AMOUNT_NOT_MATCH_GROUPING');
END IF;
COMMIT;
CALL vn.ticketCalculatePurge;
END$$
DELIMITER ;

View File

@ -1,36 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_calcCatalog`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_calcCatalog`(vSelf INT)
BEGIN
/**
* Gets the availability and prices for order items.
*
* @param vSelf The order id
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
*/
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT date_send, address_id, agency_id
INTO vDate, vAddress, vAgencyMode
FROM `order`
WHERE id = vSelf;
DROP TEMPORARY TABLE IF EXISTS tmp.item;
CREATE TEMPORARY TABLE tmp.item
(PRIMARY KEY (itemFk))
ENGINE = MEMORY
SELECT itemFk FROM orderRow
WHERE orderFk = vSelf
GROUP BY itemFk;
CALL vn.ticketCalculate(vDate, vAddress, vAgencyMode);
DROP TEMPORARY TABLE tmp.item;
END$$
DELIMITER ;

View File

@ -1,30 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_calcCatalogFromItem`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_calcCatalogFromItem`(vSelf INT, vItem INT)
BEGIN
/**
* Gets the availability and prices for the given item
* using the order parameters.
*
* @param vSelf The order id
* @table tmp.item(itemFk)
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT date_send, address_id, agency_id
INTO vDate, vAddress, vAgencyMode
FROM `order`
WHERE id = vSelf;
CALL vn.catalog_calcFromItem(vDate, vAddress, vAgencyMode, vItem);
END$$
DELIMITER ;

View File

@ -1,35 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_calcCatalogFull`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_calcCatalogFull`(vSelf INT)
BEGIN
/**
* Gets the availability and prices for the given items
* using the order parameters.
*
* @param vSelf The order id
* @table tmp.item(itemFk)
* @return tmp.ticketCalculateItem
* @return tmp.ticketComponentPrice
* @return tmp.ticketComponent
* @return tmp.ticketLot
* @return tmp.zoneGetShipped
*/
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT date_send, address_id, agency_id
INTO vDate, vAddress, vAgencyMode
FROM `order`
WHERE id = vSelf;
CALL vn.ticketCalculate(vDate, vAddress, vAgencyMode);
IF account.myUserGetName() = 'visitor'
THEN
DROP TEMPORARY TABLE tmp.ticketComponent;
UPDATE tmp.ticketCalculateItem SET price = NULL;
END IF;
END$$
DELIMITER ;

View File

@ -1,34 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_getAvailable`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_getAvailable`(vSelf INT)
BEGIN
/**
* Gets the available items list.
*
* @param vSelf The order id
* @table tmp.itemAvailable
*/
DECLARE vDelivery DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
SELECT date_send, address_id, agency_id
INTO vDelivery, vAddress, vAgencyMode
FROM `order`
WHERE id = vSelf;
CALL vn.available_calc(vDelivery, vAddress, vAgencyMode);
DROP TEMPORARY TABLE IF EXISTS tmp.itemAvailable;
CREATE TEMPORARY TABLE tmp.itemAvailable
(INDEX (id))
ENGINE = MEMORY
SELECT DISTINCT a.item_id id
FROM `cache`.available a
JOIN tmp.availableCalc c ON c.calcFk = a.calc_id
WHERE a.available > 0;
DROP TEMPORARY TABLE tmp.availableCalc;
END$$
DELIMITER ;

View File

@ -1,71 +0,0 @@
DROP procedure IF EXISTS `hedera`.`order_update`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `hedera`.`order_update`(vSelf INT)
proc: BEGIN
/**
* Actualiza las líneas de un pedido.
*
* @param vSelf Id del pedido
*/
DECLARE vDate DATE;
DECLARE vAddress INT;
DECLARE vAgencyMode INT;
DECLARE vNRows INT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
SELECT COUNT(*) INTO vNRows
FROM orderRow WHERE orderFk = vSelf;
IF vNRows > 0
THEN
CALL order_calcCatalog(vSelf);
DELETE c
FROM orderRow r
JOIN orderRowComponent c ON c.rowFk = r.id
WHERE r.orderFk = vSelf;
UPDATE orderRow r
LEFT JOIN tmp.ticketComponentPrice p
ON p.warehouseFk = r.warehouseFk
AND p.itemFk = r.itemFk
AND p.rate = r.rate
LEFT JOIN tmp.zoneGetShipped t
ON t.warehouseFk = r.warehouseFk
SET
r.price = p.price,
r.amount = IF(p.itemFk IS NOT NULL,
r.amount + IF(@m := MOD(r.amount, p.`grouping`), p.`grouping` - @m, 0), 0),
r.shipment = t.shipped
WHERE r.orderFk = vSelf;
INSERT INTO orderRowComponent(rowFk, componentFk, price)
SELECT r.id, c.componentFk, c.cost
FROM orderRow r
JOIN tmp.ticketComponent c
ON c.warehouseFk = r.warehouseFk
AND c.itemFk = r.itemFk
JOIN vn.component t
ON t.id = c.componentFk
AND (t.classRate IS NULL OR t.classRate = r.rate)
WHERE r.orderFk = vSelf;
CALL vn.ticketCalculatePurge;
END IF;
UPDATE `order` SET date_make = NOW()
WHERE id = vSelf;
COMMIT;
END$$
DELIMITER ;

View File

@ -1 +0,0 @@
RENAME TABLE hedera.myOrderMyTicket TO hedera.myOrderTicket;

View File

@ -1,10 +0,0 @@
GRANT EXECUTE ON PROCEDURE vn.zoneGetAgency TO `account`@`%`;
GRANT EXECUTE ON PROCEDURE hedera.myBasket_calcCatalogFromItem TO `guest`@`%`;
GRANT EXECUTE ON PROCEDURE hedera.myBasket_calcCatalogFull TO `guest`@`%`;
GRANT EXECUTE ON PROCEDURE hedera.myBasket_getAvailable TO `guest`@`%`;
GRANT EXECUTE ON PROCEDURE hedera.myOrder_getAvailable TO `guest`@`%`;
GRANT EXECUTE ON PROCEDURE hedera.catalog_calcFromMyAddress TO account@'%';
REVOKE SELECT ON TABLE hedera.myOrderMyTicket FROM account@'%';
GRANT SELECT ON TABLE hedera.myOrderTicket TO account@'%';
CALL account.privSync;

View File

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

View File

@ -0,0 +1,3 @@
ALTER TABLE `vn`.`zoneCalendar`
ADD COLUMN `price` DOUBLE NOT NULL AFTER `delivered`,
ADD COLUMN `bonus` DOUBLE NOT NULL AFTER `price`;

View File

@ -190,7 +190,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
(102, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (102, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(104, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (104, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
(105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, NULL, 0, 1), (105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1),
(106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1), (106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1),
(107, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1), (107, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1),
(108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1), (108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1),
@ -352,7 +352,7 @@ INSERT INTO `vn`.`creditInsurance`(`id`, `creditClassification`, `credit`, `crea
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`) INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`)
VALUES VALUES
(1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 7, 'first route', 0.1, 10, CURDATE(), CURDATE()), (1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 7, 'first route', 0.3, 10, CURDATE(), CURDATE()),
(2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 7, 'second route', 0.1, 20, CURDATE(), CURDATE()), (2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 7, 'second route', 0.1, 20, CURDATE(), CURDATE()),
(3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 7, 'third route', 0.1, 30, CURDATE(), CURDATE()), (3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 7, 'third route', 0.1, 30, CURDATE(), CURDATE()),
(4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 7, 'fourth route', 0.1, 40, CURDATE(), CURDATE()), (4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 7, 'fourth route', 0.1, 40, CURDATE(), CURDATE()),
@ -425,8 +425,8 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
VALUES VALUES
(1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), (1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), (2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3 , 1, 2, 2, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)), (3 , 1, 2, 1, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(4 , 3, 2, 2, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)), (4 , 3, 2, 1, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(5 , 3, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)), (5 , 3, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(6 , 1, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), (6 , 1, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(7 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, CURDATE()), (7 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, CURDATE()),
@ -435,8 +435,8 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(10, 1, 1, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, CURDATE()), (10, 1, 1, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, CURDATE()),
(11, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, CURDATE()), (11, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, CURDATE()),
(12, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, CURDATE()), (12, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, CURDATE()),
(13, 1, 1, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, CURDATE()), (13, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, CURDATE()),
(14, 1, 2, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, CURDATE()), (14, 1, 2, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, CURDATE()),
(15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, CURDATE()), (15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, CURDATE()),
(16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, CURDATE()), (16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, CURDATE()),
(17, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, CURDATE()), (17, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, CURDATE()),
@ -1027,15 +1027,20 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
(1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000), (1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000),
(2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000), (2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000),
(3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00), (3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00),
(4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500); (4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500),
(5, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 2, 1, 50.00, 500),
(6, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 2, 1, 50.00, 500),
(7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 2, 1, 50.00, 500);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`,`ref`) INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`,`ref`)
VALUES VALUES
(1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 442, 'Movimiento 1'), (1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 442, 'Movimiento 1'),
(2, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 442, 'Movimiento 2'), (2, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 442, 'Movimiento 2'),
(3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 442, 'Movimiento 3'), (3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 442, 'Movimiento 3'),
(4, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 69, 'Movimiento 4'); (4, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 69, 'Movimiento 4'),
(5, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 442, 'Movimiento 5'),
(6, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 6, 442, 'Movimiento 6'),
(7, 2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 7, 442, 'Movimiento 7');
INSERT INTO `bi`.`claims_ratio`(`id_Cliente`, `Consumo`, `Reclamaciones`, `Ratio`, `recobro`, `inflacion`) INSERT INTO `bi`.`claims_ratio`(`id_Cliente`, `Consumo`, `Reclamaciones`, `Ratio`, `recobro`, `inflacion`)
VALUES VALUES
@ -1053,7 +1058,14 @@ INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`package
(5, 3, 3, 10, 500, 1, 1, 1.000, 0.050, 0.000, 10, 10, 0, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()), (5, 3, 3, 10, 500, 1, 1, 1.000, 0.050, 0.000, 10, 10, 0, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(6, 4, 8, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()), (6, 4, 8, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(7, 4, 9, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()), (7, 4, 9, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(8, 4, 4, 20 , 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()); (8, 4, 4, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(9, 4, 4, 20, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(10, 5, 1, 2, 10, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(11, 5, 4, 3, 10, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(12, 6, 4, 2, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(13, 7, 1, 2, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(14, 7, 2, 5, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(15, 7, 4, 1, 1000, 1, 1, 0.700, 0.020, 0.000, 10, 10, 1, NULL, 0.00, 2.50, 1.00, 0.00, NULL, 0, 1, 0, CURDATE());
INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`) INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`)
VALUES VALUES

View File

@ -385,6 +385,7 @@ describe('Worker time control path', () => {
it('should Hank Pym check his hours are alright', async() => { it('should Hank Pym check his hours are alright', async() => {
const wholeWeekHours = await nightmare const wholeWeekHours = await nightmare
.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '56:00 Hours')
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText'); .waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
expect(wholeWeekHours).toEqual('56:00 Hours'); expect(wholeWeekHours).toEqual('56:00 Hours');

View File

@ -26,37 +26,55 @@
<vn-vertical class="body"> <vn-vertical class="body">
<vn-horizontal class="weekdays"> <vn-horizontal class="weekdays">
<section class="day" ng-click="$ctrl.selectAll(1)"> <section title="{{'Monday' | translate}}"
ng-click="$ctrl.selectAll(1)">
<span>L</span> <span>L</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(2)"> <section title="{{'Tuesday' | translate}}"
ng-click="$ctrl.selectAll(2)">
<span>M</span> <span>M</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(3)"> <section title="{{'Wednesday' | translate}}"
ng-click="$ctrl.selectAll(3)">
<span>X</span> <span>X</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(4)"> <section title="{{'Thursday' | translate}}"
ng-click="$ctrl.selectAll(4)">
<span>J</span> <span>J</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(5)"> <section title="{{'Friday' | translate}}"
ng-click="$ctrl.selectAll(5)">
<span>V</span> <span>V</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(6)"> <section title="{{'Saturday' | translate}}"
ng-click="$ctrl.selectAll(6)">
<span>S</span> <span>S</span>
</section> </section>
<section class="day" ng-click="$ctrl.selectAll(0)"> <section title="{{'Sunday' | translate}}"
ng-click="$ctrl.selectAll(0)">
<span>D</span> <span>D</span>
</section> </section>
</vn-horizontal> </vn-horizontal>
<vn-horizontal class="days"> <vn-horizontal class="days">
<section ng-repeat="day in $ctrl.days" class="day {{day.event.className || day.className}}" <section ng-repeat="day in $ctrl.days" class="day"
ng-click="$ctrl.select($index)" ng-class="{'primary': day.events.length > 0}">
ng-style="{'color': day.event.style.color}"> <div class="content">
<span ng-if="day.event" vn-tooltip="{{day.event.title}}" <div class="day-number"
ng-style="{'background-color': day.event.style.background}"> title="{{(day.events[0].description || day.events[0].name) | translate}}"
ng-style="$ctrl.renderStyle(day.style || day.events[0].style)"
ng-click="$ctrl.select($index)">
{{::day.dated | date: 'd'}} {{::day.dated | date: 'd'}}
</div>
<div ng-if="day.events" class="events">
<div ng-repeat="event in day.events" class="event"
title="{{(event.description || event.name) | translate}}">
<span class="chip ellipsize"
ng-style="::$ctrl.renderStyle(event.style)">
{{::event.name}}
</span> </span>
<span ng-if="!day.event">{{::day.dated | date: 'd'}}</span> </div>
</div>
</div>
</section> </section>
</vn-horizontal> </vn-horizontal>
</vn-vertical> </vn-vertical>

View File

@ -13,6 +13,23 @@ export default class Calendar extends Component {
this.defaultDate = new Date(); this.defaultDate = new Date();
this.displayControls = true; this.displayControls = true;
this.skip = 1; this.skip = 1;
this.window.addEventListener('resize', () => {
this.checkSize();
});
}
/**
* Resizes the calendar
* based on component height
*/
checkSize() {
const height = this.$element[0].clientHeight;
if (height < 530)
this.$element.addClass('small');
else
this.$element.removeClass('small');
} }
/** /**
@ -49,8 +66,10 @@ export default class Calendar extends Component {
this.addEvent(event); this.addEvent(event);
}); });
if (value.length && this.defaultDate) if (value.length && this.defaultDate) {
this.repaint(); this.repaint();
this.checkSize();
}
} }
/** /**
@ -165,16 +184,28 @@ export default class Calendar extends Component {
* @param {Date} dated - Date of month * @param {Date} dated - Date of month
* @param {String} className - Default class style * @param {String} className - Default class style
*/ */
insertDay(dated, className = '') { insertDay(dated) {
let event = this.events.find(event => { let events = this.events.filter(event => {
return event.dated >= dated && event.dated <= dated; return event.dated >= dated && event.dated <= dated;
}); });
// Weeekends const params = {dated, events};
if (dated.getMonth() === this.currentMonth.getMonth() && dated.getDay() == 0)
className = 'red';
this.days.push({dated, className, event}); const isSaturday = dated.getDay() === 6;
const isSunday = dated.getDay() === 0;
const isCurrentMonth = dated.getMonth() === this.currentMonth.getMonth();
const hasEvents = events.length > 0;
if (isCurrentMonth && isSunday && !hasEvents)
params.style = {color: '#f42121'};
if (isCurrentMonth && isSaturday && !hasEvents)
params.style = {color: '#666666'};
if (!isCurrentMonth && !hasEvents)
params.style = {color: '#9b9b9b'};
this.days.push(params);
} }
/** /**
@ -182,7 +213,7 @@ export default class Calendar extends Component {
* *
* @param {Object} options - Event params * @param {Object} options - Event params
* @param {Date} options.dated - Day to add event * @param {Date} options.dated - Day to add event
* @param {String} options.title - Tooltip description * @param {String} options.name - Tooltip description
* @param {String} options.className - ClassName style * @param {String} options.className - ClassName style
* @param {Object} options.style - Style properties * @param {Object} options.style - Style properties
* @param {Boolean} options.isRemovable - True if is removable by users * @param {Boolean} options.isRemovable - True if is removable by users
@ -194,11 +225,6 @@ export default class Calendar extends Component {
options.dated = new Date(options.dated); options.dated = new Date(options.dated);
options.dated.setHours(0, 0, 0, 0); options.dated.setHours(0, 0, 0, 0);
const event = this.events.findIndex(event => {
return event.dated >= options.dated && event.dated <= options.dated;
});
if (event < 0)
this.events.push(options); this.events.push(options);
} }
@ -274,6 +300,16 @@ export default class Calendar extends Component {
} }
this.emit('selection', {values: selected}); this.emit('selection', {values: selected});
} }
renderStyle(style) {
if (style) {
return {
'background-color': style.backgroundColor,
'font-weight': style.fontWeight,
'color': style.color
};
}
}
} }
Calendar.$inject = ['$element', '$scope']; Calendar.$inject = ['$element', '$scope'];

View File

@ -20,8 +20,8 @@ describe('Component vnCalendar', () => {
let currentDate = new Date().toString(); let currentDate = new Date().toString();
controller.data = [ controller.data = [
{dated: currentDate, title: 'Event 1'}, {dated: currentDate, name: 'Event 1'},
{dated: currentDate, title: 'Event 2'}, {dated: currentDate, name: 'Event 2'},
]; ];
expect(controller.events[0].dated instanceof Object).toBeTruthy(); expect(controller.events[0].dated instanceof Object).toBeTruthy();
@ -34,12 +34,11 @@ describe('Component vnCalendar', () => {
controller.events = []; controller.events = [];
controller.addEvent({ controller.addEvent({
dated: new Date(), dated: new Date(),
title: 'My event', name: 'My event'
className: 'color'
}); });
const firstEvent = controller.events[0]; const firstEvent = controller.events[0];
expect(firstEvent.title).toEqual('My event'); expect(firstEvent.name).toEqual('My event');
expect(firstEvent.isRemovable).toBeDefined(); expect(firstEvent.isRemovable).toBeDefined();
expect(firstEvent.isRemovable).toBeTruthy(); expect(firstEvent.isRemovable).toBeTruthy();
}); });
@ -50,19 +49,17 @@ describe('Component vnCalendar', () => {
controller.events = [{ controller.events = [{
dated: curDate, dated: curDate,
title: 'My event 1', name: 'My event 1'
className: 'color'
}]; }];
controller.addEvent({ controller.addEvent({
dated: curDate, dated: curDate,
title: 'My event 2', name: 'My event 2'
className: 'color'
}); });
const firstEvent = controller.events[0]; const firstEvent = controller.events[0];
expect(controller.events.length).toEqual(1); expect(controller.events.length).toEqual(2);
expect(firstEvent.title).toEqual('My event 1'); expect(firstEvent.name).toEqual('My event 1');
}); });
}); });
@ -71,7 +68,7 @@ describe('Component vnCalendar', () => {
const curDate = new Date(); const curDate = new Date();
controller._events = [{ controller._events = [{
dated: curDate, dated: curDate,
title: 'My event 1', name: 'My event 1',
className: 'color' className: 'color'
}]; }];
controller.removeEvent(curDate); controller.removeEvent(curDate);

View File

@ -1,143 +1,123 @@
@import "variables"; @import "variables";
vn-calendar.small {
.events {
display: none
}
}
vn-calendar { vn-calendar {
display: block; display: block;
max-width: 250px;
.header vn-one { .header vn-one {
text-align: center; text-align: center;
padding: 0.2em 0 padding: 0.2em 0;
height: 1.5em
}
.weekdays {
color: $color-font-secondary;
margin-bottom: 0.5em;
padding: 0.5em 0;
font-weight: bold;
font-size: 0.8em;
}
.weekdays section {
cursor: pointer
}
.weekdays section, .day {
position: relative;
text-align: center;
box-sizing: border-box;
width: 14.28%;
outline: 0;
} }
.body {
.days { .days {
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} }
.weekdays {
border-bottom: 1px solid $color-hover-cd;
border-top: 1px solid $color-hover-cd;
color: $color-font-secondary;
font-weight: bold
}
.day { .day {
box-sizing: border-box; .content {
padding: 0.1em; position: absolute;
width: 14.2857143%; bottom: 0;
line-height: 1.5em; right: 0;
outline: 0; left: 0;
top: 0
}
span { .day-number {
transition: background-color 0.3s; transition: background-color 0.3s;
text-align:center; text-align:center;
font-size: .8em; float:inline-end;
margin: 0 auto;
border-radius: 50%; border-radius: 50%;
display: block; font-size: 0.85em;
padding: 0.2em; width:2.2em;
cursor: pointer height: 1.2em;
padding: 0.5em 0;
cursor: pointer;
outline: 0
}
.day-number:hover {
background-color: lighten($color-font-secondary, 20%);
opacity: 0.8
} }
} }
.day:hover span { .day::after {
background-color: #DDD content: "";
display: block;
padding-top: 100%;
}
.day.primary .day-number {
background-color: $color-main;
color: $color-font-bg;
}
.events {
margin-top: 0.5em;
font-size: 0.6em
}
.events {
color: $color-font-secondary;
.event {
margin-bottom: .1em;
}
}
.chip {
background-color: $color-main;
color: $color-font-bg;
display: inline-block;
border-radius: .3em;
padding: 0.3em .8em;
max-width: 5em;
} }
.day.gray { .day.gray {
.day-number {
color: $color-font-secondary color: $color-font-secondary
} }
.day.orange {
font-weight: bold;
color: $color-main;
} }
.day.orange-circle {
color: $color-font;
& > span {
background-color: $color-main
}
}
.day.orange-circle:hover {
& > span {
background-color: $color-main-medium
}
}
.day.light-orange { .day.sunday {
color: $color-main-medium .day-number {
} color: $color-alert;
font-weight: bold
.day.green {
font-weight: bold;
color: $color-success;
}
.day.green-circle {
color: $color-font;
& > span {
background-color: $color-success
}
}
.day.green-circle:hover {
& > span {
background-color: $color-success-medium
}
}
.day.light-green {
font-weight: bold;
color: $color-success-medium
}
.day.blue {
font-weight: bold;
color: $color-notice;
}
.day.blue-circle {
color: $color-font;
& > span {
background-color: $color-notice
}
}
.day.blue-circle:hover {
& > span {
background-color: $color-notice-medium
}
}
.day.light-blue {
font-weight: bold;
color: $color-notice-medium
}
.day.red {
font-weight: bold;
color: $color-alert
}
.day.red-circle {
color: $color-font;
& > span {
background-color: $color-alert
}
}
.day.red-circle:hover {
& > span {
background-color: $color-alert-medium
}
}
.day.light-red {
font-weight: bold;
color: $color-alert-medium;
} }
} }
} }

View File

@ -45,8 +45,7 @@ export default class Dialog extends Component {
this.element.style.display = 'flex'; this.element.style.display = 'flex';
this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30); this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
if (this.onOpen) this.emit('open');
this.onOpen();
} }
/** /**
@ -55,6 +54,7 @@ export default class Dialog extends Component {
hide() { hide() {
this.fireResponse(); this.fireResponse();
this.realHide(); this.realHide();
this.emit('close');
} }
/** /**
@ -120,7 +120,6 @@ ngModule.component('vnDialog', {
buttons: '?tplButtons' buttons: '?tplButtons'
}, },
bindings: { bindings: {
onOpen: '&?',
onResponse: '&?' onResponse: '&?'
}, },
controller: Dialog controller: Dialog

View File

@ -7,7 +7,7 @@ describe('Component vnDialog', () => {
beforeEach(angular.mock.inject($componentController => { beforeEach(angular.mock.inject($componentController => {
$element = angular.element('<vn-dialog></vn-dialog>'); $element = angular.element('<vn-dialog></vn-dialog>');
controller = $componentController('vnDialog', {$element, $transclude: null}); controller = $componentController('vnDialog', {$element, $transclude: null});
controller.onOpen = jasmine.createSpy('onOpen'); controller.emit = jasmine.createSpy('emit');
})); }));
describe('show()', () => { describe('show()', () => {
@ -17,15 +17,15 @@ describe('Component vnDialog', () => {
controller.show(); controller.show();
expect(controller.element.style.display).toEqual('none'); expect(controller.element.style.display).toEqual('none');
expect(controller.onOpen).not.toHaveBeenCalledWith(); expect(controller.emit).not.toHaveBeenCalledWith('open');
}); });
it(`should set shown on the controller, set style.display on the element and call onOpen()`, () => { it(`should set shown on the controller, set style.display on the element and emit onOpen() event`, () => {
controller.show(); controller.show();
expect(controller.element.style.display).toEqual('flex'); expect(controller.element.style.display).toEqual('flex');
expect(controller.shown).toBeTruthy(); expect(controller.shown).toBeTruthy();
expect(controller.onOpen).toHaveBeenCalledWith(); expect(controller.emit).toHaveBeenCalledWith('open');
}); });
}); });

View File

@ -20,7 +20,7 @@ import './multi-check/multi-check';
import './date-picker/date-picker'; import './date-picker/date-picker';
import './button/button'; import './button/button';
import './check/check'; import './check/check';
import './radio/radio'; import './radio-group/radio-group';
import './textarea/textarea'; import './textarea/textarea';
import './icon-button/icon-button'; import './icon-button/icon-button';
import './submit/submit'; import './submit/submit';

View File

@ -22,7 +22,10 @@
ng-focus="$ctrl.hasFocus = true" ng-focus="$ctrl.hasFocus = true"
ng-blur="$ctrl.hasFocus = false" ng-blur="$ctrl.hasFocus = false"
tabindex="{{$ctrl.input.tabindex}}"/> tabindex="{{$ctrl.input.tabindex}}"/>
<label class="label" translate>{{::$ctrl.label}}</label> <label class="label">
<span translate>{{::$ctrl.label}}</span>
<span translate ng-show="::$ctrl.required">*</span>
</label>
</div> </div>
<div class="underline"></div> <div class="underline"></div>
<div class="selected underline"></div> <div class="selected underline"></div>

View File

@ -192,6 +192,7 @@ ngModule.component('vnInputNumber', {
label: '@?', label: '@?',
name: '@?', name: '@?',
disabled: '<?', disabled: '<?',
required: '@?',
min: '<?', min: '<?',
max: '<?', max: '<?',
step: '<?', step: '<?',

View File

@ -0,0 +1,8 @@
<md-radio-group ng-model="$ctrl.model">
<md-radio-button aria-label="::option.label"
ng-repeat="option in $ctrl.options"
ng-value="option.value"
ng-disabled="$ctrl.disabled">
<span translate>{{::option.label}}</span>
</md-radio-button>
</md-radio-group>

View File

@ -0,0 +1,41 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
export default class Controller extends Component {
constructor($element, $scope, $attrs) {
super($element, $scope);
this.hasInfo = Boolean($attrs.info);
this.info = $attrs.info || null;
}
get model() {
return this._model;
}
set model(value) {
this._model = value;
}
get field() {
return this._model;
}
set field(value) {
this._model = value;
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnRadioGroup', {
template: require('./radio-group.html'),
controller: Controller,
bindings: {
field: '=?',
options: '<?',
disabled: '<?',
checked: '<?'
}
});

View File

@ -0,0 +1,11 @@
@import "variables";
md-radio-group md-radio-button.md-checked .md-container {
.md-on {
background-color: $color-main
}
.md-off {
border-color: $color-main
}
}

View File

@ -1,7 +0,0 @@
<input
type="radio"
class="*[className]*"
name="*[name]*"
ng-model="*[model]*.*[name]*"
*[enabled]*>
<span class="mdl-radio__label" translate>*[text]*</span>

View File

@ -1,15 +0,0 @@
import ngModule from '../../module';
import template from './radio.html';
directive.$inject = ['vnTemplate'];
export default function directive(vnTemplate) {
return {
restrict: 'E',
template: (_, $attrs) =>
vnTemplate.get(template, $attrs, {
enabled: 'true',
className: 'mdl-radio mdl-js-radio mdl-js-ripple-effect'
})
};
}
ngModule.directive('vnRadio', directive);

View File

@ -16,7 +16,7 @@
tabindex="{{$ctrl.input.tabindex}}"/> tabindex="{{$ctrl.input.tabindex}}"/>
<label class="label"> <label class="label">
<span translate>{{::$ctrl.label}}</span> <span translate>{{::$ctrl.label}}</span>
<span translate ng-show="::$ctrl.required">(*)</span> <span translate vn-tooltip="Required" ng-show="::$ctrl.required">*</span>
</label> </label>
</div> </div>
<div class="underline"></div> <div class="underline"></div>

View File

@ -52,6 +52,8 @@ $color-hover-cd: rgba(0, 0, 0, .1);
$color-hover-dc: .7; $color-hover-dc: .7;
$color-disabled: .6; $color-disabled: .6;
$color-font-link-medium: lighten($color-font-link, 20%);
$color-font-link-light: lighten($color-font-link, 35%);
$color-main-medium: lighten($color-main, 20%); $color-main-medium: lighten($color-main, 20%);
$color-main-light: lighten($color-main, 35%); $color-main-light: lighten($color-main, 35%);
$color-success-medium: lighten($color-success, 20%); $color-success-medium: lighten($color-success, 20%);

View File

@ -0,0 +1,81 @@
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
module.exports = Self => {
Self.remoteMethod('editPrices', {
description: 'Changes the price and bonus of a delivery day',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Number',
description: 'The zone id',
http: {source: 'path'}
},
{
arg: 'delivered',
type: 'Date',
required: true,
},
{
arg: 'price',
type: 'Number',
required: true,
},
{
arg: 'bonus',
type: 'Number',
required: true,
},
{
arg: 'option',
type: 'String',
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/:id/editPrices`,
verb: 'POST'
}
});
Self.editPrices = async(id, delivered, price, bonus, option) => {
const models = Self.app.models;
let filter = {
where: {
zoneFk: id
}
};
let where;
let shouldPropagate = true;
if (option == 'Only this day') {
shouldPropagate = false;
where = {delivered};
} else if (option == 'From this day') {
where = {
delivered: {
gte: delivered
}
};
}
filter = mergeFilters(filter, {where});
const days = await models.ZoneCalendar.find(filter);
const areAllFromSameZone = days.every(day => day.zoneFk === id);
if (!areAllFromSameZone)
throw new UserError('All delivery days must belong to the same zone');
if (shouldPropagate) {
const zone = await models.Zone.findById(id);
zone.updateAttributes({price, bonus});
}
return models.ZoneCalendar.updateAll(filter.where, {price, bonus});
};
};

View File

@ -0,0 +1,84 @@
const app = require('vn-loopback/server/server');
describe('agency editPrices()', () => {
const zoneId = 1;
let originalZone;
beforeAll(async done => {
originalZone = await app.models.Zone.findById(zoneId);
done();
});
afterAll(async done => {
await await app.models.ZoneCalendar.updateAll({zoneFk: zoneId}, {
price: originalZone.price,
bonus: originalZone.bonus
});
done();
});
it('should apply price and bonus for a selected day', async() => {
const delivered = new Date();
delivered.setHours(0, 0, 0, 0);
delivered.setDate(delivered.getDate() + 1);
await app.models.Zone.editPrices(zoneId, delivered, 4.00, 2.00, 'Only this day');
const editedDays = await app.models.ZoneCalendar.find({
where: {
zoneFk: zoneId,
delivered: delivered
}
});
const firstEditedDay = editedDays[0];
expect(editedDays.length).toEqual(1);
expect(firstEditedDay.price).toEqual(4.00);
expect(firstEditedDay.bonus).toEqual(2.00);
});
it('should apply price and bonus for all delivery days starting from selected day', async() => {
const delivered = new Date();
delivered.setHours(0, 0, 0, 0);
delivered.setDate(delivered.getDate() + 1);
await app.models.Zone.editPrices(1, delivered, 5.50, 1.00, 'From this day');
const editedDays = await app.models.ZoneCalendar.find({
where: {
zoneFk: zoneId,
delivered: {
gte: delivered
}
}
});
const firstEditedDay = editedDays[0];
const lastEditedDay = editedDays[editedDays.length - 1];
expect(editedDays.length).toEqual(4);
expect(firstEditedDay.price).toEqual(5.50);
expect(firstEditedDay.bonus).toEqual(1.00);
expect(lastEditedDay.price).toEqual(5.50);
expect(lastEditedDay.bonus).toEqual(1.00);
});
it('should apply price and bonus for all delivery days', async() => {
const delivered = new Date();
delivered.setHours(0, 0, 0, 0);
delivered.setDate(delivered.getDate() + 1);
await app.models.Zone.editPrices(1, delivered, 7.00, 0.00, 'All days');
const editedDays = await app.models.ZoneCalendar.find({
where: {
zoneFk: zoneId
}
});
const firstEditedDay = editedDays[0];
const lastEditedDay = editedDays[editedDays.length - 1];
expect(editedDays.length).toEqual(5);
expect(firstEditedDay.price).toEqual(7.00);
expect(firstEditedDay.bonus).toEqual(0.00);
expect(lastEditedDay.price).toEqual(7.00);
expect(lastEditedDay.bonus).toEqual(0.00);
});
});

View File

@ -14,6 +14,12 @@
"delivered": { "delivered": {
"id": true, "id": true,
"type": "Date" "type": "Date"
},
"price": {
"type": "Number"
},
"bonus": {
"type": "Number"
} }
}, },
"relations": { "relations": {

View File

@ -1,5 +1,6 @@
module.exports = Self => { module.exports = Self => {
require('../methods/zone/clone')(Self); require('../methods/zone/clone')(Self);
require('../methods/zone/editPrices')(Self);
Self.validatesPresenceOf('warehouseFk', { Self.validatesPresenceOf('warehouseFk', {
message: `Warehouse cannot be blank` message: `Warehouse cannot be blank`

View File

@ -1,21 +1,74 @@
<vn-crud-model <vn-crud-model
vn-id="model" vn-id="model"
url="/agency/api/ZoneCalendars" url="/agency/api/ZoneCalendars"
fields="['zoneFk', 'delivered']"
link="{zoneFk: $ctrl.$stateParams.id}" link="{zoneFk: $ctrl.$stateParams.id}"
data="$ctrl.data" data="$ctrl.data"
primary-key="zoneFk" primary-key="zoneFk"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-calendar pad-small vn-id="stMonth" skip="2" <vn-watcher
data="$ctrl.events" vn-id="watcher"
on-selection="$ctrl.onSelection(stMonth, values)" data="$ctrl.selectedDay">
on-move-next="$ctrl.onMoveNext(ndMonth)" </vn-watcher>
on-move-previous="$ctrl.onMovePrevious(ndMonth)">
</vn-calendar> <vn-card pad-large>
<vn-calendar pad-small vn-id="ndMonth" skip="2" <vn-horizontal pad-medium style="justify-content: space-between;">
<vn-icon-button icon="keyboard_arrow_left"
ng-click="$ctrl.onMovePrevious([stMonth, ndMonth])"
vn-tooltip="Previous">
</vn-icon-button>
<vn-icon-button icon="keyboard_arrow_right"
ng-click="$ctrl.onMoveNext([stMonth, ndMonth])"
vn-tooltip="Next">
</vn-icon-button>
</vn-horizontal>
<vn-horizontal>
<vn-calendar vn-id="stMonth" vn-one pad-medium
data="$ctrl.events" data="$ctrl.events"
display-controls="false" display-controls="false"
on-selection="$ctrl.onSelection(ndMonth, values)" on-selection="$ctrl.onSelection(values)"
default-date="$ctrl.ndMonthDate"> skip="2">
</vn-calendar> </vn-calendar>
<vn-calendar vn-id="ndMonth" vn-one pad-medium
data="$ctrl.events"
display-controls="false"
on-selection="$ctrl.onSelection(values)"
default-date="$ctrl.ndMonthDate"
skip="2">
</vn-calendar>
</vn-horizontal>
</vn-card>
<!-- Edit price dialog -->
<vn-dialog class="edit"
vn-id="priceDialog"
on-close="$ctrl.onClose()"
on-response="$ctrl.onResponse(response)">
<tpl-body>
<h5 pad-small-v translate>Edit price</h5>
<vn-horizontal>
<vn-input-number vn-one
label="Price"
model="$ctrl.selectedDay.price"
min="0" step="0.01"
required="true">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
model="$ctrl.selectedDay.bonus"
min="0" step="0.01"
required="true">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-radio-group vn-one
field="$ctrl.selectedDay.option"
options="$ctrl.options">
</vn-radio-group>
</vn-horizontal>
</tpl-body>
<tpl-buttons>
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Save</button>
</tpl-buttons>
</vn-dialog>

View File

@ -1,49 +1,26 @@
import ngModule from '../module'; import ngModule from '../module';
import './style.scss';
class Controller { class Controller {
constructor($element, $scope, $stateParams, $http) { constructor($element, $scope, $http, $filter, $translate, $stateParams, vnApp) {
this.$element = $element; this.$element = $element;
this.$stateParams = $stateParams; this.$ = $scope;
this.$scope = $scope;
this.$http = $http; this.$http = $http;
this.$filter = $filter;
this.$translate = $translate;
this.$stateParams = $stateParams;
this.vnApp = vnApp;
this.stMonthDate = new Date(); this.stMonthDate = new Date();
this.ndMonthDate = new Date(); this.ndMonthDate = new Date();
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1); this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
this.selectedDay = {};
} }
$postLink() { $postLink() {
this.stMonth = this.$scope.stMonth; this.stMonth = this.$.stMonth;
this.ndMonth = this.$scope.ndMonth; this.ndMonth = this.$.ndMonth;
} }
// Disabled until implementation
// of holidays by node
/* get zone() {
return this._zone;
}
set zone(value) {
this._zone = value;
if (!value) return;
let query = '/agency/api/LabourHolidays/getByWarehouse';
this.$http.get(query, {params: {warehouseFk: value.warehouseFk}}).then(res => {
if (!res.data) return;
const events = [];
res.data.forEach(holiday => {
events.push({
date: holiday.dated,
className: 'red',
title: holiday.description || holiday.name,
isRemovable: false
});
});
this.events = this.events.concat(events);
});
} */
get data() { get data() {
return this._data; return this._data;
} }
@ -52,97 +29,106 @@ class Controller {
this._data = value; this._data = value;
if (!value) return; if (!value) return;
const events = []; const events = [];
value.forEach(event => { value.forEach(event => {
events.push({ events.push({
name: `P: ${this.$filter('currency')(event.price)}`,
description: 'Price',
dated: event.delivered, dated: event.delivered,
className: 'green-circle', style: {backgroundColor: '#a3d131'},
title: 'Has delivery' data: {price: event.price}
});
events.push({
name: `B: ${this.$filter('currency')(event.bonus)}`,
description: 'Bonus',
dated: event.delivered,
data: {bonus: event.bonus}
}); });
}); });
this.events = events; this.events = events;
} }
onSelection(calendar, values) { onSelection(values) {
let totalEvents = 0; if (values.length > 1) return false;
values.forEach(day => {
const exists = calendar.events.findIndex(event => {
return event.dated >= day.dated && event.dated <= day.dated
&& event.isRemovable;
});
if (exists > -1) totalEvents++; this.options = [
}); {label: 'Only this day', value: 'Only this day'},
{label: 'From this day', value: 'From this day'},
{label: 'All days', value: 'All days'}
];
const selection = values[0];
const events = selection.events;
const hasEvents = events.length > 0;
if (totalEvents > (values.length / 2)) if (!hasEvents)
this.removeEvents(calendar, values); return this.vnApp.showMessage(this.$translate.instant(`There's no delivery for this day`));
else
this.insertEvents(calendar, values); this.selectedDay = {
delivered: selection.dated,
option: 'Only this day'
};
events.forEach(event => {
this.selectedDay = Object.assign(this.selectedDay, event.data);
});
this.$.priceDialog.show();
} }
insertEvents(calendar, days) { onResponse(response) {
days.forEach(day => { if (response == 'ACCEPT') {
const event = calendar.events.find(event => { try {
return event.dated >= day.dated && event.dated <= day.dated; const data = {
}); delivered: this.selectedDay.delivered,
price: this.selectedDay.price,
bonus: this.selectedDay.bonus,
option: this.selectedDay.option
};
if (event) return false; this.$.watcher.check();
this.$scope.model.insert({ const path = `/api/Zones/${this.zone.id}/editPrices`;
zoneFk: this.zone.id, this.$http.post(path, data).then(() => {
delivered: day.dated this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.model.refresh();
this.card.reload();
}); });
} catch (e) {
calendar.addEvent({ this.vnApp.showError(this.$translate.instant(e.message));
dated: day.dated,
className: 'green-circle',
title: 'Has delivery'
});
});
this.$scope.model.save().then(() => {
this.events = calendar.events;
});
}
removeEvents(calendar, days) {
let dates = [];
days.forEach(day => {
const event = calendar.events.find(event => {
return event.dated >= day.dated && event.dated <= day.dated;
});
if (event && !event.isRemovable)
return false; return false;
}
dates.push(day.dated);
calendar.removeEvent(day.dated);
});
if (dates.length == 0) return;
const params = {zoneFk: this.zone.id, dates};
this.$http.post('/agency/api/zoneCalendars/removeByDate', params).then(() => {
this.events = calendar.events;
});
} }
onMoveNext(calendar) { return this.onClose();
}
onClose() {
this.$.watcher.updateOriginalData();
}
onMoveNext(calendars) {
calendars.forEach(calendar => {
calendar.moveNext(2); calendar.moveNext(2);
});
} }
onMovePrevious(calendar) { onMovePrevious(calendars) {
calendars.forEach(calendar => {
calendar.movePrevious(2); calendar.movePrevious(2);
});
} }
} }
Controller.$inject = ['$element', '$scope', '$stateParams', '$http']; Controller.$inject = ['$element', '$scope', '$http', '$filter', '$translate', '$stateParams', 'vnApp'];
ngModule.component('vnZoneCalendar', { ngModule.component('vnZoneCalendar', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
zone: '<' zone: '<'
},
require: {
card: '^vnZoneCard'
} }
}); });

View File

@ -0,0 +1,6 @@
Prices: Precios
Edit price: Modificar precio
Only this day: Solo este día
From this day: A partir de este día
All days: Todos los días
There's no delivery for this day: No hay reparto para este día

View File

@ -0,0 +1,3 @@
vn-calendar:nth-child(2n + 1) {
border-right:1px solid #ddd
}

View File

@ -8,4 +8,5 @@ import './search-panel';
import './create'; import './create';
import './basic-data'; import './basic-data';
import './location'; import './location';
import './location/calendar';
import './calendar'; import './calendar';

View File

@ -0,0 +1,21 @@
<vn-crud-model
vn-id="model"
url="/agency/api/ZoneCalendars"
fields="['zoneFk', 'delivered']"
link="{zoneFk: $ctrl.$stateParams.id}"
data="$ctrl.data"
primary-key="zoneFk"
auto-load="true">
</vn-crud-model>
<vn-calendar pad-small vn-id="stMonth" skip="2"
data="$ctrl.events"
on-selection="$ctrl.onSelection(values, stMonth)"
on-move-next="$ctrl.onMoveNext(ndMonth)"
on-move-previous="$ctrl.onMovePrevious(ndMonth)">
</vn-calendar>
<vn-calendar pad-small vn-id="ndMonth" skip="2"
data="$ctrl.events"
display-controls="false"
on-selection="$ctrl.onSelection(values, ndMonth)"
default-date="$ctrl.ndMonthDate">
</vn-calendar>

View File

@ -0,0 +1,150 @@
import ngModule from '../module';
class Controller {
constructor($element, $scope, $stateParams, $http) {
this.$element = $element;
this.$stateParams = $stateParams;
this.$scope = $scope;
this.$http = $http;
this.stMonthDate = new Date();
this.ndMonthDate = new Date();
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
}
$postLink() {
this.stMonth = this.$scope.stMonth;
this.ndMonth = this.$scope.ndMonth;
}
// Disabled until implementation
// of holidays by node
/* get zone() {
return this._zone;
}
set zone(value) {
this._zone = value;
if (!value) return;
let query = '/agency/api/LabourHolidays/getByWarehouse';
this.$http.get(query, {params: {warehouseFk: value.warehouseFk}}).then(res => {
if (!res.data) return;
const events = [];
res.data.forEach(holiday => {
events.push({
date: holiday.dated,
className: 'red',
title: holiday.description || holiday.name,
isRemovable: false
});
});
this.events = this.events.concat(events);
});
} */
get data() {
return this._data;
}
set data(value) {
this._data = value;
if (!value) return;
const events = [];
value.forEach(event => {
events.push({
name: 'Has delivery',
dated: event.delivered,
style: {backgroundColor: '#a3d131'}
});
});
this.events = events;
}
onSelection(values, calendar) {
let totalEvents = 0;
values.forEach(day => {
const exists = calendar.events.findIndex(event => {
return event.dated >= day.dated && event.dated <= day.dated
&& event.isRemovable;
});
if (exists > -1) totalEvents++;
});
if (totalEvents > (values.length / 2))
this.removeEvents(calendar, values);
else
this.insertEvents(calendar, values);
}
insertEvents(calendar, days) {
days.forEach(day => {
const event = calendar.events.find(event => {
return event.dated >= day.dated && event.dated <= day.dated;
});
if (event) return false;
this.$scope.model.insert({
zoneFk: this.zone.id,
delivered: day.dated,
price: this.zone.price,
bonus: this.zone.bonus
});
calendar.addEvent({
name: 'Has delivery',
dated: day.dated,
style: {backgroundColor: '#a3d131'}
});
});
this.$scope.model.save().then(() => {
this.events = calendar.events;
});
}
removeEvents(calendar, days) {
let dates = [];
days.forEach(day => {
const event = calendar.events.find(event => {
return event.dated >= day.dated && event.dated <= day.dated;
});
if (event && !event.isRemovable)
return false;
dates.push(day.dated);
calendar.removeEvent(day.dated);
});
if (dates.length == 0) return;
const params = {zoneFk: this.zone.id, dates};
this.$http.post('/agency/api/zoneCalendars/removeByDate', params).then(() => {
this.events = calendar.events;
});
}
onMoveNext(calendar) {
calendar.moveNext(2);
}
onMovePrevious(calendar) {
calendar.movePrevious(2);
}
}
Controller.$inject = ['$element', '$scope', '$stateParams', '$http'];
ngModule.component('vnZoneLocationCalendar', {
template: require('./calendar.html'),
controller: Controller,
bindings: {
zone: '<'
}
});

View File

@ -18,6 +18,6 @@
</vn-treeview> </vn-treeview>
</vn-card> </vn-card>
<vn-side-menu side="right"> <vn-side-menu side="right">
<vn-zone-calendar zone="::$ctrl.zone"></vn-zone-calendar> <vn-zone-location-calendar zone="::$ctrl.zone"></vn-zone-location-calendar>
</vn-side-menu> </vn-side-menu>
</div> </div>

View File

@ -6,7 +6,8 @@
"dependencies": ["worker"], "dependencies": ["worker"],
"menu": [ "menu": [
{"state": "zone.card.basicData", "icon": "settings"}, {"state": "zone.card.basicData", "icon": "settings"},
{"state": "zone.card.location", "icon": "my_location"} {"state": "zone.card.location", "icon": "my_location"},
{"state": "zone.card.calendar"}
], ],
"routes": [ "routes": [
{ {
@ -15,27 +16,31 @@
"abstract": true, "abstract": true,
"component": "ui-view", "component": "ui-view",
"description": "Zones" "description": "Zones"
}, { },
{
"url": "/index?q", "url": "/index?q",
"state": "zone.index", "state": "zone.index",
"component": "vn-zone-index", "component": "vn-zone-index",
"description": "Zones" "description": "Zones"
}, { },
{
"url": "/create", "url": "/create",
"state": "zone.create", "state": "zone.create",
"component": "vn-zone-create", "component": "vn-zone-create",
"description": "New zone" "description": "New zone"
}, { },
{
"url": "/:id", "url": "/:id",
"state": "zone.card", "state": "zone.card",
"component": "vn-zone-card", "component": "vn-zone-card",
"abstract": true, "abstract": true,
"description": "Detail" "description": "Detail"
}, { },
"url": "/location?q", {
"state": "zone.card.location", "url": "/summary",
"component": "vn-zone-location", "state": "zone.card.summary",
"description": "Locations", "component": "vn-zone-summary",
"description": "Summary",
"params": { "params": {
"zone": "$ctrl.zone" "zone": "$ctrl.zone"
} }
@ -50,10 +55,19 @@
} }
}, },
{ {
"url": "/summary", "url": "/location?q",
"state": "zone.card.summary", "state": "zone.card.location",
"component": "vn-zone-summary", "component": "vn-zone-location",
"description": "Summary", "description": "Locations",
"params": {
"zone": "$ctrl.zone"
}
},
{
"url": "/calendar",
"state": "zone.card.calendar",
"component": "vn-zone-calendar",
"description": "Prices",
"params": { "params": {
"zone": "$ctrl.zone" "zone": "$ctrl.zone"
} }

View File

@ -27,6 +27,5 @@
"model": "Client", "model": "Client",
"foreignKey": "clientFk" "foreignKey": "clientFk"
} }
}, }
"scope" : {"where": {"amount": {"gt": 0}}}
} }

View File

@ -186,7 +186,7 @@
info="Invoices minus payments"> info="Invoices minus payments">
</vn-label-value> </vn-label-value>
<vn-label-value label="Balance due" <vn-label-value label="Balance due"
value="{{$ctrl.summary.defaulters[0].amount | currency: 'EUR':2}}" value="{{($ctrl.summary.defaulters[0].amount >= 0 ? $ctrl.summary.defaulters[0].amount : '-') | currency: 'EUR':2}}"
ng-class="{alert: $ctrl.summary.defaulters[0].amount}" ng-class="{alert: $ctrl.summary.defaulters[0].amount}"
info="Deviated invoices minus payments"> info="Deviated invoices minus payments">
</vn-label-value> </vn-label-value>

View File

@ -1,11 +1,14 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('item getDiary()', () => { describe('item getDiary()', () => {
it('should return 2 entries, the first one with the property balance -100', async() => { it('should check the property balance of the 4 resultant entries', async() => {
let params = {where: {itemFk: 1, warehouseFk: 2}}; let params = {where: {itemFk: 1, warehouseFk: 2}};
let result = await app.models.Item.getDiary(params); let result = await app.models.Item.getDiary(params);
expect(result.length).toBe(2); expect(result.length).toBe(4);
expect(result[0].balance).toBe(-100); expect(result[0].balance).toBe(-1000);
expect(result[1].balance).toBe(-1100);
expect(result[2].balance).toBe(-1110);
expect(result[3].balance).toBe(-1210);
}); });
}); });

View File

@ -9,7 +9,7 @@ describe('item getLastEntries()', () => {
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
}); });
it('should return three entries for a given item', async() => { it('should return five entries for a given item', async() => {
let date = new Date(); let date = new Date();
date.setMonth(date.getMonth() - 2, 1); date.setMonth(date.getMonth() - 2, 1);
@ -17,6 +17,6 @@ describe('item getLastEntries()', () => {
let filter = {where: {itemFk: 1, date: date}}; let filter = {where: {itemFk: 1, date: date}};
let result = await app.models.Item.getLastEntries(filter); let result = await app.models.Item.getLastEntries(filter);
expect(result.length).toEqual(3); expect(result.length).toEqual(5);
}); });
}); });

View File

@ -51,7 +51,7 @@ describe('Route filter()', () => {
let result = await app.models.Route.filter(ctx); let result = await app.models.Route.filter(ctx);
expect(result.length).toEqual(4); expect(result.length).toEqual(3);
}); });
it('should return the routes matching "description"', async() => { it('should return the routes matching "description"', async() => {

View File

@ -10,7 +10,7 @@ describe('route updateVolume()', () => {
afterAll(async done => { afterAll(async done => {
await originalRoute.updateAttributes({m3: 0.1}); await originalRoute.updateAttributes({m3: 0.3});
await ticketToRestore.updateAttributes({routeFk: 2}); await ticketToRestore.updateAttributes({routeFk: 2});
await app.models.RouteLog.destroyById(logIdToDestroy); await app.models.RouteLog.destroyById(logIdToDestroy);
done(); done();
@ -19,7 +19,7 @@ describe('route updateVolume()', () => {
it('should confirm the original volume of the route is the expected', async() => { it('should confirm the original volume of the route is the expected', async() => {
originalRoute = await app.models.Route.findById(routeId); originalRoute = await app.models.Route.findById(routeId);
expect(originalRoute.m3).toEqual(0.1); expect(originalRoute.m3).toEqual(0.3);
}); });
it('should confirm the route volume is updated when a ticket is added', async() => { it('should confirm the route volume is updated when a ticket is added', async() => {
@ -37,7 +37,7 @@ describe('route updateVolume()', () => {
it('should confirm the change is logged', async() => { it('should confirm the change is logged', async() => {
let logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']}); let logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']});
let m3Log = logs.filter(log => { let m3Log = logs.filter(log => {
return log.newInstance.m3 === 0.2; return log.newInstance.m3 === 0.4;
}); });
logIdToDestroy = m3Log[0].id; logIdToDestroy = m3Log[0].id;

View File

@ -4,7 +4,7 @@ describe('ticket getSalesPersonMana()', () => {
it('should get the mana of a salesperson of a given ticket', async() => { it('should get the mana of a salesperson of a given ticket', async() => {
let mana = await app.models.Ticket.getSalesPersonMana(1); let mana = await app.models.Ticket.getSalesPersonMana(1);
expect(mana).toEqual(261); expect(mana).toEqual(301);
}); });
it('should return 0 if the given ticket does not exist', async() => { it('should return 0 if the given ticket does not exist', async() => {

View File

@ -4,7 +4,7 @@ describe('workerMana getCurrentWorkerMana()', () => {
it('should get the mana of the logged worker', async() => { it('should get the mana of the logged worker', async() => {
let mana = await app.models.WorkerMana.getCurrentWorkerMana({req: {accessToken: {userId: 18}}}); let mana = await app.models.WorkerMana.getCurrentWorkerMana({req: {accessToken: {userId: 18}}});
expect(mana).toEqual(261); expect(mana).toEqual(301);
}); });
it('should return 0 if the user doesnt uses mana', async() => { it('should return 0 if the user doesnt uses mana', async() => {

View File

@ -3,7 +3,7 @@
data="$ctrl.absenceTypes" auto-load="true"> data="$ctrl.absenceTypes" auto-load="true">
</vn-crud-model> </vn-crud-model>
<div class="main-with-right-menu"> <div class="main-with-right-menu">
<vn-card compact pad-large> <vn-card pad-large>
<vn-horizontal class="calendar-list"> <vn-horizontal class="calendar-list">
<section class="calendar" ng-repeat="month in $ctrl.months"> <section class="calendar" ng-repeat="month in $ctrl.months">
<vn-calendar <vn-calendar

View File

@ -45,10 +45,11 @@ class Controller {
const holidayName = holidayDetail || holidayType; const holidayName = holidayDetail || holidayType;
events.push({ events.push({
name: holidayName,
description: holidayName,
dated: holiday.dated, dated: holiday.dated,
className: 'red', isRemovable: false,
title: holidayName, style: {backgroundColor: '#FFFF00'}
isRemovable: false
}); });
}); });
this.events = this.events.concat(events); this.events = this.events.concat(events);
@ -62,11 +63,10 @@ class Controller {
absences.forEach(absence => { absences.forEach(absence => {
const absenceType = absence.absenceType; const absenceType = absence.absenceType;
events.push({ events.push({
name: absenceType.name,
description: absenceType.name,
dated: absence.dated, dated: absence.dated,
title: absenceType.name, style: {backgroundColor: absenceType.rgb}
style: {
background: absenceType.rgb
}
}); });
}); });
this.events = this.events.concat(events); this.events = this.events.concat(events);

View File

@ -93,7 +93,7 @@ describe('Worker', () => {
controller.setHolidays(data); controller.setHolidays(data);
expect(controller.events.length).toEqual(2); expect(controller.events.length).toEqual(2);
expect(controller.events[0].title).toEqual('New year'); expect(controller.events[0].name).toEqual('New year');
expect(controller.events[0].isRemovable).toEqual(false); expect(controller.events[0].isRemovable).toEqual(false);
}); });
}); });
@ -107,9 +107,9 @@ describe('Worker', () => {
controller.setWorkerCalendar(data); controller.setWorkerCalendar(data);
expect(controller.events.length).toEqual(2); expect(controller.events.length).toEqual(2);
expect(controller.events[0].title).toEqual('Holiday'); expect(controller.events[0].name).toEqual('Holiday');
expect(controller.events[0].style).toBeDefined(); expect(controller.events[0].style).toBeDefined();
expect(controller.events[1].title).toEqual('Leave'); expect(controller.events[1].name).toEqual('Leave');
expect(controller.events[1].style).toBeDefined(); expect(controller.events[1].style).toBeDefined();
}); });
}); });

View File

@ -1,5 +1,13 @@
@import "variables"; @import "variables";
.calendar-list .calendar {
border-bottom:1px solid #ddd
}
.calendar-list .calendar:nth-child(2n + 1) {
border-right:1px solid #ddd
}
.calendar-list { .calendar-list {
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
@ -9,7 +17,7 @@
box-sizing: border-box; box-sizing: border-box;
padding: $pad-medium; padding: $pad-medium;
overflow: hidden; overflow: hidden;
width: 20em width: 50%
} }
} }