diff --git a/CHANGELOG.md b/CHANGELOG.md index 1be03b733..bfff5e53b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,17 +5,48 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2316.01] - 2023-05-04 +## [2322.01] - 2023-06-08 + +### Added +- + + +### Changed +- + +### Fixed +- + + + +## [2320.01] - 2023-05-25 + +### Added +- (Tickets -> Crear Factura) Al facturar se envia automáticamente el pdf al cliente + + +### Changed +- (Trabajadores -> Nuevo trabajador) Los clientes se crean sin 'TR' pero se añade tipo de negocio 'Trabajador' + +### Fixed +- + + + +## [2318.01] - 2023-05-08 ### Added - (Usuarios -> Histórico) Nueva sección - (Roles -> Histórico) Nueva sección +- (General -> Traducciones) Correo de bienvenida a clientes al portugués y al francés ### Changed - (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral ### Fixed -- +- (Ticket -> Boxing) Arreglado selección de horas +- (Cesta -> Índice) Optimizada búsqueda + ## [2314.01] - 2023-04-20 diff --git a/back/tests.js b/back/tests.js index a377011d3..97e548d33 100644 --- a/back/tests.js +++ b/back/tests.js @@ -34,6 +34,8 @@ async function test() { app.boot(bootOptions, err => err ? reject(err) : resolve()); }); + // FIXME: Workaround to wait for loopback to be ready + await app.models.Application.status(); const Jasmine = require('jasmine'); const jasmine = new Jasmine(); diff --git a/db/changes/231601/00-updateIsVies.sql b/db/changes/231601/00-updateIsVies.sql deleted file mode 100644 index 83fde7352..000000000 --- a/db/changes/231601/00-updateIsVies.sql +++ /dev/null @@ -1,5 +0,0 @@ - UPDATE vn.supplier s - JOIN vn.country c ON c.id = s.countryFk - SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1) - WHERE s.isVies = TRUE - AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2); \ No newline at end of file diff --git a/db/changes/231601/00-updateisViesClient.sql b/db/changes/231601/00-updateisViesClient.sql deleted file mode 100644 index bdf62d7a8..000000000 --- a/db/changes/231601/00-updateisViesClient.sql +++ /dev/null @@ -1,5 +0,0 @@ -UPDATE IGNORE vn.client c - JOIN vn.country co ON co.id = c.countryFk - SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1) - WHERE c.isVies = TRUE - AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2); \ No newline at end of file diff --git a/db/changes/231601/00-aclClientInforma.sql b/db/changes/231801/00-aclClientInforma.sql similarity index 100% rename from db/changes/231601/00-aclClientInforma.sql rename to db/changes/231801/00-aclClientInforma.sql diff --git a/db/changes/231601/00-clientInforma.sql b/db/changes/231801/00-clientInforma.sql similarity index 100% rename from db/changes/231601/00-clientInforma.sql rename to db/changes/231801/00-clientInforma.sql diff --git a/db/changes/231601/00-client_setRatingAcl.sql b/db/changes/231801/00-client_setRatingAcl.sql similarity index 100% rename from db/changes/231601/00-client_setRatingAcl.sql rename to db/changes/231801/00-client_setRatingAcl.sql diff --git a/db/changes/231601/00-deleteProcs_refund.sql b/db/changes/231801/00-deleteProcs_refund.sql similarity index 100% rename from db/changes/231601/00-deleteProcs_refund.sql rename to db/changes/231801/00-deleteProcs_refund.sql diff --git a/db/changes/231601/00-kkearEntryNotes.sql b/db/changes/231801/00-kkearEntryNotes.sql similarity index 100% rename from db/changes/231601/00-kkearEntryNotes.sql rename to db/changes/231801/00-kkearEntryNotes.sql diff --git a/db/changes/231601/00-newCompanyI18n.sql b/db/changes/231801/00-newCompanyI18n.sql similarity index 100% rename from db/changes/231601/00-newCompanyI18n.sql rename to db/changes/231801/00-newCompanyI18n.sql diff --git a/db/changes/231601/00-newTableWeb.sql b/db/changes/231801/00-newTableWeb.sql similarity index 100% rename from db/changes/231601/00-newTableWeb.sql rename to db/changes/231801/00-newTableWeb.sql diff --git a/db/changes/231601/00-observationEmailACL.sql b/db/changes/231801/00-observationEmailACL.sql similarity index 100% rename from db/changes/231601/00-observationEmailACL.sql rename to db/changes/231801/00-observationEmailACL.sql diff --git a/db/changes/231801/00-optimiceZoneEstimatedDelivery.sql b/db/changes/231801/00-optimiceZoneEstimatedDelivery.sql new file mode 100644 index 000000000..209e1efc3 --- /dev/null +++ b/db/changes/231801/00-optimiceZoneEstimatedDelivery.sql @@ -0,0 +1,77 @@ +CREATE OR REPLACE +ALGORITHM = UNDEFINED VIEW `vn`.`zoneEstimatedDelivery` AS +select + `t`.`zoneFk` AS `zoneFk`, + cast(`util`.`VN_CURDATE`() + interval hour(ifnull(`zc`.`hour`, `z`.`hour`)) * 60 + minute(ifnull(`zc`.`hour`, `z`.`hour`)) minute as time) AS `hourTheoretical`, + cast(sum(`sv`.`volume`) as decimal(5, 1)) AS `totalVolume`, + cast(sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) as decimal(5, 1)) AS `remainingVolume`, + greatest( + ifnull(`lhp`.`m3`, 0), + ifnull(`dl`.`minSpeed`, 0) + ) AS `speed`, + cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `hourEffective`, + floor(-sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0))) AS `minutesLess`, + cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `etc` +from + ( + ( + ( + ( + ( + ( + ( + ( + ( + `vn`.`ticket` `t` + join `vn`.`ticketStateToday` `tst` on + ( + `tst`.`ticket` = `t`.`id` + ) + ) + join `vn`.`state` `s` on + ( + `s`.`id` = `tst`.`state` + ) + ) + join `vn`.`saleVolume` `sv` on + ( + `sv`.`ticketFk` = `t`.`id` + ) + ) + left join `vn`.`lastHourProduction` `lhp` on + ( + `lhp`.`warehouseFk` = `t`.`warehouseFk` + ) + ) + join `vn`.`warehouse` `w` on + ( + `w`.`id` = `t`.`warehouseFk` + ) + ) + join `vn`.`warehouseAlias` `wa` on + ( + `wa`.`id` = `w`.`aliasFk` + ) + ) + straight_join `vn`.`zone` `z` on + ( + `z`.`id` = `t`.`zoneFk` + ) + ) + left join `vn`.`zoneClosure` `zc` on + ( + `zc`.`zoneFk` = `t`.`zoneFk` + and `zc`.`dated` = `util`.`VN_CURDATE`() + ) + ) + left join `cache`.`departure_limit` `dl` on + ( + `dl`.`warehouse_id` = `t`.`warehouseFk` + and `dl`.`fecha` = `util`.`VN_CURDATE`() + ) + ) +where + `w`.`hasProduction` <> 0 + and cast(`t`.`shipped` as date) = `util`.`VN_CURDATE`() +group by + `t`.`zoneFk`; diff --git a/db/changes/231601/00-saleTracking.sql b/db/changes/231801/00-saleTracking.sql similarity index 100% rename from db/changes/231601/00-saleTracking.sql rename to db/changes/231801/00-saleTracking.sql diff --git a/db/changes/230801/00-ticketConfig.sql b/db/changes/231801/00-ticketConfig.sql similarity index 79% rename from db/changes/230801/00-ticketConfig.sql rename to db/changes/231801/00-ticketConfig.sql index ca63dbf63..7c8aa83a4 100644 --- a/db/changes/230801/00-ticketConfig.sql +++ b/db/changes/231801/00-ticketConfig.sql @@ -1 +1 @@ -ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuerade plazo'; +ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuera de plazo'; diff --git a/db/changes/231801/00-updateIsVies.sql b/db/changes/231801/00-updateIsVies.sql new file mode 100644 index 000000000..4e5277559 --- /dev/null +++ b/db/changes/231801/00-updateIsVies.sql @@ -0,0 +1,5 @@ + UPDATE `vn`.`supplier` s + JOIN `vn`.`country` c ON c.id = s.countryFk + SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1) + WHERE s.isVies = TRUE + AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2); diff --git a/db/changes/231801/00-updateisViesClient.sql b/db/changes/231801/00-updateisViesClient.sql new file mode 100644 index 000000000..a153c5219 --- /dev/null +++ b/db/changes/231801/00-updateisViesClient.sql @@ -0,0 +1,5 @@ +UPDATE IGNORE `vn`.`client` c + JOIN `vn`.`country` co ON co.id = c.countryFk + SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1) + WHERE c.isVies = TRUE + AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2); diff --git a/db/changes/231601/00-userAcl.sql b/db/changes/231801/00-userAcl.sql similarity index 100% rename from db/changes/231601/00-userAcl.sql rename to db/changes/231801/00-userAcl.sql diff --git a/db/changes/231601/00-userRoleLog.sql b/db/changes/231801/00-userRoleLog.sql similarity index 100% rename from db/changes/231601/00-userRoleLog.sql rename to db/changes/231801/00-userRoleLog.sql diff --git a/db/changes/231801/01-viewCompany10L.sql b/db/changes/231801/01-viewCompany10L.sql new file mode 100644 index 000000000..335827b42 --- /dev/null +++ b/db/changes/231801/01-viewCompany10L.sql @@ -0,0 +1,12 @@ +-- vn.companyL10n source + +CREATE OR REPLACE +ALGORITHM = UNDEFINED VIEW `vn`.`companyL10n` AS +select + `c`.`id` AS `id`, + ifnull(`ci`.`footnotes`, `c`.`footnotes`) AS `footnotes` +from + (`vn`.`company` `c` +left join `vn`.`companyI18n` `ci` on + (`ci`.`companyFk` = `c`.`id` + and `ci`.`lang` = `util`.`LANG`())); \ No newline at end of file diff --git a/db/changes/232001/00-clientWorkerName.sql b/db/changes/232001/00-clientWorkerName.sql new file mode 100644 index 000000000..676d26691 --- /dev/null +++ b/db/changes/232001/00-clientWorkerName.sql @@ -0,0 +1,73 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`clientCreate`( + vFirstname VARCHAR(50), + vSurnames VARCHAR(50), + vFi VARCHAR(9), + vAddress TEXT, + vPostcode CHAR(5), + vCity VARCHAR(25), + vProvinceFk SMALLINT(5), + vCompanyFk SMALLINT(5), + vPhone VARCHAR(11), + vEmail VARCHAR(255), + vUserFk INT) +BEGIN +/** + * Create new client + * + */ + DECLARE vPayMethodFk INT DEFAULT 4; + DECLARE vDueDay INT DEFAULT 5; + DECLARE vDefaultCredit DECIMAL(10, 2) DEFAULT 300.00; + DECLARE vIsTaxDataChecked TINYINT(1) DEFAULT 1; + DECLARE vHasCoreVnl BOOLEAN DEFAULT TRUE; + DECLARE vMandateTypeFk INT DEFAULT 2; + + INSERT INTO `client` ( + id, + name, + street, + fi, + phone, + email, + provinceFk, + city, + postcode, + socialName, + payMethodFk, + dueDay, + credit, + isTaxDataChecked, + hasCoreVnl, + isEqualizated) + VALUES ( + vUserFk, + CONCAT(vFirstname, ' ', vSurnames), + vAddress, + TRIM(vFi), + vPhone, + vEmail, + vProvinceFk, + vCity, + vPostcode, + CONCAT(vSurnames, ' ', vFirstname), + vPayMethodFk, + vDueDay, + vDefaultCredit, + vIsTaxDataChecked, + vHasCoreVnl, + FALSE + ) ON duplicate key update + payMethodFk = vPayMethodFk, + dueDay = vDueDay, + credit = vDefaultCredit, + isTaxDataChecked = vIsTaxDataChecked, + hasCoreVnl = vHasCoreVnl, + isActive = TRUE; + + IF (SELECT COUNT(*) FROM mandate WHERE clientFk = vUserFk AND companyFk = vCompanyFk AND mandateTypeFk = vMandateTypeFk) = 0 THEN + INSERT INTO mandate (clientFk, companyFk, mandateTypeFk) + VALUES (vUserFk, vCompanyFk, vMandateTypeFk); + END IF; +END$$ +DELIMITER ; \ No newline at end of file diff --git a/db/changes/232001/00-createWorker.sql b/db/changes/232001/00-createWorker.sql new file mode 100644 index 000000000..3e5af683f --- /dev/null +++ b/db/changes/232001/00-createWorker.sql @@ -0,0 +1,14 @@ + INSERT INTO `vn`.`businessType` (`code`, `description`) + VALUES ('worker','Trabajador'); + +ALTER TABLE `vn`.`workerConfig` ADD businessTypeFk varchar(100) NULL + COMMENT 'Tipo de negocio por defecto al dar de alta un trabajador nuevo'; + +UPDATE `vn`.`workerConfig` + SET businessTypeFk = 'worker' + WHERE id = 1; + + UPDATE `vn`.`client` c + JOIN `vn`.`worker` w ON w.id = c.id + SET c.name = REPLACE(c.name, 'TR ', ''), + c.businessTypeFk = 'worker'; diff --git a/db/changes/232001/00-invoiceOut_new.sql b/db/changes/232001/00-invoiceOut_new.sql new file mode 100644 index 000000000..b4fc5c824 --- /dev/null +++ b/db/changes/232001/00-invoiceOut_new.sql @@ -0,0 +1,254 @@ +DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`( + vSerial VARCHAR(255), + vInvoiceDate DATE, + vTaxArea VARCHAR(25), + OUT vNewInvoiceId INT) +BEGIN +/** + * Creación de facturas emitidas. + * requiere previamente tabla tmp.ticketToInvoice(id). + * + * @param vSerial serie a la cual se hace la factura + * @param vInvoiceDate fecha de la factura + * @param vTaxArea tipo de iva en relacion a la empresa y al cliente + * @param vNewInvoiceId id de la factura que se acaba de generar + * @return vNewInvoiceId + */ + DECLARE vIsAnySaleToInvoice BOOL; + DECLARE vIsAnyServiceToInvoice BOOL; + DECLARE vNewRef VARCHAR(255); + DECLARE vWorker INT DEFAULT account.myUser_getId(); + DECLARE vCompanyFk INT; + DECLARE vInterCompanyFk INT; + DECLARE vClientFk INT; + DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1; + DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6; + DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2; + DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R'; + DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S'; + DECLARE vNewInvoiceInFk INT; + DECLARE vIsInterCompany BOOL DEFAULT FALSE; + DECLARE vIsCEESerial BOOL DEFAULT FALSE; + DECLARE vIsCorrectInvoiceDate BOOL; + DECLARE vMaxShipped DATE; + + SET vInvoiceDate = IFNULL(vInvoiceDate, util.VN_CURDATE()); + + SELECT t.clientFk, + t.companyFk, + MAX(DATE(t.shipped)), + DATE(vInvoiceDate) >= invoiceOut_getMaxIssued( + vSerial, + t.companyFk, + YEAR(vInvoiceDate)) + INTO vClientFk, + vCompanyFk, + vMaxShipped, + vIsCorrectInvoiceDate + FROM tmp.ticketToInvoice tt + JOIN ticket t ON t.id = tt.id; + + IF(vMaxShipped > vInvoiceDate) THEN + CALL util.throw("Invoice date can't be less than max date"); + END IF; + + IF NOT vIsCorrectInvoiceDate THEN + CALL util.throw('Exists an invoice with a previous date'); + END IF; + + -- Eliminem de tmp.ticketToInvoice els tickets que no han de ser facturats + DELETE ti.* + FROM tmp.ticketToInvoice ti + JOIN ticket t ON t.id = ti.id + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN supplier su ON su.id = t.companyFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk + WHERE (YEAR(t.shipped) < 2001 AND t.isDeleted) + OR c.isTaxDataChecked = FALSE + OR t.isDeleted + OR c.hasToInvoice = FALSE + OR itc.id IS NULL; + + SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0 + INTO vIsAnySaleToInvoice + FROM tmp.ticketToInvoice t + JOIN sale s ON s.ticketFk = t.id; + + SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice + FROM tmp.ticketToInvoice t + JOIN ticketService ts ON ts.ticketFk = t.id; + + IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice) + AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase()) + THEN + + -- el trigger añade el siguiente Id_Factura correspondiente a la vSerial + INSERT INTO invoiceOut( + ref, + serial, + issued, + clientFk, + dued, + companyFk, + cplusInvoiceType477Fk + ) + SELECT + 1, + vSerial, + vInvoiceDate, + vClientFk, + getDueDate(vInvoiceDate, dueDay), + vCompanyFk, + IF(vSerial = vCorrectingSerial, + vCplusCorrectingInvoiceTypeFk, + IF(vSerial = vSimplifiedSerial, + vCplusSimplifiedInvoiceTypeFk, + vCplusStandardInvoiceTypeFk)) + FROM client + WHERE id = vClientFk; + + SET vNewInvoiceId = LAST_INSERT_ID(); + + SELECT `ref` + INTO vNewRef + FROM invoiceOut + WHERE id = vNewInvoiceId; + + UPDATE ticket t + JOIN tmp.ticketToInvoice ti ON ti.id = t.id + SET t.refFk = vNewRef; + + DROP TEMPORARY TABLE IF EXISTS tmp.updateInter; + CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY + SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador + FROM tmp.ticketToInvoice ti + LEFT JOIN ticketState ts ON ti.id = ts.ticket + JOIN state s + WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id); + + INSERT INTO ticketTracking(stateFk,ticketFk,workerFk) + SELECT * FROM tmp.updateInter; + + CALL invoiceExpenceMake(vNewInvoiceId); + CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); + + UPDATE invoiceOut io + JOIN ( + SELECT SUM(amount) total + FROM invoiceOutExpence + WHERE invoiceOutFk = vNewInvoiceId + ) base + JOIN ( + SELECT SUM(vat) total + FROM invoiceOutTax + WHERE invoiceOutFk = vNewInvoiceId + ) vat + SET io.amount = base.total + vat.total + WHERE io.id = vNewInvoiceId; + + DROP TEMPORARY TABLE tmp.updateInter; + + SELECT COUNT(*), id + INTO vIsInterCompany, vInterCompanyFk + FROM company + WHERE clientFk = vClientFk; + + IF (vIsInterCompany) THEN + + INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk) + SELECT vCompanyFk, vNewRef, vInvoiceDate, vInterCompanyFk; + + SET vNewInvoiceInFk = LAST_INSERT_ID(); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket; + CREATE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM tmp.ticketToInvoice; + + CALL `ticket_getTax`('NATIONAL'); + + SET @vTaxableBaseServices := 0.00; + SET @vTaxCodeGeneral := NULL; + + INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInFk, + @vTaxableBaseServices, + sub.expenceFk, + sub.taxTypeSageFk, + sub.transactionTypeSageFk + FROM ( + SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, + i.expenceFk, + i.taxTypeSageFk, + i.transactionTypeSageFk, + @vTaxCodeGeneral := i.taxClassCodeFk + FROM tmp.ticketServiceTax tst + JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code + WHERE i.isService + HAVING taxableBase + ) sub; + + INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInFk, + SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, + @vTaxableBaseServices, 0) taxableBase, + i.expenceFk, + i.taxTypeSageFk , + i.transactionTypeSageFk + FROM tmp.ticketTax tt + JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code + WHERE !i.isService + GROUP BY tt.pgcFk + HAVING taxableBase + ORDER BY tt.priority; + + CALL invoiceInDueDay_calculate(vNewInvoiceInFk); + + SELECT COUNT(*) INTO vIsCEESerial + FROM invoiceOutSerial + WHERE code = vSerial; + + IF vIsCEESerial THEN + + INSERT INTO invoiceInIntrastat ( + invoiceInFk, + intrastatFk, + amount, + stems, + countryFk, + net) + SELECT + vNewInvoiceInFk, + i.intrastatFk, + SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))), + SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))), + su.countryFk, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) AS DECIMAL(10, 2)) + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + WHERE t.refFk = vNewRef + GROUP BY i.intrastatFk; + + END IF; + DROP TEMPORARY TABLE tmp.ticket; + DROP TEMPORARY TABLE tmp.ticketAmount; + DROP TEMPORARY TABLE tmp.ticketTax; + DROP TEMPORARY TABLE tmp.ticketServiceTax; + END IF; + END IF; + DROP TEMPORARY TABLE `tmp`.`ticketToInvoice`; +END$$ +DELIMITER ; diff --git a/db/changes/232201/.gitkeep b/db/changes/232201/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/db/changes/231601/00-userPassExpired.sql b/db/changes/232201/00-userPassExpired.sql similarity index 98% rename from db/changes/231601/00-userPassExpired.sql rename to db/changes/232201/00-userPassExpired.sql index c076369ca..3f748e88e 100644 --- a/db/changes/231601/00-userPassExpired.sql +++ b/db/changes/232201/00-userPassExpired.sql @@ -18,4 +18,3 @@ BEGIN END IF; END$$ DELIMITER ; -USE vn; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 9e904efbb..40c33fc13 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2801,9 +2801,9 @@ INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES (1, 1); -INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) +INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `businessTypeFk`) VALUES - (1, NULL, 1); + (1, NULL, 1, 'worker'); INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) VALUES diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index b54afe5a7..fe3ef08bd 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -218,23 +218,6 @@ let actions = { return handle.jsonValue(); }, - getValue: async function(selector) { - return await this.waitToGetProperty(selector, 'value'); - }, - - getValues: async function(selectorMap) { - const values = {}; - for (const key in selectorMap) - values[key] = await this.waitToGetProperty(selectorMap[key], 'value'); - return values; - }, - - innerText: async function(selector) { - const element = await this.$(selector); - const handle = await element.getProperty('innerText'); - return handle.jsonValue(); - }, - waitPropertyLength: async function(selector, property, minLength) { await this.waitForFunction((selector, property, minLength) => { const element = document.querySelector(selector); @@ -431,7 +414,7 @@ let actions = { const selector = 'vn-snackbar .shape.shown'; await this.waitForSelector(selector); - let message = await this.evaluate(selector => { + const message = await this.evaluate(selector => { const shape = document.querySelector(selector); const message = { text: shape.querySelector('.text').innerText @@ -448,6 +431,8 @@ let actions = { return message; }, selector); + message.isSuccess = message.type == 'success'; + await this.hideSnackbar(); return message; }, @@ -483,28 +468,6 @@ let actions = { }, selector); }, - clearInput: async function(selector) { - await this.waitForSelector(selector); - - let field = await this.evaluate(selector => { - return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field; - }, selector); - - if ((field != null && field != '') || field == '0') { - let coords = await this.evaluate(selector => { - let rect = document.querySelector(selector).getBoundingClientRect(); - return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width}; - }, selector); - await this.mouse.move(coords.x, coords.y); - await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true}); - await this.waitToClick(`${selector} [icon="clear"]`); - } - - await this.evaluate(selector => { - return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == ''; - }, selector); - }, - autocompleteSearch: async function(selector, searchValue) { let builtSelector = await this.selectorFormater(selector); @@ -536,17 +499,15 @@ let actions = { checkboxState: async function(selector) { await this.waitForSelector(selector); - return this.evaluate(selector => { - let checkbox = document.querySelector(selector); - switch (checkbox.$ctrl.field) { - case null: - return 'intermediate'; - case true: - return 'checked'; - default: - return 'unchecked'; - } - }, selector); + const value = await this.getInputValue(selector); + switch (value) { + case null: + return 'intermediate'; + case true: + return 'checked'; + default: + return 'unchecked'; + } }, isDisabled: async function(selector) { @@ -639,6 +600,138 @@ let actions = { waitForContentLoaded: async function() { await this.waitForSpinnerLoad(); + }, + + async getInputValue(selector) { + return this.evaluate(selector => { + const input = document.querySelector(selector); + return input.$ctrl.field; + }, selector); + }, + + async getValue(selector) { + return await this.waitToGetProperty(selector, 'value'); + }, + + async innerText(selector) { + const element = await this.$(selector); + const handle = await element.getProperty('innerText'); + return handle.jsonValue(); + }, + + async setInput(selector, value) { + const input = await this.$(selector); + const tagName = (await input.evaluate(e => e.tagName)).toLowerCase(); + + switch (tagName) { + case 'vn-textfield': + case 'vn-datalist': + case 'vn-input-number': + await this.clearInput(selector); + if (value) + await this.write(selector, value.toString()); + break; + case 'vn-autocomplete': + if (value) + await this.autocompleteSearch(selector, value.toString()); + else + await this.clearInput(selector); + break; + case 'vn-date-picker': + if (value) + await this.pickDate(selector, value); + else + await this.clearInput(selector); + break; + case 'vn-input-time': + if (value) + await this.pickTime(selector, value); + else + await this.clearInput(selector); + break; + case 'vn-check': + for (let i = 0; i < 3; i++) { + if (await this.getInput(selector) == value) break; + await this.click(selector); + } + break; + } + }, + + async getInput(selector) { + const input = await this.$(selector); + const tagName = (await input.evaluate(e => e.tagName)).toLowerCase(); + let el; + let value; + + switch (tagName) { + case 'vn-textfield': + case 'vn-autocomplete': + case 'vn-input-time': + case 'vn-datalist': + el = await input.$('input'); + value = await el.getProperty('value'); + return value.jsonValue(); + case 'vn-check': + case 'vn-input-number': + return await this.getInputValue(selector); + case 'vn-textarea': + el = await input.$('textarea'); + value = await el.getProperty('value'); + return value.jsonValue(); + case 'vn-date-picker': + el = await input.$('input'); + value = await el.getProperty('value'); + if (value) { + const date = new Date(await value.jsonValue()); + date.setUTCHours(0, 0, 0, 0); + return date; + } else + return null; + default: + value = await this.innerText(selector); + return value.jsonValue(); + } + }, + + async clearInput(selector) { + await this.waitForSelector(selector); + + let field = await this.evaluate(selector => { + return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field; + }, selector); + + if ((field != null && field != '') || field == '0') { + let coords = await this.evaluate(selector => { + let rect = document.querySelector(selector).getBoundingClientRect(); + return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width}; + }, selector); + await this.mouse.move(coords.x, coords.y); + await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true}); + await this.waitToClick(`${selector} [icon="clear"]`); + } + + await this.evaluate(selector => { + return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == ''; + }, selector); + }, + + async fetchForm(selector, inputNames) { + const values = {}; + for (const inputName of inputNames) + values[inputName] = await this.getInput(`${selector} [vn-name="${inputName}"]`); + return values; + }, + + async fillForm(selector, values) { + for (const inputName in values) + await this.setInput(`${selector} [vn-name="${inputName}"]`, values[inputName]); + }, + + async sendForm(selector, values) { + if (values) await this.fillForm(selector, values); + await this.click(`${selector} button[type=submit]`); + return await this.waitForSnackbar(); } }; @@ -646,12 +739,14 @@ export function extendPage(page) { for (let name in actions) { page[name] = async(...args) => { try { - return actions[name].apply(page, args); + return await actions[name].apply(page, args); } catch (err) { let stringArgs = args - .map(i => typeof i == 'function' ? 'Function' : i) + .map(i => typeof i == 'function' ? 'Function' : `'${i}'`) .join(', '); - throw new Error(`.${name}(${stringArgs}): ${err.message}`); + const myErr = new Error(`${err.message}\n at Page.${name}(${stringArgs})`); + myErr.stack = err.stack; + throw myErr; } }; } diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 1740db7ca..b19db24d7 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -193,10 +193,6 @@ export default { saveNewPoscode: '#savePostcode', createButton: 'vn-client-create button[type=submit]' }, - clientDescriptor: { - moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]', - simpleTicketButton: '.vn-menu [name="simpleTicket"]' - }, clientBasicData: { name: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.name"]', contact: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.contact"]', @@ -231,23 +227,6 @@ export default { saveButton: 'button[type=submit]', watcher: 'vn-client-fiscal-data vn-watcher' }, - clientBillingData: { - payMethod: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]', - IBAN: 'vn-client-billing-data vn-textfield[ng-model="$ctrl.client.iban"]', - dueDay: 'vn-client-billing-data vn-input-number[ng-model="$ctrl.client.dueDay"]', - receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]', - receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]', - receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]', - swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]', - newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button', - newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]', - newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]', - newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]', - newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]', - acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]', - saveButton: 'vn-client-billing-data button[type=submit]', - watcher: 'vn-client-billing-data vn-watcher' - }, clientAddresses: { addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]', createAddress: 'vn-client-address-index vn-float-button', @@ -306,21 +285,6 @@ export default { clientMandate: { firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr' }, - clientBalance: { - company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]', - newPaymentButton: `vn-float-button`, - newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.bankFk"]', - newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.amountPaid"]', - newDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]', - deliveredAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.deliveredAmount"]', - refundAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.amountToReturn"]', - saveButton: '.vn-dialog.shown [response="accept"]', - anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr', - firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)', - firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable', - firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield', - compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]' - }, webPayment: { confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]', firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]' @@ -466,10 +430,6 @@ export default { packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]', isActiveCheckbox: 'vn-check[label="Active"]', priceInKgCheckbox: 'vn-check[label="Price in kg"]', - newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button', - newIntrastatId: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.newIntrastat.intrastatId"]', - newIntrastatDescription: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newIntrastat.description"]', - acceptIntrastatButton: '.vn-dialog.shown button[response="accept"]', submitBasicDataButton: `button[type=submit]` }, itemTags: { @@ -622,13 +582,6 @@ export default { saveButton: '.vn-dialog.shown [response="accept"]', expeditionRow: 'vn-ticket-expedition vn-table vn-tbody > vn-tr' }, - ticketPackages: { - firstPackage: 'vn-autocomplete[label="Package"]', - firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]', - firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', - addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', - savePackagesButton: `button[type=submit]` - }, ticketSales: { setOk: 'vn-ticket-sale vn-tool-bar > vn-button[label="Ok"] > button', saleLine: 'vn-table div > vn-tbody > vn-tr vn-check', @@ -873,15 +826,6 @@ export default { landedDatePicker: 'vn-date-picker[label="Landed"]', createButton: 'button[type=submit]' }, - orderSummary: { - id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span', - alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span', - consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span', - subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)', - vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)', - total: 'vn-order-summary vn-one.taxes > p:nth-child(3)', - sale: 'vn-order-summary vn-tbody > vn-tr', - }, orderCatalog: { plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]', type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]', @@ -899,14 +843,6 @@ export default { fifthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(5) vn-icon[icon=cancel]', sixthFilterRemoveButton: 'vn-order-catalog > vn-side-menu .chips > vn-chip:nth-child(6) vn-icon[icon=cancel]', }, - orderBasicData: { - client: 'vn-autocomplete[label="Client"]', - address: 'vn-autocomplete[label="Address"]', - agency: 'vn-autocomplete[label="Agency"]', - observation: 'vn-textarea[label="Notes"]', - saveButton: `button[type=submit]`, - acceptButton: '.vn-confirm.shown button[response="accept"]' - }, orderLine: { orderSubtotal: 'vn-order-line .header :first-child', firstLineDeleteButton: 'vn-order-line vn-tbody > vn-tr:nth-child(1) vn-icon[icon="delete"]', @@ -946,16 +882,6 @@ export default { goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a', }, - routeBasicData: { - worker: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]', - vehicle: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]', - kmStart: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmStart"]', - kmEnd: 'vn-route-basic-data vn-input-number[ng-model="$ctrl.route.kmEnd"]', - createdDate: 'vn-route-basic-data vn-date-picker[ng-model="$ctrl.route.created"]', - startedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.started"]', - finishedHour: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.finished"]', - saveButton: 'vn-route-basic-data button[type=submit]' - }, routeTickets: { firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]', firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check', @@ -1240,22 +1166,6 @@ export default { confirmed: 'vn-entry-summary vn-check[label="Confirmed"]', anyBuyLine: 'vn-entry-summary tr.dark-row' }, - entryBasicData: { - reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]', - invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]', - notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]', - observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]', - supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]', - currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]', - commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]', - company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]', - ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]', - confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]', - inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]', - raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]', - booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]', - save: 'vn-entry-basic-data button[type=submit]', - }, entryDescriptor: { agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span', travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a', diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js index f9844d5f7..c4f091d1f 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -15,81 +15,55 @@ describe('SmartTable SearchBar integration', () => { await browser.close(); }); - describe('as filters in smart-table section', () => { - it('should search by type in searchBar', async() => { - await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); - await page.waitToClick(selectors.itemsIndex.advancedSearchButton); - await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); + it('should search by type in searchBar, reload page and have same results', async() => { + await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); + await page.waitToClick(selectors.itemsIndex.advancedSearchButton); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); + + await page.reload({ + waitUntil: 'networkidle2' }); - it('should reload page and have same results', async() => { - await page.reload({ - waitUntil: 'networkidle2' - }); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); - await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); + await page.waitToClick(selectors.itemsIndex.advancedSmartTableButton); + await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1'); + await page.keyboard.press('Enter'); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); + + await page.reload({ + waitUntil: 'networkidle2' }); - it('should search by grouping in smartTable', async() => { - await page.waitToClick(selectors.itemsIndex.advancedSmartTableButton); - await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); - }); - - it('should now reload page and have same results', async() => { - await page.reload({ - waitUntil: 'networkidle2' - }); - - await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); - }); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); }); - describe('as filters in section without smart-table', () => { - it('go to zone section', async() => { - await page.loginAndModule('salesPerson', 'zone'); - await page.waitToClick(selectors.globalItems.searchButton); - }); + it('should filter in section without smart-table and search in searchBar go to zone section', async() => { + await page.loginAndModule('salesPerson', 'zone'); + await page.waitToClick(selectors.globalItems.searchButton); - it('should search in searchBar first time', async() => { - await page.doSearch('A'); - const count = await page.countElement(selectors.zoneIndex.searchResult); + await page.doSearch('A'); + const firstCount = await page.countElement(selectors.zoneIndex.searchResult); - expect(count).toEqual(7); - }); + await page.doSearch('A'); + const secondCount = await page.countElement(selectors.zoneIndex.searchResult); - it('should search in searchBar second time', async() => { - await page.doSearch('A'); - const count = await page.countElement(selectors.zoneIndex.searchResult); - - expect(count).toEqual(7); - }); - - it('should search in searchBar third time', async() => { - await page.doSearch('A'); - const count = await page.countElement(selectors.zoneIndex.searchResult); - - expect(count).toEqual(7); - }); + expect(firstCount).toEqual(7); + expect(secondCount).toEqual(7); }); - describe('as orders', () => { - it('should order by first id', async() => { - await page.loginAndModule('developer', 'item'); - await page.accessToSection('item.fixedPrice'); - await page.keyboard.press('Enter'); + it('should order orders by first id and order by last id, reload page and have same order', async() => { + await page.loginAndModule('developer', 'item'); + await page.accessToSection('item.fixedPrice'); + await page.keyboard.press('Enter'); - await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1'); - }); + await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1'); - it('should order by last id, reload page and have same order', async() => { - await page.waitToClick(selectors.itemFixedPrice.orderColumnId); - await page.reload({ - waitUntil: 'networkidle2' - }); - await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '13'); + await page.waitToClick(selectors.itemFixedPrice.orderColumnId); + await page.reload({ + waitUntil: 'networkidle2' }); + await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '13'); }); }); diff --git a/e2e/paths/02-client/03_edit_fiscal_data.spec.js b/e2e/paths/02-client/03_edit_fiscal_data.spec.js index 2a56cb535..0babb5396 100644 --- a/e2e/paths/02-client/03_edit_fiscal_data.spec.js +++ b/e2e/paths/02-client/03_edit_fiscal_data.spec.js @@ -171,100 +171,40 @@ describe('Client Edit fiscalData path', () => { expect(result).toEqual('SMASH'); }); - it('should confirm the fiscal id have been edited', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.fiscalId, 'value'); + it('should confirm the fiscal data have been edited', async() => { + const fiscalId = await page.waitToGetProperty(selectors.clientFiscalData.fiscalId, 'value'); + const address = await page.waitToGetProperty(selectors.clientFiscalData.address, 'value'); + const postcode = await page.waitToGetProperty(selectors.clientFiscalData.postcode, 'value'); + const sageTax = await page.waitToGetProperty(selectors.clientFiscalData.sageTax, 'value'); + const sageTransaction = await page.waitToGetProperty(selectors.clientFiscalData.sageTransaction, 'value'); + const city = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value'); + const province = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value'); + const country = await page.waitToGetProperty(selectors.clientFiscalData.country, 'value'); + const active = await page.checkboxState(selectors.clientFiscalData.activeCheckbox); + const frozen = await page.checkboxState(selectors.clientFiscalData.frozenCheckbox); + const hasToInvoice = await page.checkboxState(selectors.clientFiscalData.hasToInvoiceCheckbox); + const vies = await page.checkboxState(selectors.clientFiscalData.viesCheckbox); + const notifyByMail = await page.checkboxState(selectors.clientFiscalData.notifyByMailCheckbox); + const invoiceByAddress = await page.checkboxState(selectors.clientFiscalData.invoiceByAddressCheckbox); + const equalizationTax = await page.checkboxState(selectors.clientFiscalData.equalizationTaxCheckbox); + const verifiedData = await page.checkboxState(selectors.clientFiscalData.verifiedDataCheckbox); - expect(result).toEqual('94980061C'); - }); - - it('should confirm the address have been edited', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.address, 'value'); - - expect(result).toEqual('Somewhere edited'); - }); - - it('should confirm the postcode have been edited', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.postcode, 'value'); - - expect(result).toContain('46000'); - }); - - it('should confirm the sageTax have been edited', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTax, 'value'); - - expect(result).toEqual('Operaciones no sujetas'); - }); - - it('should confirm the sageTransaction have been edited', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTransaction, 'value'); - - expect(result).toEqual('36: Regularización de inversiones'); - }); - - it('should confirm the city have been autocompleted', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value'); - - expect(result).toEqual('Valencia'); - }); - - it(`should confirm the province have been autocompleted`, async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value'); - - expect(result).toContain('Province one'); - }); - - it('should confirm the country have been autocompleted', async() => { - const result = await page.waitToGetProperty(selectors.clientFiscalData.country, 'value'); - - expect(result).toEqual('España'); - }); - - it('should confirm active checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.activeCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm frozen checkbox is checked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.frozenCheckbox); - - expect(result).toBe('checked'); - }); - - it('should confirm Has to invoice checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.hasToInvoiceCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm Vies checkbox is checked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.viesCheckbox); - - expect(result).toBe('checked'); - }); - - it('should confirm Notify by email checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.notifyByMailCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm invoice by address checkbox is checked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.invoiceByAddressCheckbox); - - expect(result).toBe('checked'); - }); - - it('should confirm Equalization tax checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.equalizationTaxCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm Verified data checkbox is checked', async() => { - const result = await page.checkboxState(selectors.clientFiscalData.verifiedDataCheckbox); - - expect(result).toBe('checked'); + expect(fiscalId).toEqual('94980061C'); + expect(address).toEqual('Somewhere edited'); + expect(postcode).toContain('46000'); + expect(sageTax).toEqual('Operaciones no sujetas'); + expect(sageTransaction).toEqual('Regularización de inversiones'); + expect(city).toEqual('Valencia'); + expect(province).toContain('Province one'); + expect(country).toEqual('España'); + expect(active).toBe('unchecked'); + expect(frozen).toBe('checked'); + expect(hasToInvoice).toBe('unchecked'); + expect(vies).toBe('checked'); + expect(notifyByMail).toBe('unchecked'); + expect(invoiceByAddress).toBe('checked'); + expect(equalizationTax).toBe('unchecked'); + expect(verifiedData).toBe('checked'); }); // confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 1 diff --git a/e2e/paths/02-client/04_edit_billing_data.spec.js b/e2e/paths/02-client/04_edit_billing_data.spec.js index de3270f93..10eb85406 100644 --- a/e2e/paths/02-client/04_edit_billing_data.spec.js +++ b/e2e/paths/02-client/04_edit_billing_data.spec.js @@ -1,6 +1,23 @@ -import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + payMethod: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]', + IBAN: 'vn-client-billing-data vn-textfield[ng-model="$ctrl.client.iban"]', + dueDay: 'vn-client-billing-data vn-input-number[ng-model="$ctrl.client.dueDay"]', + receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]', + receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]', + receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]', + swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]', + newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button', + newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]', + newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]', + newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]', + newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]', + acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]', + saveButton: 'vn-client-billing-data button[type=submit]', + watcher: 'vn-client-billing-data vn-watcher' +}; + describe('Client Edit billing data path', () => { let browser; let page; @@ -17,93 +34,72 @@ describe('Client Edit billing data path', () => { }); it(`should attempt to edit the billing data without an IBAN but fail`, async() => { - await page.autocompleteSearch(selectors.clientBillingData.payMethod, 'PayMethod with IBAN'); - await page.autocompleteSearch(selectors.clientBillingData.swiftBic, 'BBKKESMMMMM'); - await page.clearInput(selectors.clientBillingData.dueDay); - await page.write(selectors.clientBillingData.dueDay, '60'); - await page.waitForTextInField(selectors.clientBillingData.dueDay, '60'); - await page.waitToClick(selectors.clientBillingData.receivedCoreLCRCheckbox); - await page.waitToClick(selectors.clientBillingData.receivedCoreVNLCheckbox); - await page.waitToClick(selectors.clientBillingData.receivedB2BVNLCheckbox); - await page.waitToClick(selectors.clientBillingData.saveButton); + await page.autocompleteSearch($.payMethod, 'PayMethod with IBAN'); + await page.autocompleteSearch($.swiftBic, 'BBKKESMMMMM'); + await page.clearInput($.dueDay); + await page.write($.dueDay, '60'); + await page.waitForTextInField($.dueDay, '60'); + await page.waitToClick($.receivedCoreLCRCheckbox); + await page.waitToClick($.receivedCoreVNLCheckbox); + await page.waitToClick($.receivedB2BVNLCheckbox); + await page.waitToClick($.saveButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('That payment method requires an IBAN'); }); it(`should create a new BIC code`, async() => { - await page.waitToClick(selectors.clientBillingData.newBankEntityButton); - await page.write(selectors.clientBillingData.newBankEntityName, 'Gotham City Bank'); - await page.write(selectors.clientBillingData.newBankEntityBIC, 'GTHMCT'); - await page.autocompleteSearch(selectors.clientBillingData.newBankEntityCountry, 'España'); - await page.write(selectors.clientBillingData.newBankEntityCode, '9999'); - await page.waitToClick(selectors.clientBillingData.acceptBankEntityButton); + await page.waitToClick($.newBankEntityButton); + await page.write($.newBankEntityName, 'Gotham City Bank'); + await page.write($.newBankEntityBIC, 'GTHMCT'); + await page.autocompleteSearch($.newBankEntityCountry, 'España'); + await page.write($.newBankEntityCode, '9999'); + await page.waitToClick($.acceptBankEntityButton); const message = await page.waitForSnackbar(); - await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'Gotham City Bank'); - const newcode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); - - expect(newcode).toEqual('GTHMCT Gotham City Bank'); + await page.waitForTextInField($.swiftBic, 'GTHMCT'); + const newcode = await page.waitToGetProperty($.swiftBic, 'value'); + expect(newcode).toEqual('GTHMCT'); expect(message.text).toContain('Data saved!'); }); it(`should confirm the IBAN pay method was sucessfully saved`, async() => { - const payMethod = await page.waitToGetProperty(selectors.clientBillingData.payMethod, 'value'); + const payMethod = await page.waitToGetProperty($.payMethod, 'value'); expect(payMethod).toEqual('PayMethod with IBAN'); }); it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => { - await page.write(selectors.clientBillingData.IBAN, 'ES9121000418450200051332'); + await page.write($.IBAN, 'ES9121000418450200051332'); await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); - await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'caixesbb'); - let automaticCode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); + await page.waitForTextInField($.swiftBic, 'caixesbb'); + let automaticCode = await page.waitToGetProperty($.swiftBic, 'value'); - expect(automaticCode).toEqual('CAIXESBB Caixa Bank'); + expect(automaticCode).toEqual('CAIXESBB'); }); it(`should save the form with all its new data`, async() => { - await page.waitForWatcherData(selectors.clientBillingData.watcher); - await page.waitToClick(selectors.clientBillingData.saveButton); + await page.waitForWatcherData($.watcher); + await page.waitToClick($.saveButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Notification sent!'); }); - it('should confirm the due day have been edited', async() => { - const dueDate = await page.waitToGetProperty(selectors.clientBillingData.dueDay, 'value'); + it('should confirm the billing data have been edited', async() => { + const dueDate = await page.waitToGetProperty($.dueDay, 'value'); + const IBAN = await page.waitToGetProperty($.IBAN, 'value'); + const swiftBic = await page.waitToGetProperty($.swiftBic, 'value'); + const receivedCoreLCR = await page.checkboxState($.receivedCoreLCRCheckbox); + const receivedCoreVNL = await page.checkboxState($.receivedCoreVNLCheckbox); + const receivedB2BVNL = await page.checkboxState($.receivedB2BVNLCheckbox); expect(dueDate).toEqual('60'); - }); - - it('should confirm the IBAN was saved', async() => { - const IBAN = await page.waitToGetProperty(selectors.clientBillingData.IBAN, 'value'); - expect(IBAN).toEqual('ES9121000418450200051332'); - }); - - it('should confirm the swift / BIC code was saved', async() => { - const code = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); - - expect(code).toEqual('CAIXESBB Caixa Bank'); - }); - - it('should confirm Received LCR checkbox is checked', async() => { - const result = await page.checkboxState(selectors.clientBillingData.receivedCoreLCRCheckbox); - - expect(result).toBe('checked'); - }); - - it('should confirm Received core VNL checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientBillingData.receivedCoreVNLCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm Received B2B VNL checkbox is unchecked', async() => { - const result = await page.checkboxState(selectors.clientBillingData.receivedB2BVNLCheckbox); - - expect(result).toBe('unchecked'); + expect(swiftBic).toEqual('CAIXESBB'); + expect(receivedCoreLCR).toBe('checked'); + expect(receivedCoreVNL).toBe('unchecked'); + expect(receivedB2BVNL).toBe('unchecked'); }); }); diff --git a/e2e/paths/02-client/10_add_greuge.spec.js b/e2e/paths/02-client/10_add_greuge.spec.js index 6ea923a28..9141c499a 100644 --- a/e2e/paths/02-client/10_add_greuge.spec.js +++ b/e2e/paths/02-client/10_add_greuge.spec.js @@ -29,19 +29,16 @@ describe('Client Add greuge path', () => { expect(message.text).toContain('Some fields are invalid'); }); - it(`should create a new greuge with all its data`, async() => { + it(`should create a new greuge with all its data and confirm the greuge was added to the list`, async() => { await page.write(selectors.clientGreuge.amount, '999'); await page.waitForTextInField(selectors.clientGreuge.amount, '999'); await page.write(selectors.clientGreuge.description, 'new armor for Batman!'); await page.waitToClick(selectors.clientGreuge.saveButton); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should confirm the greuge was added to the list', async() => { const result = await page.waitToGetProperty(selectors.clientGreuge.firstGreugeText, 'innerText'); + expect(message.text).toContain('Data saved!'); expect(result).toContain(999); expect(result).toContain('new armor for Batman!'); expect(result).toContain('Diff'); diff --git a/e2e/paths/02-client/14_balance.spec.js b/e2e/paths/02-client/14_balance.spec.js index d3de842e3..b1c0f7eea 100644 --- a/e2e/paths/02-client/14_balance.spec.js +++ b/e2e/paths/02-client/14_balance.spec.js @@ -1,6 +1,17 @@ import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]', + newPaymentButton: `vn-float-button`, + newPayment: '.vn-dialog.shown', + refundAmount: '.vn-dialog.shown [vn-name="amountToReturn"]', + saveButton: '.vn-dialog.shown [response="accept"]', + firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)', + firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable', + firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable vn-textfield', +}; + describe('Client balance path', () => { let browser; let page; @@ -18,125 +29,100 @@ describe('Client balance path', () => { it('should now edit the local user config data', async() => { await page.waitToClick(selectors.globalItems.userMenuButton); await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'CCs'); - const message = await page.waitForSnackbar(); + const companyMessage = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should access to the balance section to check the data shown matches the local settings', async() => { await page.accessToSection('client.card.balance.index'); - let result = await page.waitToGetProperty(selectors.clientBalance.company, 'value'); + const company = await page.getValue($.company); - expect(result).toEqual('CCs'); - }); - - it('should now clear the user local settings', async() => { await page.waitToClick(selectors.globalItems.userMenuButton); await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should reload the section', async() => { await page.closePopup(); await page.reloadSection('client.card.balance.index'); + + expect(companyMessage.isSuccess).toBeTrue(); + expect(company).toEqual('CCs'); + expect(message.isSuccess).toBeTrue(); }); it('should create a new payment that clears the debt', async() => { - await page.closePopup(); - await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); - await page.clearInput(selectors.clientBalance.newDescription); - await page.write(selectors.clientBalance.newDescription, 'Description'); - await page.waitToClick(selectors.clientBalance.saveButton); + await page.waitToClick($.newPaymentButton); + await page.fillForm($.newPayment, { + bank: 'Cash', + description: 'Description', + viewReceipt: false + }); + await page.respondToDialog('accept'); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); + expect(message.isSuccess).toBeTrue(); }); - it('should edit the 1st line reference', async() => { - await page.waitToClick(selectors.clientBalance.firstLineReference); - await page.write(selectors.clientBalance.firstLineReferenceInput, 'Miscellaneous payment'); + it('should edit the 1st line reference and check data', async() => { + await page.waitToClick($.firstLineReference); + await page.write($.firstLineReferenceInput, 'Miscellaneous payment'); await page.keyboard.press('Enter'); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should check balance is now 0, the reference was saved and the company is now VNL becouse the user local settings were removed', async() => { await page.waitForSpinnerLoad(); - let company = await page - .waitToGetProperty(selectors.clientBalance.company, 'value'); - - let reference = await page - .waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText'); - - let firstBalanceLine = await page - .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); + let company = await page.getValue($.company); + let reference = await page.innerText($.firstLineReference); + let firstBalanceLine = await page.innerText($.firstLineBalance); + expect(message.isSuccess).toBeTrue(); expect(company).toEqual('VNL'); expect(reference).toEqual('Miscellaneous payment'); expect(firstBalanceLine).toContain('0.00'); }); - it('should create a new payment and check the cash comparison works correctly', async() => { - const amountPaid = '100'; - const cashHanded = '500'; - const expectedRefund = '400'; - - await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); - await page.clearInput(selectors.clientBalance.newDescription); - await page.write(selectors.clientBalance.newDescription, 'Payment'); - await page.write(selectors.clientBalance.deliveredAmount, cashHanded); - const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value'); - await page.waitToClick(selectors.clientBalance.saveButton); + it('should create a new payment, check the cash comparison works correctly and balance value is -100', async() => { + await page.waitToClick($.newPaymentButton); + await page.fillForm($.newPayment, { + amountPaid: 100, + description: 'Payment', + deliveredAmount: 500, + viewReceipt: false + }); + const refund = await page.getValue($.refundAmount); + await page.respondToDialog('accept'); const message = await page.waitForSnackbar(); - expect(refund).toEqual(expectedRefund); - expect(message.text).toContain('Data saved!'); - }); - - it('should check the balance value is now -100', async() => { - let result = await page - .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); + const result = await page.innerText($.firstLineBalance); + expect(refund).toEqual('400'); + expect(message.isSuccess).toBeTrue(); expect(result).toContain('-€100.00'); }); it('should create a new payment and check the cash exceeded the maximum', async() => { - const amountPaid = '1001'; - - await page.closePopup(); - await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); - await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); - await page.clearInput(selectors.clientBalance.newDescription); - await page.write(selectors.clientBalance.newDescription, 'Payment'); - await page.waitToClick(selectors.clientBalance.saveButton); + await page.waitToClick($.newPaymentButton); + await page.fillForm($.newPayment, { + bank: 'Cash', + amountPaid: 1001, + description: 'Payment' + }); + await page.waitToClick($.saveButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Amount exceeded'); }); - it('should create a new payment that sets the balance back to the original negative value', async() => { + it('should create a new payment that sets the balance back to negative value and check it', async() => { await page.closePopup(); - await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt'); - await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150'); - await page.clearInput(selectors.clientBalance.newDescription); - await page.write(selectors.clientBalance.newDescription, 'Description'); - await page.waitToClick(selectors.clientBalance.saveButton); + await page.waitToClick($.newPaymentButton); + + await page.fillForm($.newPayment, { + bank: 'Pay on receipt', + amountPaid: -150, + description: 'Description' + }); + await page.respondToDialog('accept'); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should check balance is now 50', async() => { - let result = await page - .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); + const result = await page.innerText($.firstLineBalance); + expect(message.isSuccess).toBeTrue(); expect(result).toEqual('€50.00'); }); @@ -149,12 +135,9 @@ describe('Client balance path', () => { await page.waitForState('client.index'); }); - it('should now search for the user Petter Parker', async() => { + it('should now search for the user Petter Parker not check the payment button is not present', async() => { await page.accessToSearchResult('Petter Parker'); await page.accessToSection('client.card.balance.index'); - }); - - it('should not be able to click the new payment button as it isnt present', async() => { - await page.waitForSelector(selectors.clientBalance.newPaymentButton, {hidden: true}); + await page.waitForSelector($.newPaymentButton, {hidden: true}); }); }); diff --git a/e2e/paths/02-client/23_send_compensation.spec.js b/e2e/paths/02-client/23_send_compensation.spec.js index 6ec8936a8..7ab2d0bac 100644 --- a/e2e/paths/02-client/23_send_compensation.spec.js +++ b/e2e/paths/02-client/23_send_compensation.spec.js @@ -1,6 +1,11 @@ -import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]', + compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]', + saveButton: '.vn-dialog.shown [response="accept"]' +}; + describe('Client Send balance compensation', () => { let browser; let page; @@ -17,9 +22,9 @@ describe('Client Send balance compensation', () => { }); it(`should click on send compensation button`, async() => { - await page.autocompleteSearch(selectors.clientBalance.company, 'VNL'); - await page.waitToClick(selectors.clientBalance.compensationButton); - await page.waitToClick(selectors.clientBalance.saveButton); + await page.autocompleteSearch($.company, 'VNL'); + await page.waitToClick($.compensationButton); + await page.waitToClick($.saveButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Notification sent!'); diff --git a/e2e/paths/04-item/02_basic_data.spec.js b/e2e/paths/04-item/02_basic_data.spec.js index 3cf142816..bb8f3f134 100644 --- a/e2e/paths/04-item/02_basic_data.spec.js +++ b/e2e/paths/04-item/02_basic_data.spec.js @@ -1,14 +1,23 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + form: 'vn-item-basic-data form', + intrastatForm: '.vn-dialog.shown form', + newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button' +}; + describe('Item Edit basic data path', () => { let browser; let page; + beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('buyer', 'item'); await page.accessToSearchResult('Melee weapon combat fist 15cm'); + }); + + beforeEach(async() => { await page.accessToSection('item.card.basicData'); }); @@ -16,124 +25,42 @@ describe('Item Edit basic data path', () => { await browser.close(); }); - it(`should check the descritor edit button is visible for buyer`, async() => { - await page.waitForSelector(selectors.itemDescriptor.editButton, {visible: true}); - }); + it(`should edit the item basic data and confirm the item data was edited`, async() => { + const values = { + name: 'Rose of Purity', + longName: 'RS Rose of Purity', + type: 'Anthurium', + intrastat: 'Coral y materiales similares', + origin: 'Spain', + relevancy: 1, + generic: 'Pallet', + isActive: false, + priceInKg: true, + isFragile: true, + packingOut: 5 + }; - it(`should edit the item basic data`, async() => { - await page.clearInput(selectors.itemBasicData.name); - await page.write(selectors.itemBasicData.name, 'Rose of Purity'); - await page.clearInput(selectors.itemBasicData.longName); - await page.write(selectors.itemBasicData.longName, 'RS Rose of Purity'); - await page.autocompleteSearch(selectors.itemBasicData.type, 'Anthurium'); - await page.autocompleteSearch(selectors.itemBasicData.intrastat, 'Coral y materiales similares'); - await page.autocompleteSearch(selectors.itemBasicData.origin, 'Spain'); - await page.clearInput(selectors.itemBasicData.relevancy); - await page.write(selectors.itemBasicData.relevancy, '1'); - await page.clearInput(selectors.itemBasicData.generic); - await page.autocompleteSearch(selectors.itemBasicData.generic, '16'); - await page.waitToClick(selectors.itemBasicData.isActiveCheckbox); - await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox); - await page.waitToClick(selectors.itemBasicData.isFragile); - await page.write(selectors.itemBasicData.packingOut, '5'); - await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - - it(`should create a new intrastat`, async() => { - await page.waitToClick(selectors.itemBasicData.newIntrastatButton); - await page.write(selectors.itemBasicData.newIntrastatId, '588420239'); - await page.write(selectors.itemBasicData.newIntrastatDescription, 'Tropical Flowers'); - await page.waitToClick(selectors.itemBasicData.acceptIntrastatButton); - await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers'); - let newcode = await page.waitToGetProperty(selectors.itemBasicData.intrastat, 'value'); - - expect(newcode).toEqual('588420239 Tropical Flowers'); - }); - - it('should save with the new intrastat', async() => { - await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - - it(`should confirm the item name was edited`, async() => { + const message = await page.sendForm($.form, values); await page.reloadSection('item.card.basicData'); - const result = await page.waitToGetProperty(selectors.itemBasicData.name, 'value'); + const formValues = await page.fetchForm($.form, Object.keys(values)); - expect(result).toEqual('Rose of Purity'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); }); - it(`should confirm the item type was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.type, 'value'); + it(`should create a new intrastat and save it`, async() => { + await page.click($.newIntrastatButton); + await page.fillForm($.intrastatForm, { + id: '588420239', + description: 'Tropical Flowers' + }); + await page.respondToDialog('accept'); - expect(result).toEqual('Anthurium'); - }); + const message = await page.sendForm($.form); + await page.reloadSection('item.card.basicData'); + const formValues = await page.fetchForm($.form, ['intrastat']); - it(`should confirm the item intrastat was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.intrastat, 'value'); - - expect(result).toEqual('588420239 Tropical Flowers'); - }); - - it(`should confirm the item relevancy was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.relevancy, 'value'); - - expect(result).toEqual('1'); - }); - - it(`should confirm the item origin was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.origin, 'value'); - - expect(result).toEqual('Spain'); - }); - - it(`should confirm the item generic was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.generic, 'value'); - - expect(result).toEqual('16 - Pallet'); - }); - - it(`should confirm the item long name was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.longName, 'value'); - - expect(result).toEqual('RS Rose of Purity'); - }); - - it('should confirm isFragile checkbox is unchecked', async() => { - const result = await page - .checkboxState(selectors.itemBasicData.isFragile); - - expect(result).toBe('checked'); - }); - - it('should confirm isActive checkbox is unchecked', async() => { - const result = await page - .checkboxState(selectors.itemBasicData.isActiveCheckbox); - - expect(result).toBe('unchecked'); - }); - - it('should confirm the priceInKg checkbox is checked', async() => { - const result = await page - .checkboxState(selectors.itemBasicData.priceInKgCheckbox); - - expect(result).toBe('checked'); - }); - - it(`should confirm the item packingOut was edited`, async() => { - const result = await page - .waitToGetProperty(selectors.itemBasicData.packingOut, 'value'); - - expect(result).toEqual('5'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual({intrastat: 'Tropical Flowers'}); }); }); diff --git a/e2e/paths/04-item/03_tax.spec.js b/e2e/paths/04-item/03_tax.spec.js index 8b3b0f8b1..83f4e6bee 100644 --- a/e2e/paths/04-item/03_tax.spec.js +++ b/e2e/paths/04-item/03_tax.spec.js @@ -53,12 +53,4 @@ describe('Item edit tax path', () => { expect(firstVatType).toEqual('Reduced VAT'); }); - - // # #2680 Undo changes button bugs - xit(`should now click the undo changes button and see the form is restored`, async() => { - await page.waitToClick(selectors.itemTax.undoChangesButton); - const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value'); - - expect(firstVatType).toEqual('General VAT'); - }); }); diff --git a/e2e/paths/04-item/07_create.spec.js b/e2e/paths/04-item/07_create.spec.js index 33324cdba..c20be9ebc 100644 --- a/e2e/paths/04-item/07_create.spec.js +++ b/e2e/paths/04-item/07_create.spec.js @@ -1,6 +1,10 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + form: 'vn-item-create form' +}; + describe('Item Create', () => { let browser; let page; @@ -14,13 +18,6 @@ describe('Item Create', () => { await browser.close(); }); - it(`should search for the item Infinity Gauntlet to confirm it isn't created yet`, async() => { - await page.doSearch('Infinity Gauntlet'); - const resultsCount = await page.countElement(selectors.itemsIndex.searchResult); - - expect(resultsCount).toEqual(0); - }); - it('should access to the create item view by clicking the create floating button', async() => { await page.waitToClick(selectors.itemsIndex.createItemButton); await page.waitForState('item.create'); @@ -37,44 +34,32 @@ describe('Item Create', () => { }); it('should throw an error when insert an invalid priority', async() => { - await page.write(selectors.itemCreateView.temporalName, 'Infinity Gauntlet'); - await page.autocompleteSearch(selectors.itemCreateView.type, 'Crisantemo'); - await page.autocompleteSearch(selectors.itemCreateView.intrastat, 'Coral y materiales similares'); - await page.autocompleteSearch(selectors.itemCreateView.origin, 'Holand'); - await page.clearInput(selectors.itemCreateView.priority); - await page.waitToClick(selectors.itemCreateView.createButton); - const message = await page.waitForSnackbar(); + const values = { + name: 'Infinity Gauntlet', + type: 'Crisantemo', + intrastat: 'Coral y materiales similares', + origin: 'Holand', + priority: null + }; + const message = await page.sendForm($.form, values); expect(message.text).toContain('Valid priorities'); }); it('should create the Infinity Gauntlet item', async() => { - await page.autocompleteSearch(selectors.itemCreateView.priority, '2'); - await page.waitToClick(selectors.itemCreateView.createButton); - const message = await page.waitForSnackbar(); + const values = { + name: 'Infinity Gauntlet', + type: 'Crisantemo', + intrastat: 'Coral y materiales similares', + origin: 'Holand', + priority: '2' + }; - expect(message.text).toContain('Data saved!'); - }); + await page.fillForm($.form, values); + const formValues = await page.fetchForm($.form, Object.keys(values)); + const message = await page.sendForm($.form); - it('should confirm Infinity Gauntlet item was created', async() => { - let result = await page - .waitToGetProperty(selectors.itemBasicData.name, 'value'); - - expect(result).toEqual('Infinity Gauntlet'); - - result = await page - .waitToGetProperty(selectors.itemBasicData.type, 'value'); - - expect(result).toEqual('Crisantemo'); - - result = await page - .waitToGetProperty(selectors.itemBasicData.intrastat, 'value'); - - expect(result).toEqual('5080000 Coral y materiales similares'); - - result = await page - .waitToGetProperty(selectors.itemBasicData.origin, 'value'); - - expect(result).toEqual('Holand'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); }); }); diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index df3b4f7a3..37c4401b0 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -1,6 +1,8 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = selectors.itemFixedPrice; + describe('Item fixed prices path', () => { let browser; let page; @@ -22,63 +24,63 @@ describe('Item fixed prices path', () => { }); it('should filter using all the fields', async() => { - await page.write(selectors.itemFixedPrice.generalSearchFilter, 'item'); + await page.write($.generalSearchFilter, 'item'); await page.keyboard.press('Enter'); expect(httpRequest).toContain('search=item'); - await page.click(selectors.itemFixedPrice.chip); - await page.click(selectors.itemFixedPrice.reignFilter); + await page.click($.chip); + await page.click($.reignFilter); expect(httpRequest).toContain('categoryFk'); - await page.autocompleteSearch(selectors.itemFixedPrice.typeFilter, 'Alstroemeria'); + await page.autocompleteSearch($.typeFilter, 'Alstroemeria'); expect(httpRequest).toContain('typeFk'); - await page.click(selectors.itemFixedPrice.chip); - await page.autocompleteSearch(selectors.itemFixedPrice.buyerFilter, 'buyerNick'); + await page.click($.chip); + await page.autocompleteSearch($.buyerFilter, 'buyerNick'); expect(httpRequest).toContain('buyerFk'); - await page.click(selectors.itemFixedPrice.chip); - await page.autocompleteSearch(selectors.itemFixedPrice.warehouseFilter, 'Algemesi'); + await page.click($.chip); + await page.autocompleteSearch($.warehouseFilter, 'Algemesi'); expect(httpRequest).toContain('warehouseFk'); - await page.click(selectors.itemFixedPrice.chip); - await page.click(selectors.itemFixedPrice.mineFilter); + await page.click($.chip); + await page.click($.mineFilter); expect(httpRequest).toContain('mine=true'); - await page.click(selectors.itemFixedPrice.chip); - await page.click(selectors.itemFixedPrice.hasMinPriceFilter); + await page.click($.chip); + await page.click($.hasMinPriceFilter); expect(httpRequest).toContain('hasMinPrice=true'); - await page.click(selectors.itemFixedPrice.chip); - await page.click(selectors.itemFixedPrice.addTag); - await page.autocompleteSearch(selectors.itemFixedPrice.tagFilter, 'Color'); - await page.autocompleteSearch(selectors.itemFixedPrice.tagValueFilter, 'Brown'); + await page.click($.chip); + await page.click($.addTag); + await page.autocompleteSearch($.tagFilter, 'Color'); + await page.autocompleteSearch($.tagValueFilter, 'Brown'); expect(httpRequest).toContain('tags'); - await page.click(selectors.itemFixedPrice.chip); + await page.click($.chip); }); it('should click on the add new fixed price button', async() => { - await page.waitToClick(selectors.itemFixedPrice.add); - await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice); + await page.waitToClick($.add); + await page.waitForSelector($.fourthFixedPrice); }); it('should fill the fixed price data', async() => { const now = Date.vnNew(); - await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one'); - await page.writeOnEditableTD(selectors.itemFixedPrice.fourthGroupingPrice, '1'); - await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPackingPrice, '1'); - await page.write(selectors.itemFixedPrice.fourthMinPrice, '1'); - await page.pickDate(selectors.itemFixedPrice.fourthStarted, now); - await page.pickDate(selectors.itemFixedPrice.fourthEnded, now); + await page.autocompleteSearch($.fourthWarehouse, 'Warehouse one'); + await page.writeOnEditableTD($.fourthGroupingPrice, '1'); + await page.writeOnEditableTD($.fourthPackingPrice, '1'); + await page.write($.fourthMinPrice, '1'); + await page.pickDate($.fourthStarted, now); + await page.pickDate($.fourthEnded, now); const message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved!'); @@ -87,7 +89,7 @@ describe('Item fixed prices path', () => { it('should reload the section and check the created price has the expected ID', async() => { await page.goto(`http://localhost:5000/#!/item/fixed-price`); - const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value'); + const result = await page.waitToGetProperty($.fourthItemID, 'value'); expect(result).toContain('13'); }); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index 1b3204046..2c9646708 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -316,7 +316,7 @@ describe('Ticket Edit sale path', () => { it('should confirm the transfered quantity is the correct one', async() => { const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); - expect(result).toContain('20'); + expect(result).toContain('10'); }); it('should go back to the original ticket sales section', async() => { @@ -425,20 +425,6 @@ describe('Ticket Edit sale path', () => { expect(result).toBeFalsy(); }); - // tickets no longer update their totals instantly, a task performed ever 5-10 mins does it. disabled this test until it changes. - xit('should update all sales discount', async() => { - await page.closePopup(); - await page.waitToClick(selectors.ticketSales.moreMenu); - await page.waitToClick(selectors.ticketSales.moreMenuUpdateDiscount); - await page.waitForSelector(selectors.ticketSales.moreMenuUpdateDiscountInput); - await page.type(selectors.ticketSales.moreMenuUpdateDiscountInput, '100'); - await page.keyboard.press('Enter'); - await page.waitForTextInElement(selectors.ticketSales.totalImport, '0.00'); - const result = await page.waitToGetProperty(selectors.ticketSales.totalImport, 'innerText'); - - expect(result).toContain('0.00'); - }); - it('should log in as Production role and go to a target ticket summary', async() => { await page.loginAndModule('production', 'ticket'); await page.accessToSearchResult('13'); diff --git a/e2e/paths/05-ticket/04_packages.spec.js b/e2e/paths/05-ticket/04_packages.spec.js index f874307a8..2b79e9cb6 100644 --- a/e2e/paths/05-ticket/04_packages.spec.js +++ b/e2e/paths/05-ticket/04_packages.spec.js @@ -1,6 +1,13 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + firstPackage: 'vn-autocomplete[label="Package"]', + firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]', + firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', + addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', + savePackagesButton: `button[type=submit]` +}; + describe('Ticket Create packages path', () => { let browser; let page; @@ -18,19 +25,19 @@ describe('Ticket Create packages path', () => { }); it(`should attempt create a new package but receive an error if package is blank`, async() => { - await page.waitToClick(selectors.ticketPackages.firstRemovePackageButton); - await page.waitToClick(selectors.ticketPackages.addPackageButton); - await page.write(selectors.ticketPackages.firstQuantity, '99'); - await page.waitToClick(selectors.ticketPackages.savePackagesButton); + await page.waitToClick($.firstRemovePackageButton); + await page.waitToClick($.addPackageButton); + await page.write($.firstQuantity, '99'); + await page.waitToClick($.savePackagesButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Package cannot be blank'); }); it(`should delete the first package and receive and error to save a new one with blank quantity`, async() => { - await page.clearInput(selectors.ticketPackages.firstQuantity); - await page.autocompleteSearch(selectors.ticketPackages.firstPackage, 'Container medical box 1m'); - await page.waitToClick(selectors.ticketPackages.savePackagesButton); + await page.clearInput($.firstQuantity); + await page.autocompleteSearch($.firstPackage, 'Container medical box 1m'); + await page.waitToClick($.savePackagesButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Some fields are invalid'); @@ -40,15 +47,15 @@ describe('Ticket Create packages path', () => { const result = await page .evaluate(selector => { return document.querySelector(`${selector} input`).checkValidity(); - }, selectors.ticketPackages.firstQuantity); + }, $.firstQuantity); expect(result).toBeTruthy(); }); it(`should create a new package with correct data`, async() => { - await page.clearInput(selectors.ticketPackages.firstQuantity); - await page.write(selectors.ticketPackages.firstQuantity, '-99'); - await page.waitToClick(selectors.ticketPackages.savePackagesButton); + await page.clearInput($.firstQuantity); + await page.write($.firstQuantity, '-99'); + await page.waitToClick($.savePackagesButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved!'); @@ -56,15 +63,15 @@ describe('Ticket Create packages path', () => { it(`should confirm the first select is the expected one`, async() => { await page.reloadSection('ticket.card.package'); - await page.waitForTextInField(selectors.ticketPackages.firstPackage, 'Container medical box 1m'); - const result = await page.waitToGetProperty(selectors.ticketPackages.firstPackage, 'value'); + await page.waitForTextInField($.firstPackage, 'Container medical box 1m'); + const result = await page.waitToGetProperty($.firstPackage, 'value'); - expect(result).toEqual('7 : Container medical box 1m'); + expect(result).toEqual('Container medical box 1m'); }); it(`should confirm quantity is just a number and the string part was ignored by the imput number`, async() => { - await page.waitForTextInField(selectors.ticketPackages.firstQuantity, '-99'); - const result = await page.waitToGetProperty(selectors.ticketPackages.firstQuantity, 'value'); + await page.waitForTextInField($.firstQuantity, '-99'); + const result = await page.waitToGetProperty($.firstQuantity, 'value'); expect(result).toEqual('-99'); }); diff --git a/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js b/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js index a68ce894e..51ead6461 100644 --- a/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js +++ b/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js @@ -1,6 +1,11 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + form: 'vn-ticket-create-card', + moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]', + simpleTicketButton: '.vn-menu [name="simpleTicket"]' +}; + describe('Ticket create from client path', () => { let browser; let page; @@ -16,20 +21,17 @@ describe('Ticket create from client path', () => { await browser.close(); }); - it('should click the create simple ticket on the descriptor menu', async() => { - await page.waitToClick(selectors.clientDescriptor.moreMenu); - await page.waitToClick(selectors.clientDescriptor.simpleTicketButton); + it('should create simple ticket and check if the client details are the expected ones', async() => { + await page.waitToClick($.moreMenu); + await page.waitToClick($.simpleTicketButton); await page.waitForState('ticket.create'); - }); - it('should check if the client details are the expected ones', async() => { - const client = await page - .waitToGetProperty(selectors.createTicketView.client, 'value'); + const values = { + client: 'Petter Parker', + address: 'Petter Parker' + }; + const formValues = await page.fetchForm($.form, Object.keys(values)); - const address = await page - .waitToGetProperty(selectors.createTicketView.address, 'value'); - - expect(client).toContain('Petter Parker'); - expect(address).toContain('20 Ingram Street'); + expect(formValues).toEqual(values); }); }); diff --git a/e2e/paths/05-ticket/18_index_payout.spec.js b/e2e/paths/05-ticket/18_index_payout.spec.js index 220dacf61..7e5201d11 100644 --- a/e2e/paths/05-ticket/18_index_payout.spec.js +++ b/e2e/paths/05-ticket/18_index_payout.spec.js @@ -1,5 +1,10 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + newPayment: '.vn-dialog.shown', + anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr', + firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable' +}; describe('Ticket index payout path', () => { let browser; @@ -8,17 +13,14 @@ describe('Ticket index payout path', () => { beforeAll(async() => { browser = await getBrowser(); page = browser.page; + await page.loginAndModule('administrative', 'ticket'); + await page.waitForState('ticket.index'); }); afterAll(async() => { await browser.close(); }); - it('should navigate to the ticket index', async() => { - await page.loginAndModule('administrative', 'ticket'); - await page.waitForState('ticket.index'); - }); - it('should check the second ticket from a client and 1 of another', async() => { await page.waitToClick(selectors.globalItems.searchButton); await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox); @@ -42,27 +44,27 @@ describe('Ticket index payout path', () => { await page.waitForSelector(selectors.ticketsIndex.payoutCompany); }); - it('should fill the company and bank to perform a payout', async() => { - await page.autocompleteSearch(selectors.ticketsIndex.payoutCompany, 'VNL'); - await page.autocompleteSearch(selectors.ticketsIndex.payoutBank, 'cash'); - await page.write(selectors.clientBalance.newPaymentAmount, '100'); - await page.write(selectors.ticketsIndex.payoutDescription, 'Payment'); - await page.waitToClick(selectors.ticketsIndex.submitPayout); + it('should fill the company and bank to perform a payout and check a new balance line was entered', async() => { + await page.fillForm($.newPayment, { + company: 'VNL', + bank: 'cash', + amountPaid: 100, + description: 'Payment', + viewReceipt: false + }); + await page.respondToDialog('accept'); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should navigate to the client balance section and check a new balance line was entered', async() => { await page.waitToClick(selectors.globalItems.homeButton); await page.selectModule('client'); await page.accessToSearchResult('1101'); await page.accessToSection('client.card.balance.index'); - await page.waitForSelector(selectors.clientBalance.anyBalanceLine); - const count = await page.countElement(selectors.clientBalance.anyBalanceLine); - const reference = await page.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText'); + await page.waitForSelector($.anyBalanceLine); + const count = await page.countElement($.anyBalanceLine); + const reference = await page.innerText($.firstLineReference); + expect(message.isSuccess).toBeTrue(); expect(count).toEqual(4); - expect(reference).toContain('Cash, Albaran: 7, 8Payment'); + expect(reference).toContain('Payment'); }); }); diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 783b0c9b2..82525c1db 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -1,7 +1,8 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Ticket Future path', () => { +// 'https:// redmine.verdnatura.es/issues/5642' +xdescribe('Ticket Future path', () => { let browser; let page; let httpRequest; @@ -44,95 +45,67 @@ describe('Ticket Future path', () => { expect(message.text).toContain('originDated is a required argument'); }); - it('should search with the required data', async() => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); + // it('should search with the required data', async() => { + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // await page.waitToClick(selectors.ticketFuture.submit); - expect(httpRequest).toBeDefined(); - }); + // expect(httpRequest).toBeDefined(); + // }); - it('should search with the origin IPT', async() => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // it('should search with the origin IPT', async() => { + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); - await page.waitToClick(selectors.ticketFuture.submit); + // await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); + // await page.waitToClick(selectors.ticketFuture.submit); - expect(httpRequest).toContain('ipt=H'); - }); + // expect(httpRequest).toContain('ipt=H'); + // }); - it('should search with the destination IPT', async() => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // it('should search with the destination IPT', async() => { + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.ipt); + // await page.clearInput(selectors.ticketFuture.ipt); - await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); - await page.waitToClick(selectors.ticketFuture.submit); + // await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); + // await page.waitToClick(selectors.ticketFuture.submit); - expect(httpRequest).toContain('futureIpt=H'); - }); + // expect(httpRequest).toContain('futureIpt=H'); + // }); - it('should search with the origin grouped state', async() => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // it('should search with the origin grouped state', async() => { + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.futureIpt); + // await page.clearInput(selectors.ticketFuture.futureIpt); - await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); - await page.waitToClick(selectors.ticketFuture.submit); + // await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); + // await page.waitToClick(selectors.ticketFuture.submit); - expect(httpRequest).toContain('state=FREE'); - }); + // expect(httpRequest).toContain('state=FREE'); + // }); - it('should search with the destination grouped state', async() => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // it('should search with the destination grouped state', async() => { + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.state); + // await page.clearInput(selectors.ticketFuture.state); - await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); - await page.waitToClick(selectors.ticketFuture.submit); + // await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); + // await page.waitToClick(selectors.ticketFuture.submit); - expect(httpRequest).toContain('futureState=FREE'); + // expect(httpRequest).toContain('futureState=FREE'); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.futureState); - await page.waitToClick(selectors.ticketFuture.submit); - }); + // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + // await page.clearInput(selectors.ticketFuture.futureState); + // await page.waitToClick(selectors.ticketFuture.submit); + // }); - it('should search in smart-table with an ID Origin', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableId, '1'); - await page.keyboard.press('Enter'); + // it('should check the three last tickets and move to the future', async() => { + // await page.waitForNumberOfElements(selectors.ticketFuture.searchResult, 4); + // await page.waitToClick(selectors.ticketFuture.multiCheck); + // await page.waitToClick(selectors.ticketFuture.firstCheck); + // await page.waitToClick(selectors.ticketFuture.moveButton); + // await page.waitToClick(selectors.globalItems.acceptButton); + // const message = await page.waitForSnackbar(); - expect(httpRequest).toContain('id'); - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - }); - - it('should search in smart-table with an IPT Destination', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'H'); - - expect(httpRequest).toContain('futureIpt'); - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - }); - - it('should search in smart-table with an ID Destination', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableFutureId, '1'); - await page.keyboard.press('Enter'); - - expect(httpRequest).toContain('futureId'); - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - }); - - it('should check the three last tickets and move to the future', async() => { - await page.waitForNumberOfElements(selectors.ticketFuture.searchResult, 4); - await page.waitToClick(selectors.ticketFuture.multiCheck); - await page.waitToClick(selectors.ticketFuture.firstCheck); - await page.waitToClick(selectors.ticketFuture.moveButton); - await page.waitToClick(selectors.globalItems.acceptButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Tickets moved successfully!'); - }); + // expect(message.text).toContain('Tickets moved successfully!'); + // }); }); diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index 15f9dd5bb..f27120b3b 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -1,7 +1,8 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Ticket Advance path', () => { +// 'https:// redmine.verdnatura.es/issues/5642' +xdescribe('Ticket Advance path', () => { let browser; let page; let httpRequest; @@ -45,65 +46,43 @@ describe('Ticket Advance path', () => { expect(message.text).toContain('dateFuture is a required argument'); }); - it('should search with the required data', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); + // it('should search with the required data', async() => { + // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + // await page.waitToClick(selectors.ticketAdvance.submit); - expect(httpRequest).toBeDefined(); - }); + // expect(httpRequest).toBeDefined(); + // }); - it('should search with the origin IPT', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); - await page.waitToClick(selectors.ticketAdvance.submit); + // it('should search with the origin IPT', async() => { + // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + // await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); + // await page.waitToClick(selectors.ticketAdvance.submit); - expect(httpRequest).toContain('futureIpt=H'); + // expect(httpRequest).toContain('futureIpt=H'); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(selectors.ticketAdvance.futureIpt); - await page.waitToClick(selectors.ticketAdvance.submit); - }); + // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + // await page.clearInput(selectors.ticketAdvance.futureIpt); + // await page.waitToClick(selectors.ticketAdvance.submit); + // }); - it('should search with the destination IPT', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); - await page.waitToClick(selectors.ticketAdvance.submit); + // it('should search with the destination IPT', async() => { + // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + // await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); + // await page.waitToClick(selectors.ticketAdvance.submit); - expect(httpRequest).toContain('ipt=H'); + // expect(httpRequest).toContain('ipt=H'); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(selectors.ticketAdvance.ipt); - await page.waitToClick(selectors.ticketAdvance.submit); - }); + // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + // await page.clearInput(selectors.ticketAdvance.ipt); + // await page.waitToClick(selectors.ticketAdvance.submit); + // }); - it('should search in smart-table with an IPT Origin', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'V'); + // it('should check the first ticket and move to the present', async() => { + // await page.waitToClick(selectors.ticketAdvance.firstCheck); + // await page.waitToClick(selectors.ticketAdvance.moveButton); + // await page.waitToClick(selectors.ticketAdvance.acceptButton); + // const message = await page.waitForSnackbar(); - expect(httpRequest).toContain('futureIpt'); - - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); - }); - - it('should search in smart-table with an IPT Destination', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'V'); - - expect(httpRequest).toContain('ipt'); - - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); - }); - - it('should check the first ticket and move to the present', async() => { - await page.waitToClick(selectors.ticketAdvance.firstCheck); - await page.waitToClick(selectors.ticketAdvance.moveButton); - await page.waitToClick(selectors.ticketAdvance.acceptButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Tickets moved successfully!'); - }); + // expect(message.text).toContain('Tickets moved successfully!'); + // }); }); diff --git a/e2e/paths/07-order/01_summary.spec.js b/e2e/paths/07-order/01_summary.spec.js index 922d5eeee..9df481ef6 100644 --- a/e2e/paths/07-order/01_summary.spec.js +++ b/e2e/paths/07-order/01_summary.spec.js @@ -1,6 +1,15 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span', + alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span', + consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span', + subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)', + vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)', + total: 'vn-order-summary vn-one.taxes > p:nth-child(3)', + sale: 'vn-order-summary vn-tbody > vn-tr', +}; + describe('Order summary path', () => { let browser; let page; @@ -15,49 +24,23 @@ describe('Order summary path', () => { await browser.close(); }); - it('should reach the order summary section', async() => { + it('should reach the order summary section and check data', async() => { await page.waitForState('order.card.summary'); - }); - it('should check the summary contains the order id', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.id, 'innerText'); + const id = await page.innerText($.id); + const alias = await page.innerText($.alias); + const consignee = await page.innerText($.consignee); + const subtotal = await page.innerText($.subtotal); + const vat = await page.innerText($.vat); + const total = await page.innerText($.total); + const sale = await page.countElement($.sale); - expect(result).toEqual('16'); - }); - - it('should check the summary contains the order alias', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.alias, 'innerText'); - - expect(result).toEqual('Many places'); - }); - - it('should check the summary contains the order consignee', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.consignee, 'innerText'); - - expect(result).toEqual('address 26 - Gotham (Province one)'); - }); - - it('should check the summary contains the order subtotal', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.subtotal, 'innerText'); - - expect(result.length).toBeGreaterThan(1); - }); - - it('should check the summary contains the order vat', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.vat, 'innerText'); - - expect(result.length).toBeGreaterThan(1); - }); - - it('should check the summary contains the order total', async() => { - const result = await page.waitToGetProperty(selectors.orderSummary.total, 'innerText'); - - expect(result.length).toBeGreaterThan(1); - }); - - it('should check the summary contains the order sales', async() => { - const result = await page.countElement(selectors.orderSummary.sale); - - expect(result).toBeGreaterThan(0); + expect(id).toEqual('16'); + expect(alias).toEqual('Many places'); + expect(consignee).toEqual('address 26 - Gotham (Province one)'); + expect(subtotal.length).toBeGreaterThan(1); + expect(vat.length).toBeGreaterThan(1); + expect(total.length).toBeGreaterThan(1); + expect(sale).toBeGreaterThan(0); }); }); diff --git a/e2e/paths/07-order/02_basic_data.spec.js b/e2e/paths/07-order/02_basic_data.spec.js index 90eaf269e..b2c21b071 100644 --- a/e2e/paths/07-order/02_basic_data.spec.js +++ b/e2e/paths/07-order/02_basic_data.spec.js @@ -1,6 +1,13 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + form: 'vn-order-basic-data form', + observation: 'vn-order-basic-data form [vn-name="note"]', + saveButton: `vn-order-basic-data form button[type=submit]`, + acceptButton: '.vn-confirm.shown button[response="accept"]' +}; + describe('Order edit basic data path', () => { let browser; let page; @@ -20,90 +27,43 @@ describe('Order edit basic data path', () => { describe('when confirmed order', () => { it('should not be able to change the client', async() => { - await page.autocompleteSearch(selectors.orderBasicData.client, 'Tony Stark'); - await page.autocompleteSearch(selectors.orderBasicData.address, 'Tony Stark'); - await page.waitToClick(selectors.orderBasicData.saveButton); - const message = await page.waitForSnackbar(); + const message = await page.sendForm($.form, { + client: 'Tony Stark', + address: 'Tony Stark', + }); - expect(message.text).toContain(`You can't make changes on the basic data of an confirmed order or with rows`); - }); - }); - - describe('when order with rows', () => { - it('should now navigate to order index', async() => { - const orderId = '16'; - - await page.waitToClick(selectors.orderDescriptor.returnToModuleIndexButton); - await page.waitToClick(selectors.globalItems.acceptButton); - await page.waitForContentLoaded(); - await page.accessToSearchResult(orderId); - await page.accessToSection('order.card.basicData'); - await page.waitForSelector(selectors.orderBasicData.observation, {visible: true}); - await page.waitForState('order.card.basicData'); - }); - - it('should not be able to change anything', async() => { - await page.write(selectors.orderBasicData.observation, 'observation'); - await page.waitToClick(selectors.orderBasicData.saveButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain(`You can't make changes on the basic data of an confirmed order or with rows`); + expect(message.text).toContain(`You can't make changes on the basic data`); }); }); describe('when new order', () => { - it('should navigate to the order index and click the new order button', async() => { + it('should create an order and edit its basic data', async() => { await page.waitToClick(selectors.globalItems.returnToModuleIndexButton); - await page.waitToClick(selectors.orderBasicData.acceptButton); + await page.waitToClick($.acceptButton); await page.waitForContentLoaded(); await page.waitToClick(selectors.ordersIndex.createOrderButton); await page.waitForState('order.create'); - }); - it('should now create a new one', async() => { await page.autocompleteSearch(selectors.createOrderView.client, 'Jessica Jones'); await page.pickDate(selectors.createOrderView.landedDatePicker); await page.autocompleteSearch(selectors.createOrderView.agency, 'Other agency'); await page.waitToClick(selectors.createOrderView.createButton); await page.waitForState('order.card.catalog'); - }); - it('should navigate to the basic data section of the new order', async() => { await page.accessToSection('order.card.basicData'); - await page.waitForState('order.card.basicData'); - }); - it('should be able to modify all the properties', async() => { - await page.autocompleteSearch(selectors.orderBasicData.client, 'Tony Stark'); - await page.autocompleteSearch(selectors.orderBasicData.address, 'Tony Stark'); - await page.autocompleteSearch(selectors.orderBasicData.agency, 'Other agency'); - await page.write(selectors.orderBasicData.observation, 'my observation'); - await page.waitToClick(selectors.orderBasicData.saveButton); - const message = await page.waitForSnackbar(); + const values = { + client: 'Tony Stark', + address: 'Tony Stark', + agencyMode: 'Other agency' + }; - expect(message.text).toContain('Data saved!'); - }); - - it('should now confirm the client have been edited', async() => { + const message = await page.sendForm($.form, values); await page.reloadSection('order.card.basicData'); - const result = await page - .waitToGetProperty(selectors.orderBasicData.client, 'value'); + const formValues = await page.fetchForm($.form, Object.keys(values)); - expect(result).toEqual('1104: Tony Stark'); - }); - - it('should now confirm the agency have been edited', async() => { - const result = await page - .waitToGetProperty(selectors.orderBasicData.agency, 'value'); - - expect(result).toEqual('Other agency'); - }); - - it('should now confirm the observations have been edited', async() => { - const result = await page - .waitToGetProperty(selectors.orderBasicData.observation, 'value'); - - expect(result).toEqual('my observation'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); }); }); }); diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index ff8361499..7ab7dda42 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -1,4 +1,3 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Route basic Data path', () => { @@ -17,47 +16,27 @@ describe('Route basic Data path', () => { await browser.close(); }); - it('should edit the route basic data', async() => { + it('should edit the route basic data and confirm the route was edited', async() => { const nextMonth = Date.vnNew(); nextMonth.setMonth(nextMonth.getMonth() + 1); + nextMonth.setUTCHours(0, 0, 0, 0); - await page.autocompleteSearch(selectors.routeBasicData.worker, 'adminBossNick'); - await page.autocompleteSearch(selectors.routeBasicData.vehicle, '1111-IMK'); - await page.pickDate(selectors.routeBasicData.createdDate, nextMonth); - await page.clearInput(selectors.routeBasicData.kmStart); - await page.write(selectors.routeBasicData.kmStart, '1'); - await page.clearInput(selectors.routeBasicData.kmEnd); - await page.write(selectors.routeBasicData.kmEnd, '2'); - await page.type(`${selectors.routeBasicData.startedHour} input`, '0800'); - await page.type(`${selectors.routeBasicData.finishedHour} input`, '1230'); - await page.waitToClick(selectors.routeBasicData.saveButton); - const message = await page.waitForSnackbar(); + const form = 'vn-route-basic-data form'; + const values = { + worker: 'adminBossNick', + vehicle: '1111-IMK', + created: nextMonth, + kmStart: 1, + kmEnd: 2, + started: '08:00', + finished: '12:30', + }; - expect(message.text).toContain('Data saved!'); - }); - - it('should confirm the worker was edited', async() => { + const message = await page.sendForm(form, values); await page.reloadSection('route.card.basicData'); - const worker = await page.waitToGetProperty(selectors.routeBasicData.worker, 'value'); + const formValues = await page.fetchForm(form, Object.keys(values)); - expect(worker).toEqual('adminBoss - adminBossNick'); - }); - - it('should confirm the vehicle was edited', async() => { - const vehicle = await page.waitToGetProperty(selectors.routeBasicData.vehicle, 'value'); - - expect(vehicle).toEqual('1111-IMK'); - }); - - it('should confirm the km start was edited', async() => { - const kmStart = await page.waitToGetProperty(selectors.routeBasicData.kmStart, 'value'); - - expect(kmStart).toEqual('1'); - }); - - it('should confirm the km end was edited', async() => { - const kmEnd = await page.waitToGetProperty(selectors.routeBasicData.kmEnd, 'value'); - - expect(kmEnd).toEqual('2'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); }); }); diff --git a/e2e/paths/08-route/04_tickets.spec.js b/e2e/paths/08-route/04_tickets.spec.js index 950e11d3e..ccd5562c2 100644 --- a/e2e/paths/08-route/04_tickets.spec.js +++ b/e2e/paths/08-route/04_tickets.spec.js @@ -57,11 +57,4 @@ describe('Route tickets path', () => { it('should now count how many tickets are in route to find one less', async() => { await page.waitForNumberOfElements(selectors.routeTickets.anyTicket, 0); }); - - // #2862 updateVolume() route descriptor no actualiza volumen - xit('should confirm the route volume on the descriptor has been updated by the changes made', async() => { - const result = await page.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText'); - - expect(result).toEqual('0 / 50 m³'); - }); }); diff --git a/e2e/paths/09-invoice-in/04_tax.spec.js b/e2e/paths/09-invoice-in/04_tax.spec.js index b1dbe2008..d51c39048 100644 --- a/e2e/paths/09-invoice-in/04_tax.spec.js +++ b/e2e/paths/09-invoice-in/04_tax.spec.js @@ -17,55 +17,36 @@ describe('InvoiceIn tax path', () => { await browser.close(); }); - it('should add a new tax', async() => { + it('should add a new tax and check it', async() => { await page.waitToClick(selectors.invoiceInTax.addTaxButton); await page.autocompleteSearch(selectors.invoiceInTax.thirdExpense, '6210000567'); await page.write(selectors.invoiceInTax.thirdTaxableBase, '100'); - await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, '6'); + await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, 'H.P. IVA'); await page.autocompleteSearch(selectors.invoiceInTax.thirdTransactionType, 'Operaciones exentas'); await page.waitToClick(selectors.invoiceInTax.saveButton); const message = await page.waitForSnackbar(); - expect(message.text).toContain('Data saved!'); - }); - - it('should navigate to the summary and check the taxable base sum is correct', async() => { await page.waitToClick(selectors.invoiceInDescriptor.summaryIcon); await page.waitForState('invoiceIn.card.summary'); - const result = await page.waitToGetProperty(selectors.invoiceInSummary.totalTaxableBase, 'innerText'); + const total = await page.waitToGetProperty(selectors.invoiceInSummary.totalTaxableBase, 'innerText'); - expect(result).toEqual('Taxable base €1,323.16'); - }); - - it('should navigate back to tax section, check the reciently added line contains the expected expense', async() => { await page.accessToSection('invoiceIn.card.tax'); - const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value'); - expect(result).toEqual('6210000567: Alquiler VNH'); - }); + const thirdExpense = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value'); + const thirdTaxableBase = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxableBase, 'value'); + const thirdTaxType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxType, 'value'); + const thirdTransactionType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTransactionType, 'value'); + const thirdRate = await page.waitToGetProperty(selectors.invoiceInTax.thirdRate, 'value'); - it('should check the reciently added line contains the expected taxable base', async() => { - const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxableBase, 'value'); + expect(message.text).toContain('Data saved!'); - expect(result).toEqual('100'); - }); + expect(total).toEqual('Taxable base €1,323.16'); - it('should check the reciently added line contains the expected tax type', async() => { - const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxType, 'value'); - - expect(result).toEqual('6: H.P. IVA 4% CEE'); - }); - - it('should check the reciently added line contains the expected transaction type', async() => { - const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdTransactionType, 'value'); - - expect(result).toEqual('37: Operaciones exentas'); - }); - - it('should check the reciently added line contains the expected rate', async() => { - const result = await page.waitToGetProperty(selectors.invoiceInTax.thirdRate, 'value'); - - expect(result).toEqual('€4.00'); + expect(thirdExpense).toEqual('6210000567'); + expect(thirdTaxableBase).toEqual('100'); + expect(thirdTaxType).toEqual('H.P. IVA 4% CEE'); + expect(thirdTransactionType).toEqual('Operaciones exentas'); + expect(thirdRate).toEqual('€4.00'); }); it('should delete the added line', async() => { diff --git a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js index abb9ca7e7..dfaa55ef9 100644 --- a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js +++ b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js @@ -15,49 +15,39 @@ describe('InvoiceOut manual invoice path', () => { await browser.close(); }); - it('should open the manual invoice form', async() => { + it('should create an invoice from a ticket', async() => { await page.waitToClick(selectors.invoiceOutIndex.createInvoice); await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm); - }); - it('should create an invoice from a ticket', async() => { await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTicket, '15'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceSerial, 'Global nacional'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTaxArea, 'national'); await page.waitToClick(selectors.invoiceOutIndex.saveInvoice); const message = await page.waitForSnackbar(); + await page.waitForState('invoiceOut.card.summary'); + expect(message.text).toContain('Data saved!'); }); - it(`should have been redirected to the created invoice summary`, async() => { - await page.waitForState('invoiceOut.card.summary'); - }); - - it(`should navigate back to the invoiceOut index`, async() => { + it(`should create another invoice from a client`, async() => { await page.waitToClick(selectors.globalItems.applicationsMenuButton); await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); await page.waitToClick(selectors.globalItems.invoiceOutButton); await page.waitForSelector(selectors.invoiceOutIndex.topbarSearch); await page.waitForState('invoiceOut.index'); - }); - it('should now open the manual invoice form', async() => { await page.waitToClick(selectors.invoiceOutIndex.createInvoice); await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm); - }); - it('should create an invoice from a client', async() => { await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceClient, 'Max Eisenhardt'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceSerial, 'Global nacional'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTaxArea, 'national'); await page.waitToClick(selectors.invoiceOutIndex.saveInvoice); const message = await page.waitForSnackbar(); + await page.waitForState('invoiceOut.card.summary'); + expect(message.text).toContain('Data saved!'); }); - - it(`should have been redirected to the created invoice summary`, async() => { - await page.waitForState('invoiceOut.card.summary'); - }); }); diff --git a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js index 23aa3593c..64cddfa25 100644 --- a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js +++ b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js @@ -18,7 +18,6 @@ describe('InvoiceOut global invoice path', () => { }); let invoicesBeforeOneClient; - let invoicesBeforeAllClients; let now = Date.vnNew(); it('should count the amount of invoices listed before globla invoces are made', async() => { @@ -27,13 +26,10 @@ describe('InvoiceOut global invoice path', () => { expect(invoicesBeforeOneClient).toBeGreaterThanOrEqual(4); }); - it('should open the global invoice form', async() => { - await page.accessToSection('invoiceOut.global-invoicing'); - }); - it('should create a global invoice for charles xavier today', async() => { + await page.accessToSection('invoiceOut.global-invoicing'); await page.waitToClick(selectors.invoiceOutGlobalInvoicing.oneClient); - await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.clientId, '1108'); + await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.clientId, 'Charles Xavier'); await page.pickDate(selectors.invoiceOutGlobalInvoicing.invoiceDate, now); await page.pickDate(selectors.invoiceOutGlobalInvoicing.maxShipped, now); await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.printer, '1'); diff --git a/e2e/paths/10-travel/01_create.spec.js b/e2e/paths/10-travel/01_create.spec.js index 15da42d5d..98ade4852 100644 --- a/e2e/paths/10-travel/01_create.spec.js +++ b/e2e/paths/10-travel/01_create.spec.js @@ -4,9 +4,6 @@ import getBrowser from '../../helpers/puppeteer'; describe('Travel create path', () => { let browser; let page; - const date = Date.vnNew(); - const day = 15; - date.setDate(day); beforeAll(async() => { browser = await getBrowser(); @@ -18,60 +15,28 @@ describe('Travel create path', () => { await browser.close(); }); - it('should open the create travel form by clicking on the "new" button', async() => { + it('should create a new travel and check it was created with the correct data', async() => { + const date = Date.vnNew(); + date.setDate(15); + date.setUTCHours(0, 0, 0, 0); + await page.waitToClick(selectors.travelIndex.newTravelButton); await page.waitForState('travel.create'); - }); - it('should fill the reference, agency and ship date then save the form', async() => { - await page.write(selectors.travelIndex.reference, 'Testing reference'); - await page.autocompleteSearch(selectors.travelIndex.agency, 'inhouse pickup'); - await page.pickDate(selectors.travelIndex.shipDate, date); // this line autocompletes another 3 fields - await page.waitForTimeout(1000); - await page.waitToClick(selectors.travelIndex.save); + const values = { + reference: 'Testing reference', + agencyMode: 'inhouse pickup', + shipped: date, + landed: date, + warehouseOut: 'Warehouse One', + warehouseIn: 'Warehouse Five' + }; - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - - it('should check the user was redirected to the travel basic data upon creation', async() => { + const message = await page.sendForm('vn-travel-create form', values); await page.waitForState('travel.card.basicData'); - }); + const formValues = await page.fetchForm('vn-travel-basic-data form', Object.keys(values)); - it('should check the travel was created with the correct reference', async() => { - const reference = await page.waitToGetProperty(selectors.travelBasicData.reference, 'value'); - - expect(reference).toContain('Testing reference'); - }); - - it('should check the travel was created with the correct agency', async() => { - const agency = await page.waitToGetProperty(selectors.travelBasicData.agency, 'value'); - - expect(agency).toContain('inhouse pickup'); - }); - - it('should check the travel was created with the correct shiping date', async() => { - const shipDate = await page.waitToGetProperty(selectors.travelBasicData.shippedDate, 'value'); - - expect(shipDate).toContain(day); - }); - - it('should check the travel was created with the correct landing date', async() => { - const landingDate = await page.waitToGetProperty(selectors.travelBasicData.deliveryDate, 'value'); - - expect(landingDate).toContain(day); - }); - - it('should check the travel was created with the correct warehouseOut', async() => { - const warehouseOut = await page.waitToGetProperty(selectors.travelBasicData.outputWarehouse, 'value'); - - expect(warehouseOut).toContain('Warehouse One'); - }); - - it('should check the travel was created with the correct warehouseIn', async() => { - const warehouseIn = await page.waitToGetProperty(selectors.travelBasicData.inputWarehouse, 'value'); - - expect(warehouseIn).toContain('Warehouse Five'); + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); }); }); diff --git a/e2e/paths/12-entry/03_latestBuys.spec.js b/e2e/paths/12-entry/03_latestBuys.spec.js index a73e12659..9ec072912 100644 --- a/e2e/paths/12-entry/03_latestBuys.spec.js +++ b/e2e/paths/12-entry/03_latestBuys.spec.js @@ -42,20 +42,6 @@ describe('Entry lastest buys path', () => { expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined(); }); - it('should filter by from date', async() => { - await page.pickDate(selectors.entryLatestBuys.fromInput, new Date()); - await page.waitToClick(selectors.entryLatestBuys.chip); - - expect(httpRequests.find(req => req.includes(('from')))).toBeDefined(); - }); - - it('should filter by to date', async() => { - await page.pickDate(selectors.entryLatestBuys.toInput, new Date()); - await page.waitToClick(selectors.entryLatestBuys.chip); - - expect(httpRequests.find(req => req.includes(('to')))).toBeDefined(); - }); - it('should filter by sales person', async() => { await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick'); await page.waitToClick(selectors.entryLatestBuys.chip); diff --git a/e2e/paths/12-entry/04_create.spec.js b/e2e/paths/12-entry/04_create.spec.js index 20fa6b23d..537637671 100644 --- a/e2e/paths/12-entry/04_create.spec.js +++ b/e2e/paths/12-entry/04_create.spec.js @@ -21,8 +21,8 @@ describe('Entry create path', () => { }); it('should fill the form to create a valid entry then redirect to basic Data', async() => { - await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, '2'); - await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse Three'); + await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, 'The farmer'); + await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse'); await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN'); await page.waitToClick(selectors.entryIndex.saveNewEntry); diff --git a/e2e/paths/12-entry/05_basicData.spec.js b/e2e/paths/12-entry/05_basicData.spec.js index 0272446d9..15282820e 100644 --- a/e2e/paths/12-entry/05_basicData.spec.js +++ b/e2e/paths/12-entry/05_basicData.spec.js @@ -1,6 +1,22 @@ -import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; +const $ = { + reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]', + invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]', + notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]', + observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]', + supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]', + currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]', + commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]', + company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]', + ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]', + confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]', + inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]', + raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]', + booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]', + save: 'vn-entry-basic-data button[type=submit]', +}; + describe('Entry basic data path', () => { let browser; let page; @@ -17,98 +33,49 @@ describe('Entry basic data path', () => { await browser.close(); }); - it('should edit the basic data', async() => { - await page.write(selectors.entryBasicData.reference, 'new movement 8'); - await page.write(selectors.entryBasicData.invoiceNumber, 'new movement 8'); - await page.write(selectors.entryBasicData.observations, ' edited'); - await page.autocompleteSearch(selectors.entryBasicData.supplier, 'Plants nick'); - await page.autocompleteSearch(selectors.entryBasicData.currency, 'eur'); - await page.clearInput(selectors.entryBasicData.commission); - await page.write(selectors.entryBasicData.commission, '100'); - await page.autocompleteSearch(selectors.entryBasicData.company, 'CCs'); - await page.waitToClick(selectors.entryBasicData.ordered); - await page.waitToClick(selectors.entryBasicData.confirmed); - await page.waitToClick(selectors.entryBasicData.inventory); - await page.waitToClick(selectors.entryBasicData.raid); - await page.waitToClick(selectors.entryBasicData.booked); - await page.waitToClick(selectors.entryBasicData.save); - + it('should edit the basic data and confirm the reference was edited', async() => { + await page.write($.reference, 'new movement 8'); + await page.write($.invoiceNumber, 'new movement 8'); + await page.write($.observations, ' edited'); + await page.autocompleteSearch($.supplier, 'Plants nick'); + await page.autocompleteSearch($.currency, 'eur'); + await page.clearInput($.commission); + await page.write($.commission, '100'); + await page.autocompleteSearch($.company, 'CCs'); + await page.waitToClick($.ordered); + await page.waitToClick($.confirmed); + await page.waitToClick($.inventory); + await page.waitToClick($.raid); + await page.waitToClick($.booked); + await page.waitToClick($.save); const message = await page.waitForSnackbar(); + await page.reloadSection('entry.card.basicData'); + const reference = await page.waitToGetProperty($.reference, 'value'); + const supplier = await page.waitToGetProperty($.supplier, 'value'); + const invoiceNumber = await page.waitToGetProperty($.invoiceNumber, 'value'); + const observations = await page.waitToGetProperty($.observations, 'value'); + const currency = await page.waitToGetProperty($.currency, 'value'); + const commission = await page.waitToGetProperty($.commission, 'value'); + const company = await page.waitToGetProperty($.company, 'value'); + const ordered = await page.checkboxState($.ordered); + const confirmed = await page.checkboxState($.confirmed); + const inventory = await page.checkboxState($.inventory); + const raid = await page.checkboxState($.raid); + const booked = await page.checkboxState($.booked); + expect(message.text).toContain('Data saved!'); - }); - - it('should confirm the reference was edited', async() => { - await page.reloadSection('entry.card.basicData'); - const result = await page.waitToGetProperty(selectors.entryBasicData.reference, 'value'); - - expect(result).toEqual('new movement 8'); - }); - - it('should confirm the invoiceNumber was edited', async() => { - await page.reloadSection('entry.card.basicData'); - const result = await page.waitToGetProperty(selectors.entryBasicData.invoiceNumber, 'value'); - - expect(result).toEqual('new movement 8'); - }); - - it('should confirm the observation was edited', async() => { - const result = await page.waitToGetProperty(selectors.entryBasicData.observations, 'value'); - - expect(result).toEqual('observation two edited'); - }); - - it('should confirm the supplier was edited', async() => { - const result = await page.waitToGetProperty(selectors.entryBasicData.supplier, 'value'); - - expect(result).toEqual('1 - Plants nick'); - }); - - it('should confirm the currency was edited', async() => { - const result = await page.waitToGetProperty(selectors.entryBasicData.currency, 'value'); - - expect(result).toEqual('EUR'); - }); - - it('should confirm the commission was edited', async() => { - const result = await page.waitToGetProperty(selectors.entryBasicData.commission, 'value'); - - expect(result).toEqual('100'); - }); - - it('should confirm the company was edited', async() => { - const result = await page.waitToGetProperty(selectors.entryBasicData.company, 'value'); - - expect(result).toEqual('CCs'); - }); - - it('should confirm ordered was edited', async() => { - const result = await page.checkboxState(selectors.entryBasicData.ordered); - - expect(result).toBe('checked'); - }); - - it('should confirm confirmed was edited', async() => { - const result = await page.checkboxState(selectors.entryBasicData.confirmed); - - expect(result).toBe('checked'); - }); - - it('should confirm inventory was edited', async() => { - const result = await page.checkboxState(selectors.entryBasicData.inventory); - - expect(result).toBe('checked'); - }); - - it('should confirm raid was edited', async() => { - const result = await page.checkboxState(selectors.entryBasicData.raid); - - expect(result).toBe('checked'); - }); - - it('should confirm booked was edited', async() => { - const result = await page.checkboxState(selectors.entryBasicData.booked); - - expect(result).toBe('checked'); + expect(reference).toEqual('new movement 8'); + expect(supplier).toEqual('Plants nick'); + expect(invoiceNumber).toEqual('new movement 8'); + expect(observations).toEqual('observation two edited'); + expect(currency).toEqual('EUR'); + expect(commission).toEqual('100'); + expect(company).toEqual('CCs'); + expect(ordered).toBe('checked'); + expect(confirmed).toBe('checked'); + expect(inventory).toBe('checked'); + expect(raid).toBe('checked'); + expect(booked).toBe('checked'); }); }); diff --git a/e2e/paths/12-entry/07_buys.spec.js b/e2e/paths/12-entry/07_buys.spec.js index 4487394df..e501452bc 100644 --- a/e2e/paths/12-entry/07_buys.spec.js +++ b/e2e/paths/12-entry/07_buys.spec.js @@ -86,40 +86,47 @@ describe('Entry import, create and edit buys path', () => { await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 2); }); - it('should edit the newest buy', async() => { + it('should edit the newest buy and check data', async() => { await page.clearInput(selectors.entryBuys.secondBuyPackingPrice); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyPackingPrice, '100'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyGroupingPrice); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyGroupingPrice, '200'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyPrice); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyPrice, '300'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyGrouping); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyGrouping, '400'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyPacking); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyPacking, '500'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyWeight); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyWeight, '600'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.clearInput(selectors.entryBuys.secondBuyStickers); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyStickers, '700'); + await page.keyboard.press('Enter'); await page.waitForSnackbar(); await page.autocompleteSearch(selectors.entryBuys.secondBuyPackage, '94'); @@ -128,60 +135,28 @@ describe('Entry import, create and edit buys path', () => { await page.clearInput(selectors.entryBuys.secondBuyQuantity); await page.waitForTimeout(250); await page.write(selectors.entryBuys.secondBuyQuantity, '800'); - }); + await page.keyboard.press('Enter'); - it('should reload the section and check the packing price is as expected', async() => { await page.reloadSection('entry.card.buy.index'); - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyPackingPrice, 'value'); - expect(result).toEqual('100'); - }); + const secondBuyPackingPrice = await page.getValue(selectors.entryBuys.secondBuyPackingPrice); + const secondBuyGroupingPrice = await page.getValue(selectors.entryBuys.secondBuyGroupingPrice); + const secondBuyPrice = await page.getValue(selectors.entryBuys.secondBuyPrice); + const secondBuyGrouping = await page.getValue(selectors.entryBuys.secondBuyGrouping); + const secondBuyPacking = await page.getValue(selectors.entryBuys.secondBuyPacking); + const secondBuyWeight = await page.getValue(selectors.entryBuys.secondBuyWeight); + const secondBuyStickers = await page.getValue(selectors.entryBuys.secondBuyStickers); + const secondBuyPackage = await page.getValue(selectors.entryBuys.secondBuyPackage); + const secondBuyQuantity = await page.getValue(selectors.entryBuys.secondBuyQuantity); - it('should reload the section and check the grouping price is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyGroupingPrice, 'value'); - - expect(result).toEqual('200'); - }); - - it('should reload the section and check the price is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyPrice, 'value'); - - expect(result).toEqual('300'); - }); - - it('should reload the section and check the grouping is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyGrouping, 'value'); - - expect(result).toEqual('400'); - }); - - it('should reload the section and check the packing is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyPacking, 'value'); - - expect(result).toEqual('500'); - }); - - it('should reload the section and check the weight is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyWeight, 'value'); - - expect(result).toEqual('600'); - }); - - it('should reload the section and check the stickers are as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyStickers, 'value'); - - expect(result).toEqual('700'); - }); - - it('should reload the section and check the package is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyPackage, 'value'); - - expect(result).toEqual('94'); - }); - - it('should reload the section and check the quantity is as expected', async() => { - const result = await page.waitToGetProperty(selectors.entryBuys.secondBuyQuantity, 'value'); - - expect(result).toEqual('800'); + expect(secondBuyPackingPrice).toEqual('100'); + expect(secondBuyGroupingPrice).toEqual('200'); + expect(secondBuyPrice).toEqual('300'); + expect(secondBuyGrouping).toEqual('400'); + expect(secondBuyPacking).toEqual('500'); + expect(secondBuyWeight).toEqual('600'); + expect(secondBuyStickers).toEqual('700'); + expect(secondBuyPackage).toEqual('94'); + expect(secondBuyQuantity).toEqual('800'); }); }); diff --git a/e2e/paths/13-supplier/03_fiscal_data.spec.js b/e2e/paths/13-supplier/03_fiscal_data.spec.js index 170a8d05a..80c6c79b2 100644 --- a/e2e/paths/13-supplier/03_fiscal_data.spec.js +++ b/e2e/paths/13-supplier/03_fiscal_data.spec.js @@ -1,20 +1,5 @@ import getBrowser from '../../helpers/puppeteer'; -const $ = { - saveButton: 'vn-supplier-fiscal-data button[type="submit"]', -}; -const $inputs = { - province: 'vn-supplier-fiscal-data [name="province"]', - country: 'vn-supplier-fiscal-data [name="country"]', - postcode: 'vn-supplier-fiscal-data [name="postcode"]', - city: 'vn-supplier-fiscal-data [name="city"]', - socialName: 'vn-supplier-fiscal-data [name="socialName"]', - taxNumber: 'vn-supplier-fiscal-data [name="taxNumber"]', - account: 'vn-supplier-fiscal-data [name="account"]', - sageWithholding: 'vn-supplier-fiscal-data [ng-model="$ctrl.supplier.sageWithholdingFk"]', - sageTaxType: 'vn-supplier-fiscal-data [ng-model="$ctrl.supplier.sageTaxTypeFk"]' -}; - describe('Supplier fiscal data path', () => { let browser; let page; @@ -32,28 +17,32 @@ describe('Supplier fiscal data path', () => { it('should attempt to edit the fiscal data and check data is saved', async() => { await page.accessToSection('supplier.card.fiscalData'); - await page.clearInput($inputs.province); - await page.clearInput($inputs.country); - await page.clearInput($inputs.postcode); - await page.overwrite($inputs.city, 'Valencia'); - await page.overwrite($inputs.socialName, 'Farmer King SL'); - await page.overwrite($inputs.taxNumber, 'Wrong tax number'); - await page.overwrite($inputs.account, '0123456789'); - await page.autocompleteSearch($inputs.sageWithholding, 'retencion estimacion objetiva'); - await page.autocompleteSearch($inputs.sageTaxType, 'operaciones no sujetas'); - await page.click($.saveButton); - const errorMessage = await page.waitForSnackbar(); - await page.overwrite($inputs.taxNumber, '12345678Z'); - await page.click($.saveButton); - const successMessage = await page.waitForSnackbar(); + + const form = 'vn-supplier-fiscal-data form'; + const values = { + province: null, + country: null, + postcode: null, + city: 'Valencia', + socialName: 'Farmer King SL', + taxNumber: 'Wrong tax number', + account: '0123456789', + sageWithholding: 'retencion estimacion objetiva', + sageTaxType: 'operaciones no sujetas' + }; + + const errorMessage = await page.sendForm(form, values); + const message = await page.sendForm(form, { + taxNumber: '12345678Z' + }); await page.reloadSection('supplier.card.fiscalData'); - const values = await page.getValues($inputs); + const formValues = await page.fetchForm(form, Object.keys(values)); expect(errorMessage.text).toContain('Invalid Tax number'); - expect(successMessage.type).toBe('success'); - expect(values).toEqual({ - province: 'Province one (España)', + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual({ + province: 'Province one', country: 'España', postcode: '46000', city: 'Valencia', diff --git a/front/core/components/data-viewer/index.js b/front/core/components/data-viewer/index.js index 8d0d94402..b480997da 100644 --- a/front/core/components/data-viewer/index.js +++ b/front/core/components/data-viewer/index.js @@ -7,11 +7,10 @@ export default class DataViewer { } get status() { - if (this.model) - return this.model.status; - if (this.isLoading) return 'loading'; + if (this.model) + return this.model.status; if (!this.data) return 'clear'; if (this.data.length) diff --git a/front/core/components/field/index.js b/front/core/components/field/index.js index e89a042a5..7ce840555 100644 --- a/front/core/components/field/index.js +++ b/front/core/components/field/index.js @@ -20,7 +20,7 @@ export default class Field extends FormInput { super.$onInit(); if (this.info) this.classList.add('has-icons'); - this.input.addEventListener('change', event => + this.element.addEventListener('change', event => this.onChange(event)); } diff --git a/front/core/components/popover/index.spec.js b/front/core/components/popover/index.spec.js index dc6e3b23f..4590a8e24 100644 --- a/front/core/components/popover/index.spec.js +++ b/front/core/components/popover/index.spec.js @@ -36,30 +36,6 @@ describe('Component vnPopover', () => { expect(controller.emit).not.toHaveBeenCalledWith('open'); }); - - // #1615 migrar karma a jest (this doesn't work anymore, needs fixing) - xit(`should check that popover is visible into the screen`, () => { - $parent.css({ - backgroundColor: 'red', - position: 'absolute', - width: '50px', - height: '50px', - top: '0', - left: '100px' - }); - controller.show($parent[0]); - - let rect = controller.popover.getBoundingClientRect(); - let style = controller.window.getComputedStyle(controller.element); - - expect(style.visibility).toEqual('visible'); - expect(style.display).not.toEqual('none'); - - expect(0).toBeLessThanOrEqual(rect.top); - expect(0).toBeLessThanOrEqual(rect.left); - expect(controller.window.innerHeight).toBeGreaterThan(rect.bottom); - expect(controller.window.innerWidth).toBeGreaterThan(rect.right); - }); }); describe('hide()', () => { diff --git a/front/core/components/th/index.js b/front/core/components/th/index.js index 341558fb1..9f1e11903 100644 --- a/front/core/components/th/index.js +++ b/front/core/components/th/index.js @@ -8,18 +8,8 @@ export default class Th { $element.on('click', () => this.onToggleOrder()); } - /** - * Changes the order if the cell has a field and defaultOrder property - */ $onInit() { if (!this.field) return; - - if (this.defaultOrder) { - this.order = this.defaultOrder; - this.table.applyOrder(this.field, this.order); - this.updateArrow(); - } - this.updateArrow(); } @@ -82,9 +72,6 @@ ngModule.vnComponent('vnTh', { template: require('./index.html'), transclude: true, controller: Th, - bindings: { - defaultOrder: '@?' - }, require: { table: '^^vnTable' } diff --git a/front/core/components/th/index.spec.js b/front/core/components/th/index.spec.js index a00f73cc9..a3bf19898 100644 --- a/front/core/components/th/index.spec.js +++ b/front/core/components/th/index.spec.js @@ -17,17 +17,6 @@ describe('Component vnTh', () => { controller.column.setAttribute('field', 'MyField'); })); - describe('onInit()', () => { - it(`should define controllers order as per defaultOrder then call setOrder()`, () => { - controller.defaultOrder = 'DESC'; - jest.spyOn(controller.table, 'setOrder'); - controller.$onInit(); - - expect(controller.order).toEqual('DESC'); - expect(controller.table.setOrder).toHaveBeenCalledWith('MyField', 'DESC'); - }); - }); - describe('toggleOrder()', () => { it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => { controller.order = 'ASC'; @@ -61,7 +50,7 @@ describe('Component vnTh', () => { expect(controller.updateArrow).not.toHaveBeenCalledWith(); }); - it(`should call toggleOrder() method if field property and + it(`should call toggleOrder() method if field property and table field property equals and then call updateArrow()`, () => { controller.table.field = 'MyField'; jest.spyOn(controller, 'toggleOrder'); @@ -73,7 +62,7 @@ describe('Component vnTh', () => { expect(controller.updateArrow).toHaveBeenCalledWith(); }); - it(`should call setOrder() method if field property and + it(`should call setOrder() method if field property and table field property doesn't equals and then call updateArrow()`, () => { controller.table.field = 'MyField2'; jest.spyOn(controller.table, 'setOrder'); diff --git a/front/salix/components/log/index.html b/front/salix/components/log/index.html index b7697a1fd..c6b1ade2a 100644 --- a/front/salix/components/log/index.html +++ b/front/salix/components/log/index.html @@ -14,9 +14,12 @@ order="changedModel" auto-load="true"> - +
-
+
+ title="{{::log.creationDate | date:'dd/MM/yyyy HH:mm:ss'}}"> {{::$ctrl.relativeDate(log.creationDate)}}
diff --git a/front/salix/components/log/index.js b/front/salix/components/log/index.js index ba7c5bc55..803eea45e 100644 --- a/front/salix/components/log/index.js +++ b/front/salix/components/log/index.js @@ -160,6 +160,9 @@ export default class Controller extends Section { const to = new Date(value); to.setHours(23, 59, 59, 999); return {creationDate: {lte: to}}; + case 'userFk': + return filter.who != 'system' + ? {[prop]: value} : null; default: return {[prop]: value}; } diff --git a/front/salix/components/log/style.scss b/front/salix/components/log/style.scss index b78dc3824..381b99039 100644 --- a/front/salix/components/log/style.scss +++ b/front/salix/components/log/style.scss @@ -4,7 +4,7 @@ vn-log { .change { display: flex; - & > .user-wrapper { + & > .left { position: relative; padding-right: 10px; @@ -34,7 +34,7 @@ vn-log { bottom: -8px; } } - &:last-child > .user-wrapper > .line { + &:last-child > .left > .line { display: none; } .detail { diff --git a/loopback/locale/en.json b/loopback/locale/en.json index a9ac8aeaa..9a2b486f2 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -171,5 +171,6 @@ "Added observation": "Added observation", "Comment added to client": "Comment added to client", "This ticket is already a refund": "This ticket is already a refund", + "A claim with that sale already exists": "A claim with that sale already exists", "Pass expired": "The password has expired, change it from Salix" } diff --git a/modules/client/back/methods/client/summary.js b/modules/client/back/methods/client/summary.js index caa3d8033..7dab1f68b 100644 --- a/modules/client/back/methods/client/summary.js +++ b/modules/client/back/methods/client/summary.js @@ -27,7 +27,6 @@ module.exports = Self => { Object.assign(myOptions, options); const summaryObj = await getSummary(models.Client, clientFk, myOptions); - summaryObj.mana = await models.Client.getMana(clientFk, myOptions); summaryObj.debt = await models.Client.getDebt(clientFk, myOptions); summaryObj.averageInvoiced = await models.Client.getAverageInvoiced(clientFk, myOptions); @@ -115,6 +114,12 @@ module.exports = Self => { fields: ['claimingRate', 'priceIncreasing'], limit: 1 } + }, + { + relation: 'businessType', + scope: { + fields: ['description'] + } } ], where: {id: clientId} diff --git a/modules/client/front/balance/create/index.html b/modules/client/front/balance/create/index.html index 524b2b2ef..27b182c9a 100644 --- a/modules/client/front/balance/create/index.html +++ b/modules/client/front/balance/create/index.html @@ -13,6 +13,7 @@ @@ -33,6 +35,7 @@ fields="['accountingTypeFk']" include="{relation: 'accountingType'}" ng-model="$ctrl.bankFk" + vn-name="bank" search-function="$ctrl.bankSearchFunc($search)" selection="$ctrl.bankSelection" order="id" @@ -43,6 +46,7 @@ vn-focus label="Amount" ng-model="$ctrl.amountPaid" + vn-name="amountPaid" step="0.01" required="true" max="$ctrl.maxAmount"> @@ -52,6 +56,7 @@
Compensation
@@ -60,6 +65,7 @@ @@ -70,23 +76,27 @@ + step="0.01" + vn-name="deliveredAmount"> + label="Amount to return" + vn-name="amountToReturn"> + ng-model="$ctrl.viewReceipt" + vn-name="viewReceipt"> + ng-model="$ctrl.sendEmail" + vn-name="sendEmail"> diff --git a/modules/client/front/billing-data/index.html b/modules/client/front/billing-data/index.html index 410681930..bd4f86d1c 100644 --- a/modules/client/front/billing-data/index.html +++ b/modules/client/front/billing-data/index.html @@ -14,7 +14,6 @@ - {{bic}} {{name}} + +
{{::bic}}
+
{{::name}}
+
@@ -100,9 +96,7 @@ - - - \ No newline at end of file + diff --git a/modules/client/front/fiscal-data/index.html b/modules/client/front/fiscal-data/index.html index 4b1219f31..d232d6dab 100644 --- a/modules/client/front/fiscal-data/index.html +++ b/modules/client/front/fiscal-data/index.html @@ -1,52 +1,111 @@ - + - + - + - +
- + - + - + - + - + vn-acl="salesAssistant" + order="transaction" + rule> {{id}}: {{transaction}} - + {{code}} - {{town.name}} ({{town.province.name}}, {{town.province.country.country}}) - + - + {{name}}, {{province.name}} ({{province.country.country}}) @@ -54,48 +113,83 @@ - + {{name}} ({{country.country}}) - + - + - + - + - + - + - + - - + - - @@ -103,17 +197,26 @@ - - + - - - - \ No newline at end of file + + diff --git a/modules/client/front/greuge/index/index.html b/modules/client/front/greuge/index/index.html index 459d92fc7..014246b31 100644 --- a/modules/client/front/greuge/index/index.html +++ b/modules/client/front/greuge/index/index.html @@ -7,8 +7,8 @@ data="greuges" auto-load="true">
-
@@ -28,7 +28,7 @@ - Date + Date Created by Comment Type @@ -53,11 +53,11 @@ - \ No newline at end of file + diff --git a/modules/client/front/greuge/index/index.js b/modules/client/front/greuge/index/index.js index 7a5ccc531..4f1b77b4b 100644 --- a/modules/client/front/greuge/index/index.js +++ b/modules/client/front/greuge/index/index.js @@ -11,8 +11,7 @@ class Controller extends Section { scope: { fields: ['id', 'name'] }, - }, - { + }, { relation: 'user', scope: { fields: ['id', 'name'] @@ -24,8 +23,6 @@ class Controller extends Section { } } -Controller.$inject = ['$element', '$scope']; - ngModule.vnComponent('vnClientGreugeIndex', { template: require('./index.html'), controller: Controller diff --git a/modules/client/front/summary/index.html b/modules/client/front/summary/index.html index 1b58d42cc..a0d4b918a 100644 --- a/modules/client/front/summary/index.html +++ b/modules/client/front/summary/index.html @@ -64,6 +64,9 @@ + +

diff --git a/modules/client/front/summary/locale/es.yml b/modules/client/front/summary/locale/es.yml index ca6e96fef..c1fde0c17 100644 --- a/modules/client/front/summary/locale/es.yml +++ b/modules/client/front/summary/locale/es.yml @@ -23,3 +23,4 @@ Latest tickets: Últimos tickets Rating: Clasificación Value from 1 to 20. The higher the better value: Valor del 1 al 20. Cuanto más alto mejor valoración Go to grafana: Ir a grafana +Business type: Tipo de negocio \ No newline at end of file diff --git a/modules/entry/front/basic-data/index.html b/modules/entry/front/basic-data/index.html index 4e4631a3c..0b3537fac 100644 --- a/modules/entry/front/basic-data/index.html +++ b/modules/entry/front/basic-data/index.html @@ -8,7 +8,7 @@
- - {{::id}} - {{::nickname}} +
#{{::nickname}}
+
#{{::id}}
- {{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) → - {{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}}) +
+ {{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) → + {{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}}) +
+
#{{::id}}
@@ -159,11 +164,11 @@ value-field="id"> @@ -174,7 +179,7 @@ - \ No newline at end of file + diff --git a/modules/entry/front/buy/index/index.html b/modules/entry/front/buy/index/index.html index de784198c..e6d1a0b76 100644 --- a/modules/entry/front/buy/index/index.html +++ b/modules/entry/front/buy/index/index.html @@ -16,7 +16,7 @@
- - @@ -66,14 +66,15 @@ vn-focus url="Items/withName" ng-model="buy.itemFk" - show-field="name" + show-field="id" value-field="id" search-function="$ctrl.itemSearchFunc($search)" on-change="$ctrl.saveBuy(buy)" order="id DESC" tabindex="1"> - {{::id}} - {{::name}} +
{{::name}}
+
#{{::id}}
@@ -174,7 +175,7 @@ - {{buy.quantity * buy.buyingValue | currency: 'EUR':2}} @@ -246,4 +247,4 @@ question="You are going to delete buy(s) from this entry" message="Continue anyway?" on-accept="$ctrl.deleteBuys()"> - \ No newline at end of file + diff --git a/modules/entry/front/create/index.html b/modules/entry/front/create/index.html index ed08b5c76..e1e4dc064 100644 --- a/modules/entry/front/create/index.html +++ b/modules/entry/front/create/index.html @@ -21,7 +21,8 @@ order="nickname" required="true"> - {{::id}} - {{::nickname}} +
{{::nickname}}
+
#{{::id}}
@@ -31,11 +32,16 @@ ng-model="$ctrl.entry.travelFk" url="Travels/filter" search-function="$ctrl.searchFunction($search)" + show-field="warehouseInName" order="id" required="true"> - {{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) → - {{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}}) +
+ {{::agencyModeName}} + - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) + → {{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}}) +
+
#{{::id}}
diff --git a/modules/invoiceIn/front/tax/index.html b/modules/invoiceIn/front/tax/index.html index acc9cf492..e13f769ce 100644 --- a/modules/invoiceIn/front/tax/index.html +++ b/modules/invoiceIn/front/tax/index.html @@ -34,7 +34,7 @@ rule> {{id}}: {{name}} - @@ -57,7 +57,10 @@ search-function="{or: [{id: $search}, {vat: {like: '%'+ $search +'%'}}]}" selection="taxRateSelection" rule> - {{id}}: {{vat}} + +
{{::vat}}
+
#{{::id}}
+
- {{id}}: {{transaction}} + +
{{::transaction}}
+
#{{::id}}
+
- + @@ -105,7 +111,7 @@ - + @@ -115,7 +121,7 @@ @@ -129,7 +135,7 @@ @@ -140,4 +146,4 @@ - \ No newline at end of file + diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index ebe46b84a..6d5b16329 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -98,7 +98,10 @@ ng-model="$ctrl.clientId" required="true" ng-if="$ctrl.clientsToInvoice == 'one'"> - {{::id}} - {{::name}} + +
{{::name}}
+
#{{::id}}
+
- {{::id}} - {{::nickname}} +
#{{::id}}
+
{{::nickname}}
Or diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html index 974aa37d8..a7e603bd1 100644 --- a/modules/item/front/basic-data/index.html +++ b/modules/item/front/basic-data/index.html @@ -20,47 +20,52 @@ - -
{{name}}
+
{{::name}}
- {{category.name}} + {{::category.name}}
- - -
{{::id}}
+
{{::description}}
+
+ #{{::id}} +
- -
+ ng-model="$ctrl.item.stemMultiplier" + vn-name="stemMultiplier"> - {{::id}} - {{::name}} +
{{::name}}
+
+ #{{::id}} +
+ ng-model="$ctrl.item.isActive" + vn-name="isActive"> + ng-model="$ctrl.item.hasKgPrice" + vn-name="priceInKg"> @@ -211,16 +221,19 @@ message="New intrastat"> - - diff --git a/modules/item/front/create/index.html b/modules/item/front/create/index.html index 15e212250..b284abf06 100644 --- a/modules/item/front/create/index.html +++ b/modules/item/front/create/index.html @@ -18,6 +18,7 @@ + label="Tag" + vn-name="tag"> + value-field="priority" + vn-name="priority">
- -
{{::id}}
+
{{::description}}
+
+ #{{::id}} +
- + ng-model="$ctrl.item.originFk" + vn-name="origin">
diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 9a143d10d..d9a955fe1 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -81,7 +81,8 @@ class="dense" url="Items/withName" ng-model="price.itemFk" - show-field="name" + fields="['name']" + show-field="id" value-field="id" search-function="$ctrl.itemSearchFunc($search)" on-change="$ctrl.upsertPrice(price, true)" diff --git a/modules/order/back/methods/order/filter.js b/modules/order/back/methods/order/filter.js index 008c0e5c9..10185af7e 100644 --- a/modules/order/back/methods/order/filter.js +++ b/modules/order/back/methods/order/filter.js @@ -141,7 +141,7 @@ module.exports = Self => { let stmt; stmt = new ParameterizedSQL( - `CREATE TEMPORARY TABLE tmp.filter + `CREATE OR REPLACE TEMPORARY TABLE tmp.filter (INDEX (id)) ENGINE = MEMORY SELECT diff --git a/modules/order/front/basic-data/index.html b/modules/order/front/basic-data/index.html index 109168e29..019153b0d 100644 --- a/modules/order/front/basic-data/index.html +++ b/modules/order/front/basic-data/index.html @@ -19,13 +19,17 @@ vn-one url="Clients" label="Client" - search-function="{or: [{id: $search}, {name: {like: '%'+$search+'%'}}]}" + search-function="{or: [{id: $search}, {name: {like: '%'+ $search +'%'}}]}" show-field="name" value-field="id" ng-model="$ctrl.order.clientFk" + vn-name="client" selection="$ctrl.selection" fields="['defaultAddressFk']"> - {{::id}}: {{::name}} + +
{{::name}}
+
#{{::id}}
+
{{::nickname}} - + ng-model="$ctrl.order.agencyModeFk" + vn-name="agencyMode"> diff --git a/modules/order/front/create/card.html b/modules/order/front/create/card.html index d252d680f..ed6f752d3 100644 --- a/modules/order/front/create/card.html +++ b/modules/order/front/create/card.html @@ -7,6 +7,7 @@ show-field="name" value-field="id" ng-model="$ctrl.clientFk" + vn-name="client" order="id"> {{id}}: {{name}} @@ -15,14 +16,16 @@ url="{{ $ctrl.clientFk ? 'Clients/'+ $ctrl.clientFk +'/addresses' : null }}" fields="['nickname', 'street', 'city']" ng-model="$ctrl.addressFk" + vn-name="address" show-field="nickname" value-field="id" label="Address"> {{nickname}}: {{street}}, {{city}} - + + ng-model="$ctrl.order.agencyModeFk" + vn-name="agencyMode"> diff --git a/modules/order/front/volume/index.html b/modules/order/front/volume/index.html index 7c2ff4e3d..e0053f9ed 100644 --- a/modules/order/front/volume/index.html +++ b/modules/order/front/volume/index.html @@ -12,11 +12,11 @@ @@ -24,7 +24,7 @@ - Item + Item Description Quantity m³ per quantity diff --git a/modules/order/front/volume/index.js b/modules/order/front/volume/index.js index aaadf2af6..c1bc5ec7d 100644 --- a/modules/order/front/volume/index.js +++ b/modules/order/front/volume/index.js @@ -6,9 +6,10 @@ class Controller extends Section { constructor($element, $) { super($element, $); this.filter = { - include: [{ + include: { relation: 'item' - }] + }, + order: 'itemFk' }; this.order = {}; this.ticketVolumes = []; diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 831599ae8..c63fee53b 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -9,76 +9,80 @@ + label="Worker" + vn-name="worker"> -
{{name}} - {{nickname}}
+
{{::nickname}}
+
{{::name}}
+ label="Vehicle" + vn-name="vehicle">
+ ng-model="$ctrl.route.created" + vn-name="created"> + label="Agency" + vn-name="agencyMode"> + ng-model="$ctrl.route.started" + vn-name="started"> - - - + ng-model="$ctrl.route.finished" + vn-name="finished"> + + + diff --git a/modules/supplier/front/fiscal-data/index.html b/modules/supplier/front/fiscal-data/index.html index 3a0aefbf2..218fe284d 100644 --- a/modules/supplier/front/fiscal-data/index.html +++ b/modules/supplier/front/fiscal-data/index.html @@ -42,7 +42,7 @@ vn-two vn-focus label="Social name" - name="socialName" + vn-name="socialName" ng-model="$ctrl.supplier.name" info="Only letters, numbers and spaces can be used" required="true" @@ -51,18 +51,17 @@ + rule> { const isDeliveryBoss = await models.VnUser.hasRole(userId, 'deliveryBoss', myOptions); if (!isDeliveryBoss) { const zoneShipped = await models.Agency.getShipped( + ctx, args.landed, args.addressFk, args.agencyModeFk, diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index bd899ef7b..d8ec5eb9a 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -24,7 +24,6 @@ module.exports = function(Self) { }); Self.makeInvoice = async(ctx, ticketsIds, options) => { - const userId = ctx.req.accessToken.userId; const models = Self.app.models; const date = Date.vnNew(); date.setHours(0, 0, 0, 0); @@ -42,6 +41,7 @@ module.exports = function(Self) { let serial; let invoiceId; + let invoiceOut; try { const tickets = await models.Ticket.find({ where: { @@ -89,24 +89,14 @@ module.exports = function(Self) { invoiceId = resultInvoice.id; - for (let ticket of tickets) { - const ticketInvoice = await models.Ticket.findById(ticket.id, { - fields: ['refFk'] - }, myOptions); - - await models.TicketLog.create({ - originFk: ticket.id, - userFk: userId, - action: 'insert', - changedModel: 'Ticket', - changedModelId: ticket.id, - newInstance: ticketInvoice - }, myOptions); - } - if (serial != 'R' && invoiceId) await Self.rawSql('CALL invoiceOutBooking(?)', [invoiceId], myOptions); + invoiceOut = await models.InvoiceOut.findById(invoiceId, { + include: { + relation: 'client' + } + }, myOptions); if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); @@ -116,6 +106,15 @@ module.exports = function(Self) { if (serial != 'R' && invoiceId) await models.InvoiceOut.createPdf(ctx, invoiceId); + if (invoiceId) { + ctx.args = { + reference: invoiceOut.ref, + recipientId: invoiceOut.clientFk, + recipient: invoiceOut.client().email + }; + await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); + } + return {invoiceFk: invoiceId, serial: serial}; }; }; diff --git a/modules/ticket/back/methods/ticket/new.js b/modules/ticket/back/methods/ticket/new.js index a5d04bc4c..5f7cf3cb6 100644 --- a/modules/ticket/back/methods/ticket/new.js +++ b/modules/ticket/back/methods/ticket/new.js @@ -100,7 +100,7 @@ module.exports = Self => { } if (!args.shipped && args.landed) { - const shippedResult = await models.Agency.getShipped(args.landed, + const shippedResult = await models.Agency.getShipped(ctx, args.landed, address.id, args.agencyModeId, args.warehouseId, myOptions); args.shipped = (shippedResult && shippedResult.shipped) || args.landed; } diff --git a/modules/ticket/back/methods/ticket/priceDifference.js b/modules/ticket/back/methods/ticket/priceDifference.js index a0a10d997..16812dcb0 100644 --- a/modules/ticket/back/methods/ticket/priceDifference.js +++ b/modules/ticket/back/methods/ticket/priceDifference.js @@ -81,6 +81,7 @@ module.exports = Self => { const isDeliveryBoss = await models.VnUser.hasRole(userId, 'deliveryBoss', myOptions); if (!isDeliveryBoss) { const zoneShipped = await models.Agency.getShipped( + ctx, args.landed, args.addressId, args.agencyModeId, diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js index 24d4a48ba..270ba5c93 100644 --- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -6,6 +6,9 @@ describe('ticket makeInvoice()', () => { const ticketId = 11; const clientId = 1102; const activeCtx = { + getLocale: () => { + return 'en'; + }, accessToken: {userId: userId}, headers: {origin: 'http://localhost:5000'}, }; @@ -67,6 +70,7 @@ describe('ticket makeInvoice()', () => { it('should invoice a ticket, then try again to fail', async() => { const invoiceOutModel = models.InvoiceOut; spyOn(invoiceOutModel, 'createPdf'); + spyOn(invoiceOutModel, 'invoiceEmail'); const tx = await models.Ticket.beginTransaction({}); @@ -90,6 +94,7 @@ describe('ticket makeInvoice()', () => { it('should success to invoice a ticket', async() => { const invoiceOutModel = models.InvoiceOut; spyOn(invoiceOutModel, 'createPdf'); + spyOn(invoiceOutModel, 'invoiceEmail'); const tx = await models.Ticket.beginTransaction({}); diff --git a/modules/ticket/front/create/card.html b/modules/ticket/front/create/card.html index e48aea681..015d92fa0 100644 --- a/modules/ticket/front/create/card.html +++ b/modules/ticket/front/create/card.html @@ -4,7 +4,8 @@ data="warehouses" order="name"> - - {{id}}: {{name}} + +
{{::name}}
+
#{{::id}}
+
- {{nickname}}: {{street}}, {{city}} + +
{{::nickname}}
+
{{::street}}, {{::city}}
+
+ label="Landed" + ng-model="$ctrl.landed" + vn-name="landed"> - \ No newline at end of file + ng-model="$ctrl.agencyModeId" + vn-name="agencyMode"> + diff --git a/modules/ticket/front/package/index.html b/modules/ticket/front/package/index.html index c5d83edfb..c588fb8ed 100644 --- a/modules/ticket/front/package/index.html +++ b/modules/ticket/front/package/index.html @@ -1,4 +1,4 @@ - - {{itemFk}} : {{name}} + +
{{::name}}
+
+ #{{itemFk}} +
-
+ - - + + --> - \ No newline at end of file + diff --git a/modules/ticket/front/volume/index.html b/modules/ticket/front/volume/index.html index f5dd18033..ff0a86772 100644 --- a/modules/ticket/front/volume/index.html +++ b/modules/ticket/front/volume/index.html @@ -1,4 +1,5 @@ -
- -
@@ -23,7 +24,7 @@ Item - Description + Description Packing type Quantity m³ per quantity diff --git a/modules/ticket/front/volume/index.js b/modules/ticket/front/volume/index.js index a3d531898..7acecf570 100644 --- a/modules/ticket/front/volume/index.js +++ b/modules/ticket/front/volume/index.js @@ -5,9 +5,10 @@ class Controller extends Section { constructor($element, $) { super($element, $); this.filter = { - include: [{ + include: { relation: 'item' - }] + }, + order: 'concept' }; this.ticketVolumes = []; diff --git a/modules/ticket/front/weekly/index.html b/modules/ticket/front/weekly/index.html index ca3b6e662..6b10efcb5 100644 --- a/modules/ticket/front/weekly/index.html +++ b/modules/ticket/front/weekly/index.html @@ -21,7 +21,7 @@ @@ -76,7 +76,7 @@ - - \ No newline at end of file + diff --git a/modules/travel/front/basic-data/index.html b/modules/travel/front/basic-data/index.html index e7143ffc0..783208d9a 100644 --- a/modules/travel/front/basic-data/index.html +++ b/modules/travel/front/basic-data/index.html @@ -17,7 +17,8 @@ + ng-model="$ctrl.travel.ref" + vn-name="reference"> + label="Agency" + vn-name="agencyMode">
+ ng-model="$ctrl.travel.shipped" + vn-name="shipped"> + ng-model="$ctrl.travel.landed" + vn-name="landed"> + ng-model="$ctrl.travel.ref" + vn-name="reference"> @@ -22,22 +24,26 @@ + ng-model="$ctrl.travel.shipped" + vn-name="shipped"> + ng-model="$ctrl.travel.landed" + vn-name="landed"> diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 5ff7135a7..cec7524c6 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -1,4 +1,4 @@ -/* eslint max-len: ["error", { "code": 130 }]*/ +/* eslint max-len: ["error", { "code": 150 }]*/ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { @@ -139,7 +139,7 @@ module.exports = Self => { if (!client) { const nickname = args.firstName.concat(' ', args.lastNames); - const workerConfig = await models.WorkerConfig.findOne({fields: ['roleFk']}); + const workerConfig = await models.WorkerConfig.findOne({fields: ['roleFk', 'businessTypeFk']}); const [randomPassword] = await models.Worker.rawSql( 'SELECT account.passwordGenerate() as password;' ); @@ -196,7 +196,7 @@ module.exports = Self => { client = await models.Client.findById( user.id, - {fields: ['id', 'name', 'socialName', 'street', 'city', 'iban', 'bankEntityFk', 'defaultAddressFk', 'fi']}, + {fields: ['id', 'name', 'socialName', 'street', 'city', 'iban', 'bankEntityFk', 'defaultAddressFk', 'businessTypeFk', 'fi']}, myOptions ); @@ -205,6 +205,7 @@ module.exports = Self => { iban: args.iban, bankEntityFk: args.bankEntityFk, defaultAddressFk: address.id, + businessTypeFk: workerConfig.businessTypeFk, }, myOptions ); diff --git a/modules/worker/back/models/worker-config.json b/modules/worker/back/models/worker-config.json index 05cdfef42..bcee74067 100644 --- a/modules/worker/back/models/worker-config.json +++ b/modules/worker/back/models/worker-config.json @@ -14,6 +14,9 @@ }, "roleFk": { "type": "number" + }, + "businessTypeFk": { + "type": "string" } }, "acls": [ diff --git a/modules/zone/back/methods/agency/getShipped.js b/modules/zone/back/methods/agency/getShipped.js index 165dd6731..7ef912abd 100644 --- a/modules/zone/back/methods/agency/getShipped.js +++ b/modules/zone/back/methods/agency/getShipped.js @@ -1,7 +1,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { - Self.remoteMethod('getShipped', { + Self.remoteMethodCtx('getShipped', { description: 'Returns the first shipped possible for params', accessType: 'READ', accepts: [{ @@ -34,18 +34,22 @@ module.exports = Self => { } }); - Self.getShipped = async(landed, addressFk, agencyModeFk, warehouseFk, options) => { + Self.getShipped = async(ctx, landed, addressFk, agencyModeFk, warehouseFk, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const stmts = []; + const userId = ctx.req.accessToken.userId; + const models = Self.app.models; + const isProductionAssistant = await models.VnUser.hasRole(userId, 'productionAssi', myOptions); stmts.push(new ParameterizedSQL( - `CALL vn.zone_getShipped(?, ?, ?, TRUE)`, [ + `CALL vn.zone_getShipped(?, ?, ?, ?)`, [ landed, addressFk, - agencyModeFk + agencyModeFk, + isProductionAssistant ] )); diff --git a/modules/zone/back/methods/agency/specs/getShipped.spec.js b/modules/zone/back/methods/agency/specs/getShipped.spec.js index c262357a7..b226557fb 100644 --- a/modules/zone/back/methods/agency/specs/getShipped.spec.js +++ b/modules/zone/back/methods/agency/specs/getShipped.spec.js @@ -1,6 +1,9 @@ -const {models} = require('vn-loopback/server/server'); +const models = require('vn-loopback/server/server').models; describe('agency getShipped()', () => { + const employeeId = 1; + const ctx = {req: {accessToken: {userId: employeeId}}}; + it('should return a shipment date', async() => { const landed = Date.vnNew(); landed.setDate(landed.getDate() + 1); @@ -12,8 +15,7 @@ describe('agency getShipped()', () => { try { const options = {transaction: tx}; - - const result = await models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options); + const result = await models.Agency.getShipped(ctx, landed, addressFk, agencyModeFk, warehouseFk, options); expect(result).toBeDefined(); @@ -37,7 +39,7 @@ describe('agency getShipped()', () => { try { const options = {transaction: tx}; - const result = await models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options); + const result = await models.Agency.getShipped(ctx, landed, addressFk, agencyModeFk, warehouseFk, options); expect(result).toBeUndefined(); diff --git a/package-lock.json b/package-lock.json index fae8837fa..05ff6466a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "salix-back", - "version": "23.16.01", - "lockfileVersion": 2, + "version": "23.22.01", + "lockfileVersion": 1, "requires": true, "packages": { "": { diff --git a/package.json b/package.json index 8d6c5340b..d068d6615 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.16.01", + "version": "23.22.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", diff --git a/print/core/components/report-footer/report-footer.js b/print/core/components/report-footer/report-footer.js index 0eaab8ce4..077ef0bde 100755 --- a/print/core/components/report-footer/report-footer.js +++ b/print/core/components/report-footer/report-footer.js @@ -4,13 +4,14 @@ const db = require('../../database'); module.exports = { name: 'report-footer', async serverPrefetch() { - this.company = await db.findOne( - `SELECT - ci.footnotes - FROM companyI18n ci - JOIN company c ON c.id = ci.companyFk - WHERE c.code = ? AND ci.lang = (SELECT lang FROM account.user WHERE id = ?)`, - [this.companyCode, this.recipientId]); + this.company = await db.findOne(` + SELECT IFNULL(ci.footnotes, cl.footnotes) as footnotes + FROM company c + LEFT JOIN companyL10n cl ON c.id = cl.id + LEFT JOIN companyI18n ci ON ci.companyFk = cl.id + AND ci.lang = (SELECT lang FROM account.user where id = ?) + WHERE c.code = ?`, + [this.recipientId, this.companyCode]); }, props: ['leftText', 'companyCode', 'recipientId', 'centerText'] diff --git a/print/templates/email/weekly-hour-record/locale/en.yml b/print/templates/email/weekly-hour-record/locale/en.yml index 817e5451e..b76372fb9 100644 --- a/print/templates/email/weekly-hour-record/locale/en.yml +++ b/print/templates/email/weekly-hour-record/locale/en.yml @@ -1,6 +1,7 @@ subject: Weekly time log title: Record of hours week {0} year {1} dear: Dear worker -description: Access the following link:

- {0}

+Acceda al siguiente enlace: Access the following link:
+description: Click 'SATISFIED' if you agree with the hours worked. Otherwise, press 'NOT SATISFIED', detailing the cause of the disagreement. +Hours: Hours \ No newline at end of file diff --git a/print/templates/email/weekly-hour-record/locale/es.yml b/print/templates/email/weekly-hour-record/locale/es.yml index b70862f16..95466addb 100644 --- a/print/templates/email/weekly-hour-record/locale/es.yml +++ b/print/templates/email/weekly-hour-record/locale/es.yml @@ -1,6 +1,7 @@ subject: Registro de horas semanal title: Registro de horas semana {0} año {1} dear: Estimado trabajador -description: Acceda al siguiente enlace:

- {0}

+toaccess: Acceda al siguiente enlace:
+description: Pulse 'CONFORME' si esta de acuerdo con las horas trabajadas. En caso contrario pulse 'NO CONFORME', detallando la causa de la disconformidad. +Hours: Horas \ No newline at end of file diff --git a/print/templates/email/weekly-hour-record/weekly-hour-record.html b/print/templates/email/weekly-hour-record/weekly-hour-record.html index 84abb4c61..b1eb4e0b3 100644 --- a/print/templates/email/weekly-hour-record/weekly-hour-record.html +++ b/print/templates/email/weekly-hour-record/weekly-hour-record.html @@ -3,7 +3,9 @@

{{ $t('title', [week, year]) }}

{{$t('dear')}},

-

+

+ +

{{$t('description')}}