diff --git a/back/model-config.json b/back/model-config.json index 4ce11b99d..343210383 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -68,6 +68,12 @@ "Language": { "dataSource": "vn" }, + "MachineWorker": { + "dataSource": "vn" + }, + "MobileAppVersionControl": { + "dataSource": "vn" + }, "Module": { "dataSource": "vn" }, diff --git a/back/models/app-version-control.json b/back/models/app-version-control.json new file mode 100644 index 000000000..46c53be3c --- /dev/null +++ b/back/models/app-version-control.json @@ -0,0 +1,24 @@ +{ + "name": "MobileAppVersionControl", + "base": "VnModel", + "options": { + "mysql": { + "table": "vn.mobileAppVersionControl" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + }, + "appName": { + "type": "string" + }, + "version": { + "type": "string" + }, + "isVersionCritical": { + "type": "boolean" + } + } +} diff --git a/back/models/machine-worker.json b/back/models/machine-worker.json new file mode 100644 index 000000000..2244a533f --- /dev/null +++ b/back/models/machine-worker.json @@ -0,0 +1,33 @@ +{ + "name": "MachineWorker", + "base": "VnModel", + "options": { + "mysql": { + "table": "vn.machineWorker" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + }, + "workerFk": { + "type": "number" + }, + "machineFk": { + "type": "number" + }, + "inTime": { + "type": "date", + "mysql": { + "columnName": "inTimed" + } + }, + "outTime": { + "type": "date", + "mysql": { + "columnName": "outTimed" + } + } + } +} diff --git a/db/changes/10451-april/00-ticket_doRefund.sql b/db/changes/10451-april/00-ticket_doRefund.sql index 5540ff8cf..5725b4fe5 100644 --- a/db/changes/10451-april/00-ticket_doRefund.sql +++ b/db/changes/10451-april/00-ticket_doRefund.sql @@ -2,49 +2,64 @@ DROP PROCEDURE IF EXISTS vn.ticket_doRefund; DELIMITER $$ $$ -CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_doRefund`(IN vOriginTicket INT, OUT vNewTicket INT) +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_doRefund`(OUT vNewTicket INT) BEGIN - +/** + * Crea un ticket de abono a partir de tmp.sale y/o tmp.ticketService + * + * @return vNewTicket + */ DECLARE vDone BIT DEFAULT 0; - DECLARE vCustomer MEDIUMINT; + DECLARE vClientFk MEDIUMINT; DECLARE vWarehouse TINYINT; DECLARE vCompany MEDIUMINT; DECLARE vAddress MEDIUMINT; - DECLARE vRefundAgencyMode INT; - DECLARE vItemFk INT; - DECLARE vQuantity DECIMAL (10,2); - DECLARE vConcept VARCHAR(50); - DECLARE vPrice DECIMAL (10,2); - DECLARE vDiscount TINYINT; + DECLARE vRefundAgencyMode INT; + DECLARE vItemFk INT; + DECLARE vQuantity DECIMAL (10,2); + DECLARE vConcept VARCHAR(50); + DECLARE vPrice DECIMAL (10,2); + DECLARE vDiscount TINYINT; DECLARE vSaleNew INT; - DECLARE vSaleMain INT; - DECLARE vZoneFk INT; - DECLARE vDescription VARCHAR(50); - DECLARE vTaxClassFk INT; - DECLARE vTicketServiceTypeFk INT; - - DECLARE cSales CURSOR FOR - SELECT * - FROM tmp.sale; - + DECLARE vSaleMain INT; + DECLARE vZoneFk INT; + DECLARE vDescription VARCHAR(50); + DECLARE vTaxClassFk INT; + DECLARE vTicketServiceTypeFk INT; + DECLARE vOriginTicket INT; + + DECLARE cSales CURSOR FOR + SELECT s.id, s.itemFk, - s.quantity, s.concept, s.price, s.discount + FROM tmp.sale s; + DECLARE cTicketServices CURSOR FOR - SELECT * - FROM tmp.ticketService; - - DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1; - - SELECT id INTO vRefundAgencyMode + SELECT ts.description, - ts.quantity, ts.price, ts.taxClassFk, ts.ticketServiceTypeFk + FROM tmp.ticketService ts; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + + SELECT sub.ticketFk INTO vOriginTicket + FROM ( + SELECT s.ticketFk + FROM tmp.sale s + UNION ALL + SELECT ts.ticketFk + FROM tmp.ticketService ts + ) sub + LIMIT 1; + + SELECT id INTO vRefundAgencyMode FROM agencyMode WHERE `name` = 'ABONO'; SELECT clientFk, warehouseFk, companyFk, addressFk - INTO vCustomer, vWarehouse, vCompany, vAddress - FROM ticket - WHERE id = vOriginTicket; - - SELECT id INTO vZoneFk + INTO vClientFk, vWarehouse, vCompany, vAddress + FROM ticket + WHERE id = vOriginTicket; + + SELECT id INTO vZoneFk FROM zone WHERE agencyModeFk = vRefundAgencyMode - LIMIT 1; - + LIMIT 1; + INSERT INTO vn.ticket ( clientFk, shipped, @@ -54,10 +69,10 @@ BEGIN warehouseFk, companyFk, landed, - zoneFk + zoneFk ) SELECT - vCustomer, + vClientFk, CURDATE(), vAddress, vRefundAgencyMode, @@ -65,49 +80,48 @@ BEGIN vWarehouse, vCompany, CURDATE(), - vZoneFk + vZoneFk FROM address a WHERE a.id = vAddress; SET vNewTicket = LAST_INSERT_ID(); - SET vDone := 0; + SET vDone := FALSE; OPEN cSales; - FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount; + FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount; WHILE NOT vDone DO - + INSERT INTO vn.sale(ticketFk, itemFk, quantity, concept, price, discount) VALUES( vNewTicket, vItemFk, vQuantity, vConcept, vPrice, vDiscount ); - - SET vSaleNew = LAST_INSERT_ID(); - - INSERT INTO vn.saleComponent(saleFk,componentFk,`value`) - SELECT vSaleNew,componentFk,`value` - FROM vn.saleComponent - WHERE saleFk = vSaleMain; - + + SET vSaleNew = LAST_INSERT_ID(); + + INSERT INTO vn.saleComponent(saleFk,componentFk,`value`) + SELECT vSaleNew,componentFk,`value` + FROM vn.saleComponent + WHERE saleFk = vSaleMain; + FETCH cSales INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount; - + END WHILE; CLOSE cSales; - SET vDone := 0; + SET vDone := FALSE; OPEN cTicketServices; - FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk; + FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk; WHILE NOT vDone DO - + INSERT INTO vn.ticketService(description, quantity, price, taxClassFk, ticketFk, ticketServiceTypeFk) VALUES(vDescription, vQuantity, vPrice, vTaxClassFk, vNewTicket, vTicketServiceTypeFk); - + FETCH cTicketServices INTO vDescription, vQuantity, vPrice, vTaxClassFk, vTicketServiceTypeFk; - + END WHILE; CLOSE cTicketServices; INSERT INTO vn.ticketRefund(refundTicketFk, originalTicketFk) VALUES(vNewTicket, vOriginTicket); - END$$ DELIMITER ; diff --git a/db/changes/10460-motherDay/00-aclItemType.sql b/db/changes/10460-motherDay/00-aclItemType.sql new file mode 100644 index 000000000..836a69dfd --- /dev/null +++ b/db/changes/10460-motherDay/00-aclItemType.sql @@ -0,0 +1,4 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('ItemType', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('ItemType', '*', 'WRITE', 'ALLOW', 'ROLE', 'buyer'); \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 4871dde30..4114f0e73 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -99,13 +99,19 @@ INSERT INTO `account`.`mailForward`(`account`, `forwardTo`) VALUES (1, 'employee@domain.local'); -INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`) +INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`) VALUES - (1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106), - (1107, 'ANT', 'Hank' , 'Pym' , 1107, 19, 432978107), - (1108, 'DCX', 'Charles' , 'Xavier', 1108, 19, 432978108), - (1109, 'HLK', 'Bruce' , 'Banner', 1109, 19, 432978109), - (1110, 'JJJ', 'Jessica' , 'Jones' , 1110, 19, 432978110); + (1, 'printer1', 'path1', 0), + (2, 'printer2', 'path2', 1); + + +INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`) + VALUES + (1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL), + (1107, 'ANT', 'Hank' , 'Pym' , 1107, 19, 432978107, NULL, 1), + (1108, 'DCX', 'Charles' , 'Xavier', 1108, 19, 432978108, 1, NULL), + (1109, 'HLK', 'Bruce' , 'Banner', 1109, 19, 432978109, 1, 2), + (1110, 'JJJ', 'Jessica' , 'Jones' , 1110, 19, 432978110, 2, 1); INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) VALUES @@ -113,7 +119,7 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) (2, 'USD', 'Dollar USA', 1.4), (3, 'GBP', 'Libra', 1), (4, 'JPY', 'Yen Japones', 1); - + INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`) VALUES (1, 'España', 1, 'ES', 1, 24, 4, 0, 1), @@ -745,14 +751,19 @@ INSERT INTO `vn`.`itemCategory`(`id`, `name`, `display`, `color`, `icon`, `code` (7, 'Accessories', 1, NULL, 'icon-accessory', 'accessory'), (8, 'Fruit', 1, NULL, 'icon-fruit', 'fruit'); -INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `warehouseFk`, `life`,`workerFk`, `isPackaging`) +INSERT INTO `vn`.`temperature`(`code`, `name`, `description`) VALUES - (1, 'CRI', 'Crisantemo', 2, 1, 31, 35, 0), - (2, 'ITG', 'Anthurium', 1, 1, 31, 35, 0), - (3, 'WPN', 'Paniculata', 2, 1, 31, 35, 0), - (4, 'PRT', 'Delivery ports', 3, 1, NULL, 35, 1), - (5, 'CON', 'Container', 3, 1, NULL, 35, 1), - (6, 'ALS', 'Alstroemeria', 1, 1, 31, 16, 0); + ('warm', 'Warm', 'Warm'), + ('cool', 'Cool', 'Cool'); + +INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `warehouseFk`, `life`,`workerFk`, `isPackaging`, `temperatureFk`) + VALUES + (1, 'CRI', 'Crisantemo', 2, 1, 31, 35, 0, 'cool'), + (2, 'ITG', 'Anthurium', 1, 1, 31, 35, 0, 'cool'), + (3, 'WPN', 'Paniculata', 2, 1, 31, 35, 0, 'cool'), + (4, 'PRT', 'Delivery ports', 3, 1, NULL, 35, 1, 'warm'), + (5, 'CON', 'Container', 3, 1, NULL, 35, 1, 'warm'), + (6, 'ALS', 'Alstroemeria', 1, 1, 31, 16, 0, 'warm'); INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`) VALUES @@ -810,25 +821,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`) ('VT', 'Sales'); INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, - `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`) + `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`) VALUES - (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0), - (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0), - (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0), - (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), - (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), - (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), - (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), - (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL, 0), - (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL, 0), - (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), - (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), - (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), - (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 2, 'VT', 1, NULL, NULL, 1), - (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL, 0), - (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0), - (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0), - (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL, 0); + (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0, 15), + (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10), + (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5), + (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL), + (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL), + (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL, 0, NULL), + (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL, 0, NULL), + (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, NULL), + (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL, 0, NULL), + (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL, 0, NULL), + (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL, 0, NULL), + (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL), + (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 2, 'VT', 1, NULL, NULL, 1, NULL), + (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL, 0, NULL), + (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0, NULL), + (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0, NULL), + (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL, 0, NULL); -- Update the taxClass after insert of the items UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 @@ -2291,11 +2302,6 @@ INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `week (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000); INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11'); - -INSERT INTO `vn`.`temperature`(`code`, `name`, `description`) - VALUES - ('warm', 'Warm', 'Warm'), - ('cool', 'Cool', 'Cool'); INSERT INTO `vn`.`thermograph`(`id`, `model`) VALUES @@ -2545,3 +2551,21 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage (3, 2, 0, 15.00, 0.00, NULL, 0, 0.00, 0), (4, 2, 0, 20.00, 0.00, NULL, 0, 0.00, 0), (5, 442, 0, 0.00, 3.05, NULL, 0, 0.00, 0); + +INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`) + VALUES + ('delivery', '9.2', 0), + ('warehouse', '8.1', 0); + +INSERT INTO `vn`.`machine` (`plate`, `maker`, `model`, `warehouseFk`, `departmentFk`, `type`, `use`, `productionYear`, `workerFk`, `companyFk`) + VALUES + ('RE-001', 'STILL', 'LTX-20', 60, 23, 'ELECTRIC TOW', 'Drag cars', 2020, 103, 442), + ('RE-002', 'STILL', 'LTX-20', 60, 23, 'ELECTRIC TOW', 'Drag cars', 2020, 103, 442); + +INSERT INTO `vn`.`machineWorker` (`workerFk`, `machineFk`, `inTimed`, `outTimed`) + VALUES + (1106, 1, CURDATE(), CURDATE()), + (1106, 1, DATE_ADD(CURDATE(), INTERVAL + 1 DAY), DATE_ADD(CURDATE(), INTERVAL +1 DAY)), + (1106, 2, CURDATE(), NULL), + (1106, 2, DATE_ADD(CURDATE(), INTERVAL + 1 DAY), DATE_ADD(CURDATE(), INTERVAL +1 DAY)); + diff --git a/db/dump/structure.sql b/db/dump/structure.sql index fdd7e1151..21ef7758c 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -37460,6 +37460,31 @@ SET character_set_client = utf8; ) ENGINE=MyISAM */; SET character_set_client = @saved_cs_client; +-- +-- Temporary table structure for view `printer` +-- + +DROP TABLE IF EXISTS `printer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `printer` ( + `id` tinyint(3) unsigned NOT NULL, + `name` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `path` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `modelFk` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `macWifi` varchar(20) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `ipAddress` varchar(15) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `reference` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL, + `isLabeler` tinyint(1) DEFAULT 0 COMMENT 'Indica si es impresora de etiquetas', + PRIMARY KEY (`id`), + UNIQUE KEY `printer_UN` (`reference`), + UNIQUE KEY `printer_UN1` (`macWifi`), + UNIQUE KEY `printer_UN2` (`name`), + KEY `printer_FK` (`modelFk`), + CONSTRAINT `printer_FK` FOREIGN KEY (`modelFk`) REFERENCES `printerModel` (`code`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `printingQueueCheck` -- diff --git a/db/export-structure.sh b/db/export-structure.sh index 388231306..9b23f43ac 100755 --- a/db/export-structure.sh +++ b/db/export-structure.sh @@ -60,7 +60,6 @@ IGNORETABLES=( --ignore-table=vn.plantpassportAuthority__ --ignore-table=vn.preparationException --ignore-table=vn.priceFixed__ - --ignore-table=vn.printer --ignore-table=vn.printingQueue --ignore-table=vn.printServerQueue__ --ignore-table=vn.promissoryNote diff --git a/modules/account/front/role/summary/index.js b/modules/account/front/role/summary/index.js index 0a08fe8b2..4f321fa98 100644 --- a/modules/account/front/role/summary/index.js +++ b/modules/account/front/role/summary/index.js @@ -6,7 +6,6 @@ class Controller extends Component { this._role = value; this.$.summary = null; if (!value) return; - this.$http.get(`Roles/${value.id}`) .then(res => this.$.summary = res.data); } diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 859486ab1..ef4c9a62e 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -76,6 +76,13 @@ translate> Show CITES letter + + Refund + + + diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index 7738845f9..b884e50cb 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -116,6 +116,35 @@ class Controller extends Section { invoiceId: this.id }); } + + async refundInvoiceOut() { + let filter = { + where: {refFk: this.invoiceOut.ref} + }; + const tickets = await this.$http.get('Tickets', {filter}); + this.tickets = tickets.data; + this.ticketsIds = []; + for (let ticket of this.tickets) + this.ticketsIds.push(ticket.id); + + filter = { + where: {ticketFk: {inq: this.ticketsIds}} + }; + const sales = await this.$http.get('Sales', {filter}); + this.sales = sales.data; + + const ticketServices = await this.$http.get('TicketServices', {filter}); + this.services = ticketServices.data; + + const params = { + sales: this.sales, + services: this.services + }; + const query = `Sales/refund`; + return this.$http.post(query, params).then(res => { + this.$state.go('ticket.card.sale', {id: res.data}); + }); + } } Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail']; diff --git a/modules/invoiceOut/front/descriptor-menu/index.spec.js b/modules/invoiceOut/front/descriptor-menu/index.spec.js index fced12e0d..c84c97a57 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.spec.js +++ b/modules/invoiceOut/front/descriptor-menu/index.spec.js @@ -122,4 +122,34 @@ describe('vnInvoiceOutDescriptorMenu', () => { expect(controller.vnApp.showMessage).toHaveBeenCalled(); }); }); + + // #4084 review with Juan + xdescribe('refundInvoiceOut()', () => { + it('should make a query and go to ticket.card.sale', () => { + controller.$state.go = jest.fn(); + + const invoiceOut = { + id: 1, + ref: 'T1111111' + }; + controller.invoiceOut = invoiceOut; + const tickets = [{id: 1}]; + const sales = [{id: 1}]; + const services = [{id: 2}]; + + $httpBackend.expectGET(`Tickets`).respond(tickets); + $httpBackend.expectGET(`Sales`).respond(sales); + $httpBackend.expectGET(`TicketServices`).respond(services); + + const expectedParams = { + sales: sales, + services: services + }; + $httpBackend.expectPOST(`Sales/refund`, expectedParams).respond(); + controller.refundInvoiceOut(); + $httpBackend.flush(); + + expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: undefined}); + }); + }); }); diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index a76f6aad3..8949f1f91 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -12,6 +12,8 @@ Are you sure you want to delete this invoice?: Estas seguro de eliminar esta fac Are you sure you want to clone this invoice?: Estas seguro de clonar esta factura? InvoiceOut booked: Factura asentada Are you sure you want to book this invoice?: Estas seguro de querer asentar esta factura? +Are you sure you want to refund this invoice?: Estas seguro de querer abonar esta factura? +Create a single ticket with all the content of the current invoice: Crear un ticket unico con todo el contenido de la factura actual Regenerate PDF invoice: Regenerar PDF factura The invoice PDF document has been regenerated: El documento PDF de la factura ha sido regenerado The email can't be empty: El correo no puede estar vacío diff --git a/modules/item/back/models/item-type.json b/modules/item/back/models/item-type.json index cb9d5ace8..843d9877f 100644 --- a/modules/item/back/models/item-type.json +++ b/modules/item/back/models/item-type.json @@ -21,8 +21,11 @@ "life": { "type": "number" }, - "isPackaging": { - "type": "boolean" + "promo": { + "type": "number" + }, + "isUnconventionalSize": { + "type": "number" } }, "relations": { @@ -40,6 +43,16 @@ "type": "belongsTo", "model": "ItemCategory", "foreignKey": "categoryFk" + }, + "itemPackingType": { + "type": "belongsTo", + "model": "ItemPackingType", + "foreignKey": "itemPackingTypeFk" + }, + "temperature": { + "type": "belongsTo", + "model": "Temperature", + "foreignKey": "temperatureFk" } }, "acls": [ diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index efde2690f..01b6ba093 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -140,6 +140,9 @@ }, "isFloramondo": { "type": "boolean" + }, + "packingShelve": { + "type": "number" } }, "relations": { diff --git a/modules/item/front/index.js b/modules/item/front/index.js index c328b1c8d..6a8d1b3b7 100644 --- a/modules/item/front/index.js +++ b/modules/item/front/index.js @@ -23,4 +23,4 @@ import './waste/index/'; import './waste/detail'; import './fixed-price'; import './fixed-price-search-panel'; - +import './item-type'; diff --git a/modules/item/front/item-type/basic-data/index.html b/modules/item/front/item-type/basic-data/index.html new file mode 100644 index 000000000..1417a05ab --- /dev/null +++ b/modules/item/front/item-type/basic-data/index.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/item/front/item-type/basic-data/index.js b/modules/item/front/item-type/basic-data/index.js new file mode 100644 index 000000000..ec280fdf8 --- /dev/null +++ b/modules/item/front/item-type/basic-data/index.js @@ -0,0 +1,12 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section {} + +ngModule.component('vnItemTypeBasicData', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/card/index.html b/modules/item/front/item-type/card/index.html new file mode 100644 index 000000000..80af6088e --- /dev/null +++ b/modules/item/front/item-type/card/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/modules/item/front/item-type/card/index.js b/modules/item/front/item-type/card/index.js new file mode 100644 index 000000000..fa6b37340 --- /dev/null +++ b/modules/item/front/item-type/card/index.js @@ -0,0 +1,23 @@ +import ngModule from '../../module'; +import ModuleCard from 'salix/components/module-card'; + +class Controller extends ModuleCard { + reload() { + const filter = { + include: [ + {relation: 'worker'}, + {relation: 'category'}, + {relation: 'itemPackingType'}, + {relation: 'temperature'} + ] + }; + + this.$http.get(`ItemTypes/${this.$params.id}`, {filter}) + .then(res => this.itemType = res.data); + } +} + +ngModule.vnComponent('vnItemTypeCard', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/card/index.spec.js b/modules/item/front/item-type/card/index.spec.js new file mode 100644 index 000000000..ab2314bb9 --- /dev/null +++ b/modules/item/front/item-type/card/index.spec.js @@ -0,0 +1,27 @@ +import './index'; + +describe('component vnItemTypeCard', () => { + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + controller = $componentController('vnItemTypeCard', {$element: null}); + })); + + describe('reload()', () => { + it('should reload the controller data', () => { + controller.$params.id = 1; + + const itemType = {id: 1}; + + $httpBackend.expectGET('ItemTypes/1').respond(itemType); + controller.reload(); + $httpBackend.flush(); + + expect(controller.itemType).toEqual(itemType); + }); + }); +}); diff --git a/modules/item/front/item-type/create/index.html b/modules/item/front/item-type/create/index.html new file mode 100644 index 000000000..44cb5183d --- /dev/null +++ b/modules/item/front/item-type/create/index.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/item/front/item-type/create/index.js b/modules/item/front/item-type/create/index.js new file mode 100644 index 000000000..ccf7744be --- /dev/null +++ b/modules/item/front/item-type/create/index.js @@ -0,0 +1,15 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + onSubmit() { + return this.$.watcher.submit().then(res => + this.$state.go('item.itemType.card.basicData', {id: res.data.id}) + ); + } +} + +ngModule.component('vnItemTypeCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/create/index.spec.js b/modules/item/front/item-type/create/index.spec.js new file mode 100644 index 000000000..4b000df9a --- /dev/null +++ b/modules/item/front/item-type/create/index.spec.js @@ -0,0 +1,34 @@ +import './index'; + +describe('component vnItemTypeCreate', () => { + let $scope; + let $state; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $state = _$state_; + $scope.watcher = { + submit: () => { + return { + then: callback => { + callback({data: {id: '1234'}}); + } + }; + } + }; + const $element = angular.element(''); + controller = $componentController('vnItemTypeCreate', {$element, $scope}); + })); + + describe('onSubmit()', () => { + it(`should call submit() on the watcher then expect a callback`, () => { + jest.spyOn($state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('item.itemType.card.basicData', {id: '1234'}); + }); + }); +}); diff --git a/modules/item/front/item-type/descriptor/index.html b/modules/item/front/item-type/descriptor/index.html new file mode 100644 index 000000000..5a0e8ed49 --- /dev/null +++ b/modules/item/front/item-type/descriptor/index.html @@ -0,0 +1,25 @@ + + +
+ + + + + + + + +
+
+
\ No newline at end of file diff --git a/modules/item/front/item-type/descriptor/index.js b/modules/item/front/item-type/descriptor/index.js new file mode 100644 index 000000000..9322c599a --- /dev/null +++ b/modules/item/front/item-type/descriptor/index.js @@ -0,0 +1,20 @@ +import ngModule from '../../module'; +import Descriptor from 'salix/components/descriptor'; + +class Controller extends Descriptor { + get itemType() { + return this.entity; + } + + set itemType(value) { + this.entity = value; + } +} + +ngModule.component('vnItemTypeDescriptor', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/index.js b/modules/item/front/item-type/index.js new file mode 100644 index 000000000..5dcbe4097 --- /dev/null +++ b/modules/item/front/item-type/index.js @@ -0,0 +1,8 @@ +import './main'; +import './index/'; +import './summary'; +import './card'; +import './descriptor'; +import './create'; +import './basic-data'; +import './search-panel'; diff --git a/modules/item/front/item-type/index/index.html b/modules/item/front/item-type/index/index.html new file mode 100644 index 000000000..50b9eb172 --- /dev/null +++ b/modules/item/front/item-type/index/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/item-type/index/index.js b/modules/item/front/item-type/index/index.js new file mode 100644 index 000000000..54ecba997 --- /dev/null +++ b/modules/item/front/item-type/index/index.js @@ -0,0 +1,14 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + preview(itemType) { + this.selectedItemType = itemType; + this.$.summary.show(); + } +} + +ngModule.component('vnItemTypeIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/index/index.spec.js b/modules/item/front/item-type/index/index.spec.js new file mode 100644 index 000000000..887c03f7f --- /dev/null +++ b/modules/item/front/item-type/index/index.spec.js @@ -0,0 +1,34 @@ +import './index'; + +describe('Item', () => { + describe('Component vnItemTypeIndex', () => { + let controller; + let $window; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$window_) => { + $window = _$window_; + const $element = angular.element(''); + controller = $componentController('vnItemTypeIndex', {$element}); + })); + + describe('preview()', () => { + it('should show the dialog summary', () => { + controller.$.summary = {show: () => {}}; + jest.spyOn(controller.$.summary, 'show'); + + const itemType = {id: 1}; + + const event = new MouseEvent('click', { + view: $window, + bubbles: true, + cancelable: true + }); + controller.preview(event, itemType); + + expect(controller.$.summary.show).toHaveBeenCalledWith(); + }); + }); + }); +}); diff --git a/modules/item/front/item-type/index/locale/es.yml b/modules/item/front/item-type/index/locale/es.yml new file mode 100644 index 000000000..1a71ff212 --- /dev/null +++ b/modules/item/front/item-type/index/locale/es.yml @@ -0,0 +1,2 @@ +Item Type: Familia +New itemType: Nueva familia \ No newline at end of file diff --git a/modules/item/front/item-type/main/index.html b/modules/item/front/item-type/main/index.html new file mode 100644 index 000000000..faba696c0 --- /dev/null +++ b/modules/item/front/item-type/main/index.html @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/item-type/main/index.js b/modules/item/front/item-type/main/index.js new file mode 100644 index 000000000..0dea00abb --- /dev/null +++ b/modules/item/front/item-type/main/index.js @@ -0,0 +1,24 @@ +import ngModule from '../../module'; +import ModuleMain from 'salix/components/module-main'; + +export default class ItemType extends ModuleMain { + exprBuilder(param, value) { + switch (param) { + case 'search': + return /^\d+$/.test(value) + ? {id: value} + : {or: [ + {name: {like: `%${value}%`}}, + {code: {like: `%${value}%`}} + ]}; + case 'name': + case 'code': + return {[param]: {like: `%${value}%`}}; + } + } +} + +ngModule.vnComponent('vnItemType', { + controller: ItemType, + template: require('./index.html') +}); diff --git a/modules/item/front/item-type/main/index.spec.js b/modules/item/front/item-type/main/index.spec.js new file mode 100644 index 000000000..dcb14ec0e --- /dev/null +++ b/modules/item/front/item-type/main/index.spec.js @@ -0,0 +1,31 @@ +import './index'; + +describe('Item', () => { + describe('Component vnItemType', () => { + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject($componentController => { + const $element = angular.element(''); + controller = $componentController('vnItemType', {$element}); + })); + + describe('exprBuilder()', () => { + it('should return a filter based on a search by id', () => { + const filter = controller.exprBuilder('search', '123'); + + expect(filter).toEqual({id: '123'}); + }); + + it('should return a filter based on a search by name or code', () => { + const filter = controller.exprBuilder('search', 'Alstroemeria'); + + expect(filter).toEqual({or: [ + {name: {like: '%Alstroemeria%'}}, + {code: {like: '%Alstroemeria%'}}, + ]}); + }); + }); + }); +}); diff --git a/modules/item/front/item-type/main/locale/es.yml b/modules/item/front/item-type/main/locale/es.yml new file mode 100644 index 000000000..7aceac46f --- /dev/null +++ b/modules/item/front/item-type/main/locale/es.yml @@ -0,0 +1 @@ +Search itemType by id, name or code: Buscar familia por id, nombre o código \ No newline at end of file diff --git a/modules/item/front/item-type/search-panel/index.html b/modules/item/front/item-type/search-panel/index.html new file mode 100644 index 000000000..4aa762900 --- /dev/null +++ b/modules/item/front/item-type/search-panel/index.html @@ -0,0 +1,22 @@ +
+
+ + + + + + + + + + + +
+
\ No newline at end of file diff --git a/modules/item/front/item-type/search-panel/index.js b/modules/item/front/item-type/search-panel/index.js new file mode 100644 index 000000000..17a439c39 --- /dev/null +++ b/modules/item/front/item-type/search-panel/index.js @@ -0,0 +1,7 @@ +import ngModule from '../../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +ngModule.component('vnItemTypeSearchPanel', { + template: require('./index.html'), + controller: SearchPanel +}); diff --git a/modules/item/front/item-type/summary/index.html b/modules/item/front/item-type/summary/index.html new file mode 100644 index 000000000..d003c8f38 --- /dev/null +++ b/modules/item/front/item-type/summary/index.html @@ -0,0 +1,50 @@ + +
+ {{summary.id}} - {{summary.name}} - {{summary.worker.firstName}} {{summary.worker.lastName}} +
+ + +

Basic data

+ + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/modules/item/front/item-type/summary/index.js b/modules/item/front/item-type/summary/index.js new file mode 100644 index 000000000..7645de8b1 --- /dev/null +++ b/modules/item/front/item-type/summary/index.js @@ -0,0 +1,33 @@ +import ngModule from '../../module'; +import Component from 'core/lib/component'; + +class Controller extends Component { + set itemType(value) { + this._itemType = value; + this.$.summary = null; + if (!value) return; + + const filter = { + include: [ + {relation: 'worker'}, + {relation: 'category'}, + {relation: 'itemPackingType'}, + {relation: 'temperature'} + ] + }; + this.$http.get(`ItemTypes/${value.id}`, {filter}) + .then(res => this.$.summary = res.data); + } + + get itemType() { + return this._itemType; + } +} + +ngModule.component('vnItemTypeSummary', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/summary/locale/es.yml b/modules/item/front/item-type/summary/locale/es.yml new file mode 100644 index 000000000..8f4cef70f --- /dev/null +++ b/modules/item/front/item-type/summary/locale/es.yml @@ -0,0 +1,4 @@ +Life: Vida +Promo: Promoción +Item packing type: Tipo de embalaje +Is unconventional size: Es de tamaño poco convencional \ No newline at end of file diff --git a/modules/item/front/routes.json b/modules/item/front/routes.json index 9e21e1697..5743d0ce7 100644 --- a/modules/item/front/routes.json +++ b/modules/item/front/routes.json @@ -9,7 +9,8 @@ {"state": "item.index", "icon": "icon-item"}, {"state": "item.request", "icon": "icon-buyrequest"}, {"state": "item.waste.index", "icon": "icon-claims"}, - {"state": "item.fixedPrice", "icon": "icon-fixedPrice"} + {"state": "item.fixedPrice", "icon": "icon-fixedPrice"}, + {"state": "item.itemType", "icon": "contact_support"} ], "card": [ {"state": "item.card.basicData", "icon": "settings"}, @@ -20,6 +21,9 @@ {"state": "item.card.diary", "icon": "icon-transaction"}, {"state": "item.card.last-entries", "icon": "icon-regentry"}, {"state": "item.card.log", "icon": "history"} + ], + "itemType": [ + {"state": "item.itemType.card.basicData", "icon": "settings"} ] }, "keybindings": [ @@ -169,6 +173,47 @@ "component": "vn-fixed-price", "description": "Fixed prices", "acl": ["buyer"] + }, + { + "url" : "/item-type?q", + "state": "item.itemType", + "component": "vn-item-type", + "description": "Item Type", + "acl": ["buyer"] + }, + { + "url": "/create", + "state": "item.itemType.create", + "component": "vn-item-type-create", + "description": "New itemType", + "acl": ["buyer"] + }, + { + "url": "/:id", + "state": "item.itemType.card", + "component": "vn-item-type-card", + "abstract": true, + "description": "Detail" + }, + { + "url": "/summary", + "state": "item.itemType.card.summary", + "component": "vn-item-type-summary", + "description": "Summary", + "params": { + "item-type": "$ctrl.itemType" + }, + "acl": ["buyer"] + }, + { + "url": "/basic-data", + "state": "item.itemType.card.basicData", + "component": "vn-item-type-basic-data", + "description": "Basic data", + "params": { + "item-type": "$ctrl.itemType" + }, + "acl": ["buyer"] } ] } \ No newline at end of file diff --git a/modules/ticket/back/methods/sale/refund.js b/modules/ticket/back/methods/sale/refund.js index 9c87f23d3..83a420a8e 100644 --- a/modules/ticket/back/methods/sale/refund.js +++ b/modules/ticket/back/methods/sale/refund.js @@ -2,19 +2,19 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('refund', { - description: 'Create ticket with the selected lines changing the sign to the quantites', + description: 'Create ticket refund with lines and services changing the sign to the quantites', accessType: 'WRITE', accepts: [{ arg: 'sales', description: 'The sales', type: ['object'], - required: true + required: false }, { - arg: 'ticketId', - type: 'number', - required: true, - description: 'The ticket id' + arg: 'services', + type: ['object'], + required: false, + description: 'The services' }], returns: { type: 'number', @@ -26,7 +26,7 @@ module.exports = Self => { } }); - Self.refund = async(ctx, sales, ticketId, options) => { + Self.refund = async(ctx, sales, services, options) => { const myOptions = {}; let tx; @@ -39,7 +39,6 @@ module.exports = Self => { } try { - const salesIds = []; const userId = ctx.req.accessToken.userId; const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager'); @@ -49,39 +48,47 @@ module.exports = Self => { if (!hasValidRole) throw new UserError(`You don't have privileges to create refund`); - for (let sale of sales) - salesIds.push(sale.id); + const salesIds = []; + if (sales) { + for (let sale of sales) + salesIds.push(sale.id); + } else + salesIds.push(null); + + const servicesIds = []; + if (services) { + for (let service of services) + servicesIds.push(service.id); + } else + servicesIds.push(null); const query = ` DROP TEMPORARY TABLE IF EXISTS tmp.sale; DROP TEMPORARY TABLE IF EXISTS tmp.ticketService; CREATE TEMPORARY TABLE tmp.sale - SELECT s.id, s.itemFk, - s.quantity, s.concept, s.price, s.discount + SELECT s.id, s.itemFk, s.quantity, s.concept, s.price, s.discount, s.ticketFk FROM sale s WHERE s.id IN (?); - CREATE TEMPORARY TABLE tmp.ticketService( - description VARCHAR(50), - quantity DECIMAL (10,2), - price DECIMAL (10,2), - taxClassFk INT, - ticketServiceTypeFk INT - ); - - CALL vn.ticket_doRefund(?, @newTicket); + CREATE TEMPORARY TABLE tmp.ticketService + SELECT ts.description, ts.quantity, ts.price, ts.taxClassFk, ts.ticketServiceTypeFk, ts.ticketFk + FROM ticketService ts + WHERE ts.id IN (?); + + CALL vn.ticket_doRefund(@newTicket); DROP TEMPORARY TABLE tmp.sale; DROP TEMPORARY TABLE tmp.ticketService;`; - await Self.rawSql(query, [salesIds, ticketId], myOptions); + await Self.rawSql(query, [salesIds, servicesIds], myOptions); const [newTicket] = await Self.rawSql('SELECT @newTicket id', null, myOptions); - ticketId = newTicket.id; + const newTicketId = newTicket.id; if (tx) await tx.commit(); - return ticketId; + return newTicketId; } catch (e) { if (tx) await tx.rollback(); throw e; diff --git a/modules/ticket/back/methods/sale/refundAll.js b/modules/ticket/back/methods/sale/refundAll.js deleted file mode 100644 index 6fcd27f0a..000000000 --- a/modules/ticket/back/methods/sale/refundAll.js +++ /dev/null @@ -1,78 +0,0 @@ -const UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.remoteMethodCtx('refundAll', { - description: 'Create ticket with all lines and services changing the sign to the quantites', - accessType: 'WRITE', - accepts: [{ - arg: 'ticketId', - type: 'number', - required: true, - description: 'The ticket id' - }], - returns: { - type: 'number', - root: true - }, - http: { - path: `/refundAll`, - verb: 'post' - } - }); - - Self.refundAll = async(ctx, ticketId, options) => { - const myOptions = {}; - let tx; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - - try { - const userId = ctx.req.accessToken.userId; - - const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager'); - const isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant'); - const hasValidRole = isClaimManager || isSalesAssistant; - - if (!hasValidRole) - throw new UserError(`You don't have privileges to create refund`); - - const query = ` - DROP TEMPORARY TABLE IF EXISTS tmp.sale; - DROP TEMPORARY TABLE IF EXISTS tmp.ticketService; - - CREATE TEMPORARY TABLE tmp.sale - SELECT s.id, s.itemFk, - s.quantity, s.concept, s.price, s.discount - FROM sale s - JOIN ticket t ON t.id = s.ticketFk - WHERE t.id IN (?); - - CREATE TEMPORARY TABLE tmp.ticketService - SELECT ts.description, - ts.quantity, ts.price, ts.taxClassFk, ts.ticketServiceTypeFk - FROM ticketService ts - WHERE ts.ticketFk IN (?); - - CALL vn.ticket_doRefund(?, @newTicket); - - DROP TEMPORARY TABLE tmp.sale; - DROP TEMPORARY TABLE tmp.ticketService;`; - - await Self.rawSql(query, [ticketId, ticketId, ticketId], myOptions); - - const [newTicket] = await Self.rawSql('SELECT @newTicket id', null, myOptions); - ticketId = newTicket.id; - - if (tx) await tx.commit(); - - return ticketId; - } catch (e) { - if (tx) await tx.rollback(); - throw e; - } - }; -}; diff --git a/modules/ticket/back/methods/sale/specs/refund.spec.js b/modules/ticket/back/methods/sale/specs/refund.spec.js index 40fd6c17e..5cb353055 100644 --- a/modules/ticket/back/methods/sale/specs/refund.spec.js +++ b/modules/ticket/back/methods/sale/specs/refund.spec.js @@ -1,20 +1,20 @@ const models = require('vn-loopback/server/server').models; describe('sale refund()', () => { + const sales = [ + {id: 7, ticketFk: 11}, + {id: 8, ticketFk: 11} + ]; + const services = [{id: 1}]; + it('should create ticket with the selected lines changing the sign to the quantites', async() => { const tx = await models.Sale.beginTransaction({}); const ctx = {req: {accessToken: {userId: 9}}}; - const ticketId = 11; - const sales = [ - {id: 7, ticketFk: 11}, - {id: 8, ticketFk: 11} - ]; - try { const options = {transaction: tx}; - const response = await models.Sale.refund(ctx, sales, ticketId, options); + const response = await models.Sale.refund(ctx, sales, services, options); const [newTicketId] = await models.Sale.rawSql('SELECT MAX(t.id) id FROM vn.ticket t;', null, options); expect(response).toEqual(newTicketId.id); @@ -30,17 +30,12 @@ describe('sale refund()', () => { const tx = await models.Sale.beginTransaction({}); const ctx = {req: {accessToken: {userId: 1}}}; - const ticketId = 11; - const sales = [ - {id: 7, ticketFk: 11} - ]; - let error; try { const options = {transaction: tx}; - await models.Sale.refund(ctx, sales, ticketId, options); + await models.Sale.refund(ctx, sales, services, options); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index 2652aded2..2a4457263 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -7,7 +7,6 @@ module.exports = Self => { require('../methods/sale/updateConcept')(Self); require('../methods/sale/recalculatePrice')(Self); require('../methods/sale/refund')(Self); - require('../methods/sale/refundAll')(Self); require('../methods/sale/canEdit')(Self); Self.validatesPresenceOf('concept', { diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index c99575d42..1dcfd669f 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -302,7 +302,7 @@ \ No newline at end of file diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 1c80a6f9d..c6388654e 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -273,9 +273,21 @@ class Controller extends Section { .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); } - refundAll() { - const params = {ticketId: this.id}; - const query = `Sales/refundAll`; + async refund() { + const filter = { + where: {ticketFk: this.id} + }; + const sales = await this.$http.get('Sales', {filter}); + this.sales = sales.data; + + const ticketServices = await this.$http.get('TicketServices', {filter}); + this.services = ticketServices.data; + + const params = { + sales: this.sales, + services: this.services + }; + const query = `Sales/refund`; return this.$http.post(query, params).then(res => { this.$state.go('ticket.card.sale', {id: res.data}); }); diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 75f3522ae..af377d8ea 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -262,16 +262,27 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { }); }); - describe('refundAll()', () => { + // #4084 review with Juan + xdescribe('refund()', () => { it('should make a query and go to ticket.card.sale', () => { - jest.spyOn(controller.$state, 'go').mockReturnValue(); - const expectedParams = {ticketId: ticket.id}; + controller.$state.go = jest.fn(); - $httpBackend.expect('POST', `Sales/refundAll`, expectedParams).respond({ticketId: 16}); - controller.refundAll(); + controller._id = ticket.id; + const sales = [{id: 1}]; + const services = [{id: 2}]; + + $httpBackend.expectGET(`Sales`).respond(sales); + $httpBackend.expectGET(`TicketServices`).respond(services); + + const expectedParams = { + sales: sales, + services: services + }; + $httpBackend.expectPOST(`Sales/refund`, expectedParams).respond(); + controller.refund(); $httpBackend.flush(); - expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: {ticketId: ticket.id}}); + expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: undefined}); }); }); diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index bb8a81bc4..987333e28 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -483,7 +483,7 @@ class Controller extends Section { const sales = this.selectedValidSales(); if (!sales) return; - const params = {sales: sales, ticketId: this.ticket.id}; + const params = {sales: sales}; const query = `Sales/refund`; this.resetChanges(); this.$http.post(query, params).then(res => { diff --git a/modules/ticket/front/services/index.html b/modules/ticket/front/services/index.html index 13fd84b00..bb5505ce6 100644 --- a/modules/ticket/front/services/index.html +++ b/modules/ticket/front/services/index.html @@ -42,7 +42,7 @@