diff --git a/db/changes/10290-invoiceIn/00-ACL.sql b/db/changes/10290-invoiceIn/00-ACL.sql index 661eb0d48..e3551c667 100644 --- a/db/changes/10290-invoiceIn/00-ACL.sql +++ b/db/changes/10290-invoiceIn/00-ACL.sql @@ -1,3 +1,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('StarredModule', '*', '*', 'ALLOW', 'ROLE', 'employee'); + ('StarredModule', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('ItemBotanical', '*', 'WRITE', 'ALLOW', 'ROLE', 'logisticBoss'); \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 90aae8932..857df70d3 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1064,25 +1064,25 @@ INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `level`) VALUES (1, 1, 1); -INSERT INTO `edi`.`genus`(`genus_id`, `latin_genus_name`, `entry_date`, `expiry_date`, `change_date_time`) +INSERT INTO `vn`.`genus`(`id`, `name`) VALUES - (1, 'Abelia' , CURDATE(), NULL, CURDATE()), - (2, 'Abies', CURDATE(), NULL, CURDATE()), - (3, 'Abutilon', CURDATE(), NULL, CURDATE()); + (1, 'Abelia'), + (2, 'Abies'), + (3, 'Abutilon'); -INSERT INTO `edi`.`specie`(`specie_id`, `genus_id`, `latin_species_name`, `entry_date`, `expiry_date`, `change_date_time`) +INSERT INTO `vn`.`specie`(`id`, `name`) VALUES - (1, 1, 'grandiflora', CURDATE(), NULL, CURDATE()), - (2, 2, 'procera', CURDATE(), NULL, CURDATE()), - (3, 3, 'decurrens', CURDATE(), NULL, CURDATE()), - (4, 3, 'dealbata', CURDATE(), NULL, CURDATE()); + (1, 'grandiflora'), + (2, 'procera'), + (3, 'decurrens'), + (4, 'dealbata'); -INSERT INTO `vn`.`itemBotanical`(`itemFk`, `botanical`, `genusFk`, `specieFk`) +INSERT INTO `vn`.`itemBotanical`(`itemFk`, `genusFk`, `specieFk`) VALUES - (1, 'Hedera helix', 1, 1), - (2, NULL, 2, 2), - (3, 'Cycas revoluta', 2, NULL), - (4, 'Polygonum', NULL, NULL); + (1, 1, 1), + (2, 2, 2), + (3, 2, NULL), + (4, NULL, NULL); INSERT INTO `vn`.`tag`(`id`, `code`, `name`, `isFree`, `isQuantitatif`, `sourceTable`, `unit`, `ediTypeFk`, `overwrite`) VALUES @@ -1233,11 +1233,18 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`) (104, 500), (105, 5000); -INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`) +INSERT INTO `vn`.`supplierActivity`(`code`, `name`) VALUES - (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18), - (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18), - (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18); + ('animals', 'Food and complements for pets'), + ('complements', 'Other complements'), + ('flowerPlants', 'Wholesale of flowers and plants'), + ('vegetablesFruits', 'Fruit and vegetable trade'); + +INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`) + VALUES + (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants'), + (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals'), + (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants'); INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`) VALUES diff --git a/db/dump/structure.sql b/db/dump/structure.sql index a57473241..7a598d9d7 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -1,4 +1,4 @@ --- MariaDB dump 10.18 Distrib 10.5.8-MariaDB, for Linux (x86_64) +-- MariaDB dump 10.19 Distrib 10.5.9-MariaDB, for Linux (x86_64) -- -- Host: test-db.verdnatura.es Database: account -- ------------------------------------------------------ @@ -7119,7 +7119,7 @@ CREATE TABLE `cache_calc` ( KEY `cache_id` (`cache_id`), KEY `cacheName` (`cacheName`), KEY `expires` (`expires`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +) ENGINE=InnoDBDEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -7133,7 +7133,7 @@ CREATE TABLE `cache_valid` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `valid` tinyint(3) unsigned NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MEMORY DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +) ENGINE=MEMORYDEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -9243,6 +9243,7 @@ BEGIN DECLARE vError VARCHAR(100) DEFAULT 'Orderregel niet meer teruggevonden op basis van de orderps'; DECLARE vVmpIdError INT DEFAULT 7; DECLARE vVmpFk INT; + DECLARE vSupplyResponseNumberOfUnits INT; SELECT sr.vmpID INTO vVmpFk FROM edi.supplyResponse sr @@ -9258,6 +9259,17 @@ BEGIN SET NEW.OrderStatus = 2; END IF; + + -- Error de disponible menor de lo solicitado + IF NEW.error LIKE 'error2602%' THEN + + SELECT NumberOfUnits INTO vSupplyResponseNumberOfUnits + FROM edi.supplyResponse sr + WHERE sr.ID = NEW.supplyResponseID; + + SET NEW.error = CONCAT('(',vSupplyResponseNumberOfUnits,') ', NEW.error); + + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -10063,9 +10075,9 @@ DELIMITER ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET character_set_client = utf8 */ ; +/*!50003 SET character_set_results = utf8 */ ; +/*!50003 SET collation_connection = utf8_general_ci */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; @@ -10080,6 +10092,7 @@ proc: BEGIN DECLARE vIsAuctionDay BOOLEAN; DECLARE vMaxNewItems INT DEFAULT 100000; DECLARE vStartingTime DATETIME; + DECLARE vAalsmeerMarketPlaceID VARCHAR(13) DEFAULT '8713783439043'; DECLARE cur1 CURSOR FOR SELECT id @@ -10123,10 +10136,11 @@ proc: BEGIN FROM ( SELECT * FROM edi.supplyOffer - ORDER BY NumberOfUnits DESC) t + ORDER BY (MarketPlaceID = vAalsmeerMarketPlaceID) DESC, NumberOfUnits DESC) t JOIN edi.item_groupToOffer igo ON igo.group_code = t.group_id LEFT JOIN edi.item_defaultType idt ON idt.item_id = t.Item_ArticleCode - GROUP BY Item_ArticleCode, s1, s2, s3, s4, s5, s6, company_name, Quality, NumberOfItemsPerCask, EmbalageCode, Price ; + GROUP BY Item_ArticleCode, s1, s2, s3, s4, s5, s6, company_name, Quality, NumberOfItemsPerCask, EmbalageCode, Price + ; -- -- select now(),'Antes de crear edi.offer'; DROP TEMPORARY TABLE IF EXISTS edi.offer; @@ -10368,6 +10382,423 @@ proc: BEGIN 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.agencyFk + JOIN vn.item i ON i.id = b.itemFk + JOIN edi.supplyResponse sr ON i.supplyResponseFk = sr.ID + LEFT JOIN edi.putOrder po ON b.deliveryFk = po.deliveryInformationID + LEFT JOIN edi.deliveryInformation di ON di.ID = b.deliveryFk + SET b.quantity = 0 + WHERE (di.LatestOrderDateTime < NOW() + OR sr.ID 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.floramondo_getEntry(TIMESTAMPADD(DAY,travellingDays,vLanded), 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); + + -- Se eliminan las ofertas ya incluidas en las entradas + DELETE o + FROM edi.offer o + JOIN vn.item i ON i.supplyResponseFk = o.srId + JOIN vn.buy b ON i.id = b.itemFk + JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk; + + -- Se inserta el resto + SET vLastInserted := NOW(); + + -- Inserta la oferta + INSERT INTO vn.buy(entryFk, + itemFk, + quantity, + buyingValue, + stickers, + packing, + `grouping`, + groupingMode, + packageFk, + deliveryFk) + + SELECT wf.entryFk, + i.id, + o.NumberOfUnits * o.NumberOfItemsPerCask as quantity, + o.Price, + o.NumberOfUnits as etiquetas, + o.NumberOfItemsPerCask as packing, + GREATEST(1, IFNULL(o.MinimumQuantity,0)) * o.NumberOfItemsPerCask as `grouping`, + 2, -- Obliga al Packing + o.embalageCode, + o.diId + FROM edi.offer o + JOIN vn.item i ON i.supplyResponseFk = o.srId + JOIN vn.itemType it ON it.id = i.typeFk + JOIN edi.warehouseFloramondo wf ON wf.isFV = it.isFV OR wf.isFV IS NULL + JOIN vn.packaging p ON p.id LIKE o.embalageCode; -- llevar esta linea i mirar de crear els packages a temps real + + DROP TEMPORARY TABLE IF EXISTS tmp.buyRecalc; + + CREATE TEMPORARY TABLE tmp.buyRecalc + SELECT b.id + FROM vn.buy b + JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk + WHERE b.created >= vLastInserted; + + CALL vn.buy_recalcPrices(); + + END IF; + + DROP TEMPORARY TABLE + edi.offer, + itemToInsert; + + DROP TABLE tmp.item; + + 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; + + INSERT INTO edi.log(tableName, fieldName,fieldValue) + VALUES('floramondo_offerRefresh','Tiempo de proceso',TIMEDIFF(NOW(),vStartingTime)); + + + +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP PROCEDURE IF EXISTS `floramondo_offerRefresh__` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8 */ ; +/*!50003 SET character_set_results = utf8 */ ; +/*!50003 SET collation_connection = utf8_general_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`%` PROCEDURE `floramondo_offerRefresh__`() +proc: BEGIN + + DECLARE vLanded DATETIME; + DECLARE done INT DEFAULT FALSE; + DECLARE vFreeId INT; + DECLARE vSupplyResponseFk INT; + DECLARE vLastInserted DATETIME; + DECLARE vIsAuctionDay BOOLEAN; + DECLARE vMaxNewItems INT DEFAULT 100000; + DECLARE vStartingTime DATETIME; + + 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 done = TRUE; + DECLARE EXIT HANDLER FOR SQLSTATE '45000' + BEGIN + ROLLBACK; + RESIGNAL; + END; + + SET vStartingTime = NOW(); + + -- CALL vn.clean_logiflora(); + + -- Refresca las fotos de los items existentes, con prioridad baja (0.7 seg) + 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 + WHERE i.image != edi.imageName(sr.PictureReference) + AND sr.NumberOfUnits > 0; + + DELETE itf.* + FROM edi.item_free itf + JOIN vn.item i ON i.id = itf.id; + + -- -- select now(),'Tras borrar'; + DROP TEMPORARY TABLE IF EXISTS tmp; + CREATE TEMPORARY TABLE tmp (INDEX (`Item_ArticleCode`)) ENGINE = MEMORY + SELECT t.*, + IFNULL(idt.itemTypeFk, igo.itemTypeFk) itemTypeFk, + igo.expenseFk , + igo.intrastatFk , + igo.originFk + FROM ( + SELECT * + FROM edi.supplyOffer + ORDER BY NumberOfUnits DESC) t + JOIN edi.item_groupToOffer igo ON igo.group_code = t.group_id + LEFT JOIN edi.item_defaultType idt ON idt.item_id = t.Item_ArticleCode + GROUP BY Item_ArticleCode, s1, s2, s3, s4, s5, s6, company_name, Quality, NumberOfItemsPerCask, EmbalageCode, Price ; + + -- -- select now(),'Antes de crear edi.offer'; + DROP TEMPORARY TABLE IF EXISTS edi.offer; + CREATE TEMPORARY TABLE edi.offer (INDEX (`srID`), INDEX (`EmbalageCode`)) 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; + + + START TRANSACTION; + + -- Actualizamos el campo supplyResponseFk para aquellos articulos que ya estan creados y reutilizamos + UPDATE IGNORE edi.offer o + LEFT JOIN vn.item iExist ON iExist.supplyResponseFk = o.srID + 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 + LEFT JOIN deliveryInformation di ON di.supplyResponseID = i.supplyResponseFk + JOIN vn.itemType it ON it.id = i.typeFk + SET i.supplyResponseFk = o.srID + WHERE iExist.id IS NULL + AND (di.LatestOrderDateTime < NOW() OR di.ID IS NULL) + AND it.isInventory + ; + -- select now(),'Antes de crear ITO'; + DROP TEMPORARY TABLE IF EXISTS itemToInsert; + CREATE TEMPORARY TABLE itemToInsert ENGINE = MEMORY + SELECT o.*, CAST(NULL AS DECIMAL(6,0)) as 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 done 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, + expenceFk, + typeFk, + intrastatFk, + originFk, + supplyResponseFk, + numberOfItemsPerCask, + embalageCode, + quality, + isFloramondo) + SELECT itemFk, + product_name, + product_name, + company_name, + expenseFk, + itemTypeFk, + intrastatFk, + originFk, + `srId`, + NumberOfItemsPerCask, + EmbalageCode, + Quality, + TRUE + FROM itemToInsert; + + 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; + + 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; + + -- Inserta los tags sólo en los articulos nuevos + + -- desabilita el trigger para recalcular los tags al final + SET @isTriggerDisabled = TRUE; + + 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`; + + 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`; + + 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`; + + 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 s1Value != ''; + + 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 s2Value != ''; + + 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 s3Value != ''; + + 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 s4Value != ''; + + 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 s5Value != ''; + + 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 s6Value != ''; + + INSERT INTO vn.itemTag(itemFk, tagFk, value, priority) + SELECT i.id, t.id, ink.name, 11 + FROM itemToInsert ii + JOIN vn.item i ON i.supplyResponseFk = ii.`srId` + JOIN vn.tag t ON t.`name` = 'Color' + JOIN edi.feature f ON f.item_id = ii.Item_ArticleCode + JOIN edi.`type` tp ON tp.type_id = f.feature_type_id AND tp.`description` = 'Hoofdkleur 1' + JOIN vn.ink ON ink.dutchCode = f.feature_value; + + UPDATE vn.item i + JOIN itemToInsert ii ON i.supplyResponseFk = ii.`srId` + JOIN vn.packaging p ON p.id LIKE ii.EmbalageCode AND hasCompressionVariations + JOIN vn.itemTag diameter ON diameter.itemFk = i.id + JOIN vn.tag tDiameter ON tDiameter.overwrite = 'diameter' AND tDiameter.id = diameter.tagFk + JOIN vn.itemTag size ON size.itemFk = i.id + JOIN vn.tag tSize ON tSize.overwrite = 'size' AND tSize.id = size.tagFk + SET i.`compression` = + (PI() * POW(diameter.`value`/ 2, 2) * size.`value`) + / + ((p.width * p.depth * p.height) / ii.NumberOfItemsPerCask); + + DROP TABLE IF EXISTS tmp.item; + CREATE 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(); + + SET @isTriggerDisabled = FALSE; + + 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(NOW()), CURDATE(), TIMESTAMPADD(DAY,1,CURDATE())); + + 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 @@ -10382,14 +10813,14 @@ proc: BEGIN AND sr.ID IS NULL AND am.name = 'LOGIFLORA' AND e.isRaid; - /* + UPDATE vn.buy b JOIN edi.warehouseFloramondo wf ON wf.entryFk = b.entryFk JOIN vn.item i ON i.id = b.itemFk LEFT JOIN edi.supplyResponse sr ON sr.ID = i.supplyResponseFk SET b.quantity = 0 WHERE sr.ID IS NULL; - */ + -- Localiza las entradas de cada almacen UPDATE edi.warehouseFloramondo SET entryFk = vn.floramondo_getEntry(TIMESTAMPADD(DAY,travellingDays,vLanded), warehouseFk); @@ -20607,7 +21038,7 @@ BEGIN mc.ImporteRetencion, mc.SiglaNacion, mc.EjercicioFactura, - mc.FechaOperacion, + x.FECHA, mc.Exclusion347, mc.MantenerAsiento, mc.Metalico347, @@ -24444,7 +24875,8 @@ SET character_set_client = utf8; `account` tinyint NOT NULL, `accountingTypeFk` tinyint NOT NULL, `entityFk` tinyint NOT NULL, - `isActive` tinyint NOT NULL + `isActive` tinyint NOT NULL, + `currencyFk` tinyint NOT NULL ) ENGINE=MyISAM */; SET character_set_client = @saved_cs_client; @@ -26715,7 +27147,7 @@ CREATE TABLE `cmr_expeditionPallet` ( KEY `cmr_expeditionPallet_fk2_idx` (`expeditionPalletFk`), CONSTRAINT `cmr_expeditionPallet_fk1` FOREIGN KEY (`cmrFk`) REFERENCES `cmr` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `cmr_expeditionPallet_fk2` FOREIGN KEY (`expeditionPalletFk`) REFERENCES `expeditionPallet` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDBDEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='relaciona los cmr con los pallets de expediciones'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='relaciona los cmr con los pallets de expediciones'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -28653,6 +29085,26 @@ CREATE TABLE `entryLog` ( ) ENGINE=InnoDBDEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `entryObservation` +-- + +DROP TABLE IF EXISTS `entryObservation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `entryObservation` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `entryFk` int(11) NOT NULL, + `observationTypeFk` tinyint(3) unsigned DEFAULT NULL, + `description` text COLLATE utf8_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `entryFk_observationTypeFk_UNIQUE` (`entryFk`,`observationTypeFk`), + KEY `observationType_id_observationTypeFk` (`observationTypeFk`), + CONSTRAINT `entry_id_entryFk` FOREIGN KEY (`entryFk`) REFERENCES `entry` (`id`), + CONSTRAINT `observationType_id_observationTypeFk` FOREIGN KEY (`observationTypeFk`) REFERENCES `observationType` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `entryShelving__` -- @@ -30760,14 +31212,13 @@ DROP TABLE IF EXISTS `itemBotanical`; CREATE TABLE `itemBotanical` ( `itemFk` int(11) NOT NULL, `botanical` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, - `genusFk` int(11) DEFAULT NULL, + `genusFk` int(11) NOT NULL, `specieFk` int(11) DEFAULT NULL, PRIMARY KEY (`itemFk`), KEY `genusFgn_idx` (`genusFk`), KEY `specieFgn_idx` (`specieFk`), CONSTRAINT `itemBotanicalItemFkFk` FOREIGN KEY (`itemFk`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `itemBotanical_FK` FOREIGN KEY (`specieFk`) REFERENCES `specie` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT `itemBotanical_fk2` FOREIGN KEY (`genusFk`) REFERENCES `genus` (`id`) ON DELETE SET NULL ON UPDATE CASCADE + CONSTRAINT `itemBotanical_FK` FOREIGN KEY (`specieFk`) REFERENCES `specie` (`id`) ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Sustituye a antiguo NomBotanic de Articles'; /*!40101 SET character_set_client = @saved_cs_client */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; @@ -33982,7 +34433,16 @@ DELIMITER ;; BEFORE INSERT ON receipt FOR EACH ROW BEGIN + DECLARE vIsAutoConciliated BOOLEAN; + + IF NEW.isConciliate = FALSE THEN + SELECT isAutoConciliated INTO vIsAutoConciliated + FROM accounting a + JOIN accountingType at2 ON at2.id = a.accountingTypeFk + WHERE a.id = NEW.bankFk; + SET NEW.isConciliate = vIsAutoConciliated; + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -35776,6 +36236,8 @@ CREATE TABLE `supplier` ( `withholdingSageFk` smallint(6) DEFAULT NULL COMMENT 'Tipos de retención SAGE', `transactionTypeSageFk` tinyint(4) DEFAULT NULL COMMENT 'Ti po de transacción SAGE', `isTrucker` tinyint(1) NOT NULL DEFAULT 0, + `supplierActivityFk` varchar(45) NOT NULL DEFAULT 'flowersPlants', + `healthRegister` varchar(45) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `cuenta` (`account`), UNIQUE KEY `NIF` (`nif`), @@ -35787,13 +36249,15 @@ CREATE TABLE `supplier` ( KEY `supplier_taxTypeFk_idx` (`taxTypeSageFk`), KEY `supplier_withholdingFk_idx` (`withholdingSageFk`), KEY `supplier_transactionFk_idx` (`transactionTypeSageFk`), + KEY `suppplier_supplierActivityFk` (`supplierActivityFk`), CONSTRAINT `Id_Pais` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE, CONSTRAINT `pay_dem_id` FOREIGN KEY (`payDemFk`) REFERENCES `payDem` (`id`) ON UPDATE CASCADE, CONSTRAINT `pay_met_id` FOREIGN KEY (`payMethodFk`) REFERENCES `payMethod` (`id`) ON UPDATE CASCADE, CONSTRAINT `province_id` FOREIGN KEY (`provinceFk`) REFERENCES `province` (`id`) ON UPDATE CASCADE, CONSTRAINT `supplier_taxTypeFk` FOREIGN KEY (`taxTypeSageFk`) REFERENCES `sage`.`TiposIva` (`CodigoIva`) ON UPDATE CASCADE, CONSTRAINT `supplier_transactionFk` FOREIGN KEY (`transactionTypeSageFk`) REFERENCES `sage`.`TiposTransacciones` (`CodigoTransaccion`) ON UPDATE CASCADE, - CONSTRAINT `supplier_withholdingFk` FOREIGN KEY (`withholdingSageFk`) REFERENCES `sage`.`TiposRetencion` (`CodigoRetencion`) ON UPDATE CASCADE + CONSTRAINT `supplier_withholdingFk` FOREIGN KEY (`withholdingSageFk`) REFERENCES `sage`.`TiposRetencion` (`CodigoRetencion`) ON UPDATE CASCADE, + CONSTRAINT `suppplier_supplierActivityFk` FOREIGN KEY (`supplierActivityFk`) REFERENCES `supplierActivity` (`code`) ON UPDATE CASCADE ) ENGINE=InnoDBDEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -35849,6 +36313,20 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +-- +-- Table structure for table `supplierActivity` +-- + +DROP TABLE IF EXISTS `supplierActivity`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `supplierActivity` ( + `code` varchar(45) CHARACTER SET utf8 NOT NULL, + `name` varchar(45) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `supplierContact` -- @@ -77948,7 +78426,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_general_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`%` SQL SECURITY DEFINER */ -/*!50001 VIEW `accounting` AS select `b`.`Id_Banco` AS `id`,`b`.`Banco` AS `bank`,`b`.`Cuenta` AS `account`,`b`.`cash` AS `accountingTypeFk`,`b`.`entity_id` AS `entityFk`,`b`.`activo` AS `isActive` from `vn2008`.`Bancos` `b` */; +/*!50001 VIEW `accounting` AS select `b`.`id` AS `id`,`b`.`bank` AS `bank`,`b`.`account` AS `account`,`b`.`cash` AS `accountingTypeFk`,`b`.`entityFk` AS `entityFk`,`b`.`isActive` AS `isActive`,`b`.`currencyFk` AS `currencyFk` from `bank` `b` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -80248,4 +80726,4 @@ USE `vncontrol`; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2021-03-02 7:45:42 +-- Dump completed on 2021-03-04 8:02:58 diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 931d72654..67921d4cb 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -357,7 +357,6 @@ export default { submitNichesButton: 'vn-item-niche button[type=submit]' }, itemBotanical: { - botanical: 'vn-item-botanical vn-horizontal:nth-child(1) vn-textfield[ng-model="$ctrl.botanical.botanical"]', genus: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]', species: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]', submitBotanicalButton: `vn-item-botanical button[type=submit]` diff --git a/e2e/paths/04-item/01_summary.spec.js b/e2e/paths/04-item/01_summary.spec.js index 7658cb752..d6f784be8 100644 --- a/e2e/paths/04-item/01_summary.spec.js +++ b/e2e/paths/04-item/01_summary.spec.js @@ -48,10 +48,10 @@ describe('Item summary path', () => { }); it(`should check the item summary preview shows fields from botanical`, async() => { - await page.waitForTextInElement(selectors.itemSummary.botanical, 'Hedera helix'); + await page.waitForTextInElement(selectors.itemSummary.botanical, 'Abelia'); const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); - expect(result).toContain('Hedera helix'); + expect(result).toContain('Abelia'); }); it(`should check the item summary preview shows fields from barcode`, async() => { @@ -102,7 +102,7 @@ describe('Item summary path', () => { await page.waitForSelector(selectors.itemSummary.basicData, {hidden: true}); }); - it(`should navigate to the one of the items detailed section`, async() => { + it(`should navigate to one of the items detailed section`, async() => { await page.accessToSearchResult('Melee weapon combat fist 15cm'); await page.waitForState('item.card.summary'); }); @@ -135,7 +135,7 @@ describe('Item summary path', () => { it(`should check the item summary shows fields from botanical section`, async() => { const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); - expect(result).toContain('-'); + expect(result).toContain('procera'); }); it(`should check the item summary shows fields from barcodes section`, async() => { diff --git a/e2e/paths/04-item/06_botanical.spec.js b/e2e/paths/04-item/06_botanical.spec.js index 47609842c..1671cc5d2 100644 --- a/e2e/paths/04-item/06_botanical.spec.js +++ b/e2e/paths/04-item/06_botanical.spec.js @@ -17,7 +17,6 @@ describe('Item Create botanical path', () => { }); it(`should create a new botanical for the item`, async() => { - await page.write(selectors.itemBotanical.botanical, 'Cicuta maculata'); await page.autocompleteSearch(selectors.itemBotanical.genus, 'Abelia'); await page.autocompleteSearch(selectors.itemBotanical.species, 'dealbata'); await page.waitToClick(selectors.itemBotanical.submitBotanicalButton); @@ -26,15 +25,6 @@ describe('Item Create botanical path', () => { expect(message.text).toContain('Data saved!'); }); - it(`should confirm the botanical for the item was created`, async() => { - await page.reloadSection('item.card.botanical'); - await page.waitForTextInField(selectors.itemBotanical.botanical, 'Cicuta maculata'); - const result = await page - .waitToGetProperty(selectors.itemBotanical.botanical, 'value'); - - expect(result).toEqual('Cicuta maculata'); - }); - it(`should confirm the Genus for the item was created`, async() => { await page.waitForTextInField(selectors.itemBotanical.genus, 'Abelia'); const result = await page @@ -51,8 +41,6 @@ describe('Item Create botanical path', () => { }); it(`should edit botanical for the item`, async() => { - await page.clearInput(selectors.itemBotanical.botanical); - await page.write(selectors.itemBotanical.botanical, 'Herp Derp'); await page.autocompleteSearch(selectors.itemBotanical.genus, 'Abies'); await page.autocompleteSearch(selectors.itemBotanical.species, 'decurrens'); await page.waitToClick(selectors.itemBotanical.submitBotanicalButton); @@ -61,15 +49,6 @@ describe('Item Create botanical path', () => { expect(message.text).toContain('Data saved!'); }); - it(`should confirm the botanical for the item was edited`, async() => { - await page.reloadSection('item.card.botanical'); - await page.waitForTextInField(selectors.itemBotanical.botanical, 'Herp Derp'); - const result = await page - .waitToGetProperty(selectors.itemBotanical.botanical, 'value'); - - expect(result).toEqual('Herp Derp'); - }); - it(`should confirm the Genus for the item was edited`, async() => { await page.waitForTextInField(selectors.itemBotanical.genus, 'Abies'); const result = await page diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 174a9e093..8d5156842 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -174,5 +174,7 @@ "That item doesn't exists": "Ese artículo no existe", "There's a new urgent ticket": "Hay un nuevo ticket urgente: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})", "Invalid account": "Cuenta inválida", - "Compensation account is empty": "La cuenta para compensar está vacia" + "Compensation account is empty": "La cuenta para compensar está vacia", + "This genus already exist": "Este genus ya existe", + "This specie already exist": "Esta especie ya existe" } \ No newline at end of file diff --git a/modules/item/back/models/genus.js b/modules/item/back/models/genus.js new file mode 100644 index 000000000..c105e06b4 --- /dev/null +++ b/modules/item/back/models/genus.js @@ -0,0 +1,9 @@ +let UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`This genus already exist`); + return err; + }); +}; diff --git a/modules/item/back/models/genus.json b/modules/item/back/models/genus.json index 48eab3169..b675f334a 100644 --- a/modules/item/back/models/genus.json +++ b/modules/item/back/models/genus.json @@ -3,26 +3,17 @@ "base": "VnModel", "options": { "mysql": { - "table": "edi.genus" + "table": "vn.genus" } }, "properties": { - "genus_id": { + "id": { "type": "Number", "id": true, "description": "Identifier" }, - "latin_genus_name": { + "name": { "type": "String" - }, - "entry_date": { - "type": "date" - }, - "expiry_date": { - "type": "date" - }, - "change_date_time": { - "type": "date" } }, "acls": [ @@ -31,6 +22,12 @@ "principalType": "ROLE", "principalId": "$everyone", "permission": "ALLOW" + }, + { + "accessType": "WRITE", + "principalType": "ROLE", + "principalId": "logisticBoss", + "permission": "ALLOW" } ] } \ No newline at end of file diff --git a/modules/item/back/models/item-botanical.json b/modules/item/back/models/item-botanical.json index 12248602d..541218145 100644 --- a/modules/item/back/models/item-botanical.json +++ b/modules/item/back/models/item-botanical.json @@ -16,9 +16,6 @@ "type": "Number", "id": true, "description": "Identifier" - }, - "botanical": { - "type": "String" } }, "relations": { diff --git a/modules/item/back/models/specie.js b/modules/item/back/models/specie.js new file mode 100644 index 000000000..e6a03f851 --- /dev/null +++ b/modules/item/back/models/specie.js @@ -0,0 +1,9 @@ +let UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`This specie already exist`); + return err; + }); +}; diff --git a/modules/item/back/models/specie.json b/modules/item/back/models/specie.json index 1388be53b..1a4435ea6 100644 --- a/modules/item/back/models/specie.json +++ b/modules/item/back/models/specie.json @@ -3,33 +3,17 @@ "base": "VnModel", "options": { "mysql": { - "table": "edi.specie" + "table": "vn.specie" } }, "properties": { - "specie_id": { + "id": { "type": "Number", "id": true, "description": "Identifier" }, - "latin_species_name": { + "name": { "type": "String" - }, - "entry_date": { - "type": "date" - }, - "expiry_date": { - "type": "date" - }, - "change_date_time": { - "type": "date" - } - }, - "relations": { - "genus": { - "type": "belongsTo", - "model": "Genus", - "foreignKey": "genus_id" } }, "acls": [ @@ -38,6 +22,12 @@ "principalType": "ROLE", "principalId": "$everyone", "permission": "ALLOW" + }, + { + "accessType": "WRITE", + "principalType": "ROLE", + "principalId": "logisticBoss", + "permission": "ALLOW" } ] } \ No newline at end of file diff --git a/modules/item/front/botanical/index.html b/modules/item/front/botanical/index.html index 052e7d9e4..3d1beefd7 100644 --- a/modules/item/front/botanical/index.html +++ b/modules/item/front/botanical/index.html @@ -1,46 +1,46 @@ -
+ - - - - + show-field="name" + value-field="id"> + + + + + show-field="name" + value-field="id"> -
{{latin_species_name}}
+
{{name}}
- {{genus.latin_genus_name}} + {{genus.name}}
+ + + +
@@ -57,4 +57,42 @@ ng-click="watcher.loadOriginalData()"> --> -
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/botanical/index.js b/modules/item/front/botanical/index.js index 3786cdb45..d0ff3f466 100644 --- a/modules/item/front/botanical/index.js +++ b/modules/item/front/botanical/index.js @@ -1,9 +1,89 @@ import ngModule from '../module'; import Section from 'salix/components/section'; +class Controller extends Section { + get item() { + return this._item; + } -class Controller extends Section {} + set item(value) { + this._item = value; + if (value) + this.getBotanicalData(); + } + + showGenus(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + + this.$.genus.show(); + } + + showSpecies(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + + this.$.species.show(); + } + + onGenusAccept() { + try { + if (!this.data.name) + throw new Error(`The name of the genus can't be empty`); + + this.$http.post(`genera`, this.data).then(res => { + this.vnApp.showMessage(this.$t('The genus has been created')); + this.emit('response', {$response: res.data}); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } + + onSpeciesAccept() { + try { + if (!this.data.name) + throw new Error(`The name of the specie can't be empty`); + + this.$http.post(`species`, this.data).then(res => { + this.vnApp.showMessage(this.$t('The specie has been created')); + this.emit('response', {$response: res.data}); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } + + getBotanicalData() { + const filter = { + where: {itemFk: this.item.id} + }; + const filterParams = encodeURIComponent(JSON.stringify(filter)); + this.$http.get(`ItemBotanicals?filter=${filterParams}`).then(res => { + if (res.data[0]) + this.botanical = res.data[0]; + + else + this.botanical = {itemFk: this.item.id}; + }); + } + + onSubmit() { + this.$.watcher.check(); + this.$http.patch(`ItemBotanicals`, this.botanical).then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } +} ngModule.vnComponent('vnItemBotanical', { template: require('./index.html'), + bindings: { + item: '<' + }, controller: Controller }); diff --git a/modules/item/front/botanical/index.spec.js b/modules/item/front/botanical/index.spec.js new file mode 100644 index 000000000..f679a58f4 --- /dev/null +++ b/modules/item/front/botanical/index.spec.js @@ -0,0 +1,179 @@ +import './index.js'; + +describe('vnItemBotanical', () => { + describe('Component vnItemBotanical', () => { + let $httpBackend; + let $scope; + let controller; + let vnApp; + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => { + $httpBackend = _$httpBackend_; + vnApp = _vnApp_; + jest.spyOn(vnApp, 'showError'); + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnItemBotanical', {$element, $scope}); + controller.item = {id: 5}; + controller.$params = {itemFk: 5}; + controller.$ = { + watcher: { + check: () => {}, + notifySaved: () => {}, + updateOriginalData: () => {}}, + genus: { + show: () => {} + }, + species: { + show: () => {} + }}; + })); + + describe('showGenus()', () => { + it('should do nothing in genus field if it default is prevented', () => { + const event = { + defaultPrevented: true, + preventDefault: () => {} + }; + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.genus, 'show'); + + controller.showGenus(event); + + expect(event.preventDefault).not.toHaveBeenCalledWith(); + expect(controller.$.genus.show).not.toHaveBeenCalledWith(); + }); + + it('should call preventDefault() and show() in genus field when the default is not prevented', () => { + const event = { + defaultPrevented: false, + preventDefault: () => {} + }; + + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.genus, 'show'); + + controller.showGenus(event); + + expect(event.preventDefault).toHaveBeenCalledWith(); + expect(controller.$.genus.show).toHaveBeenCalledWith(); + }); + }); + + describe('showSpecies()', () => { + it('should do nothing in species field if it default is prevented', () => { + const event = { + defaultPrevented: true, + preventDefault: () => {} + }; + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.species, 'show'); + + controller.showSpecies(event); + + expect(event.preventDefault).not.toHaveBeenCalledWith(); + expect(controller.$.species.show).not.toHaveBeenCalledWith(); + }); + + it('should call preventDefault() and show() in species field when the default is not prevented', () => { + const event = { + defaultPrevented: false, + preventDefault: () => {} + }; + + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.species, 'show'); + + controller.showSpecies(event); + + expect(event.preventDefault).toHaveBeenCalledWith(); + expect(controller.$.species.show).toHaveBeenCalledWith(); + }); + }); + + describe('onGenusAccept()', () => { + it('should throw an error if there is no name in the genus name field', () => { + jest.spyOn(controller.vnApp, 'showMessage'); + + controller.data = {}; + + controller.onGenusAccept(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The name of the genus can't be empty`); + }); + + it('should do add the new genus', () => { + $httpBackend.whenRoute('GET', 'ItemBotanicals').respond({}); + $httpBackend.resetExpectations(); + + controller.data = { + name: 'Anilius' + }; + + $httpBackend.expectPOST('genera', controller.data).respond(200, controller.data); + + controller.onGenusAccept(); + $httpBackend.flush(); + }); + }); + + describe('onSpeciesAccept()', () => { + it('should throw an error if there is no name in the specie name field', () => { + jest.spyOn(controller.vnApp, 'showMessage'); + + controller.data = {}; + + controller.onSpeciesAccept(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The name of the specie can't be empty`); + }); + + it('should do add the new specie', () => { + $httpBackend.whenRoute('GET', 'ItemBotanicals').respond({}); + $httpBackend.resetExpectations(); + + controller.data = { + name: 'Spasiva' + }; + + $httpBackend.expectPOST('species', controller.data).respond(200, controller.data); + + controller.onSpeciesAccept(); + $httpBackend.flush(); + }); + }); + + describe('onSubmit()', () => { + it('should make an HTTP POST request to save the genus and species data', () => { + $httpBackend.whenRoute('GET', 'ItemBotanicals').respond({}); + $httpBackend.resetExpectations(); + + jest.spyOn(controller.$.watcher, 'updateOriginalData'); + jest.spyOn(controller.$.watcher, 'check'); + jest.spyOn(controller.$.watcher, 'notifySaved'); + + controller.botanical = [{itemFk: 5, genusFk: 3, specieFk: 2}]; + $httpBackend.expectPATCH('ItemBotanicals', controller.botanical).respond({}); + controller.onSubmit(); + $httpBackend.flush(); + + expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith(); + expect(controller.$.watcher.check).toHaveBeenCalledWith(); + expect(controller.$.watcher.notifySaved).toHaveBeenCalledWith(); + }); + }); + + describe('getBotanicalData()', () => { + it('should get the item data from itemBotanical', () => { + const response = ['MyResult']; + $httpBackend.whenRoute('GET', `ItemBotanicals`).respond(response); + controller.getBotanicalData(); + $httpBackend.flush(); + + expect(controller.botanical).toEqual(response[0]); + }); + }); + }); +}); + diff --git a/modules/item/front/botanical/locale/es.yml b/modules/item/front/botanical/locale/es.yml new file mode 100644 index 000000000..e22400654 --- /dev/null +++ b/modules/item/front/botanical/locale/es.yml @@ -0,0 +1,5 @@ +The genus has been created: El genus ha sido creado +The specie has been created: La especie ha sido creada +Latin species name: Nombre de la especie en latín +Latin genus name: Nombre del genus en latín +Species: Especie \ No newline at end of file diff --git a/modules/item/front/locale/es.yml b/modules/item/front/locale/es.yml index 8046fbafe..46e40e412 100644 --- a/modules/item/front/locale/es.yml +++ b/modules/item/front/locale/es.yml @@ -26,7 +26,8 @@ Intrastat code: Código intrastat Warehouse: Almacén Code: Código State: Estado -Species: Especie +New species: Nueva especie +New genus: Nuevo genus Add tag: Añadir etiqueta Remove tag: Quitar etiqueta Add niche: Añadir nicho diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index 67d3bf3c6..926c95ee6 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -169,14 +169,11 @@ ng-show="!$ctrl.isBuyer"> Botanical - - + value="{{$ctrl.summary.botanical.genus.name}}"> + value="{{$ctrl.summary.botanical.specie.name}}">