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

This commit is contained in:
Carlos Satorres 2024-09-13 13:06:51 +02:00
commit c3c60b1fa7
106 changed files with 856 additions and 1245 deletions

View File

@ -9,7 +9,7 @@
},
"vn": {
"view": {
"expeditionPallet_Print": "ced2b84a114fcb99fce05f0c34f4fc03f3fa387bef92621be1bc306608a84345"
"expeditionPallet_Print": "99f75145ac2e7b612a6d71e74b6e55f194a465780fd9875a15eb01e6596b447e"
}
}
}

View File

@ -2488,7 +2488,7 @@ INSERT INTO `vn`.`clientDms`(`clientFk`, `dmsFk`)
(1104, 2),
(1104, 3);
INSERT INTO `vn`.`workerDocument`(`id`, `worker`, `document`,`isReadableByWorker`)
INSERT INTO `vn`.`workerDms`(`id`, `workerFk`, `dmsFk`,`isReadableByWorker`)
VALUES
(1, 1106, 4, TRUE),
(2, 1107, 3, FALSE);
@ -3057,9 +3057,6 @@ INSERT INTO `vn`.`workerTimeControlMail` (`id`, `workerFk`, `year`, `week`, `sta
(3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL),
(4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL);
INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minHeightBetweenTrays`, `maxTrays`)
VALUES
(1, 1350, 1900, 200, 50, 6);
INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`)
VALUES
@ -3068,15 +3065,19 @@ INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`)
(3, 'green', '#00ff00'),
(4, 'blue', '#0000ff');
INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minHeightBetweenTrays`, `maxTrays`, `defaultTrayColorFk`)
VALUES
(1, 1350, 1900, 200, 50, 6, 1);
INSERT INTO `vn`.`wagonType` (`id`, `name`, `divisible`)
VALUES
(1, 'Wagon Type #1', 1);
INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
INSERT INTO `vn`.`wagonTypeTray` (`id`, `wagonTypeFk`, `height`, `wagonTypeColorFk`)
VALUES
(1, 1, 100, 1),
(1, 1, 0, 1),
(2, 1, 50, 2),
(3, 1, 0, 3);
(3, 1, 100, 3);
INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `courtesyTime`, `renewInterval`)
VALUES

View File

@ -1,8 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `edi`.`floramondo`
ON SCHEDULE EVERY 6 MINUTE
STARTS '2022-01-28 09:52:45.000'
ON COMPLETION NOT PRESERVE
DISABLE
DO CALL edi.floramondo_offerRefresh()$$
DELIMITER ;

View File

@ -1,522 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `edi`.`floramondo_offerRefresh`()
proc: BEGIN
DECLARE vLanded DATETIME;
DECLARE vDone INT DEFAULT FALSE;
DECLARE vFreeId INT;
DECLARE vSupplyResponseFk INT;
DECLARE vLastInserted DATETIME;
DECLARE vIsAuctionDay BOOLEAN;
DECLARE vMaxNewItems INT DEFAULT 10000;
DECLARE vStartingTime DATETIME;
DECLARE vAalsmeerMarketPlaceID VARCHAR(13) DEFAULT '8713783439043';
DECLARE vDayRange INT;
DECLARE cur1 CURSOR FOR
SELECT id
FROM edi.item_free;
DECLARE cur2 CURSOR FOR
SELECT srId
FROM itemToInsert;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLSTATE '45000'
BEGIN
ROLLBACK;
RESIGNAL;
END;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
DO RELEASE_LOCK('edi.floramondo_offerRefresh');
SET @isTriggerDisabled = FALSE;
RESIGNAL;
END;
IF 'test' = (SELECT environment FROM util.config) THEN
LEAVE proc;
END IF;
IF !GET_LOCK('edi.floramondo_offerRefresh', 0) THEN
LEAVE proc;
END IF;
SELECT dayRange INTO vDayRange
FROM offerRefreshConfig;
IF vDayRange IS NULL THEN
CALL util.throw("Variable vDayRange not declared");
END IF;
SET vStartingTime = util.VN_NOW();
TRUNCATE edi.offerList;
INSERT INTO edi.offerList(supplier, total)
SELECT v.name, COUNT(DISTINCT sr.ID) total
FROM edi.supplyResponse sr
JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID
WHERE sr.NumberOfUnits > 0
AND sr.EmbalageCode != 999
GROUP BY sr.vmpID;
UPDATE edi.offerList o
JOIN (SELECT v.name, COUNT(*) total
FROM edi.supplyOffer sr
JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID
GROUP BY sr.vmpID) sub ON o.supplier = sub.name
SET o.`filter` = sub.total;
-- Elimina de la lista de items libres aquellos que ya existen
DELETE itf.*
FROM edi.item_free itf
JOIN vn.item i ON i.id = itf.id;
CREATE OR REPLACE TEMPORARY TABLE tmp
(INDEX (`Item_ArticleCode`))
ENGINE = MEMORY
SELECT t.*
FROM (
SELECT *
FROM edi.supplyOffer
ORDER BY (MarketPlaceID = vAalsmeerMarketPlaceID) DESC,
NumberOfUnits DESC LIMIT 10000000000000000000) t
GROUP BY t.srId;
CREATE OR REPLACE TEMPORARY TABLE edi.offer (INDEX (`srID`), INDEX (`EmbalageCode`),
INDEX (`ef1`), INDEX (`ef2`), INDEX (`ef3`), INDEX (`ef4`),INDEX (`ef5`), INDEX (`ef6`),
INDEX (`s1Value`), INDEX (`s2Value`), INDEX (`s3Value`), INDEX (`s4Value`),INDEX (`s5Value`), INDEX (`s6Value`))
ENGINE = MEMORY
SELECT so.*,
ev1.type_description s1Value,
ev2.type_description s2Value,
ev3.type_description s3Value,
ev4.type_description s4Value,
ev5.type_description s5Value,
ev6.type_description s6Value,
eif1.feature ef1,
eif2.feature ef2,
eif3.feature ef3,
eif4.feature ef4,
eif5.feature ef5,
eif6.feature ef6
FROM tmp so
LEFT JOIN edi.item_feature eif1 ON eif1.item_id = so.Item_ArticleCode
AND eif1.presentation_order = 1
AND eif1.expiry_date IS NULL
LEFT JOIN edi.item_feature eif2 ON eif2.item_id = so.Item_ArticleCode
AND eif2.presentation_order = 2
AND eif2.expiry_date IS NULL
LEFT JOIN edi.item_feature eif3 ON eif3.item_id = so.Item_ArticleCode
AND eif3.presentation_order = 3
AND eif3.expiry_date IS NULL
LEFT JOIN edi.item_feature eif4 ON eif4.item_id = so.Item_ArticleCode
AND eif4.presentation_order = 4
AND eif4.expiry_date IS NULL
LEFT JOIN edi.item_feature eif5 ON eif5.item_id = so.Item_ArticleCode
AND eif5.presentation_order = 5
AND eif5.expiry_date IS NULL
LEFT JOIN edi.item_feature eif6 ON eif6.item_id = so.Item_ArticleCode
AND eif6.presentation_order = 6
AND eif6.expiry_date IS NULL
LEFT JOIN edi.`value` ev1 ON ev1.type_id = eif1.feature
AND so.s1 = ev1.type_value
LEFT JOIN edi.`value` ev2 ON ev2.type_id = eif2.feature
AND so.s2 = ev2.type_value
LEFT JOIN edi.`value` ev3 ON ev3.type_id = eif3.feature
AND so.s3 = ev3.type_value
LEFT JOIN edi.`value` ev4 ON ev4.type_id = eif4.feature
AND so.s4 = ev4.type_value
LEFT JOIN edi.`value` ev5 ON ev5.type_id = eif5.feature
AND so.s5 = ev5.type_value
LEFT JOIN edi.`value` ev6 ON ev6.type_id = eif6.feature
AND so.s6 = ev6.type_value
ORDER BY Price;
DROP TEMPORARY TABLE tmp;
DELETE o
FROM edi.offer o
LEFT JOIN vn.tag t1 ON t1.ediTypeFk = o.ef1 AND t1.overwrite = 'size'
LEFT JOIN vn.tag t2 ON t2.ediTypeFk = o.ef2 AND t2.overwrite = 'size'
LEFT JOIN vn.tag t3 ON t3.ediTypeFk = o.ef3 AND t3.overwrite = 'size'
LEFT JOIN vn.tag t4 ON t4.ediTypeFk = o.ef4 AND t4.overwrite = 'size'
LEFT JOIN vn.tag t5 ON t5.ediTypeFk = o.ef5 AND t5.overwrite = 'size'
LEFT JOIN vn.tag t6 ON t6.ediTypeFk = o.ef6 AND t6.overwrite = 'size'
JOIN vn.floramondoConfig fc ON TRUE
WHERE (t1.id IS NOT NULL AND CONVERT(s1Value, UNSIGNED) > fc.itemMaxSize)
OR (t2.id IS NOT NULL AND CONVERT(s2Value, UNSIGNED) > fc.itemMaxSize)
OR (t3.id IS NOT NULL AND CONVERT(s3Value, UNSIGNED) > fc.itemMaxSize)
OR (t4.id IS NOT NULL AND CONVERT(s4Value, UNSIGNED) > fc.itemMaxSize)
OR (t5.id IS NOT NULL AND CONVERT(s5Value, UNSIGNED) > fc.itemMaxSize)
OR (t6.id IS NOT NULL AND CONVERT(s6Value, UNSIGNED) > fc.itemMaxSize);
START TRANSACTION;
-- Actualizamos el campo supplyResponseFk para aquellos articulos que ya estan creados y reutilizamos
UPDATE IGNORE edi.offer o
JOIN vn.item i
ON i.name = o.product_name
AND i.subname <=> o.company_name
AND i.value5 <=> o.s1Value
AND i.value6 <=> o.s2Value
AND i.value7 <=> o.s3Value
AND i.value8 <=> o.s4Value
AND i.value9 <=> o.s5Value
AND i.value10 <=> o.s6Value
AND i.NumberOfItemsPerCask <=> o.NumberOfItemsPerCask
AND i.EmbalageCode <=> o.EmbalageCode
AND i.quality <=> o.Quality
JOIN vn.itemType it ON it.id = i.typeFk
LEFT JOIN vn.sale s ON s.itemFk = i.id
LEFT JOIN vn.ticket t ON t.id = s.ticketFk
AND t.shipped > (util.VN_CURDATE() - INTERVAL 1 WEEK)
LEFT JOIN edi.supplyResponse sr ON sr.ID = i.supplyResponseFk
LEFT JOIN edi.deliveryInformation di ON di.supplyResponseID = sr.ID
LEFT JOIN edi.putOrder po ON po.supplyResponseID = i.supplyResponseFk
AND po.OrderTradeLineDateTime > (util.VN_CURDATE() - INTERVAL 1 WEEK)
SET i.supplyResponseFk = o.srID
WHERE (sr.ID IS NULL
OR sr.NumberOfUnits = 0
OR di.LatestOrderDateTime < util.VN_NOW()
OR di.ID IS NULL)
AND it.isInventory
AND t.id IS NULL
AND po.id IS NULL;
CREATE OR REPLACE TEMPORARY TABLE itemToInsert
ENGINE = MEMORY
SELECT o.*, CAST(NULL AS DECIMAL(6,0)) itemFk
FROM edi.offer o
LEFT JOIN vn.item i ON i.supplyResponseFk = o.srId
WHERE i.id IS NULL
LIMIT vMaxNewItems;
-- Reciclado de nº de item
OPEN cur1;
OPEN cur2;
read_loop: LOOP
FETCH cur2 INTO vSupplyResponseFk;
FETCH cur1 INTO vFreeId;
IF vDone THEN
LEAVE read_loop;
END IF;
UPDATE itemToInsert
SET itemFk = vFreeId
WHERE srId = vSupplyResponseFk;
END LOOP;
CLOSE cur1;
CLOSE cur2;
-- Insertamos todos los items en Articles de la oferta
INSERT INTO vn.item(id,
`name`,
longName,
subName,
expenseFk,
typeFk,
intrastatFk,
originFk,
supplyResponseFk,
numberOfItemsPerCask,
embalageCode,
quality,
isFloramondo)
SELECT iti.itemFk,
iti.product_name,
iti.product_name,
iti.company_name,
iti.expenseFk,
iti.itemTypeFk,
iti.intrastatFk,
iti.originFk,
iti.`srId`,
iti.NumberOfItemsPerCask,
iti.EmbalageCode,
iti.Quality,
TRUE
FROM itemToInsert iti;
-- Inserta la foto de los articulos nuevos (prioridad alta)
INSERT IGNORE INTO vn.itemImageQueue(itemFk, url)
SELECT i.id, PictureReference
FROM itemToInsert ii
JOIN vn.item i ON i.supplyResponseFk = ii.srId
WHERE PictureReference IS NOT NULL
AND i.image IS NULL;
INSERT INTO edi.`log`(tableName, fieldName,fieldValue)
SELECT 'itemImageQueue','NumImagenesPtes', COUNT(*)
FROM vn.itemImageQueue
WHERE attempts = 0;
-- Inserta si se añadiesen tags nuevos
INSERT IGNORE INTO vn.tag (name, ediTypeFk)
SELECT description, type_id FROM edi.type;
-- Desabilita el trigger para recalcular los tags al final
SET @isTriggerDisabled = TRUE;
-- Inserta los tags sólo en los articulos nuevos
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , ii.product_name, 1
FROM itemToInsert ii
JOIN vn.tag t ON t.`name` = 'Producto'
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT ii.product_name IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , ii.Quality, 3
FROM itemToInsert ii
JOIN vn.tag t ON t.`name` = 'Calidad'
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT ii.Quality IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , ii.company_name, 4
FROM itemToInsert ii
JOIN vn.tag t ON t.`name` = 'Productor'
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT ii.company_name IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s1Value, 5
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef1
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s1Value IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s2Value, 6
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef2
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s2Value IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s3Value, 7
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef3
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s3Value IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s4Value, 8
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef4
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s4Value IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s5Value, 9
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef5
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s5Value IS NULL;
INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id , s6Value, 10
FROM itemToInsert ii
JOIN vn.tag t ON t.ediTypeFk = ii.ef6
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
WHERE NOT s6Value IS NULL;
INSERT IGNORE INTO vn.itemTag(itemFk, tagFk, value, priority)
SELECT i.id, t.id, IFNULL(ink.name, ik.color), 11
FROM itemToInsert ii
JOIN vn.item i ON i.supplyResponseFk = ii.`srId`
JOIN vn.tag t ON t.`name` = 'Color'
LEFT JOIN edi.feature f ON f.item_id = ii.Item_ArticleCode
LEFT JOIN edi.`type` tp ON tp.type_id = f.feature_type_id
AND tp.`description` = 'Hoofdkleur 1'
LEFT JOIN vn.ink ON ink.dutchCode = f.feature_value
LEFT JOIN vn.itemInk ik ON ik.longName = i.longName
WHERE ink.name IS NOT NULL
OR ik.color IS NOT NULL;
CREATE OR REPLACE TABLE tmp.item
(PRIMARY KEY (id))
SELECT i.id FROM vn.item i
JOIN itemToInsert ii ON i.supplyResponseFk = ii.`srId`;
CALL vn.item_refreshTags();
DROP TABLE tmp.item;
SELECT MIN(LatestDeliveryDateTime) INTO vLanded
FROM edi.supplyResponse sr
JOIN edi.deliveryInformation di ON di.supplyResponseID = sr.ID
JOIN edi.marketPlace mp ON mp.id = sr.MarketPlaceID
JOIN vn.floramondoConfig fc
WHERE mp.isLatestOrderDateTimeRelevant
AND di.LatestOrderDateTime > IF(
fc.MaxLatestOrderHour > HOUR(util.VN_NOW()),
util.VN_CURDATE(),
util.VN_CURDATE() + INTERVAL 1 DAY);
UPDATE vn.floramondoConfig
SET nextLanded = vLanded
WHERE vLanded IS NOT NULL;
-- Elimina la oferta obsoleta
UPDATE vn.buy b
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.agencyMode am ON am.id = tr.agencyModeFk
JOIN vn.item i ON i.id = b.itemFk
LEFT JOIN edi.supplyResponse sr ON i.supplyResponseFk = sr.ID
LEFT JOIN edi.deliveryInformation di ON di.ID = b.deliveryFk
SET b.quantity = 0
WHERE (IFNULL(di.LatestOrderDateTime,util.VN_NOW()) <= util.VN_NOW()
OR i.supplyResponseFk IS NULL
OR sr.NumberOfUnits = 0)
AND am.name = 'LOGIFLORA'
AND e.isRaid;
-- Localiza las entradas de cada almacen
UPDATE edi.warehouseFloramondo
SET entryFk = vn.entry_getForLogiflora(vLanded + INTERVAL travellingDays DAY, warehouseFk);
IF vLanded IS NOT NULL THEN
-- Actualiza la oferta existente
UPDATE vn.buy b
JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk
JOIN vn.item i ON i.id = b.itemFk
JOIN edi.offer o ON i.supplyResponseFk = o.`srId`
SET b.quantity = o.NumberOfUnits * o.NumberOfItemsPerCask,
b.buyingValue = o.price
WHERE (b.quantity <> o.NumberOfUnits * o.NumberOfItemsPerCask
OR b.buyingValue <> o.price);
-- Inserta el resto
SET vLastInserted := util.VN_NOW();
-- Inserta la oferta
INSERT INTO vn.buy (
entryFk,
itemFk,
quantity,
buyingValue,
stickers,
packing,
`grouping`,
groupingMode,
packagingFk,
deliveryFk)
SELECT wf.entryFk,
i.id,
o.NumberOfUnits * o.NumberOfItemsPerCask quantity,
o.Price,
o.NumberOfUnits etiquetas,
o.NumberOfItemsPerCask packing,
GREATEST(1, IFNULL(o.MinimumQuantity,0)) * o.NumberOfItemsPerCask `grouping`,
'packing',
o.embalageCode,
o.diId
FROM edi.offer o
JOIN vn.item i ON i.supplyResponseFk = o.srId
JOIN edi.warehouseFloramondo wf
JOIN vn.packaging p ON p.id
LIKE o.embalageCode
LEFT JOIN vn.buy b ON b.itemFk = i.id
AND b.entryFk = wf.entryFk
WHERE b.id IS NULL; -- Quitar esta linea y mirar de crear los packages a tiempo REAL
INSERT INTO vn.itemCost(
itemFk,
warehouseFk,
cm3,
cm3delivery)
SELECT b.itemFk,
wf.warehouseFk,
@cm3 := vn.buy_getUnitVolume(b.id),
IFNULL((vc.standardFlowerBox * 1000) / i.packingOut, @cm3)
FROM warehouseFloramondo wf
JOIN vn.volumeConfig vc
JOIN vn.buy b ON b.entryFk = wf.entryFk
JOIN vn.item i ON i.id = b.itemFk
LEFT JOIN vn.itemCost ic ON ic.itemFk = b.itemFk
AND ic.warehouseFk = wf.warehouseFk
WHERE (ic.cm3 IS NULL OR ic.cm3 = 0)
ON DUPLICATE KEY UPDATE cm3 = @cm3, cm3delivery = IFNULL((vc.standardFlowerBox * 1000) / i.packingOut, @cm3);
CREATE OR REPLACE TEMPORARY TABLE tmp.buyRecalc
SELECT b.id
FROM vn.buy b
JOIN warehouseFloramondo wf ON wf.entryFk = b.entryFk
WHERE b.created >= vLastInserted;
CALL vn.buy_recalcPrices();
UPDATE edi.offerList o
JOIN (SELECT v.name, COUNT(DISTINCT b.itemFk) total
FROM vn.buy b
JOIN vn.item i ON i.id = b.itemFk
JOIN edi.supplyResponse sr ON sr.ID = i.supplyResponseFk
JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID
JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk
JOIN vn.warehouse w ON w.id = wf.warehouseFk
WHERE w.name = 'VNH'
AND b.quantity > 0
GROUP BY sr.vmpID) sub ON o.supplier = sub.name
SET o.vnh = sub.total;
UPDATE edi.offerList o
JOIN (SELECT v.name, COUNT(DISTINCT b.itemFk) total
FROM vn.buy b
JOIN vn.item i ON i.id = b.itemFk
JOIN edi.supplyResponse sr ON sr.ID = i.supplyResponseFk
JOIN edi.VMPSettings v ON v.VMPID = sr.vmpID
JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk
JOIN vn.warehouse w ON w.id = wf.warehouseFk
WHERE w.name = 'ALGEMESI'
AND b.quantity > 0
GROUP BY sr.vmpID) sub ON o.supplier = sub.name
SET o.algemesi = sub.total;
END IF;
DROP TEMPORARY TABLE
edi.offer,
itemToInsert;
SET @isTriggerDisabled = FALSE;
COMMIT;
-- Esto habria que pasarlo a procesos programados o trabajar con tags y dejar las familias
UPDATE vn.item i
SET typeFk = 121
WHERE i.longName LIKE 'Rosa Garden %'
AND typeFk = 17;
UPDATE vn.item i
SET typeFk = 156
WHERE i.longName LIKE 'Rosa ec %'
AND typeFk = 17;
-- Refresca las fotos de los items existentes que mostramos (prioridad baja)
INSERT IGNORE INTO vn.itemImageQueue(itemFk, url, priority)
SELECT i.id, sr.PictureReference, 100
FROM edi.supplyResponse sr
JOIN vn.item i ON i.supplyResponseFk = sr.ID
JOIN edi.supplyOffer so ON so.srId = sr.ID
JOIN hedera.image i2 ON i2.name = i.image
AND i2.collectionFk = 'catalog'
WHERE i2.updated <= (UNIX_TIMESTAMP(util.VN_NOW()) - vDayRange)
AND sr.NumberOfUnits;
INSERT INTO edi.`log`
SET tableName = 'floramondo_offerRefresh',
fieldName = 'Tiempo de proceso',
fieldValue = TIMEDIFF(util.VN_NOW(), vStartingTime);
DO RELEASE_LOCK('edi.floramondo_offerRefresh');
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `util`.`log_clean`
ON SCHEDULE EVERY 1 DAY
STARTS '2024-07-09 00:30:00.000'
ON COMPLETION PRESERVE
ENABLE
DO CALL util.log_clean$$
DELIMITER ;

View File

@ -0,0 +1,54 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `util`.`log_clean`()
BEGIN
/**
* Hace limpieza de los datos de las tablas log,
* dejando únicamente los días de retención configurados.
*/
DECLARE vSchemaName VARCHAR(65);
DECLARE vSchemaNameQuoted VARCHAR(65);
DECLARE vTableName VARCHAR(65);
DECLARE vTableNameQuoted VARCHAR(65);
DECLARE vRetentionDays INT;
DECLARE vStarted DATETIME;
DECLARE vDated DATE;
DECLARE vDone BOOL;
DECLARE vQueue CURSOR FOR
SELECT schemaName, tableName, retentionDays
FROM logCleanMultiConfig
ORDER BY `order`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
OPEN vQueue;
l: LOOP
SET vDone = FALSE;
FETCH vQueue INTO vSchemaName, vTableName, vRetentionDays;
IF vDone THEN
LEAVE l;
END IF;
IF vRetentionDays THEN
SET vStarted = VN_NOW();
SET vSchemaNameQuoted = quoteIdentifier(vSchemaName);
SET vTableNameQuoted = quoteIdentifier(vTableName);
SET vDated = VN_CURDATE() - INTERVAL vRetentionDays DAY;
EXECUTE IMMEDIATE CONCAT(
'DELETE FROM ', vSchemaNameQuoted,
'.', vTableNameQuoted,
" WHERE creationDate < '", vDated, "'"
);
UPDATE logCleanMultiConfig
SET `started` = vStarted,
`finished` = VN_NOW()
WHERE schemaName = vSchemaName
AND tableName = vTableName;
END IF;
END LOOP;
CLOSE vQueue;
END$$
DELIMITER ;

View File

@ -1,64 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`entry_getForLogiflora`(vLanded DATE, vWarehouseFk INT)
RETURNS int(11)
NOT DETERMINISTIC
READS SQL DATA
BEGIN
/**
* Devuelve una entrada para Logiflora. Si no existe la crea.
*
* @param vLanded Fecha de llegada al almacén
* @param vWarehouseFk Identificador de vn.warehouse
*/
DECLARE vTravelFk INT;
DECLARE vEntryFk INT;
DECLARE previousEntryFk INT;
SET vTravelFk = vn.travel_getForLogiflora(vLanded, vWarehouseFk);
IF vLanded THEN
SELECT IFNULL(MAX(id),0) INTO vEntryFk
FROM vn.entry
WHERE travelFk = vTravelFk
AND isRaid;
IF NOT vEntryFk THEN
INSERT INTO vn.entry(travelFk, supplierFk, commission, companyFk, currencyFk, isRaid)
SELECT vTravelFk, s.id, 4, c.id, cu.id, TRUE
FROM vn.supplier s
JOIN vn.company c ON c.code = 'VNL'
JOIN vn.currency cu ON cu.code = 'EUR'
WHERE s.name = 'KONINKLIJE COOPERATIEVE BLOEMENVEILING FLORAHOLLAN';
SELECT MAX(id) INTO vEntryFk
FROM vn.entry
WHERE travelFk = vTravelFk;
END IF;
END IF;
SELECT entryFk INTO previousEntryFk
FROM edi.warehouseFloramondo wf
WHERE wf.warehouseFk = vWarehouseFk;
IF IFNULL(previousEntryFk,0) != vEntryFk THEN
UPDATE buy b
SET b.printedStickers = 0
WHERE entryFk = previousEntryFk;
DELETE FROM buy WHERE entryFk = previousEntryFk;
DELETE FROM entry WHERE id = previousEntryFk;
END IF;
RETURN vEntryFk;
END$$
DELIMITER ;

View File

@ -1,52 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`travel_getForLogiflora`(vLanded DATE, vWarehouseFk INT)
RETURNS int(11)
NOT DETERMINISTIC
READS SQL DATA
BEGIN
/**
* Devuelve un número de travel para compras de Logiflora a partir de la fecha de llegada y del almacén.
* Si no existe lo genera.
*
* @param vLanded Fecha de llegada al almacén
* @param vWarehouseFk Identificador de vn.warehouse
*/
DECLARE vTravelFk INT;
IF vLanded THEN
SELECT IFNULL(MAX(tr.id),0) INTO vTravelFk
FROM vn.travel tr
JOIN vn.warehouse wIn ON wIn.id = tr.warehouseInFk
JOIN vn.warehouse wOut ON wOut.id = tr.warehouseOutFk
JOIN vn.agencyMode am ON am.id = tr.agencyModeFk
WHERE wIn.id = vWarehouseFk
AND wOut.name = 'Holanda'
AND am.name = 'LOGIFLORA'
AND landed = vLanded;
IF NOT vTravelFk THEN
INSERT INTO vn.travel(landed, shipped, warehouseInFk, warehouseOutFk, agencyModeFk)
SELECT vLanded, util.VN_CURDATE(), vWarehouseFk, wOut.id, am.id
FROM vn.warehouse wOut
JOIN vn.agencyMode am ON am.name = 'LOGIFLORA'
WHERE wOut.name = 'Holanda';
SELECT MAX(tr.id) INTO vTravelFk
FROM vn.travel tr
JOIN vn.warehouse wIn ON wIn.id = tr.warehouseInFk
JOIN vn.warehouse wOut ON wOut.id = tr.warehouseOutFk
WHERE wIn.id = vWarehouseFk
AND wOut.name = 'Holanda'
AND landed = vLanded;
END IF;
END IF;
RETURN vTravelFk;
END$$
DELIMITER ;

View File

@ -167,7 +167,8 @@ BEGIN
OR LENGTH(pb.problem)
OR pb.lines > vLinesLimit
OR pb.m3 > vVolumeLimit
OR sub.maxSize > vSizeLimit;
OR sub.maxSize > vSizeLimit
OR pb.hasPlantTray;
END IF;
-- Hay que excluir aquellos que no tengan la misma hora de preparacion, si procede

View File

@ -10,7 +10,7 @@ BEGIN
SELECT * FROM (
SELECT cc.client clientFk, ci.grade
FROM creditClassification cc
JOIN creditInsurance ci ON cc.id = ci.creditClassification
JOIN creditInsurance ci ON cc.id = ci.creditClassificationFk
WHERE dateEnd IS NULL
ORDER BY ci.creationDate DESC
LIMIT 10000000000000000000) t1

View File

@ -30,6 +30,8 @@ BEGIN
FROM operator
WHERE workerFk = account.myUser_getId();
CALL util.debugAdd('itemShelvingSale_addBySectorCollection',CONCAT(vSectorCollectionFk,' - ', account.myUser_getId()));
OPEN vSales;
l: LOOP
SET vDone = FALSE;

View File

@ -46,7 +46,8 @@ BEGIN
AND buyFk = vBuyFk) THEN
UPDATE itemShelving
SET visible = visible + vQuantity
SET visible = visible + vQuantity,
available = available + vQuantity
WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk AND itemFk = vItemFk AND packing = vPacking;
ELSE

View File

@ -211,8 +211,6 @@ proc: BEGIN
salesInParkingCount INT DEFAULT 0)
ENGINE = MEMORY;
-- Insertamos todos los tickets que tienen productos parkineados
-- en sectores de previa, segun el sector
CREATE OR REPLACE TEMPORARY TABLE tItemShelvingStock
(PRIMARY KEY(itemFk, sectorFk))
ENGINE = MEMORY
@ -245,7 +243,6 @@ proc: BEGIN
AND s.quantity > 0
GROUP BY pb.ticketFk;
-- Se calcula la cantidad de productos que estan ya preparados porque su saleGroup está aparcado
UPDATE tmp.ticketWithPrevia twp
JOIN (
SELECT pb.ticketFk, COUNT(DISTINCT s.id) salesInParkingCount
@ -259,12 +256,28 @@ proc: BEGIN
) sub ON twp.ticketFk = sub.ticketFk
SET twp.salesInParkingCount = sub.salesInParkingCount;
-- Marcamos como pendientes aquellos que no coinciden las cantidades
UPDATE tmp.productionBuffer pb
JOIN tmp.ticketWithPrevia twp ON twp.ticketFk = pb.ticketFk
SET pb.previousWithoutParking = TRUE
WHERE twp.salesCount > twp.salesInParkingCount;
-- hasPlantTray
ALTER TABLE tmp.productionBuffer
ADD hasPlantTray BOOL DEFAULT FALSE;
UPDATE tmp.productionBuffer pb
JOIN sale s ON s.ticketFk = pb.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN itemCategory ic ON ic.id = it.categoryFk
JOIN cache.last_buy lb ON lb.warehouse_id = vWarehouseFk AND lb.item_id = s.itemFk
JOIN buy b ON b.id = lb.buy_id
JOIN packaging p ON p.id = b.packagingFk
JOIN productionConfig pc
SET hasPlantTray = TRUE
WHERE ic.code = 'plant'
AND p.`depth` >= pc.minPlantTrayLength;
DROP TEMPORARY TABLE
tmp.productionTicket,
tmp.ticket,

View File

@ -55,7 +55,6 @@ BEGIN
i.itemPackingTypeFk,
isa.`size`,
isa.Estado,
isa.sectorProdPriority,
isa.available,
isa.sectorFk,
isa.matricula,

View File

@ -160,7 +160,10 @@ w1: WHILE vQuantity >= vPacking DO
UPDATE sale SET quantity = quantity - vPacking WHERE id = vSaleFk;
UPDATE itemShelving SET visible = visible - vPacking WHERE id = vItemShelvingFk;
UPDATE itemShelving
SET visible = visible - vPacking,
available = available - vPacking
WHERE id = vItemShelvingFk;
SET vNewSaleFk = NULL;

View File

@ -51,7 +51,6 @@ BEGIN
hasTicketRequest,
isTaxDataChecked,
hasComponentLack,
hasRounding,
isTooLittle)
SELECT sgp.ticketFk,
s.id,
@ -62,10 +61,6 @@ BEGIN
IF(FIND_IN_SET('hasTicketRequest', t.problem), TRUE, FALSE) hasTicketRequest,
IF(FIND_IN_SET('isTaxDataChecked', t.problem), FALSE, TRUE) isTaxDataChecked,
IF(FIND_IN_SET('hasComponentLack', s.problem), TRUE, FALSE) hasComponentLack,
IF(FIND_IN_SET('hasRounding', s.problem),
LEFT(GROUP_CONCAT('RE: ', i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250),
NULL
) hasRounding,
IF(FIND_IN_SET('isTooLittle', t.problem)
AND util.VN_NOW() < (util.VN_CURDATE() + INTERVAL HOUR(zc.`hour`) HOUR) + INTERVAL MINUTE(zc.`hour`) MINUTE,
TRUE, FALSE) isTooLittle
@ -208,24 +203,31 @@ BEGIN
GROUP BY sgp.ticketFk
) sub
ON DUPLICATE KEY UPDATE itemDelay = sub.problem, saleFk = sub.saleFk;
-- Redondeo: cantidad incorrecta con respecto al grouping
CALL buy_getUltimate(NULL, vWarehouseFk, vDate);
INSERT INTO tmp.sale_problems(ticketFk, hasRounding, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
s.id saleFk,
LEFT(GROUP_CONCAT('RE: ',i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250) problem
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
AND t.warehouseFk = vWarehouseFk
JOIN sale s ON s.ticketFk = sgp.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
JOIN buy b ON b.id = bu.buyFk
WHERE MOD(s.quantity, b.`grouping`)
GROUP BY sgp.ticketFk
)sub
ON DUPLICATE KEY UPDATE hasRounding = sub.problem, saleFk = sub.saleFk;
DROP TEMPORARY TABLE tmp.buyUltimate;
END LOOP;
CLOSE vCursor;
INSERT INTO tmp.sale_problems(ticketFk, hasRounding, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
s.id saleFk,
LEFT(GROUP_CONCAT('RE: ', i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250) problem
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
JOIN sale s ON s.ticketFk = sgp.ticketFk
JOIN item i ON i.id = s.itemFk
WHERE FIND_IN_SET('hasRounding', s.problem)
GROUP BY sgp.ticketFk
) sub
ON DUPLICATE KEY UPDATE hasRounding = sub.problem, saleFk = sub.saleFk;
DROP TEMPORARY TABLE tItemShelvingStock_byWarehouse;
END$$
DELIMITER ;

View File

@ -1,37 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`sale_setProblemRounding`(
vSelf INT
)
BEGIN
/**
* Update the rounding problem for a sales line
* @param vSelf Id sale
*/
DECLARE vItemFk INT;
DECLARE vWarehouseFk INT;
DECLARE vShipped DATE;
DECLARE vQuantity INT;
DECLARE vIsProblemCalcNeeded BOOL;
SELECT s.itemFk, t.warehouseFk, t.shipped, s.quantity, ticket_isProblemCalcNeeded(t.id)
INTO vItemFk, vWarehouseFk, vShipped, vQuantity, vIsProblemCalcNeeded
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
WHERE s.id = vSelf;
CALL buy_getUltimate(vItemFk, vWarehouseFk, vShipped);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
SELECT vSelf saleFk,
MOD(vQuantity, b.`grouping`) hasProblem,
vIsProblemCalcNeeded isProblemCalcNeeded
FROM tmp.buyUltimate bu
JOIN buy b ON b.id = bu.buyFk
WHERE bu.itemFk = vItemFk;
CALL sale_setProblem('hasRounding');
DROP TEMPORARY TABLE tmp.sale;
DROP TEMPORARY TABLE tmp.buyUltimate;
END$$
DELIMITER ;

View File

@ -1,75 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_setProblemRoundingByBuy`(
vBuyFk INT
)
BEGIN
/**
* Update rounding problem for all sales related to a buy.
*
* @param vBuyFk Buy id
*/
DECLARE vItemFk INT;
DECLARE vWarehouseFk INT;
DECLARE vMaxDated DATE;
DECLARE vMinDated DATE;
DECLARE vLanding DATE;
DECLARE vLastBuy INT;
DECLARE vCurrentBuy INT;
DECLARE vGrouping INT;
SELECT b.itemFk, t.warehouseInFk
INTO vItemFk, vWarehouseFk
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE b.id = vBuyFk;
IF vItemFk AND vWarehouseFk THEN
SELECT DATE(MAX(t.shipped)) + INTERVAL 1 DAY, DATE(MIN(t.shipped))
INTO vMaxDated, vMinDated
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
WHERE t.shipped >= util.VN_CURDATE()
AND s.itemFk = vItemFk
AND s.quantity > 0;
CALL buy_getUltimate(vItemFk, vWarehouseFk, vMinDated);
SELECT bu.buyFk, b.grouping INTO vLastBuy, vGrouping
FROM tmp.buyUltimate bu
JOIN buy b ON b.id = bu.buyFk;
DROP TEMPORARY TABLE tmp.buyUltimate;
SET vLanding = vMaxDated;
WHILE vCurrentBuy <> vLastBuy OR vLanding > vMinDated DO
SET vMaxDated = vLanding - INTERVAL 1 DAY;
CALL buy_getUltimate(vItemFk, vWarehouseFk, vMaxDated);
SELECT buyFk, landing
INTO vCurrentBuy, vLanding
FROM tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.buyUltimate;
END WHILE;
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(INDEX(saleFk, isProblemCalcNeeded))
ENGINE = MEMORY
SELECT s.id saleFk,
MOD(s.quantity, vGrouping) hasProblem,
ticket_isProblemCalcNeeded(t.id) isProblemCalcNeeded
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
WHERE s.itemFk = vItemFk
AND s.quantity > 0
AND t.shipped BETWEEN vMinDated AND util.dayEnd(vMaxDated);
CALL sale_setProblem('hasRounding');
DROP TEMPORARY TABLE tmp.sale;
END IF;
END$$
DELIMITER ;

View File

@ -19,8 +19,7 @@ BEGIN
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT
origin.ticketFk futureId,
SELECT origin.ticketFk futureId,
dest.ticketFk id,
dest.state,
origin.futureState,
@ -51,48 +50,48 @@ BEGIN
origin.warehouseFk futureWarehouseFk,
origin.companyFk futureCompanyFk,
IFNULL(dest.nickname, origin.nickname) nickname,
dest.landed
dest.landed,
dest.preparation
FROM (
SELECT
s.ticketFk,
c.salesPersonFk workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM(s.quantity <= (IFNULL(il.stock,0) + IFNULL(im.amount, 0))) hasStock,
z.id futureZoneFk,
z.name futureZoneName,
st.classColor,
t.clientFk,
t.nickname,
t.addressFk,
t.warehouseFk,
t.companyFk,
t.agencyModeFk
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
JOIN zone z ON t.zoneFk = z.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.itemMinacum im ON im.itemFk = i.id
AND im.warehouseFk = vWarehouseFk
LEFT JOIN tmp.itemList il ON il.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
SELECT s.ticketFk,
c.salesPersonFk workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM(s.quantity <= (IFNULL(il.stock,0) + IFNULL(im.amount, 0))) hasStock,
z.id futureZoneFk,
z.name futureZoneName,
st.classColor,
t.clientFk,
t.nickname,
t.addressFk,
t.warehouseFk,
t.companyFk,
t.agencyModeFk
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN `state` st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
JOIN `zone` z ON t.zoneFk = z.id
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.itemMinacum im ON im.itemFk = i.id
AND im.warehouseFk = vWarehouseFk
LEFT JOIN tmp.itemList il ON il.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) origin
LEFT JOIN (
SELECT
t.id ticketFk,
SELECT t.id ticketFk,
st.name state,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t.shipped,
@ -108,18 +107,25 @@ BEGIN
t.warehouseFk,
t.companyFk,
t.landed,
t.agencyModeFk
t.agencyModeFk,
SEC_TO_TIME(
COALESCE(HOUR(t.shipped), HOUR(zc.hour), HOUR(z.hour)) * 3600 +
COALESCE(MINUTE(t.shipped), MINUTE(zc.hour), MINUTE(z.hour)) * 60
) preparation
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN `state` st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN `zone` z ON z.id = t.zoneFk
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
JOIN ticketCanAdvanceConfig tc
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t.warehouseFk = vWarehouseFk
AND st.order <= 5
AND st.order <= tc.destinationOrder
GROUP BY t.id
) dest ON dest.addressFk = origin.addressFk
WHERE origin.hasStock;

View File

@ -21,6 +21,7 @@ BEGIN
t.clientFk,
t.warehouseFk,
ts.alertLevel,
sub2.alertLevel futureAlertLevel,
t.shipped,
t.totalWithVat,
sub2.shipped futureShipped,
@ -47,6 +48,7 @@ BEGIN
t.addressFk,
t.id,
t.shipped,
ts.alertLevel,
st.name state,
st.code,
st.classColor,

View File

@ -36,7 +36,7 @@ BEGIN
UPDATE tmp.ticket_problems
SET totalProblems = (
(isFreezed) +
(hasRisk) +
(hasHighRisk) +
(hasTicketRequest) +
(!isTaxDataChecked) +
(hasComponentLack) +

View File

@ -1,37 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_setProblemRounding`(
vSelf INT
)
BEGIN
/**
* Update the rounding problem for the sales lines of a ticket
*
* @param vSelf Id de ticket
*/
DECLARE vWarehouseFk INT;
DECLARE vDated DATE;
SELECT warehouseFk, shipped
INTO vWarehouseFk, vDated
FROM ticket
WHERE id = vSelf;
CALL buy_getUltimate(NULL, vWarehouseFk, vDated);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(INDEX(saleFk, isProblemCalcNeeded))
SELECT s.id saleFk ,
MOD(s.quantity, b.`grouping`) hasProblem,
ticket_isProblemCalcNeeded(t.id) isProblemCalcNeeded
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
JOIN buy b ON b.id = bu.buyFk
WHERE t.id = vSelf;
CALL sale_setProblem('hasRounding');
DROP TEMPORARY TABLE tmp.sale;
DROP TEMPORARY TABLE tmp.buyUltimate;
END$$
DELIMITER ;

View File

@ -5,7 +5,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`creditInsurance_afterIn
BEGIN
UPDATE `client` c
JOIN vn.creditClassification cc ON cc.client = c.id
SET creditInsurance = NEW.credit WHERE cc.id = NEW.creditClassification;
SET creditInsurance = NEW.credit WHERE cc.id = NEW.creditClassificationFk;
END$$
DELIMITER ;

View File

@ -1,10 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`creditInsurance_beforeInsert`
BEFORE INSERT ON `creditInsurance`
FOR EACH ROW
BEGIN
IF NEW.creditClassificationFk THEN
SET NEW.creditClassification = NEW.creditClassificationFk;
END IF;
END$$
DELIMITER ;

View File

@ -5,7 +5,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`solunionCAP_afterInsert
BEGIN
UPDATE client c
JOIN creditClassification cc ON cc.client = c.id
JOIN creditInsurance ci ON ci.creditClassification = cc.id
JOIN creditInsurance ci ON ci.creditClassificationFk = cc.id
SET creditInsurance = ci.credit * 2 WHERE ci.id = NEW.creditInsurance;
END$$
DELIMITER ;

View File

@ -6,12 +6,12 @@ BEGIN
IF NEW.dateLeaving IS NOT NULL THEN
UPDATE client c
JOIN creditClassification cc ON cc.client = c.id
JOIN creditInsurance ci ON ci.creditClassification = cc.id
JOIN creditInsurance ci ON ci.creditClassificationFk = cc.id
SET creditInsurance = ci.credit WHERE ci.id = OLD.creditInsurance;
ELSE
UPDATE client c
JOIN creditClassification cc ON cc.client = c.id
JOIN creditInsurance ci ON ci.creditClassification = cc.id
JOIN creditInsurance ci ON ci.creditClassificationFk = cc.id
SET creditInsurance = ci.credit * 2 WHERE ci.id = OLD.creditInsurance;
END IF;
END$$

View File

@ -5,7 +5,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`solunionCAP_beforeDelet
BEGIN
UPDATE client c
JOIN creditClassification cc ON cc.client = c.id
JOIN creditInsurance ci ON ci.creditClassification = cc.id
JOIN creditInsurance ci ON ci.creditClassificationFk = cc.id
SET creditInsurance = ci.credit WHERE ci.id = OLD.creditInsurance;
END$$
DELIMITER ;

View File

@ -1,11 +1,11 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDocument_afterDelete`
AFTER DELETE ON `workerDocument`
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDms_afterDelete`
AFTER DELETE ON `workerDms`
FOR EACH ROW
BEGIN
INSERT INTO workerLog
SET `action` = 'delete',
`changedModel` = 'WorkerDocument',
`changedModel` = 'WorkerDms',
`changedModelId` = OLD.id,
`userFk` = account.myUser_getId();
END$$

View File

@ -1,6 +1,6 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDocument_beforeUpdate`
BEFORE UPDATE ON `workerDocument`
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDms_beforeInsert`
BEFORE INSERT ON `workerDms`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();

View File

@ -1,6 +1,6 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDocument_beforeInsert`
BEFORE INSERT ON `workerDocument`
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerDms_beforeUpdate`
BEFORE UPDATE ON `workerDms`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();

View File

@ -10,7 +10,6 @@ AS SELECT `s`.`id` AS `saleFk`,
`s`.`concept` AS `concept`,
`i`.`size` AS `size`,
`st`.`name` AS `Estado`,
`st`.`sectorProdPriority` AS `sectorProdPriority`,
`stock`.`visible` AS `available`,
`stock`.`sectorFk` AS `sectorFk`,
`stock`.`shelvingFk` AS `matricula`,

View File

@ -6,7 +6,6 @@ AS SELECT `s`.`id` AS `id`,
`s`.`order` AS `order`,
`s`.`alertLevel` AS `alert_level`,
`s`.`code` AS `code`,
`s`.`sectorProdPriority` AS `sectorProdPriority`,
`s`.`nextStateFk` AS `nextStateFk`,
`s`.`isPreviousPreparable` AS `isPreviousPreparable`,
`s`.`isPicked` AS `isPicked`

View File

@ -0,0 +1,19 @@
ALTER TABLE vn.collectionWagonTicket DROP FOREIGN KEY IF EXISTS collectionWagonTicket_tray;
ALTER TABLE vn.wagonConfig DROP FOREIGN KEY IF EXISTS wagonConfig_wagonTypeColor_FK;
CREATE OR REPLACE TABLE vn.wagonTypeTray (
id INT(11) UNSIGNED,
wagonTypeFk INT(11) unsigned NULL,
height INT(11) UNSIGNED NULL,
wagonTypeColorFk int(11) unsigned NULL,
CONSTRAINT wagonTypeTray_pk PRIMARY KEY (id),
CONSTRAINT wagonTypeTray_wagonType_FK FOREIGN KEY (wagonTypeFk) REFERENCES vn.wagonType(id) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT wagonTypeTray_wagonTypeColor_FK FOREIGN KEY (wagonTypeColorFk) REFERENCES vn.wagonTypeColor(id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb3
COLLATE=utf8mb3_unicode_ci;
ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultHeight INT UNSIGNED DEFAULT 0 NULL COMMENT 'Default height in cm for a base tray';
ALTER TABLE vn.wagonConfig ADD IF NOT EXISTS defaultTrayColorFk int(11) unsigned NULL COMMENT 'Default color for a base tray';
ALTER TABLE vn.wagonConfig ADD CONSTRAINT wagonConfig_wagonTypeColor_FK FOREIGN KEY (defaultTrayColorFk) REFERENCES vn.wagonTypeColor(id);
ALTER TABLE vn.collectionWagonTicket ADD CONSTRAINT collectionWagonTicket_tray FOREIGN KEY (trayFk) REFERENCES vn.wagonTypeTray(id);

View File

@ -0,0 +1,13 @@
CREATE OR REPLACE TABLE `util`.`logCleanMultiConfig` (
`schemaName` varchar(64) NOT NULL,
`tableName` varchar(64) NOT NULL,
`retentionDays` int(11) DEFAULT NULL,
`order` int(11) DEFAULT NULL,
`started` datetime DEFAULT NULL,
`finished` datetime DEFAULT NULL,
PRIMARY KEY (`schemaName`,`tableName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO `util`.`logCleanMultiConfig` (`schemaName`, `tableName`)
SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.`COLUMNS`
WHERE COLUMN_NAME IN ('newInstance', 'newInstance');

View File

@ -0,0 +1 @@
CREATE INDEX userLog_creationDate_IDX USING BTREE ON account.userLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX roleLog_creationDate_IDX USING BTREE ON account.roleLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX ACLLog_creationDate_IDX USING BTREE ON salix.ACLLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX supplierLog_creationDate_IDX USING BTREE ON vn.supplierLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX deviceProductionLog_creationDate_IDX USING BTREE ON vn.deviceProductionLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX routeLog_creationDate_IDX USING BTREE ON vn.routeLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX itemLog_creationDate_IDX USING BTREE ON vn.itemLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX userLog_creationDate_IDX USING BTREE ON vn.userLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX invoiceInLog_creationDate_IDX USING BTREE ON vn.invoiceInLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX zoneLog_creationDate_IDX USING BTREE ON vn.zoneLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX clientLog_creationDate_IDX USING BTREE ON vn.clientLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX workerLog_creationDate_IDX USING BTREE ON vn.workerLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX rateLog_creationDate_IDX USING BTREE ON vn.rateLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX claimLog_creationDate_IDX USING BTREE ON vn.claimLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX packingSiteDeviceLog_creationDate_IDX USING BTREE ON vn.packingSiteDeviceLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX travelLog_creationDate_IDX USING BTREE ON vn.travelLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX shelvingLog_creationDate_IDX USING BTREE ON vn.shelvingLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX productionConfigLog_creationDate_IDX USING BTREE ON vn.productionConfigLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX entryLog_creationDate_IDX USING BTREE ON vn.entryLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX agencyLog_creationDate_IDX USING BTREE ON vn.agencyLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX parkingLog_creationDate_IDX USING BTREE ON vn.parkingLog (creationDate DESC);

View File

@ -0,0 +1 @@
CREATE INDEX bufferLog_creationDate_IDX USING BTREE ON srt.bufferLog (creationDate DESC);

View File

@ -0,0 +1,16 @@
ALTER TABLE IF EXISTS `vn`.`payrollWorker`
MODIFY COLUMN IF EXISTS `nss__` varchar(23) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `codpuesto__` int(10) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `codcontrato__` int(10) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `FAntiguedad__` date NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `grupotarifa__` int(10) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `codcategoria__` int(10) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `ContratoTemporal__` tinyint(1) NOT NULL DEFAULT 0 COMMENT '@deprecated 2024-03-15';
ALTER TABLE IF EXISTS `vn`.`payrollWorkCenter`
MODIFY COLUMN IF EXISTS `Centro__` varchar(255) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `nss_cotizacion__` varchar(15) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `domicilio__` varchar(255) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `poblacion__` varchar(45) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `cp__` varchar(5) NOT NULL COMMENT '@deprecated 2024-03-15',
MODIFY COLUMN IF EXISTS `empresa_id__` int(10) NOT NULL COMMENT '@deprecated 2024-03-15';

View File

@ -1,4 +1,5 @@
-- Calculamos todos los volumenes de todos los tickets una sola vez
/* Se ejecutará el dia de test - master manualmente para no hacer lenta la subida
CREATE OR REPLACE TEMPORARY TABLE tmp.tTicketVolume
(PRIMARY KEY (id))
ENGINE = MEMORY
@ -14,3 +15,4 @@ UPDATE vn.ticket t
SET t.volume = tv.volume;
DROP TEMPORARY TABLE tmp.tTicketVolume;
*/

View File

@ -0,0 +1,9 @@
-- Place your SQL code here
INSERT INTO salix.ACL
SET model = 'Ticket',
property = 'setWeight',
accessType = 'WRITE',
permission = 'ALLOW',
principalType = 'ROLE',
principalId = 'salesPerson';

View File

@ -0,0 +1,12 @@
-- Place your SQL code here
DELETE FROM salix.ACL WHERE model = 'Province' LIMIT 1;
DELETE FROM salix.ACL WHERE model = 'Town' LIMIT 1;
UPDATE salix.ACL SET accessType = 'READ' WHERE model = 'BankEntity';
INSERT INTO salix.ACL
SET model = 'BankEntity',
property = '*',
accessType = 'WRITE',
permission = 'ALLOW',
principalType = 'ROLE',
principalId = 'financial';

View File

@ -0,0 +1 @@
CREATE INDEX saleGroupLog_creationDate_IDX USING BTREE ON vn.saleGroupLog (creationDate DESC);

View File

@ -0,0 +1,9 @@
-- Place your SQL code here
CREATE TABLE IF NOT EXISTS vn.ticketCanAdvanceConfig (
id int(10) unsigned NOT NULL,
destinationOrder INT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `ticketCanAdvanceConfig_check` CHECK (`id` = 1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO vn.ticketCanAdvanceConfig SET id =1, destinationOrder = 5;

View File

@ -0,0 +1 @@
ALTER TABLE vn.state DROP COLUMN sectorProdPriority;

View File

@ -0,0 +1,2 @@
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES( 'Device', 'handleUser', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,3 @@
ALTER TABLE vn.creditInsurance DROP FOREIGN KEY CreditInsurance_Fk1;
ALTER TABLE vn.creditInsurance
CHANGE creditClassification creditClassification__ int(11) DEFAULT NULL COMMENT '@deprecated 2024-09-11';

View File

@ -0,0 +1 @@
ALTER TABLE vn.workerDocument CHANGE worker workerFk int(10) unsigned DEFAULT NULL NULL;

View File

@ -0,0 +1 @@
ALTER TABLE vn.workerDocument CHANGE document dmsFk int(11) DEFAULT NULL NULL;

View File

@ -0,0 +1 @@
RENAME TABLE vn.workerDocument TO vn.workerDms;

View File

@ -0,0 +1,3 @@
-- Place your SQL code here
ALTER TABLE vn.productionConfig ADD minPlantTrayLength INT DEFAULT 53 NOT NULL
COMMENT 'minimum length for plant tray restriction. Avoid to make collection of the ticket with this kind of item';

View File

@ -687,8 +687,8 @@ export default {
ticketFuture: {
searchResult: 'vn-ticket-future tbody tr',
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
originDated: 'vn-date-picker[label="Origin date"]',
futureDated: 'vn-date-picker[label="Destination date"]',
originScopeDays: 'vn-date-picker[label="Origin date"]',
futureScopeDays: 'vn-date-picker[label="Destination date"]',
linesMax: 'vn-textfield[label="Max Lines"]',
litersMax: 'vn-textfield[label="Max Liters"]',
ipt: 'vn-autocomplete[label="Origin IPT"]',

View File

@ -35,6 +35,14 @@ describe('Client Edit billing data path', () => {
it(`should attempt to edit the billing data without an IBAN but fail`, async() => {
await page.autocompleteSearch($.payMethod, 'PayMethod with IBAN');
await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('That payment method requires an IBAN');
});
it(`should edit the billing data and save the form`, async() => {
await page.autocompleteSearch($.payMethod, 'PayMethod five');
await page.autocompleteSearch($.swiftBic, 'BBKKESMMMMM');
await page.clearInput($.dueDay);
await page.write($.dueDay, '60');
@ -45,10 +53,13 @@ describe('Client Edit billing data path', () => {
await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('That payment method requires an IBAN');
expect(message.text).toContain('Notification sent!');
});
it(`should create a new BIC code`, async() => {
await page.loginAndModule('financial', 'client');
await page.accessToSearchResult('Bruce Banner');
await page.accessToSection('client.card.billingData');
await page.waitToClick($.newBankEntityButton);
await page.write($.newBankEntityName, 'Gotham City Bank');
await page.write($.newBankEntityBIC, 'GTHMCT');
@ -66,7 +77,7 @@ describe('Client Edit billing data path', () => {
it(`should confirm the IBAN pay method was sucessfully saved`, async() => {
const payMethod = await page.waitToGetProperty($.payMethod, 'value');
expect(payMethod).toEqual('PayMethod with IBAN');
expect(payMethod).toEqual('PayMethod five');
});
it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => {
@ -79,14 +90,6 @@ describe('Client Edit billing data path', () => {
expect(automaticCode).toEqual('CAIXESBB');
});
it(`should save the form with all its new data`, async() => {
await page.waitForWatcherData($.watcher);
await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Notification sent!');
});
it('should confirm the billing data have been edited', async() => {
const dueDate = await page.waitToGetProperty($.dueDay, 'value');
const IBAN = await page.waitToGetProperty($.IBAN, 'value');
@ -94,7 +97,9 @@ describe('Client Edit billing data path', () => {
const receivedCoreLCR = await page.checkboxState($.receivedCoreLCRCheckbox);
const receivedCoreVNL = await page.checkboxState($.receivedCoreVNLCheckbox);
const receivedB2BVNL = await page.checkboxState($.receivedB2BVNLCheckbox);
const payMethod = await page.waitToGetProperty($.payMethod, 'value');
expect(payMethod).toEqual('PayMethod five');
expect(dueDate).toEqual('60');
expect(IBAN).toEqual('ES9121000418450200051332');
expect(swiftBic).toEqual('CAIXESBB');

View File

@ -30,18 +30,18 @@ describe('Ticket Future path', () => {
expect(message.text).toContain('warehouseFk is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.futureDated);
await page.clearInput(selectors.ticketFuture.futureScopeDays);
await page.waitToClick(selectors.ticketFuture.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('futureDated is a required argument');
expect(message.text).toContain('futureScopeDays is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.originDated);
await page.clearInput(selectors.ticketFuture.originScopeDays);
await page.waitToClick(selectors.ticketFuture.submit);
message = await page.waitForSnackbar();
expect(message.text).toContain('originDated is a required argument');
expect(message.text).toContain('originScopeDays is a required argument');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketFuture.submit);
@ -71,7 +71,7 @@ describe('Ticket Future path', () => {
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
expect(httpRequest).toContain('state=FREE');
expect(httpRequest).toContain('state=0');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
@ -80,7 +80,7 @@ describe('Ticket Future path', () => {
await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
expect(httpRequest).toContain('futureState=FREE');
expect(httpRequest).toContain('futureState=0');
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.state);

View File

@ -33,7 +33,7 @@ module.exports = function(Self) {
const defaultLimit = this.app.orm.selectLimit;
const filter = ctx.args.filter || {limit: defaultLimit};
if (filter.limit > defaultLimit) {
if (!filter.limit || filter.limit > defaultLimit) {
filter.limit = defaultLimit;
ctx.args.filter = filter;
}
@ -349,9 +349,10 @@ module.exports = function(Self) {
},
hasFilter(ctx) {
return ctx.req.method.toUpperCase() === 'GET' &&
ctx.method.accepts.some(x => x.arg === 'filter' && x.type.toLowerCase() === 'object');
}
const {method, req} = ctx;
if (method.noLimit) return false;
return req.method.toUpperCase() === 'GET' &&
method.accepts.some(x => x.arg === 'filter' && x.type.toLowerCase() === 'object');
},
});
};

View File

@ -236,6 +236,8 @@
"Cannot send mail": "Cannot send mail",
"CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`",
"This postcode already exists": "This postcode already exists",
"Original invoice not found": "Original invoice not found"
"Original invoice not found": "Original invoice not found",
"There is already a tray with the same height": "There is already a tray with the same height",
"The height must be greater than 50cm": "The height must be greater than 50cm",
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm"
}

View File

@ -372,5 +372,10 @@
"The entry not have stickers": "La entrada no tiene etiquetas",
"Too many records": "Demasiados registros",
"Original invoice not found": "Factura original no encontrada",
"The entry has no lines or does not exist": "La entrada no tiene lineas o no existe"
"The entry has no lines or does not exist": "La entrada no tiene lineas o no existe",
"Weight already set": "El peso ya está establecido",
"This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento",
"There is already a tray with the same height": "Ya existe una bandeja con la misma altura",
"The height must be greater than 50cm": "La altura debe ser superior a 50cm",
"The maximum height of the wagon is 200cm": "La altura máxima es 200cm"
}

View File

@ -16,7 +16,8 @@ module.exports = Self => {
http: {
path: `/getBalance`,
verb: 'GET'
}
},
noLimit: true
});
Self.getBalance = async(ctx, filter, options) => {

View File

@ -105,13 +105,12 @@ module.exports = Self => {
stmt = new ParameterizedSQL(
`CALL vn.ticket_canAdvance(?,?,?)`,
[args.dateFuture, args.dateToAdvance, args.warehouseFk]);
[args.dateFuture, args.dateToAdvance, args.warehouseFk]
);
stmts.push(stmt);
stmt = new ParameterizedSQL(`
SELECT f.*
FROM tmp.filter f`);
stmt = new ParameterizedSQL(`SELECT f.* FROM tmp.filter f`);
stmt.merge(conn.makeWhere(filter.where));
@ -119,9 +118,7 @@ module.exports = Self => {
stmt.merge(conn.makeLimit(filter));
const ticketsIndex = stmts.push(stmt) - 1;
stmts.push(
`DROP TEMPORARY TABLE
tmp.filter`);
stmts.push(`DROP TEMPORARY TABLE tmp.filter`);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);

View File

@ -9,13 +9,13 @@ module.exports = Self => {
accessType: 'READ',
accepts: [
{
arg: 'originDated',
arg: 'originScopeDays',
type: 'date',
description: 'The date in question',
required: true
},
{
arg: 'futureDated',
arg: 'futureScopeDays',
type: 'date',
description: 'The date to probe',
required: true
@ -129,9 +129,9 @@ module.exports = Self => {
]
};
case 'state':
return {'f.stateCode': {like: `%${value}%`}};
return {'f.alertLevel': value};
case 'futureState':
return {'f.futureStateCode': {like: `%${value}%`}};
return {'f.futureAlertLevel': value};
}
});
@ -141,7 +141,7 @@ module.exports = Self => {
stmt = new ParameterizedSQL(
`CALL vn.ticket_canbePostponed(?,?,?)`,
[args.originDated, args.futureDated, args.warehouseFk]);
[args.originScopeDays, args.futureScopeDays, args.warehouseFk]);
stmts.push(stmt);
@ -170,7 +170,7 @@ module.exports = Self => {
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
`);
if (args.problems != undefined && (!args.originDated && !args.futureDated))
if (args.problems != undefined && (!args.originScopeDays && !args.futureScopeDays))
throw new UserError('Choose a date range or days forward');
let condition;

View File

@ -138,7 +138,7 @@ module.exports = Self => {
id: id,
url: `${url}ticket/${id}/summary`
});
await models.Chat.send(ctx, `@${salesPersonUser.name}`, message);
await models.Chat.sendCheckingPresence(ctx, salesPersonUser.id, message);
}
const updatedTicket = await ticket.updateAttribute('isDeleted', true, myOptions);

View File

@ -0,0 +1,86 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('setWeight', {
description: 'Sets weight of a ticket',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The ticket id',
http: {source: 'path'}
}, {
arg: 'weight',
type: 'number',
required: true,
description: 'The weight value',
}],
returns: {
type: 'Array',
root: true
},
http: {
path: `/:id/setWeight`,
verb: 'POST'
}
});
Self.setWeight = async(ctx, ticketId, weight, options) => {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {userId};
let tx;
if (typeof options == 'object') Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const ticket = await Self.findById(ticketId, null, myOptions);
if (ticket.weight) throw new UserError('Weight already set');
const canEdit = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'updateAttributes');
const client = await models.Client.findById(ticket.clientFk, {
include: {relation: 'salesPersonUser'}},
myOptions);
if (!canEdit) {
const salesPersonUser = client.salesPersonUser();
const workerDepartments = await models.WorkerDepartment.find({
include: {relation: 'department'},
where: {workerFk: {inq: [userId, salesPersonUser.id]}}
}, myOptions);
if (
workerDepartments.length == 2 &&
workerDepartments[0].departmentFk != workerDepartments[1].departmentFk
)
throw new UserError('This ticket is not allocated to your department');
}
await ticket.updateAttribute('weight', weight, myOptions);
const packedState = await models.State.findOne({where: {code: 'PACKED'}}, myOptions);
const ticketState = await models.TicketState.findOne({where: {ticketFk: ticketId}}, myOptions);
const [{taxArea}] = await Self.rawSql('SELECT clientTaxArea(?,?) taxArea',
[ticket.clientFk, ticket.warehouseFk], myOptions);
const isInvoiceable = ticketState.alertLevel >= packedState.alertLevel &&
taxArea == 'WORLD' && client.hasDailyInvoice;
if (tx) await tx.commit();
let invoiceIds = [];
if (isInvoiceable) invoiceIds = [...await Self.invoiceTicketsAndPdf(ctx, [ticketId])];
return invoiceIds;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -12,8 +12,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
};
@ -35,8 +35,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
problems: true
};
@ -60,8 +60,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
problems: false
};
@ -85,8 +85,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
problems: null
};
@ -110,8 +110,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
state: 'OK'
};
@ -135,8 +135,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
futureState: 'OK'
};
@ -160,8 +160,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
ipt: null
};
@ -185,8 +185,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
ipt: 'H'
};
@ -210,8 +210,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
futureIpt: null
};
@ -235,8 +235,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
futureIpt: 'H'
};
@ -260,8 +260,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
id: 13
};
@ -285,8 +285,8 @@ describe('ticket getTicketsFuture()', () => {
const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: 1,
futureId: 12
};

View File

@ -0,0 +1,70 @@
const {models} = require('vn-loopback/server/server');
describe('ticket setWeight()', () => {
const ctx = beforeAll.getCtx();
beforeAll.mockLoopBackContext();
let opts;
let tx;
const employeeId = 1;
const administrativeId = 5;
beforeEach(async() => {
opts = {transaction: tx};
tx = await models.Ticket.beginTransaction({});
opts.transaction = tx;
ctx.req.accessToken.userId = administrativeId;
});
afterEach(async() => await tx.rollback());
it('should throw an error if the weight is already set', async() => {
try {
const ticketId = 1;
const weight = 10;
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
} catch (e) {
expect(e.message).toEqual('Weight already set');
}
});
it('should set the weight of a ticket', async() => {
const ticketId = 31;
const weight = 15;
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
const ticket = await models.Ticket.findById(ticketId, null, opts);
expect(ticket.weight).toEqual(weight);
});
it('should throw an error if the user is not allocated to the same department', async() => {
ctx.req.accessToken.userId = employeeId;
try {
const ticketId = 10;
const weight = 20;
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
} catch (e) {
expect(e.message).toEqual('This ticket is not allocated to your department');
}
});
it('should call invoiceTicketsAndPdf if the ticket is invoiceable', async() => {
const ticketId = 10;
const weight = 25;
spyOn(models.Client, 'findById').and.returnValue({
hasDailyInvoice: true,
salesPersonUser: () => ({id: 1})
});
spyOn(models.TicketState, 'findOne').and.returnValue({alertLevel: 3});
spyOn(models.Ticket, 'rawSql').and.returnValue([{taxArea: 'WORLD'}]);
spyOn(models.Ticket, 'invoiceTicketsAndPdf').and.returnValue([10]);
const invoiceIds = await models.Ticket.setWeight(ctx, ticketId, weight, opts);
expect(invoiceIds.length).toBeGreaterThan(0);
});
});

View File

@ -46,4 +46,5 @@ module.exports = function(Self) {
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
require('../methods/ticket/docuwareDownload')(Self);
require('../methods/ticket/myLastModified')(Self);
require('../methods/ticket/setWeight')(Self);
};

View File

@ -39,14 +39,8 @@
<thead>
<tr second-header>
<td></td>
<th colspan="7">
<span translate>Destination</span>
{{model.userParams.dateToAdvance| date: 'dd/MM/yyyy'}}
</th>
<th colspan="11">
<span translate>Origin</span>
{{model.userParams.dateFuture | date: 'dd/MM/yyyy'}}
</th>
<th colspan="9" translate>Destination</th>
<th colspan="11" translate>Origin</th>
</tr>
<tr>
<th shrink>
@ -56,14 +50,16 @@
check-field="checked">
</vn-multi-check>
</th>
<th shrink>
</th>
<th shrink></th>
<th field="id">
<span translate>ID</span>
</th>
<th field="ipt" title="{{'Item Packing Type' | translate}}">
<span>IPT</span>
</th>
<th field="preparation">
<span translate>Preparation</span>
</th>
<th field="state">
<span translate>State</span>
</th>
@ -125,6 +121,7 @@
</span>
</td>
<td>{{::ticket.ipt | dashIfEmpty}}</td>
<td>{{::ticket.preparation | dashIfEmpty}}</td>
<td>
<span
class="chip {{ticket.classColor}}">
@ -165,7 +162,6 @@
{{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}}
</span>
</td>
</tr>
</tbody>
</table>

View File

@ -9,13 +9,13 @@
<vn-date-picker
vn-one
label="Origin date"
ng-model="filter.originDated"
ng-model="filter.originScopeDays"
required="true">
</vn-date-picker>
<vn-date-picker
vn-one
label="Destination date"
ng-model="filter.futureDated"
ng-model="filter.futureScopeDays"
required="true">
</vn-date-picker>
</vn-horizontal>
@ -59,7 +59,7 @@
<vn-autocomplete vn-one
data="$ctrl.groupedStates"
label="Origin Grouped State"
value-field="code"
value-field="id"
show-field="name"
ng-model="filter.state">
<tpl-item>
@ -69,7 +69,7 @@
<vn-autocomplete vn-one
data="$ctrl.groupedStates"
label="Destination Grouped State"
value-field="code"
value-field="id"
show-field="name"
ng-model="filter.futureState">
<tpl-item>

View File

@ -65,8 +65,8 @@ export default class Controller extends Section {
this.$http.get(`UserConfigs/getUserConfig`)
.then(res => {
this.filterParams = {
originDated: today,
futureDated: today,
originScopeDays: today,
futureScopeDays: today,
warehouseFk: res.data.warehouseFk
};
this.$.model.applyFilter(null, this.filterParams);

View File

@ -14,3 +14,4 @@ Success: Tickets movidos correctamente
IPT: Encajado
Origin Date: Fecha origen
Destination Date: Fecha destino
Preparation: Preparación

View File

@ -4,3 +4,4 @@ Client phone: Tel. cliente
Client mobile: Móv. cliente
Go to the ticket: Ir al ticket
Change state: Cambiar estado
Weight: Peso

View File

@ -1,57 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('createWagonType', {
description: 'Creates a new wagon type',
accessType: 'WRITE',
accepts: [
{
arg: 'name',
type: 'String',
required: true
},
{
arg: 'divisible',
type: 'boolean',
required: true
}, {
arg: 'trays',
type: 'any',
required: true
}
],
http: {
path: `/createWagonType`,
verb: 'PATCH'
}
});
Self.createWagonType = async(ctx, options) => {
const args = ctx.args;
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const newWagonType = await models.WagonType.create({name: args.name, divisible: args.divisible}, myOptions);
args.trays.forEach(async tray => {
await models.WagonTypeTray.create({
typeFk: newWagonType.id,
height: tray.position,
colorFk: tray.color.id
}, myOptions);
});
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,43 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('deleteWagonType', {
description: 'Deletes a wagon type',
accessType: 'WRITE',
accepts: [
{
arg: 'id',
type: 'Number',
required: true
}
],
http: {
path: `/deleteWagonType`,
verb: 'DELETE'
}
});
Self.deleteWagonType = async(ctx, options) => {
const args = ctx.args;
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
await models.Wagon.destroyAll({typeFk: args.id}, myOptions);
await models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions);
await models.WagonType.destroyAll({id: args.id}, myOptions);
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,64 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('editWagonType', {
description: 'Edits a new wagon type',
accessType: 'WRITE',
accepts: [
{
arg: 'id',
type: 'String',
required: true
},
{
arg: 'name',
type: 'String',
required: true
},
{
arg: 'divisible',
type: 'boolean',
required: true
}, {
arg: 'trays',
type: 'any',
required: true
}
],
http: {
path: `/editWagonType`,
verb: 'PATCH'
}
});
Self.editWagonType = async(ctx, options) => {
const args = ctx.args;
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const wagonType = await models.WagonType.findById(args.id, null, myOptions);
wagonType.updateAttributes({name: args.name, divisible: args.divisible}, myOptions);
models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions);
args.trays.forEach(async tray => {
await models.WagonTypeTray.create({
typeFk: args.id,
height: tray.position,
colorFk: tray.color.id
}, myOptions);
});
if (tx) await tx.commit();
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,58 +1,16 @@
const models = require('vn-loopback/server/server').models;
describe('WagonType crudWagonType()', () => {
const ctx = {
args: {
name: 'Mock wagon type',
divisible: true,
trays: [{position: 0, color: {id: 1}},
{position: 50, color: {id: 2}},
{position: 100, color: {id: 3}}]
}
};
it(`should create, edit and delete a new wagon type and its trays`, async() => {
const tx = await models.WagonType.beginTransaction({});
try {
const options = {transaction: tx};
// create
await models.WagonType.createWagonType(ctx, options);
const wagonType = await models.WagonType.create({name: 'Mock wagon type'}, options);
const newWagonTrays = await models.WagonTypeTray.findOne({where: {typeFk: wagonType.id}}, options);
const newWagonType = await models.WagonType.findOne({where: {name: ctx.args.name}}, options);
const newWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
expect(newWagonType).not.toEqual(null);
expect(newWagonType.name).toEqual(ctx.args.name);
expect(newWagonType.divisible).toEqual(ctx.args.divisible);
expect(newWagonTrays.length).toEqual(ctx.args.trays.length);
ctx.args = {
id: newWagonType.id,
name: 'Edited wagon type',
divisible: false,
trays: [{position: 0, color: {id: 1}}]
};
// edit
await models.WagonType.editWagonType(ctx, options);
const editedWagonType = await models.WagonType.findById(newWagonType.id, null, options);
const editedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
expect(editedWagonType.name).toEqual(ctx.args.name);
expect(editedWagonType.divisible).toEqual(ctx.args.divisible);
expect(editedWagonTrays.length).toEqual(ctx.args.trays.length);
// delete
await models.WagonType.deleteWagonType(ctx, options);
const deletedWagonType = await models.WagonType.findById(newWagonType.id, null, options);
const deletedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
expect(deletedWagonType).toEqual(null);
expect(deletedWagonTrays).toEqual([]);
expect(newWagonTrays).toBeDefined();
await tx.rollback();
} catch (e) {

View File

@ -0,0 +1,58 @@
const models = require('vn-loopback/server/server').models;
describe('WagonTray max height()', () => {
it(`should throw an error if the tray's height is above the maximum of the wagon`, async() => {
const tx = await models.WagonTypeTray.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.WagonTypeTray.create({height: 210, wagonTypeFk: 1, wagonTypeColorFk: 4}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toBe('The maximum height of the wagon is 200cm');
});
it(`should throw an error if the tray's height is already in the wagon`, async() => {
const tx = await models.WagonTypeTray.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.WagonTypeTray.create({height: 50, wagonTypeFk: 1, wagonTypeColorFk: 2}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toBe('There is already a tray with the same height');
});
it(`should throw an error if the tray's height is below the minimum between the trays`, async() => {
const tx = await models.WagonTypeTray.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.WagonTypeTray.create({height: 40, wagonTypeFk: 1, wagonTypeColorFk: 4}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toBe('The height must be greater than 50cm');
});
});

View File

@ -25,6 +25,19 @@
},
"maxTrays": {
"type": "number"
},
"defaultHeight": {
"type": "number"
},
"defaultTrayColorFk": {
"type": "number"
}
},
"relations": {
"WagonTypeColor": {
"type": "belongsTo",
"model": "WagonTypeColor",
"foreignKey": "defaultTrayColorFk"
}
}
}

View File

@ -0,0 +1,25 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.observe('before save', async ctx => {
if (ctx.isNewInstance) {
const models = Self.app.models;
const {wagonTypeFk, height} = ctx.instance;
const trays = await models.WagonTypeTray.find({where: {wagonTypeFk}});
const config = await models.WagonConfig.findOne();
const tray = await models.WagonTypeTray.find({where: {wagonTypeFk, height}});
if (!trays.length) return;
if (tray.length)
throw new UserError('There is already a tray with the same height');
if (height < config.minHeightBetweenTrays)
throw new UserError('The height must be greater than 50cm');
if (height > config.maxWagonHeight)
throw new UserError('The maximum height of the wagon is 200cm');
}
});
};

View File

@ -11,13 +11,13 @@
"id": true,
"type": "number"
},
"typeFk": {
"wagonTypeFk": {
"type": "number"
},
"height": {
"type": "number"
},
"colorFk": {
"wagonTypeColorFk": {
"type": "number"
}
},
@ -25,12 +25,12 @@
"type": {
"type": "belongsTo",
"model": "WagonType",
"foreignKey": "typeFk"
"foreignKey": "wagonTypeFk"
},
"color": {
"type": "belongsTo",
"model": "WagonTypeColor",
"foreignKey": "colorFk"
"foreignKey": "wagonTypeColorFk"
}
}
}

View File

@ -1,5 +1,14 @@
module.exports = Self => {
require('../methods/wagonType/createWagonType')(Self);
require('../methods/wagonType/editWagonType')(Self);
require('../methods/wagonType/deleteWagonType')(Self);
Self.observe('after save', async ctx => {
if (ctx.isNewInstance) {
const models = Self.app.models;
const config = await models.WagonConfig.findOne();
await models.WagonTypeTray.create({
wagonTypeFk: ctx.instance.id,
height: config.defaultHeight,
wagonTypeColorFk: config.defaultTrayColorFk
}, ctx.options);
}
});
};

View File

@ -0,0 +1,118 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('handleUser', {
description: 'Manage various aspects related to a user with the app',
accepts: [
{
arg: 'androidId',
type: 'String',
description: 'Android id'
},
{
arg: 'deviceId',
type: 'String',
description: 'Device id'
},
{
arg: 'versionApp',
type: 'String',
description: 'Version app'
}, {
arg: 'nameApp',
type: 'String',
description: 'Version app'
},
],
returns: {
type: 'object',
root: true
},
http: {
path: `/handleUser`,
verb: 'POST'
}
});
Self.handleUser = async(ctx, androidId, deviceId, versionApp, nameApp, options) => {
const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const accessToken = ctx.req.accessToken;
let user = await models.VnUser.findById(accessToken.userId);
const [[{vIsAuthorized, vMessage}]] =
await Self.rawSql('CALL vn.device_checkLogin(?, ?);',
[user.id, androidId], myOptions);
if (!vIsAuthorized)
throw new UserError('Not authorized');
const isUserInOperator = await models.Operator.findOne({
where: {
workerFk: user.id
}
}, myOptions);
if (!isUserInOperator) {
await models.Operator.create({
'workerFk': user.id,
'isOnReservationMode': false
});
}
const whereCondition = deviceId ? {id: deviceId} : {android_id: androidId};
const serialNumber =
(await models.DeviceProduction.findOne({where: whereCondition}, myOptions))?.serialNumber ?? '';
await models.DeviceLog.create({
'android_id': androidId,
'userFk': user.id,
'nameApp': nameApp,
'versionApp': versionApp,
'serialNumber': serialNumber
}, myOptions);
const getDataUser = await models.VnUser.getCurrentUserData(ctx);
const getDataOperator = await models.Operator.findOne({
where: {workerFk: user.id},
fields: ['numberOfWagons', 'warehouseFk', 'itemPackingTypeFk', 'sectorFk', 'sector',
'trainFk', 'train', 'labelerFk', 'printer'],
include: [
{
relation: 'sector',
scope: {
fields: ['warehouseFk', 'description'],
}
}, {
relation: 'printer',
scope: {
fields: ['name'],
}
}, {
relation: 'train',
scope: {
fields: ['name'],
}
}
]
}, myOptions);
const getVersion = await models.MobileAppVersionControl.getVersion(ctx, nameApp);
const combinedResult = {
...getDataOperator.toObject(),
...getDataUser.toObject(),
...getVersion,
message: vMessage,
serialNumber,
};
return combinedResult;
};
};

View File

@ -0,0 +1,16 @@
const {models} = require('vn-loopback/server/server');
describe('Device handleUser()', () => {
const ctx = {req: {accessToken: {userId: 9}}};
it('should return data from user', async() => {
const androidId = 'androidid11234567890';
const deviceId = 1;
const nameApp = 'warehouse';
const versionApp = '10';
const data = await models.Device.handleUser(ctx, androidId, deviceId, versionApp, nameApp);
expect(data.numberOfWagons).toBe(2);
});
});

View File

@ -8,19 +8,19 @@ module.exports = Self => {
accepts: [
{
arg: 'id',
type: 'Number',
type: 'number',
description: 'The worker id',
http: {source: 'path'}
},
{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -36,38 +36,50 @@ module.exports = Self => {
// Get ids alloweds
const account = await models.VnUser.findById(userId);
const stmt = new ParameterizedSQL(
`SELECT d.id, d.id dmsFk
FROM workerDocument wd
JOIN dms d ON d.id = wd.document
FROM workerDms wd
JOIN dms d ON d.id = wd.dmsFk
JOIN dmsType dt ON dt.id = d.dmsTypeFk
LEFT JOIN account.roleRole rr ON rr.inheritsFrom = dt.readRoleFk AND rr.role = ?
LEFT JOIN account.roleRole rr ON rr.inheritsFrom = dt.readRoleFk
AND rr.role = ?
`, [account.roleFk]
);
const yourOwnDms = {and: [{isReadableByWorker: true}, {worker: userId}]};
const where = {
or: [yourOwnDms, {
role: {
neq: null
}
}]
const yourOwnDms = {
or: [
{and: [
{isReadableByWorker: true},
{'wd.workerFk': userId}
]},
{
role: {
neq: null
}
}]
};
stmt.merge(conn.makeSuffix(mergeWhere(filter.where, where)));
// Get workerDms alloweds
const where = mergeWhere(filter.where, yourOwnDms);
stmt.merge(conn.makeSuffix({where}));
const dmsIds = await conn.executeStmt(stmt);
const allowedIds = dmsIds.map(dms => dms.id);
const allowedFilter = mergeFilters(filter, {where: {dmsFk: {inq: allowedIds}, workerFk: id}});
let workerDms = await models.WorkerDms.find(allowedFilter);
// Get docuware info
const docuware = await models.Docuware.findOne({
fields: ['dmsTypeFk'],
where: {code: 'hr', action: 'find'}
});
const docuwareDmsType = docuware.dmsTypeFk;
let workerDocuware = [];
if (!filter.skip && (!docuwareDmsType || (docuwareDmsType && await models.DmsType.hasReadRole(ctx, docuwareDmsType)))) {
const workerDms = await models.WorkerDms.find(allowedFilter);
const workerDocuware = filter.skip ? [] : await getDocuware(ctx, id);
return workerDms.concat(workerDocuware);
async function getDocuware(ctx, id) {
const {dmsTypeFk} = await models.Docuware.findOne({
fields: ['dmsTypeFk'],
where: {code: 'hr', action: 'find'}
});
if (!await models.DmsType.hasReadRole(ctx, dmsTypeFk)) return [];
let workerDocuware = [];
const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']});
const docuwareParse = {
'Filename': 'dmsFk',
@ -80,7 +92,7 @@ module.exports = Self => {
};
workerDocuware =
await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? [];
await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? [];
const url = (await Self.app.models.Url.getUrl('docuware')) + 'WebClient';
for (document of workerDocuware) {
const docuwareId = document.id;
@ -105,7 +117,7 @@ module.exports = Self => {
};
Object.assign(document, defaultData);
}
return workerDocuware;
}
return workerDms.concat(workerDocuware);
};
};

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