From ef6af87d892a3747b8858d5797ad5bd79f280a1f Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 18 Nov 2022 09:21:21 +0100 Subject: [PATCH 01/63] feat: add supplier.isVies funcionality --- .../10503-november/00-supplierIsVies.sql | 3 + .../10503-november/01-sage_supplierAdd.sql | 124 ++++++++++++++++++ .../back/methods/supplier/updateFiscalData.js | 7 +- modules/supplier/back/models/supplier.json | 5 +- modules/supplier/front/fiscal-data/index.html | 23 ++-- 5 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 db/changes/10503-november/00-supplierIsVies.sql create mode 100644 db/changes/10503-november/01-sage_supplierAdd.sql diff --git a/db/changes/10503-november/00-supplierIsVies.sql b/db/changes/10503-november/00-supplierIsVies.sql new file mode 100644 index 000000000..e1911a7b7 --- /dev/null +++ b/db/changes/10503-november/00-supplierIsVies.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`supplier` ADD `isVies` tinyint(4) DEFAULT 0 NOT NULL; + +/*FALTA HACER EL UPDATE MASIVO SOBRE SUPPLIER */ diff --git a/db/changes/10503-november/01-sage_supplierAdd.sql b/db/changes/10503-november/01-sage_supplierAdd.sql new file mode 100644 index 000000000..e678fa2f0 --- /dev/null +++ b/db/changes/10503-november/01-sage_supplierAdd.sql @@ -0,0 +1,124 @@ +CREATE DEFINER=`root`@`localhost` PROCEDURE `sage`.`clientSupplier_add`(vCompanyFk INT) +BEGIN +/** + * Prepara los datos de clientes y proveedores para exportarlos a Sage + * @vCompanyFk Empresa dela que se quiere trasladar datos + */ + DECLARE vCountryCeutaMelillaFk INT; + DECLARE vCountryCanariasCode, vCountryCeutaMelillaCode VARCHAR(2); + + SELECT SiglaNacion INTO vCountryCanariasCode + FROM Naciones + WHERE Nacion ='ISLAS CANARIAS'; + + SELECT CodigoNacion, SiglaNacion INTO vCountryCeutaMelillaFk, vCountryCeutaMelillaCode + FROM Naciones + WHERE Nacion ='CEUTA Y MELILLA'; + + TRUNCATE TABLE clientesProveedores; + + INSERT INTO clientesProveedores + (CodigoEmpresa, + ClienteOProveedor, + CodigoClienteProveedor, + RazonSocial, + Nombre, + Domicilio, + CodigoCuenta, + CifDni, + CifEuropeo, + CodigoPostal, + Municipio, + CodigoProvincia, + Provincia, + CodigoNacion, + SiglaNacion, + PersonaFisicaJuridica, + TipoDocumentoPersona, + CodigoIva, + Nacion, + Telefono, + Telefono2, + CodigoTransaccion, + CodigoRetencion, + Email1, + iban) + SELECT + company_getCode(vCompanyFk), + 'C', + c.id, + c.socialName, + c.socialName, + IFNULL(c.street, ''), + c.accountingAccount, + TRIM(IF(cu.code = LEFT(c.fi, 2), MID(c.fi, 3, LENGTH(c.fi)-1), c.fi)), + IF(n.NacionCEE,TRIM(IF(cu.code = LEFT(c.fi, 2), c.fi, CONCAT(cu.code,c.fi))) , ''), + IFNULL(c.postcode, ''), + IFNULL(c.city, ''), + IFNULL(pr.CodigoProvincia, ''), + IFNULL(p.name, ''), + IF(n.SiglaNacion = vCountryCanariasCode COLLATE utf8mb3_unicode_ci, IF(@isCeutaMelilla := IF(pr.Provincia IN ('CEUTA', 'MELILLA'), TRUE, FALSE), vCountryCeutaMelillaFk, IF (@isCanarias, vCountryCanariasCode, n.CodigoNacion)), n.CodigoNacion), + IF(n.SiglaNacion = vCountryCanariasCode COLLATE utf8mb3_unicode_ci, IF(@isCeutaMelilla, vCountryCeutaMelillaCode, IF (@isCanarias, vCountryCanariasCode, n.SiglaNacion)), n.SiglaNacion), + IF((c.fi REGEXP '^([[:blank:]]|[[:digit:]])'), 'J','F'), + IF(cu.code IN('ES','EX'), + 1, + IF((cu.isUeeMember AND c.isVies), 2, 4)), + IFNULL(c.taxTypeSageFk,0), + IF(n.SiglaNacion = vCountryCanariasCode COLLATE utf8mb3_unicode_ci, + IF(@isCeutaMelilla, 'CEUTA Y MELILLA', IF (@isCanarias, 'ISLAS CANARIAS', n.Nacion)), + n.Nacion), + IFNULL(c.phone, ''), + IFNULL(c.mobile, ''), + IFNULL(c.transactionTypeSageFk, 0), + '0', + IFNULL(SUBSTR(c.email, 1, LOCATE(',', CONCAT(c.email, ','))-1), ''), + IFNULL(c.iban, '') + FROM vn.`client` c + JOIN clientLastTwoMonths clm ON clm.clientFk = c.id + LEFT JOIN vn.country cu ON cu.id = c.countryFk + LEFT JOIN Naciones n ON n.countryFk = cu.id + LEFT JOIN vn.province p ON p.id = c.provinceFk + LEFT JOIN Provincias pr ON pr.provinceFk = p.id + WHERE c.isRelevant + AND clm.companyFk = vCompanyFk + UNION ALL + SELECT company_getCode(vCompanyFk), + 'P', + s.id, + s.name, + s.name, + IFNULL(s.street, ''), + s.account, + TRIM(IF(co.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif) - 1), s.nif)), + IF(n.NacionCEE, TRIM(CONCAT(co.code, IF(co.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif) - 1), s.nif))), ''), + IFNULL(s.postCode,''), + IFNULL(s.city, ''), + IFNULL(pr.CodigoProvincia, ''), + IFNULL(p.name, ''), + n.CodigoNacion, + n.SiglaNacion COLLATE utf8mb3_unicode_ci, + IF((s.nif REGEXP '^([[:blank:]]|[[:digit:]])'),'J','F'), + IF(co.code IN('ES','EX'), + 1, + IF((co.isUeeMember AND s.isVies), 2, 4)), + IFNULL(s.taxTypeSageFk, 0), + n.Nacion, + IFNULL(sc.phone, ''), + IFNULL(sc.mobile, ''), + IFNULL(s.transactionTypeSageFk, 0), + IFNULL(s.withholdingSageFk, '0'), + IFNULL(SUBSTR(sc.email, 1, (COALESCE(NULLIF(LOCATE(',', sc.email), 0), 99) - 1)), ''), + IFNULL(iban, '') + FROM vn.supplier s + JOIN supplierLastThreeMonths pl ON pl.supplierFk = s.id + LEFT JOIN vn.country co ON co.id = s.countryFk + LEFT JOIN Naciones n ON n.countryFk = co.id + LEFT JOIN vn.province p ON p.id = s.provinceFk + LEFT JOIN Provincias pr ON pr.provinceFk = p.id + LEFT JOIN vn.supplierContact sc ON sc.supplierFk = s.id + LEFT JOIN vn.supplierAccount sa ON sa.supplierFk = s.id + WHERE pl.companyFk = vCompanyFk AND + s.isActive AND + s.nif <> '' + GROUP BY pl.supplierFk, pl.companyFk; +END diff --git a/modules/supplier/back/methods/supplier/updateFiscalData.js b/modules/supplier/back/methods/supplier/updateFiscalData.js index 4604b3f91..51e02bf94 100644 --- a/modules/supplier/back/methods/supplier/updateFiscalData.js +++ b/modules/supplier/back/methods/supplier/updateFiscalData.js @@ -64,7 +64,12 @@ module.exports = Self => { { arg: 'healthRegister', type: 'string' - }], + }, + { + arg: 'isVies', + type: 'boolean' + } + ], returns: { arg: 'res', type: 'string', diff --git a/modules/supplier/back/models/supplier.json b/modules/supplier/back/models/supplier.json index 3cd6386a8..ee2c4fbbd 100644 --- a/modules/supplier/back/models/supplier.json +++ b/modules/supplier/back/models/supplier.json @@ -110,6 +110,9 @@ }, "healthRegister": { "type": "string" + }, + "isVies": { + "type": "boolean" } }, "relations": { @@ -175,4 +178,4 @@ "foreignKey": "supplierActivityFk" } } -} \ No newline at end of file +} diff --git a/modules/supplier/front/fiscal-data/index.html b/modules/supplier/front/fiscal-data/index.html index a3ede2058..ccbd5b0d9 100644 --- a/modules/supplier/front/fiscal-data/index.html +++ b/modules/supplier/front/fiscal-data/index.html @@ -129,7 +129,7 @@ show-field="code" rule> - {{code}} - {{town.name}} ({{town.province.name}}, + {{code}} - {{town.name}} ({{town.province.name}}, {{town.province.country.country}}) @@ -144,7 +144,7 @@ - - - - + + + + + + @@ -203,4 +210,4 @@ - \ No newline at end of file + From 7e98a255b847838f9338dc9360b5d069169869fc Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 21 Nov 2022 08:11:01 +0100 Subject: [PATCH 02/63] refs #4849 SQL --- db/changes/10503-november/00-supplierIsVies.sql | 15 ++++++++++++++- db/changes/10503-november/01-sage_supplierAdd.sql | 15 +++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/db/changes/10503-november/00-supplierIsVies.sql b/db/changes/10503-november/00-supplierIsVies.sql index e1911a7b7..0af1a61ab 100644 --- a/db/changes/10503-november/00-supplierIsVies.sql +++ b/db/changes/10503-november/00-supplierIsVies.sql @@ -1,3 +1,16 @@ ALTER TABLE `vn`.`supplier` ADD `isVies` tinyint(4) DEFAULT 0 NOT NULL; -/*FALTA HACER EL UPDATE MASIVO SOBRE SUPPLIER */ +UPDATE `vn`.`supplier` s + JOIN vn.country c ON c.id = s.countryFk + SET s.nif = MID(s.nif, 3, LENGTH(s.nif)-1), s.isVies = TRUE +WHERE s.nif <> TRIM(IF(c.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif)-1), s.nif)); + +INSERT IGNORE INTO `vn`.`chat` +(senderFk, recipient, checkUserStatus, message, status, attempts) +VALUES(19294, '#informatica-cau', 0, ' +``` +UPDATE `vn`.`supplier` s + JOIN vn.country c ON c.id = s.countryFk + SET s.nif = MID(s.nif, 3, LENGTH(s.nif)-1), s.isVies = TRUE +WHERE s.nif <> TRIM(IF(c.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif)-1), s.nif)); +```', 0, 0); diff --git a/db/changes/10503-november/01-sage_supplierAdd.sql b/db/changes/10503-november/01-sage_supplierAdd.sql index e678fa2f0..cd68ebfcb 100644 --- a/db/changes/10503-november/01-sage_supplierAdd.sql +++ b/db/changes/10503-november/01-sage_supplierAdd.sql @@ -1,3 +1,7 @@ +DROP PROCEDURE IF EXISTS `sage`.`clientSupplier_add`; + +DELIMITER $$ +$$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sage`.`clientSupplier_add`(vCompanyFk INT) BEGIN /** @@ -51,7 +55,7 @@ BEGIN c.socialName, IFNULL(c.street, ''), c.accountingAccount, - TRIM(IF(cu.code = LEFT(c.fi, 2), MID(c.fi, 3, LENGTH(c.fi)-1), c.fi)), + TRIM(IF(c.isVies, CONCAT(cu.code,c.fi), c.fi)), IF(n.NacionCEE,TRIM(IF(cu.code = LEFT(c.fi, 2), c.fi, CONCAT(cu.code,c.fi))) , ''), IFNULL(c.postcode, ''), IFNULL(c.city, ''), @@ -89,7 +93,7 @@ BEGIN s.name, IFNULL(s.street, ''), s.account, - TRIM(IF(co.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif) - 1), s.nif)), + TRIM(IF(s.isVies, CONCAT(co.code,c.fi), s.nif)), IF(n.NacionCEE, TRIM(CONCAT(co.code, IF(co.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif) - 1), s.nif))), ''), IFNULL(s.postCode,''), IFNULL(s.city, ''), @@ -98,9 +102,7 @@ BEGIN n.CodigoNacion, n.SiglaNacion COLLATE utf8mb3_unicode_ci, IF((s.nif REGEXP '^([[:blank:]]|[[:digit:]])'),'J','F'), - IF(co.code IN('ES','EX'), - 1, - IF((co.isUeeMember AND s.isVies), 2, 4)), + IF(co.country IN ('España', 'España exento'), 1,IF(co.isUeeMember = 1, 2, 4)), IFNULL(s.taxTypeSageFk, 0), n.Nacion, IFNULL(sc.phone, ''), @@ -121,4 +123,5 @@ BEGIN s.isActive AND s.nif <> '' GROUP BY pl.supplierFk, pl.companyFk; -END +END$$ +DELIMITER ; From 99338bb6f80f973e2a38bbc1fd92b009df3fb740 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 17 Jan 2023 10:11:41 +0100 Subject: [PATCH 03/63] isPhotoRequired implemented --- back/models/image.js | 7 +++++++ modules/item/back/methods/item/new.js | 5 ++++- modules/item/back/models/item.json | 6 ++++++ modules/item/front/basic-data/index.html | 6 ++++++ modules/item/front/basic-data/locale/es.yml | 4 +++- modules/item/front/summary/index.html | 10 ++++++++++ 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/back/models/image.js b/back/models/image.js index d736e924f..f646543fc 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -145,6 +145,13 @@ module.exports = Self => { fileName, myOptions ); + if (item.isPhotoRequested) { + await item.updateAttribute( + 'isPhotoRequested', + false, + myOptions + ); + } } if (fs.existsSync(srcFilePath)) diff --git a/modules/item/back/methods/item/new.js b/modules/item/back/methods/item/new.js index fae37836f..a20437887 100644 --- a/modules/item/back/methods/item/new.js +++ b/modules/item/back/methods/item/new.js @@ -24,6 +24,8 @@ module.exports = Self => { const myOptions = {}; let tx; + params.isPhotoRequested = true; + if (typeof options == 'object') Object.assign(myOptions, options); @@ -37,7 +39,8 @@ module.exports = Self => { 'typeFk', 'intrastatFk', 'originFk', - 'relevancy' + 'relevancy', + 'isPhotoRequested', ]; for (const key in params) { diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index 2f58c30a9..10300f7a1 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -146,6 +146,12 @@ }, "isLaid": { "type": "boolean" + }, + "isPhotoRequested": { + "type": "boolean", + "mysql":{ + "columnName": "doPhoto" + } } }, "relations": { diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html index fd21ab240..974aa37d8 100644 --- a/modules/item/front/basic-data/index.html +++ b/modules/item/front/basic-data/index.html @@ -182,6 +182,12 @@ ng-model="$ctrl.item.isFragile" info="Is shown at website, app that this item cannot travel (wreath, palms, ...)"> + + diff --git a/modules/item/front/basic-data/locale/es.yml b/modules/item/front/basic-data/locale/es.yml index d59752ebb..747dfe792 100644 --- a/modules/item/front/basic-data/locale/es.yml +++ b/modules/item/front/basic-data/locale/es.yml @@ -11,4 +11,6 @@ Identifier: Identificador Fragile: Frágil Is shown at website, app that this item cannot travel (wreath, palms, ...): Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...) Multiplier: Multiplicador -Generic: Genérico \ No newline at end of file +Generic: Genérico +This item does need a photo: Este artículo necesita una foto +Do photo: Hacer foto \ No newline at end of file diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index a4d40c829..801a82ee0 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -65,6 +65,16 @@ {{$ctrl.summary.item.itemType.worker.user.name}} + + + +

From 2e988ea701a5d294a0a7a8063b3e2385a0dfe31f Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Fri, 20 Jan 2023 13:34:36 +0100 Subject: [PATCH 04/63] doPhoto updated on item upload --- back/models/image.js | 7 ------- modules/item/back/models/item.js | 9 +++++++++ modules/item/front/summary/index.html | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/back/models/image.js b/back/models/image.js index f646543fc..d736e924f 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -145,13 +145,6 @@ module.exports = Self => { fileName, myOptions ); - if (item.isPhotoRequested) { - await item.updateAttribute( - 'isPhotoRequested', - false, - myOptions - ); - } } if (fs.existsSync(srcFilePath)) diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index b8baa97ea..03a6fb721 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -21,6 +21,15 @@ module.exports = Self => { Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'}); Self.observe('before save', async function(ctx) { + let currentInstance = ctx.currentInstance; + let oldInstance; + let newInstance; + ctx.hookState.oldInstance === undefined ? oldInstance = false : oldInstance = ctx.hookState.oldInstance; + ctx.hookState.newInstance === undefined ? newInstance = false : newInstance = ctx.hookState.newInstance; + if (oldInstance.image && newInstance.image) { + let query = `UPDATE vn.item SET doPhoto = 0 WHERE id = ${currentInstance.id}`; + await Self.rawSql(query); + } await Self.availableId(ctx); }); diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index 801a82ee0..8f958bd3b 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -65,6 +65,26 @@ {{$ctrl.summary.item.itemType.worker.user.name}} + + + + + + + + Date: Tue, 24 Jan 2023 08:02:42 +0100 Subject: [PATCH 05/63] change c.fi to s.nif --- db/changes/10503-november/01-sage_supplierAdd.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/changes/10503-november/01-sage_supplierAdd.sql b/db/changes/10503-november/01-sage_supplierAdd.sql index cd68ebfcb..66cb0aff1 100644 --- a/db/changes/10503-november/01-sage_supplierAdd.sql +++ b/db/changes/10503-november/01-sage_supplierAdd.sql @@ -93,7 +93,7 @@ BEGIN s.name, IFNULL(s.street, ''), s.account, - TRIM(IF(s.isVies, CONCAT(co.code,c.fi), s.nif)), + TRIM(IF(s.isVies, CONCAT(co.code,s.nif), s.nif)), IF(n.NacionCEE, TRIM(CONCAT(co.code, IF(co.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif) - 1), s.nif))), ''), IFNULL(s.postCode,''), IFNULL(s.city, ''), From ef6b06e1479bed656b15bdf9719f902c3c5fb9df Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Wed, 25 Jan 2023 14:44:00 +0100 Subject: [PATCH 06/63] added logs --- back/methods/image/upload.js | 3 ++- back/models/image.js | 3 ++- modules/item/back/models/item.js | 24 ++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/back/methods/image/upload.js b/back/methods/image/upload.js index 676a4b5fb..6e5b80f81 100644 --- a/back/methods/image/upload.js +++ b/back/methods/image/upload.js @@ -40,6 +40,7 @@ module.exports = Self => { const TempContainer = models.TempContainer; const fileOptions = {}; const args = ctx.args; + const user = ctx.req.accessToken.userId; let srcFile; try { @@ -59,7 +60,7 @@ module.exports = Self => { const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name); srcFile = path.join(file.client.root, file.container, file.name); - await models.Image.registerImage(args.collection, srcFile, args.fileName, args.id); + await models.Image.registerImage(args.collection, srcFile, args.fileName, args.id, user); } catch (e) { if (fs.existsSync(srcFile)) await fs.unlink(srcFile); diff --git a/back/models/image.js b/back/models/image.js index d736e924f..f7063c654 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -46,7 +46,7 @@ module.exports = Self => { }).bitmap; } - Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => { + Self.registerImage = async(collectionName, srcFilePath, fileName, entityId, user) => { const models = Self.app.models; const tx = await Self.beginTransaction({}); const myOptions = {transaction: tx}; @@ -140,6 +140,7 @@ module.exports = Self => { const item = await model.findById(entityId, null, myOptions); if (item) { + collection.model == 'item' ? fileName = fileName + '-' + user : fileName; await item.updateAttribute( collection.property, fileName, diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index 03a6fb721..acccf617b 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -21,14 +21,34 @@ module.exports = Self => { Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'}); Self.observe('before save', async function(ctx) { - let currentInstance = ctx.currentInstance; + let instance = ctx.currentInstance; let oldInstance; let newInstance; ctx.hookState.oldInstance === undefined ? oldInstance = false : oldInstance = ctx.hookState.oldInstance; ctx.hookState.newInstance === undefined ? newInstance = false : newInstance = ctx.hookState.newInstance; if (oldInstance.image && newInstance.image) { - let query = `UPDATE vn.item SET doPhoto = 0 WHERE id = ${currentInstance.id}`; + let image = newInstance.image.split('-')[0]; + let user = newInstance.image.split('-')[1]; + + ctx.hookState.newInstance.image = image; + + let query = `UPDATE vn.item SET doPhoto=0 WHERE id = ${instance.id}`; await Self.rawSql(query); + let logQuery = + 'INSERT INTO vn.itemLog(originFk, userFk, action, creationDate, description, oldInstance, newInstance) ' + + 'VALUES (?, ?, ?, ?, ?, ?, ?)'; + + let logParams = [ + instance.id, + user, + 'update', + new Date(), + 'Image', + JSON.stringify(oldInstance), + JSON.stringify(newInstance) + ]; + + await Self.rawSql(logQuery, logParams); } await Self.availableId(ctx); }); From 7614b48c9a150ee12c036ccc71d2dc9c4472b5de Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 30 Jan 2023 11:44:14 +0100 Subject: [PATCH 07/63] refs #5115 transfer_sales --- .../ticket/specs/transferSales.spec.js | 28 ------------------- .../back/methods/ticket/transferSales.js | 3 +- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js index cd2ce8599..270aae2f8 100644 --- a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js +++ b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js @@ -80,34 +80,6 @@ describe('sale transferSales()', () => { expect(error.message).toEqual(`Can't transfer claimed sales`); }); - it('should be able to transfer claimed sales if the role is claimManager', async() => { - const tx = await models.Ticket.beginTransaction({}); - - let error; - try { - const options = {transaction: tx}; - - const claimManagerId = 72; - const myActiveCtx = { - accessToken: {userId: claimManagerId}, - }; - const myCtx = {req: myActiveCtx}; - - const ticketId = 11; - const receiverTicketId = null; - const sales = await models.Ticket.getSales(ticketId, options); - - await models.Ticket.transferSales(myCtx, ticketId, receiverTicketId, sales, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error).toBeUndefined(); - }); - it('should transfer the sales from a ticket to a new one', async() => { const tx = await models.Ticket.beginTransaction({}); diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js index 1b8476184..57f620f3d 100644 --- a/modules/ticket/back/methods/ticket/transferSales.js +++ b/modules/ticket/back/methods/ticket/transferSales.js @@ -77,9 +77,8 @@ module.exports = Self => { const saleIds = sales.map(sale => sale.id); - const isClaimManager = await models.Account.hasRole(userId, 'claimManager'); const hasClaimedSales = await models.ClaimBeginning.findOne({where: {saleFk: {inq: saleIds}}}); - if (hasClaimedSales && !isClaimManager) + if (hasClaimedSales) throw new UserError(`Can't transfer claimed sales`); for (const sale of sales) { From 6709012e597afa5d2017d6cf07561d61ec9b4d8a Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Mon, 30 Jan 2023 12:33:28 +0100 Subject: [PATCH 08/63] refs #5070 @2h refactor goToBuscaman method --- modules/route/front/tickets/index.html | 9 ++++++++- modules/route/front/tickets/index.js | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index dae894ac7..f95ff08af 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -91,7 +91,14 @@ {{::ticket.street}} - {{::ticket.city}} + + {{::ticket.city}} + {{::ticket.postalCode}} { @@ -96,7 +97,9 @@ class Controller extends Section { addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street; }); - window.open(url + addresses, '_blank'); + if (clickedLine) addresses = addresses.replace(address + '+to:', '',); + + window.open(url + encodeURI(addresses), '_blank'); }); } From 5c0354bc1755f4ba61831f99aa1c0c752643035c Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 31 Jan 2023 14:26:57 +0100 Subject: [PATCH 09/63] add method to check if the ticket has refunds --- .../ticket/back/methods/ticket/setDeleted.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index cec8096a6..28488ade6 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -42,6 +42,11 @@ module.exports = Self => { if (!isEditable) throw new UserError(`The sales of this ticket can't be modified`); + const hasRefunds = await checkRefunds(id, myOptions); + + if (hasRefunds) + throw new UserError(`You must delete the refund id %d first`, 'DELETE_REFUND_FIRST', hasRefunds); + // Check if has sales with shelving const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', myOptions); const sales = await models.Sale.find({ @@ -150,4 +155,16 @@ module.exports = Self => { throw e; } }; + + async function checkRefunds(id, options) { + const models = Self.app.models; + let refunds = await models.TicketRefund.find({ + where: {ticketFk: id} + }, options); + + if (refunds.length > 0) + return refunds[0].refundTicketFk; + else + return false; + } }; From e3de54b81109e98541be7374ea1c2ca295c7be5f Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Fri, 3 Feb 2023 08:35:15 +0100 Subject: [PATCH 10/63] changed styles on summary --- modules/item/front/summary/index.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index 8f958bd3b..e6746eedf 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -65,19 +65,23 @@ {{$ctrl.summary.item.itemType.worker.user.name}} - + - + + + + - + + - +

From 4a562c311022261165a1246b99d98610abb744bb Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 7 Feb 2023 15:40:03 +0100 Subject: [PATCH 11/63] unificado todo a claimState isEditable --- db/changes/230601/00-acl_claim.sql | 6 ++++ db/dump/fixtures.sql | 8 ++--- .../{claim => claim-state}/isEditable.js | 29 +++++++------------ .../specs/isEditable.spec.js | 16 +++++----- .../claim/back/methods/claim/getSummary.js | 13 +++++---- .../claim/back/methods/claim/updateClaim.js | 22 +++----------- modules/claim/back/models/claim-beginning.js | 22 +++++++++++++- modules/claim/back/models/claim-state.js | 3 ++ modules/claim/back/models/claim.js | 1 - modules/claim/front/detail/index.js | 2 +- 10 files changed, 65 insertions(+), 57 deletions(-) create mode 100644 db/changes/230601/00-acl_claim.sql rename modules/claim/back/methods/{claim => claim-state}/isEditable.js (52%) rename modules/claim/back/methods/{claim => claim-state}/specs/isEditable.spec.js (76%) create mode 100644 modules/claim/back/models/claim-state.js diff --git a/db/changes/230601/00-acl_claim.sql b/db/changes/230601/00-acl_claim.sql new file mode 100644 index 000000000..ea96e130a --- /dev/null +++ b/db/changes/230601/00-acl_claim.sql @@ -0,0 +1,6 @@ +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) + VALUES('ClaimBeginning', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee'); + +DELETE FROM salix.ACL + WHERE model='Claim' AND property='isEditable'; + diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5c7bbf192..94b815107 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1766,12 +1766,12 @@ INSERT INTO `vn`.`clientSample`(`id`, `clientFk`, `typeFk`, `created`, `workerFk INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`) VALUES ( 1, 'pending', 'Pendiente', 1, 1, 0), - ( 2, 'managed', 'Gestionado', 1, 5, 0), + ( 2, 'managed', 'Gestionado', 72, 5, 0), ( 3, 'resolved', 'Resuelto', 72, 7, 0), ( 4, 'canceled', 'Anulado', 72, 6, 1), - ( 5, 'incomplete', 'Incompleta', 72, 3, 1), - ( 6, 'mana', 'Mana', 1, 4, 0), - ( 7, 'lack', 'Faltas', 1, 2, 0); + ( 5, 'incomplete', 'Incompleta', 1, 3, 1), + ( 6, 'mana', 'Mana', 72, 4, 0), + ( 7, 'lack', 'Faltas', 72, 2, 0); INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`) VALUES diff --git a/modules/claim/back/methods/claim/isEditable.js b/modules/claim/back/methods/claim-state/isEditable.js similarity index 52% rename from modules/claim/back/methods/claim/isEditable.js rename to modules/claim/back/methods/claim-state/isEditable.js index cd14d70c7..b144f0a53 100644 --- a/modules/claim/back/methods/claim/isEditable.js +++ b/modules/claim/back/methods/claim-state/isEditable.js @@ -1,12 +1,12 @@ module.exports = Self => { Self.remoteMethodCtx('isEditable', { - description: 'Check if a claim is editable', + description: 'Check if an state is editable', accessType: 'READ', accepts: [{ arg: 'id', type: 'number', required: true, - description: 'the claim id', + description: 'the st id', http: {source: 'path'} }], returns: { @@ -21,25 +21,18 @@ module.exports = Self => { Self.isEditable = async(ctx, id, options) => { const userId = ctx.req.accessToken.userId; + const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - - const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager', myOptions); - - const claim = await Self.app.models.Claim.findById(id, { - fields: ['claimStateFk'], - include: [{ - relation: 'claimState' - }] - }, myOptions); - - const isClaimResolved = claim && claim.claimState().code == 'resolved'; - - if (!claim || (isClaimResolved && !isClaimManager)) - return false; - - return true; + + const state = await models.ClaimState.findById(id, { + include: { + relation: 'writeRole' + } + }, myOptions); + const roleWithGrants = state && state.writeRole().name; + return await models.Account.hasRole(userId, roleWithGrants, myOptions); }; }; diff --git a/modules/claim/back/methods/claim/specs/isEditable.spec.js b/modules/claim/back/methods/claim-state/specs/isEditable.spec.js similarity index 76% rename from modules/claim/back/methods/claim/specs/isEditable.spec.js rename to modules/claim/back/methods/claim-state/specs/isEditable.spec.js index 3afea7843..4ce7af1c2 100644 --- a/modules/claim/back/methods/claim/specs/isEditable.spec.js +++ b/modules/claim/back/methods/claim-state/specs/isEditable.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); -describe('claim isEditable()', () => { - const salesPerdonId = 18; +describe('claimstate isEditable()', () => { + const salesPersonId = 18; const claimManagerId = 72; it('should return false if the given claim does not exist', async() => { const tx = await app.models.Claim.beginTransaction({}); @@ -10,7 +10,7 @@ describe('claim isEditable()', () => { const options = {transaction: tx}; const ctx = {req: {accessToken: {userId: claimManagerId}}}; - const result = await app.models.Claim.isEditable(ctx, 99999, options); + const result = await app.models.ClaimState.isEditable(ctx, 9999, options); expect(result).toEqual(false); @@ -27,8 +27,8 @@ describe('claim isEditable()', () => { try { const options = {transaction: tx}; - const ctx = {req: {accessToken: {userId: salesPerdonId}}}; - const result = await app.models.Claim.isEditable(ctx, 4, options); + const ctx = {req: {accessToken: {userId: salesPersonId}}}; + const result = await app.models.ClaimState.isEditable(ctx, 3, options); expect(result).toEqual(false); @@ -46,7 +46,7 @@ describe('claim isEditable()', () => { const options = {transaction: tx}; const ctx = {req: {accessToken: {userId: claimManagerId}}}; - const result = await app.models.Claim.isEditable(ctx, 4, options); + const result = await app.models.ClaimState.isEditable(ctx, 3, options); expect(result).toEqual(true); @@ -63,8 +63,8 @@ describe('claim isEditable()', () => { try { const options = {transaction: tx}; - const ctx = {req: {accessToken: {userId: salesPerdonId}}}; - const result = await app.models.Claim.isEditable(ctx, 1, options); + const ctx = {req: {accessToken: {userId: claimManagerId}}}; + const result = await app.models.ClaimState.isEditable(ctx, 7, options); expect(result).toEqual(true); diff --git a/modules/claim/back/methods/claim/getSummary.js b/modules/claim/back/methods/claim/getSummary.js index ca376f853..d384f7ebb 100644 --- a/modules/claim/back/methods/claim/getSummary.js +++ b/modules/claim/back/methods/claim/getSummary.js @@ -65,7 +65,8 @@ module.exports = Self => { ] }; - promises.push(Self.app.models.Claim.find(filter, myOptions)); + const models = Self.app.models; + promises.push(models.Claim.find(filter, myOptions)); // Claim detail filter = { @@ -82,7 +83,7 @@ module.exports = Self => { } ] }; - promises.push(Self.app.models.ClaimBeginning.find(filter, myOptions)); + promises.push(models.ClaimBeginning.find(filter, myOptions)); // Claim observations filter = { @@ -96,7 +97,7 @@ module.exports = Self => { } ] }; - promises.push(Self.app.models.ClaimObservation.find(filter, myOptions)); + promises.push(models.ClaimObservation.find(filter, myOptions)); // Claim developments filter = { @@ -128,7 +129,7 @@ module.exports = Self => { } ] }; - promises.push(Self.app.models.ClaimDevelopment.find(filter, myOptions)); + promises.push(models.ClaimDevelopment.find(filter, myOptions)); // Claim action filter = { @@ -145,11 +146,11 @@ module.exports = Self => { {relation: 'claimBeggining'} ] }; - promises.push(Self.app.models.ClaimEnd.find(filter, myOptions)); + promises.push(models.ClaimEnd.find(filter, myOptions)); const res = await Promise.all(promises); - summary.isEditable = await Self.isEditable(ctx, id, myOptions); + summary.isEditable = await models.ClaimState.isEditable(ctx, res[0][0].claimStateFk, myOptions); [summary.claim] = res[0]; summary.salesClaimed = res[1]; summary.observations = res[2]; diff --git a/modules/claim/back/methods/claim/updateClaim.js b/modules/claim/back/methods/claim/updateClaim.js index cc9937c19..5271136d6 100644 --- a/modules/claim/back/methods/claim/updateClaim.js +++ b/modules/claim/back/methods/claim/updateClaim.js @@ -2,6 +2,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethod('updateClaim', { description: 'Update a claim with privileges', + accessType: 'WRITE', accepts: [{ arg: 'ctx', type: 'object', @@ -78,11 +79,11 @@ module.exports = Self => { // Validate when claimState has been changed if (args.claimStateFk) { - const canUpdate = await canChangeState(ctx, claim.claimStateFk, myOptions); - const hasRights = await canChangeState(ctx, args.claimStateFk, myOptions); + const canEditOldState = await models.ClaimState.isEditable(ctx, claim.claimStateFk, myOptions); + const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions); const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions); - if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager) + if (!canEditOldState || !canEditNewState || changedHasToPickUp && !isClaimManager) throw new UserError(`You don't have enough privileges to change that field`); } @@ -113,21 +114,6 @@ module.exports = Self => { } }; - async function canChangeState(ctx, id, options) { - let models = Self.app.models; - let userId = ctx.req.accessToken.userId; - - let state = await models.ClaimState.findById(id, { - include: { - relation: 'writeRole' - } - }, options); - let stateRole = state.writeRole().name; - let canUpdate = await models.Account.hasRole(userId, stateRole, options); - - return canUpdate; - } - async function notifyStateChange(ctx, workerId, claim, state) { const models = Self.app.models; const origin = ctx.req.headers.origin; diff --git a/modules/claim/back/models/claim-beginning.js b/modules/claim/back/models/claim-beginning.js index 681aaebc7..4283e37e2 100644 --- a/modules/claim/back/models/claim-beginning.js +++ b/modules/claim/back/models/claim-beginning.js @@ -22,8 +22,28 @@ module.exports = Self => { async function claimIsEditable(ctx) { const loopBackContext = LoopBackContext.getCurrentContext(); const httpCtx = {req: loopBackContext.active}; + const models = Self.app.models; + const myOptions = {}; + + if (ctx.options && ctx.options.transaction) + myOptions.transaction = ctx.options.transaction; + const claimBeginning = await Self.findById(ctx.where.id); - const isEditable = await Self.app.models.Claim.isEditable(httpCtx, claimBeginning.claimFk); + + const filter = { + where: {id: claimBeginning.claimFk}, + include: [ + { + relation: 'claimState', + scope: { + fields: ['id', 'code', 'description'] + } + } + ] + }; + + const [claim] = await models.Claim.find(filter, myOptions); + const isEditable = await models.ClaimState.isEditable(httpCtx, claim.ClaimState()); if (!isEditable) throw new UserError(`The current claim can't be modified`); diff --git a/modules/claim/back/models/claim-state.js b/modules/claim/back/models/claim-state.js new file mode 100644 index 000000000..e0df5ac4d --- /dev/null +++ b/modules/claim/back/models/claim-state.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/claim-state/isEditable')(Self); +}; diff --git a/modules/claim/back/models/claim.js b/modules/claim/back/models/claim.js index c9d7ee7d4..5989b44cc 100644 --- a/modules/claim/back/models/claim.js +++ b/modules/claim/back/models/claim.js @@ -6,7 +6,6 @@ module.exports = Self => { require('../methods/claim/regularizeClaim')(Self); require('../methods/claim/uploadFile')(Self); require('../methods/claim/updateClaimAction')(Self); - require('../methods/claim/isEditable')(Self); require('../methods/claim/updateClaimDestination')(Self); require('../methods/claim/downloadFile')(Self); require('../methods/claim/claimPickupPdf')(Self); diff --git a/modules/claim/front/detail/index.js b/modules/claim/front/detail/index.js index 7c3c04f44..33ce1a581 100644 --- a/modules/claim/front/detail/index.js +++ b/modules/claim/front/detail/index.js @@ -151,7 +151,7 @@ class Controller extends Section { isClaimEditable() { if (!this.claim) return; - this.$http.get(`Claims/${this.claim.id}/isEditable`).then(res => { + this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => { this.isRewritable = res.data; }); } From df38f30f74c071c4adda2ccebe00a44d5b864489 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 15 Feb 2023 09:10:55 +0100 Subject: [PATCH 12/63] se incluyen los test intermintents que estaban incluidos --- .../invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js | 1 - .../back/methods/invoiceOut/specs/downloadZip.spec.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js index 26eae45ac..803338ef3 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js @@ -11,7 +11,6 @@ describe('InvoiceOut createPdf()', () => { const ctx = {req: activeCtx}; it('should create a new PDF file and set true the hasPdf property', async() => { - pending('https://redmine.verdnatura.es/issues/5035'); const invoiceId = 1; spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js index 0f62a6876..41ea45487 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js @@ -30,8 +30,6 @@ describe('InvoiceOut downloadZip()', () => { }); it('should return an error if the size of the files is too large', async() => { - pending('https://redmine.verdnatura.es/issues/5035'); - const tx = await models.InvoiceOut.beginTransaction({}); let error; From 5ecf55a1e7be056f9398019b19c1ea09806bd901 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 15 Feb 2023 09:51:27 +0100 Subject: [PATCH 13/63] movida sql a carpeta changes actual --- db/changes/{224903 => 230401}/00-supplierIsVies.sql | 0 db/changes/{224903 => 230401}/01-sage_supplierAdd.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename db/changes/{224903 => 230401}/00-supplierIsVies.sql (100%) rename db/changes/{224903 => 230401}/01-sage_supplierAdd.sql (100%) diff --git a/db/changes/224903/00-supplierIsVies.sql b/db/changes/230401/00-supplierIsVies.sql similarity index 100% rename from db/changes/224903/00-supplierIsVies.sql rename to db/changes/230401/00-supplierIsVies.sql diff --git a/db/changes/224903/01-sage_supplierAdd.sql b/db/changes/230401/01-sage_supplierAdd.sql similarity index 100% rename from db/changes/224903/01-sage_supplierAdd.sql rename to db/changes/230401/01-sage_supplierAdd.sql From fda428d73e9b1e28d09cb25ee700453ef901de50 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 15 Feb 2023 09:52:35 +0100 Subject: [PATCH 14/63] refactor: change user --- db/changes/230401/00-supplierIsVies.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/changes/230401/00-supplierIsVies.sql b/db/changes/230401/00-supplierIsVies.sql index 0af1a61ab..5861e7615 100644 --- a/db/changes/230401/00-supplierIsVies.sql +++ b/db/changes/230401/00-supplierIsVies.sql @@ -7,7 +7,7 @@ WHERE s.nif <> TRIM(IF(c.code = LEFT(s.nif, 2), MID(s.nif, 3, LENGTH(s.nif)-1), INSERT IGNORE INTO `vn`.`chat` (senderFk, recipient, checkUserStatus, message, status, attempts) -VALUES(19294, '#informatica-cau', 0, ' +VALUES(19263, '#informatica-cau', 0, ' ``` UPDATE `vn`.`supplier` s JOIN vn.country c ON c.id = s.countryFk From 443118a7ac25406993bd6a66e91def9ec28b403d Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 15 Feb 2023 12:37:31 +0100 Subject: [PATCH 15/63] esto se debe BORRAR --- back/tests.js | 4 +++- modules/invoiceOut/back/methods/invoiceOut/createPdf.js | 3 ++- .../invoiceOut/back/methods/invoiceOut/specs/filter.spec.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/back/tests.js b/back/tests.js index ab6893791..20118c0e0 100644 --- a/back/tests.js +++ b/back/tests.js @@ -34,6 +34,8 @@ async function test() { const Jasmine = require('jasmine'); const jasmine = new Jasmine(); + jasmine.seed('02137'); + // jasmine.randomizeTests(false); const SpecReporter = require('jasmine-spec-reporter').SpecReporter; jasmine.addReporter(new SpecReporter({ @@ -63,7 +65,7 @@ async function test() { jasmine.loadConfig({ spec_dir: '.', spec_files: backSpecs, - helpers: [], + helpers: [] }); await jasmine.execute(); diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index e56516237..18b5e796a 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -44,7 +44,8 @@ module.exports = Self => { try { const invoiceOut = await Self.findById(id, null, myOptions); const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions); - + console.log(hasInvoicing); + console.log(invoiceOut); if (invoiceOut.hasPdf && !hasInvoicing) throw new UserError(`You don't have enough privileges`); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js index d3d789393..15e3e887e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js @@ -66,7 +66,7 @@ describe('InvoiceOut filter()', () => { const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options); - expect(result.length).toBeGreaterThanOrEqual(1); + expect(result.length).toEqual(1); await tx.rollback(); } catch (e) { From c69679e204eee44b4ddf352d35ec3667e564d383 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 16 Feb 2023 12:02:36 +0100 Subject: [PATCH 16/63] test --- back/tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/tests.js b/back/tests.js index 20118c0e0..28497fd91 100644 --- a/back/tests.js +++ b/back/tests.js @@ -34,7 +34,7 @@ async function test() { const Jasmine = require('jasmine'); const jasmine = new Jasmine(); - jasmine.seed('02137'); + jasmine.seed('68436'); // jasmine.randomizeTests(false); const SpecReporter = require('jasmine-spec-reporter').SpecReporter; From 77c454f95330a836c2593ff9839d96fd8b925f61 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 17 Feb 2023 10:45:08 +0100 Subject: [PATCH 17/63] move sql changes and add changelog --- CHANGELOG.md | 2 +- db/changes/{230401 => 230801}/00-supplierIsVies.sql | 0 db/changes/{230401 => 230801}/01-sage_supplierAdd.sql | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename db/changes/{230401 => 230801}/00-supplierIsVies.sql (100%) rename db/changes/{230401 => 230801}/01-sage_supplierAdd.sql (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80fa1fb95..53779316a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2308.01] - 2023-03-09 ### Added -- +- (Proveedores -> Datos fiscales) Añadido checkbox 'Vies' ### Changed - diff --git a/db/changes/230401/00-supplierIsVies.sql b/db/changes/230801/00-supplierIsVies.sql similarity index 100% rename from db/changes/230401/00-supplierIsVies.sql rename to db/changes/230801/00-supplierIsVies.sql diff --git a/db/changes/230401/01-sage_supplierAdd.sql b/db/changes/230801/01-sage_supplierAdd.sql similarity index 100% rename from db/changes/230401/01-sage_supplierAdd.sql rename to db/changes/230801/01-sage_supplierAdd.sql From c7f22a10bab9c37130adf7b04f7635dba413bd55 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 20 Feb 2023 10:39:12 +0100 Subject: [PATCH 18/63] refs #5063 refactored hook --- back/methods/image/upload.js | 3 +- back/models/image.js | 4 +-- modules/item/back/models/item.js | 58 ++++++++++++-------------------- 3 files changed, 25 insertions(+), 40 deletions(-) diff --git a/back/methods/image/upload.js b/back/methods/image/upload.js index 6e5b80f81..676a4b5fb 100644 --- a/back/methods/image/upload.js +++ b/back/methods/image/upload.js @@ -40,7 +40,6 @@ module.exports = Self => { const TempContainer = models.TempContainer; const fileOptions = {}; const args = ctx.args; - const user = ctx.req.accessToken.userId; let srcFile; try { @@ -60,7 +59,7 @@ module.exports = Self => { const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name); srcFile = path.join(file.client.root, file.container, file.name); - await models.Image.registerImage(args.collection, srcFile, args.fileName, args.id, user); + await models.Image.registerImage(args.collection, srcFile, args.fileName, args.id); } catch (e) { if (fs.existsSync(srcFile)) await fs.unlink(srcFile); diff --git a/back/models/image.js b/back/models/image.js index e8cab11aa..ba92ee383 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -46,7 +46,7 @@ module.exports = Self => { }).bitmap; } - Self.registerImage = async(collectionName, srcFilePath, fileName, entityId, user) => { + Self.registerImage = async(collectionName, srcFilePath, fileName, entityId) => { const models = Self.app.models; const tx = await Self.beginTransaction({}); const myOptions = {transaction: tx}; @@ -140,7 +140,7 @@ module.exports = Self => { const item = await model.findById(entityId, null, myOptions); if (item) { - collection.model == 'item' ? fileName = fileName + '-' + user : fileName; + if (collection.model == 'Item') fileName += '#'; await item.updateAttribute( collection.property, fileName, diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index acccf617b..ec4be2f7b 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -21,52 +21,38 @@ module.exports = Self => { Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'}); Self.observe('before save', async function(ctx) { - let instance = ctx.currentInstance; - let oldInstance; - let newInstance; - ctx.hookState.oldInstance === undefined ? oldInstance = false : oldInstance = ctx.hookState.oldInstance; - ctx.hookState.newInstance === undefined ? newInstance = false : newInstance = ctx.hookState.newInstance; - if (oldInstance.image && newInstance.image) { - let image = newInstance.image.split('-')[0]; - let user = newInstance.image.split('-')[1]; + if (ctx.isNewInstance) await Self.availableId(ctx); + else { + const changes = ctx.data || ctx.instance; + const orgData = ctx.currentInstance; - ctx.hookState.newInstance.image = image; + const hasChanges = orgData && changes; + const image = changes.image || orgData.image; + const imageChanged = hasChanges && orgData.image != image; - let query = `UPDATE vn.item SET doPhoto=0 WHERE id = ${instance.id}`; - await Self.rawSql(query); - let logQuery = - 'INSERT INTO vn.itemLog(originFk, userFk, action, creationDate, description, oldInstance, newInstance) ' + - 'VALUES (?, ?, ?, ?, ?, ?, ?)'; - - let logParams = [ - instance.id, - user, - 'update', - new Date(), - 'Image', - JSON.stringify(oldInstance), - JSON.stringify(newInstance) - ]; - - await Self.rawSql(logQuery, logParams); + if (imageChanged) { + try { + changes.image = changes.image.slice(0, -1); + if (orgData.isPhotoRequested == true) changes.isPhotoRequested = false; + } catch (e) { + throw new UserError(e); + } + } } - await Self.availableId(ctx); }); Self.availableId = async function(ctx) { - if (ctx.isNewInstance) { - try { - let query = `SELECT i1.id + 1 as id FROM vn.item i1 + try { + let query = `SELECT i1.id + 1 as id FROM vn.item i1 LEFT JOIN vn.item i2 ON i1.id + 1 = i2.id WHERE i2.id IS NULL ORDER BY i1.id LIMIT 1`; - let newId = await Self.rawSql(query); + let newId = await Self.rawSql(query); - ctx.instance.id = newId[0].id; - return ctx.instance.id; - } catch (e) { - throw new UserError(e); - } + ctx.instance.id = newId[0].id; + return ctx.instance.id; + } catch (e) { + throw new UserError(e); } }; }; From 04877c1425a036816f5375e03930b75891d51b3a Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 20 Feb 2023 13:15:47 +0100 Subject: [PATCH 19/63] refs #5063 refactor hook --- modules/item/back/methods/item/new.js | 6 ++---- modules/item/front/summary/index.html | 25 ------------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/modules/item/back/methods/item/new.js b/modules/item/back/methods/item/new.js index 0bd9035cf..d066f2c9f 100644 --- a/modules/item/back/methods/item/new.js +++ b/modules/item/back/methods/item/new.js @@ -24,8 +24,6 @@ module.exports = Self => { const myOptions = {}; let tx; - params.isPhotoRequested = true; - if (typeof options == 'object') Object.assign(myOptions, options); @@ -40,8 +38,7 @@ module.exports = Self => { 'intrastatFk', 'originFk', 'priority', - 'tag', - 'isPhotoRequested' + 'tag' ]; for (const key in params) { @@ -60,6 +57,7 @@ module.exports = Self => { const itemType = await models.ItemType.findById(params.typeFk, {fields: ['isLaid']}, myOptions); params.isLaid = itemType.isLaid; + params.isPhotoRequested = true; const item = await models.Item.create(params, myOptions); diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index c604f5c8f..46a2baef4 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -75,31 +75,6 @@ {{$ctrl.summary.item.itemType.worker.user.name}} - - - - - - - - - - - - Date: Mon, 20 Feb 2023 13:35:50 +0100 Subject: [PATCH 20/63] add console.log --- modules/invoiceOut/back/methods/invoiceOut/createPdf.js | 1 - modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index 18b5e796a..65eaae657 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -44,7 +44,6 @@ module.exports = Self => { try { const invoiceOut = await Self.findById(id, null, myOptions); const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions); - console.log(hasInvoicing); console.log(invoiceOut); if (invoiceOut.hasPdf && !hasInvoicing) throw new UserError(`You don't have enough privileges`); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js index 15e3e887e..9264bf77d 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js @@ -65,6 +65,7 @@ describe('InvoiceOut filter()', () => { await invoiceOut.updateAttribute('hasPdf', true, options); const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options); + console.log(result); expect(result.length).toEqual(1); From 7a812551b3aebf5a8932446aa8f6dc2080066496 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 20 Feb 2023 13:56:17 +0100 Subject: [PATCH 21/63] delete seed --- back/tests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/back/tests.js b/back/tests.js index 28497fd91..591548d59 100644 --- a/back/tests.js +++ b/back/tests.js @@ -34,8 +34,7 @@ async function test() { const Jasmine = require('jasmine'); const jasmine = new Jasmine(); - jasmine.seed('68436'); - // jasmine.randomizeTests(false); + // jasmine.seed('68436'); const SpecReporter = require('jasmine-spec-reporter').SpecReporter; jasmine.addReporter(new SpecReporter({ From 432c8a9ab8898bedfcc08fb5bbbd255e38cae335 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 21 Feb 2023 10:56:46 +0100 Subject: [PATCH 22/63] refactor: cambiados estilos de los chips --- front/core/components/chip/style.scss | 27 +++++++++++- modules/ticket/front/sale-tracking/index.html | 44 ++++++++++++++++--- modules/ticket/front/sale-tracking/index.js | 25 ----------- modules/ticket/front/sale-tracking/style.scss | 11 +++-- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/front/core/components/chip/style.scss b/front/core/components/chip/style.scss index 7651638be..562861441 100644 --- a/front/core/components/chip/style.scss +++ b/front/core/components/chip/style.scss @@ -58,10 +58,33 @@ vn-chip { background-color: $color-font-bg-dark; color: $color-font-bg; } + &.pink, + &.pink.clickable:hover, + &.pink.clickable:focus { + background-color: $color-pink; + } + &.dark-notice, + &.dark-notice.clickable:hover, + &.dark-notice.clickable:focus { + background-color: $color-notice; + } + &.yellow, + &.yellow.clickable:hover, + &.yellow.clickable:focus { + background-color: $color-yellow; + } + &.none, + &.none.clickable:hover, + &.none.clickable:focus { + background-color: $color-bg-panel; + border-radius: 50%; + border: 1px solid $color-font-link + + } &.clickable { @extend %clickable; opacity: 0.8; - + &:hover, &:focus { opacity: 1; @@ -118,4 +141,4 @@ vn-avatar { display: inline-block; min-width: 28px; border-radius: 50%; -} \ No newline at end of file +} diff --git a/modules/ticket/front/sale-tracking/index.html b/modules/ticket/front/sale-tracking/index.html index 8d3f414c2..33d22f92e 100644 --- a/modules/ticket/front/sale-tracking/index.html +++ b/modules/ticket/front/sale-tracking/index.html @@ -24,12 +24,44 @@ - - - - - - + + + + + + + + + + + Date: Fri, 24 Feb 2023 10:25:08 +0100 Subject: [PATCH 23/63] refs #5063 deleted item checked in image, added front test --- back/models/image.js | 1 - modules/item/back/models/item.js | 33 ++++++--------------- modules/item/front/descriptor/index.js | 5 ++++ modules/item/front/descriptor/index.spec.js | 16 +++++++++- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/back/models/image.js b/back/models/image.js index ba92ee383..37f4ec20d 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -140,7 +140,6 @@ module.exports = Self => { const item = await model.findById(entityId, null, myOptions); if (item) { - if (collection.model == 'Item') fileName += '#'; await item.updateAttribute( collection.property, fileName, diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index ec4be2f7b..72b172f48 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -22,37 +22,22 @@ module.exports = Self => { Self.observe('before save', async function(ctx) { if (ctx.isNewInstance) await Self.availableId(ctx); - else { - const changes = ctx.data || ctx.instance; - const orgData = ctx.currentInstance; - - const hasChanges = orgData && changes; - const image = changes.image || orgData.image; - const imageChanged = hasChanges && orgData.image != image; - - if (imageChanged) { - try { - changes.image = changes.image.slice(0, -1); - if (orgData.isPhotoRequested == true) changes.isPhotoRequested = false; - } catch (e) { - throw new UserError(e); - } - } - } }); Self.availableId = async function(ctx) { - try { - let query = `SELECT i1.id + 1 as id FROM vn.item i1 + if (ctx.isNewInstance) { + try { + let query = `SELECT i1.id + 1 as id FROM vn.item i1 LEFT JOIN vn.item i2 ON i1.id + 1 = i2.id WHERE i2.id IS NULL ORDER BY i1.id LIMIT 1`; - let newId = await Self.rawSql(query); + let newId = await Self.rawSql(query); - ctx.instance.id = newId[0].id; - return ctx.instance.id; - } catch (e) { - throw new UserError(e); + ctx.instance.id = newId[0].id; + return ctx.instance.id; + } catch (e) { + throw new UserError(e); + } } }; }; diff --git a/modules/item/front/descriptor/index.js b/modules/item/front/descriptor/index.js index 972c89ae0..f45a5ed1f 100644 --- a/modules/item/front/descriptor/index.js +++ b/modules/item/front/descriptor/index.js @@ -91,6 +91,11 @@ class Controller extends Descriptor { this.$.photo.setAttribute('src', newSrc); this.$.photo.setAttribute('zoom-image', newZoomSrc); + + if (this.item.isPhotoRequested) { + this.$http.patch(`Items/${this.item.id}`, {isPhotoRequested: false}) + .then(() => this.item.isPhotoRequested = false); + } } getWarehouseName(warehouseFk) { diff --git a/modules/item/front/descriptor/index.spec.js b/modules/item/front/descriptor/index.spec.js index 23053432e..8df0b3fa8 100644 --- a/modules/item/front/descriptor/index.spec.js +++ b/modules/item/front/descriptor/index.spec.js @@ -8,7 +8,8 @@ describe('vnItemDescriptor', () => { id: 1, itemType: { warehouseFk: 1 - } + }, + isPhotoRequested: true }; const stock = { visible: 1, @@ -43,4 +44,17 @@ describe('vnItemDescriptor', () => { expect(controller.item).toEqual(item); }); }); + + describe('onUploadResponse()', () => { + it(`should change isPhotoRequested when a new photo is uploaded`, () => { + $httpBackend.expectPATCH(`Items/${item.id}`).respond(); + controller.$rootScope = {imagePath: () => {}}; + controller.$.photo = {setAttribute: () => {}}; + controller.item = item; + controller.onUploadResponse(); + $httpBackend.flush(); + + expect(controller.item.isPhotoRequested).toEqual(false); + }); + }); }); From 6d6fa11da14b8c339c7d314a83ed9e93b69e3037 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 24 Feb 2023 10:37:35 +0100 Subject: [PATCH 24/63] refs #5063 fixed front test --- modules/item/front/descriptor/index.js | 6 ++---- modules/item/front/descriptor/index.spec.js | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/modules/item/front/descriptor/index.js b/modules/item/front/descriptor/index.js index f45a5ed1f..5f38d08dd 100644 --- a/modules/item/front/descriptor/index.js +++ b/modules/item/front/descriptor/index.js @@ -92,10 +92,8 @@ class Controller extends Descriptor { this.$.photo.setAttribute('src', newSrc); this.$.photo.setAttribute('zoom-image', newZoomSrc); - if (this.item.isPhotoRequested) { - this.$http.patch(`Items/${this.item.id}`, {isPhotoRequested: false}) - .then(() => this.item.isPhotoRequested = false); - } + if (this.item.isPhotoRequested) + this.$http.patch(`Items/${this.item.id}`, {isPhotoRequested: false}); } getWarehouseName(warehouseFk) { diff --git a/modules/item/front/descriptor/index.spec.js b/modules/item/front/descriptor/index.spec.js index 8df0b3fa8..dc2a5acf7 100644 --- a/modules/item/front/descriptor/index.spec.js +++ b/modules/item/front/descriptor/index.spec.js @@ -47,14 +47,13 @@ describe('vnItemDescriptor', () => { describe('onUploadResponse()', () => { it(`should change isPhotoRequested when a new photo is uploaded`, () => { - $httpBackend.expectPATCH(`Items/${item.id}`).respond(); + controller.item = item; controller.$rootScope = {imagePath: () => {}}; controller.$.photo = {setAttribute: () => {}}; - controller.item = item; + + $httpBackend.expectPATCH(`Items/${item.id}`).respond(200); controller.onUploadResponse(); $httpBackend.flush(); - - expect(controller.item.isPhotoRequested).toEqual(false); }); }); }); From 698a3396fc19d7265cda9a1faeb7979337813533 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 24 Feb 2023 10:40:24 +0100 Subject: [PATCH 25/63] refs #5063 deleted changes in item hook --- modules/item/back/models/item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index 72b172f48..b8baa97ea 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -21,7 +21,7 @@ module.exports = Self => { Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'}); Self.observe('before save', async function(ctx) { - if (ctx.isNewInstance) await Self.availableId(ctx); + await Self.availableId(ctx); }); Self.availableId = async function(ctx) { From 5d9220c5c0f3292d000da42799b232d6f65ad49a Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 27 Feb 2023 08:39:46 +0100 Subject: [PATCH 26/63] refs #5287 locker added --- CHANGELOG.md | 2 ++ db/changes/230801/.gitkeep | 0 db/changes/230801/00-workerLocker.sql | 1 + e2e/helpers/selectors.js | 2 ++ e2e/paths/03-worker/01_summary.spec.js | 3 +- e2e/paths/03-worker/02_basicData.spec.js | 2 ++ loopback/locale/es.json | 3 +- modules/worker/back/models/worker.js | 4 +++ modules/worker/back/models/worker.json | 3 ++ modules/worker/front/basic-data/index.html | 19 +++++++----- modules/worker/front/basic-data/locale/es.yml | 3 +- modules/worker/front/summary/index.html | 31 ++++++++++--------- modules/worker/front/summary/locale/es.yml | 3 +- 13 files changed, 51 insertions(+), 25 deletions(-) delete mode 100644 db/changes/230801/.gitkeep create mode 100644 db/changes/230801/00-workerLocker.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 17259f545..3388ceb73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - (Client -> Descriptor) Nuevo icono $ con barrotes para los clientes con impago +- (Trabajador -> Datos Básicos) Añadido nuevo campo Taquilla +- (Trabajador -> PDA) Nueva sección ### Changed - diff --git a/db/changes/230801/.gitkeep b/db/changes/230801/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/230801/00-workerLocker.sql b/db/changes/230801/00-workerLocker.sql new file mode 100644 index 000000000..1a7c2e98e --- /dev/null +++ b/db/changes/230801/00-workerLocker.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`worker` ADD locker INT UNSIGNED NULL UNIQUE; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index efaa13ee3..a96b7fd51 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -973,6 +973,7 @@ export default { id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span', email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span', department: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(5) > section > span', + locker: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(10) > section > span', userId: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(2) > section > span', userName: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) > section > span', role: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(4) > section > span', @@ -983,6 +984,7 @@ export default { name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]', surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]', phone: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.phone"]', + locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]', saveButton: 'vn-worker-basic-data button[type=submit]' }, workerPbx: { diff --git a/e2e/paths/03-worker/01_summary.spec.js b/e2e/paths/03-worker/01_summary.spec.js index 4e5b0cfa9..bcb6ad848 100644 --- a/e2e/paths/03-worker/01_summary.spec.js +++ b/e2e/paths/03-worker/01_summary.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Worker summary path', () => { +fdescribe('Worker summary path', () => { const workerId = 3; let browser; let page; @@ -29,5 +29,6 @@ describe('Worker summary path', () => { expect(await page.getProperty(selectors.workerSummary.userName, 'innerText')).toEqual('agency'); expect(await page.getProperty(selectors.workerSummary.role, 'innerText')).toEqual('agency'); expect(await page.getProperty(selectors.workerSummary.extension, 'innerText')).toEqual('1101'); + expect(await page.getProperty(selectors.workerSummary.locker, 'innerText')).toEqual('-'); }); }); diff --git a/e2e/paths/03-worker/02_basicData.spec.js b/e2e/paths/03-worker/02_basicData.spec.js index 66a597dd1..381375dc7 100644 --- a/e2e/paths/03-worker/02_basicData.spec.js +++ b/e2e/paths/03-worker/02_basicData.spec.js @@ -25,6 +25,7 @@ describe('Worker basic data path', () => { await page.overwrite(selectors.workerBasicData.name, 'David C.'); await page.overwrite(selectors.workerBasicData.surname, 'H.'); await page.overwrite(selectors.workerBasicData.phone, '444332211'); + await page.overwrite(selectors.workerBasicData.locker, '1'); await page.click(selectors.workerBasicData.saveButton); const message = await page.waitForSnackbar(); @@ -36,5 +37,6 @@ describe('Worker basic data path', () => { expect(await page.waitToGetProperty(selectors.workerBasicData.name, 'value')).toEqual('David C.'); expect(await page.waitToGetProperty(selectors.workerBasicData.surname, 'value')).toEqual('H.'); expect(await page.waitToGetProperty(selectors.workerBasicData.phone, 'value')).toEqual('444332211'); + expect(await page.waitToGetProperty(selectors.workerBasicData.locker, 'value')).toEqual('1'); }); }); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ad6d53d64..10db9a54f 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -263,6 +263,7 @@ "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", - "There is no assigned email for this client": "No hay correo asignado para este cliente" + "There is no assigned email for this client": "No hay correo asignado para este cliente", + "This locker has already been assigned": "Esta taquilla ya ha sido asignada" } diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index e66259cd0..68baec6ca 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -14,4 +14,8 @@ module.exports = Self => { require('../methods/worker/holidays')(Self); require('../methods/worker/activeContract')(Self); require('../methods/worker/new')(Self); + + Self.validatesUniquenessOf('locker', { + message: 'This locker has already been assigned' + }); }; diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index e3a941dd3..d21094f26 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -55,6 +55,9 @@ }, "code": { "type" : "string" + }, + "locker": { + "type" : "number" } }, "relations": { diff --git a/modules/worker/front/basic-data/index.html b/modules/worker/front/basic-data/index.html index 5a3acdde5..d89d88f2e 100644 --- a/modules/worker/front/basic-data/index.html +++ b/modules/worker/front/basic-data/index.html @@ -11,7 +11,7 @@ @@ -24,14 +24,14 @@ @@ -73,11 +73,16 @@ + + diff --git a/modules/worker/front/basic-data/locale/es.yml b/modules/worker/front/basic-data/locale/es.yml index a83c30d99..edf08de90 100644 --- a/modules/worker/front/basic-data/locale/es.yml +++ b/modules/worker/front/basic-data/locale/es.yml @@ -5,4 +5,5 @@ SSN: NSS Married: Casado/a Single: Soltero/a Business phone: Teléfono de empresa -Mobile extension: Extensión móvil \ No newline at end of file +Mobile extension: Extensión móvil +Locker: Taquilla diff --git a/modules/worker/front/summary/index.html b/modules/worker/front/summary/index.html index 0a6bec822..72b8e729a 100644 --- a/modules/worker/front/summary/index.html +++ b/modules/worker/front/summary/index.html @@ -11,23 +11,23 @@

- Basic data

-

Basic data

- - - - - - + + +

User data

- - - -
- - \ No newline at end of file + diff --git a/modules/worker/front/summary/locale/es.yml b/modules/worker/front/summary/locale/es.yml index e9c8e5583..fb9d2e2ca 100644 --- a/modules/worker/front/summary/locale/es.yml +++ b/modules/worker/front/summary/locale/es.yml @@ -1,3 +1,4 @@ Business phone: Teléfono de empresa Personal phone: Teléfono personal -Mobile extension: Extensión móvil \ No newline at end of file +Mobile extension: Extensión móvil +Locker: Taquilla From 5b7306a9caf365284a48cab85132af18ca097f50 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 27 Feb 2023 08:41:27 +0100 Subject: [PATCH 27/63] refs #5287 f describe --- e2e/paths/03-worker/01_summary.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/03-worker/01_summary.spec.js b/e2e/paths/03-worker/01_summary.spec.js index bcb6ad848..51992b41d 100644 --- a/e2e/paths/03-worker/01_summary.spec.js +++ b/e2e/paths/03-worker/01_summary.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Worker summary path', () => { +describe('Worker summary path', () => { const workerId = 3; let browser; let page; From 94901d5b1f38604cd918f6f979edfc9f7aea8394 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 07:49:34 +0100 Subject: [PATCH 28/63] refs #5287 pda section added, tests added --- db/changes/230801/00-workerLocker.sql | 8 +++ db/dump/fixtures.sql | 27 +++++++ e2e/helpers/selectors.js | 6 ++ e2e/paths/03-worker/07_pda.spec.js | 41 +++++++++++ front/salix/locale/es.yml | 1 + .../worker/back/methods/worker/allocatePDA.js | 66 +++++++++++++++++ .../back/methods/worker/deallocatePDA.js | 53 ++++++++++++++ .../methods/worker/specs/allocatePDA.spec.js | 46 ++++++++++++ .../worker/specs/deallocatePDA.spec.js | 26 +++++++ modules/worker/back/model-config.json | 12 ++++ .../back/models/device-production-models.json | 15 ++++ .../back/models/device-production-state.json | 18 +++++ .../back/models/device-production-user.json | 33 +++++++++ .../worker/back/models/device-production.json | 54 ++++++++++++++ modules/worker/back/models/worker.js | 2 + modules/worker/front/index.js | 1 + modules/worker/front/locale/es.yml | 9 ++- modules/worker/front/pda/index.html | 48 +++++++++++++ modules/worker/front/pda/index.js | 53 ++++++++++++++ modules/worker/front/pda/index.spec.js | 72 +++++++++++++++++++ modules/worker/front/pda/style.scss | 6 ++ modules/worker/front/routes.json | 8 +++ 22 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 e2e/paths/03-worker/07_pda.spec.js create mode 100644 modules/worker/back/methods/worker/allocatePDA.js create mode 100644 modules/worker/back/methods/worker/deallocatePDA.js create mode 100644 modules/worker/back/methods/worker/specs/allocatePDA.spec.js create mode 100644 modules/worker/back/methods/worker/specs/deallocatePDA.spec.js create mode 100644 modules/worker/back/models/device-production-models.json create mode 100644 modules/worker/back/models/device-production-state.json create mode 100644 modules/worker/back/models/device-production-user.json create mode 100644 modules/worker/back/models/device-production.json create mode 100644 modules/worker/front/pda/index.html create mode 100644 modules/worker/front/pda/index.js create mode 100644 modules/worker/front/pda/index.spec.js create mode 100644 modules/worker/front/pda/style.scss diff --git a/db/changes/230801/00-workerLocker.sql b/db/changes/230801/00-workerLocker.sql index 1a7c2e98e..1fcea50ac 100644 --- a/db/changes/230801/00-workerLocker.sql +++ b/db/changes/230801/00-workerLocker.sql @@ -1 +1,9 @@ ALTER TABLE `vn`.`worker` ADD locker INT UNSIGNED NULL UNIQUE; +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('DeviceProduction', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('DeviceProductionModels', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('DeviceProductionState', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('DeviceProductionUser', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'deallocatePDA', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'allocatePDA', '*', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 8fb12e822..c0989f1ed 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2787,3 +2787,30 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) VALUES (1, NULL, 1); +INSERT INTO `vn`.`deviceProductionModels` (`code`) + VALUES + ('BLACKVIEW'), + ('DODGEE'), + ('ZEBRA'); + +INSERT INTO `vn`.`deviceProductionState` (`code`, `description`) + VALUES + ('active', 'activo'), + ('idle', 'inactivo'), + ('lost', 'perdida'), + ('repair', 'reparación'), + ('retired', 'retirada'); + +INSERT INTO `vn`.`deviceProduction` (`imei`, `modelFk`, `macWifi`, `serialNumber`, `android_id`, `purchased`, `stateFk`, `isInScalefusion`, `description`) + VALUES + ('ime1', 'BLACKVIEW', 'macWifi1', 'serialNumber1', 'android_id1', util.VN_NOW(), 'active', 0, NULL), + ('ime2', 'DODGEE', 'macWifi2', 'serialNumber2', 'android_id2', util.VN_NOW(), 'idle', 0, NULL), + ('ime3', 'ZEBRA', 'macWifi3', 'serialNumber3', 'android_id3', util.VN_NOW(), 'active', 0, NULL), + ('ime4', 'BLACKVIEW', 'macWifi4', 'serialNumber4', 'android_id4', util.VN_NOW(), 'idle', 0, NULL); + +INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `created`) + VALUES + (1, 1, util.VN_NOW()), + (3, 3, util.VN_NOW()); + + diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index a96b7fd51..e32bab57d 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1042,6 +1042,12 @@ export default { switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]', createButton: 'vn-worker-create vn-submit[label="Create"]', }, + workerPda: { + currentPDA: 'vn-worker-pda vn-textfield[ng-model="$ctrl.currentPDA.description"]', + newPDA: 'vn-worker-pda vn-autocomplete[ng-model="$ctrl.newPDA"]', + delete: 'vn-worker-pda vn-icon-button[icon=delete]', + submit: 'vn-worker-pda vn-submit[label="Assign"]', + }, invoiceOutIndex: { topbarSearch: 'vn-searchbar', searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr', diff --git a/e2e/paths/03-worker/07_pda.spec.js b/e2e/paths/03-worker/07_pda.spec.js new file mode 100644 index 000000000..f583a9e4f --- /dev/null +++ b/e2e/paths/03-worker/07_pda.spec.js @@ -0,0 +1,41 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Worker pda path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'worker'); + await page.accessToSearchResult('employeeNick'); + await page.accessToSection('worker.card.pda'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should check if worker has already a PDA allocated', async() => { + expect(await page.waitToGetProperty(selectors.workerPda.currentPDA, 'value')).toContain('serialNumber1'); + }); + + it('should deallocate the PDA', async() => { + await page.waitToClick(selectors.workerPda.delete); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('PDA deallocated'); + }); + + it('should allocate a new PDA', async() => { + await page.autocompleteSearch(selectors.workerPda.newPDA, 'serialNumber2'); + await page.waitToClick(selectors.workerPda.submit); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('PDA allocated'); + }); + + it('should check if a new PDA has been allocated', async() => { + expect(await page.waitToGetProperty(selectors.workerPda.currentPDA, 'value')).toContain('serialNumber2'); + }); +}); diff --git a/front/salix/locale/es.yml b/front/salix/locale/es.yml index d92c32b33..bed41c63b 100644 --- a/front/salix/locale/es.yml +++ b/front/salix/locale/es.yml @@ -23,6 +23,7 @@ There is a new version, click here to reload: Hay una nueva versión, pulse aqu Back: Volver Save: Guardar +Assign: Asignar Create: Crear Send: Enviar Delete: Eliminar diff --git a/modules/worker/back/methods/worker/allocatePDA.js b/modules/worker/back/methods/worker/allocatePDA.js new file mode 100644 index 000000000..096718c80 --- /dev/null +++ b/modules/worker/back/methods/worker/allocatePDA.js @@ -0,0 +1,66 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('allocatePDA', { + description: 'Deallocate the worker\'s PDA', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'The worker id', + http: {source: 'path'} + }, { + arg: 'pda', + type: 'number', + required: true, + description: 'The pda id' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/:id/allocatePDA`, + verb: 'POST' + } + }); + + Self.allocatePDA = async(ctx, options) => { + const models = Self.app.models; + const args = ctx.args; + let tx; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const pda = await models.DeviceProduction.findById(args.pda, myOptions); + if (pda.stateFk != 'idle') throw new UserError(`The PDA state is not idle`); + await pda.updateAttributes({stateFk: 'active'}, myOptions); + await models.DeviceProductionUser.create({ + deviceProductionFk: args.pda, + userFk: args.id, + created: new Date() + }, myOptions); + + if (tx) await tx.commit(); + + return { + deviceProductionFk: pda.id, + deviceProduction: { + modelFk: pda.modelFk, + serialNumber: pda.serialNumber + } + }; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/worker/back/methods/worker/deallocatePDA.js b/modules/worker/back/methods/worker/deallocatePDA.js new file mode 100644 index 000000000..7fa7855d1 --- /dev/null +++ b/modules/worker/back/methods/worker/deallocatePDA.js @@ -0,0 +1,53 @@ +module.exports = Self => { + Self.remoteMethodCtx('deallocatePDA', { + description: 'Deallocate the worker\'s PDA', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'The worker id', + http: {source: 'path'} + }, { + arg: 'pda', + type: 'number', + required: true, + description: 'The pda id' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/:id/deallocatePDA`, + verb: 'POST' + } + }); + + Self.deallocatePDA = async(ctx, options) => { + const models = Self.app.models; + const args = ctx.args; + let tx; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const pda = await models.DeviceProduction.findById(args.pda, myOptions); + await pda.updateAttributes({stateFk: 'idle'}, myOptions); + await models.DeviceProductionUser.destroyAll({userFk: args.id, deviceProductionFk: args.pda}, myOptions); + + if (tx) await tx.commit(); + + return pda; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/worker/back/methods/worker/specs/allocatePDA.spec.js b/modules/worker/back/methods/worker/specs/allocatePDA.spec.js new file mode 100644 index 000000000..5c80b6408 --- /dev/null +++ b/modules/worker/back/methods/worker/specs/allocatePDA.spec.js @@ -0,0 +1,46 @@ +const models = require('vn-loopback/server/server').models; + +describe('Worker allocatePDA()', () => { + it('should allocate a new worker\'s PDA', async() => { + const tx = await models.Worker.beginTransaction({}); + try { + const workerWithoutPDA = 1101; + const PDAWithIdleState = 4; + const options = {transaction: tx}; + const ctx = {args: {id: workerWithoutPDA, pda: PDAWithIdleState}}; + + await models.Worker.allocatePDA(ctx, options); + const deviceProduction = await models.DeviceProduction.findById(PDAWithIdleState, null, options); + const deviceProductionUser = await models.DeviceProductionUser + .findById(PDAWithIdleState, null, options); + + expect(deviceProduction.stateFk).toEqual('active'); + expect(deviceProductionUser).not.toBeNull(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should throw error trying to allocate a non idle PDA', async() => { + const tx = await models.Worker.beginTransaction({}); + let error; + try { + const workerWithoutPDA = 1101; + const PDAWithActiveState = 1; + const options = {transaction: tx}; + const ctx = {args: {id: workerWithoutPDA, pda: PDAWithActiveState}}; + + await models.Worker.allocatePDA(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error).toBeDefined(); + }); +}); diff --git a/modules/worker/back/methods/worker/specs/deallocatePDA.spec.js b/modules/worker/back/methods/worker/specs/deallocatePDA.spec.js new file mode 100644 index 000000000..bddd017cd --- /dev/null +++ b/modules/worker/back/methods/worker/specs/deallocatePDA.spec.js @@ -0,0 +1,26 @@ +const models = require('vn-loopback/server/server').models; + +describe('Worker deallocatePDA()', () => { + it('should deallocate a worker\'s PDA', async() => { + const tx = await models.Worker.beginTransaction({}); + try { + const workerWithPDA = 1; + const PDAWithActiveState = 1; + const options = {transaction: tx}; + const ctx = {args: {id: workerWithPDA, pda: PDAWithActiveState}}; + + await models.Worker.deallocatePDA(ctx, options); + const deviceProduction = await models.DeviceProduction.findById(PDAWithActiveState, null, options); + const deviceProductionUser = await models.DeviceProductionUser + .findById(PDAWithActiveState, null, options); + + expect(deviceProduction.stateFk).toEqual('idle'); + expect(deviceProductionUser).toBe(null); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index 7e03c8a23..8079bd165 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -20,6 +20,18 @@ "Device": { "dataSource": "vn" }, + "DeviceProduction": { + "dataSource": "vn" + }, + "DeviceProductionModels": { + "dataSource": "vn" + }, + "DeviceProductionState": { + "dataSource": "vn" + }, + "DeviceProductionUser": { + "dataSource": "vn" + }, "EducationLevel": { "dataSource": "vn" }, diff --git a/modules/worker/back/models/device-production-models.json b/modules/worker/back/models/device-production-models.json new file mode 100644 index 000000000..dcf447520 --- /dev/null +++ b/modules/worker/back/models/device-production-models.json @@ -0,0 +1,15 @@ +{ + "name": "DeviceProductionModels", + "base": "VnModel", + "options": { + "mysql": { + "table": "deviceProductionModels" + } + }, + "properties": { + "code": { + "type": "string", + "id": true + } + } +} diff --git a/modules/worker/back/models/device-production-state.json b/modules/worker/back/models/device-production-state.json new file mode 100644 index 000000000..32695621a --- /dev/null +++ b/modules/worker/back/models/device-production-state.json @@ -0,0 +1,18 @@ +{ + "name": "DeviceProductionState", + "base": "VnModel", + "options": { + "mysql": { + "table": "deviceProductionState" + } + }, + "properties": { + "code": { + "type": "string", + "id": true + }, + "description": { + "type": "string" + } + } +} diff --git a/modules/worker/back/models/device-production-user.json b/modules/worker/back/models/device-production-user.json new file mode 100644 index 000000000..568e79413 --- /dev/null +++ b/modules/worker/back/models/device-production-user.json @@ -0,0 +1,33 @@ +{ + "name": "DeviceProductionUser", + "base": "VnModel", + "options": { + "mysql": { + "table": "deviceProductionUser" + } + }, + "properties": { + "deviceProductionFk": { + "type": "number", + "id": true + }, + "userFk": { + "type": "number" + }, + "created": { + "type": "date" + } + }, + "relations": { + "deviceProduction": { + "type": "belongsTo", + "model": "DeviceProduction", + "foreignKey": "deviceProductionFk" + }, + "user": { + "type": "belongsTo", + "model": "User", + "foreignKey": "userFk" + } + } +} diff --git a/modules/worker/back/models/device-production.json b/modules/worker/back/models/device-production.json new file mode 100644 index 000000000..63672500b --- /dev/null +++ b/modules/worker/back/models/device-production.json @@ -0,0 +1,54 @@ +{ + "name": "DeviceProduction", + "base": "VnModel", + "options": { + "mysql": { + "table": "deviceProduction" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + }, + "imei": { + "type": "string" + }, + "modelFk": { + "type": "number" + }, + "macWifi": { + "type" : "string" + }, + "serialNumber": { + "type" : "string" + }, + "android_id": { + "type" : "string" + }, + "purchased": { + "type" : "date" + }, + "stateFk": { + "type" : "string" + }, + "isInScaleFusion": { + "type" : "boolean" + }, + "description": { + "type" : "string" + } + }, + "relations": { + "model": { + "type": "belongsTo", + "model": "DeviceProductionModels", + "foreignKey": "modelFk" + }, + "state": { + "type": "belongsTo", + "model": "DeviceProductionState", + "foreignKey": "stateFk" + } + } +} diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index 68baec6ca..fa17640a8 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -14,6 +14,8 @@ module.exports = Self => { require('../methods/worker/holidays')(Self); require('../methods/worker/activeContract')(Self); require('../methods/worker/new')(Self); + require('../methods/worker/deallocatePDA')(Self); + require('../methods/worker/allocatePDA')(Self); Self.validatesUniquenessOf('locker', { message: 'This locker has already been assigned' diff --git a/modules/worker/front/index.js b/modules/worker/front/index.js index 97126407c..657f6a8c6 100644 --- a/modules/worker/front/index.js +++ b/modules/worker/front/index.js @@ -10,6 +10,7 @@ import './descriptor-popover'; import './search-panel'; import './basic-data'; import './pbx'; +import './pda'; import './department'; import './calendar'; import './time-control'; diff --git a/modules/worker/front/locale/es.yml b/modules/worker/front/locale/es.yml index 672f4c52f..b5bcfefa4 100644 --- a/modules/worker/front/locale/es.yml +++ b/modules/worker/front/locale/es.yml @@ -23,4 +23,11 @@ worker: trabajador Go to the worker: Ir al trabajador Click to exclude the user from getting disabled: Marcar para no deshabilitar Click to allow the user to be disabled: Marcar para deshabilitar -This user can't be disabled: Fijado para no deshabilitar \ No newline at end of file +This user can't be disabled: Fijado para no deshabilitar +Model: Modelo +Serial Number: Número de serie +Current PDA: PDA Actual +Deallocate PDA: Desasignar PDA +PDA deallocated: PDA desasignada +PDA allocated: PDA asignada +New PDA: Nueva PDA diff --git a/modules/worker/front/pda/index.html b/modules/worker/front/pda/index.html new file mode 100644 index 000000000..b102f616a --- /dev/null +++ b/modules/worker/front/pda/index.html @@ -0,0 +1,48 @@ +
+ + + + + + + + + + +
+
+ + + + + ID: {{id}} + + {{'Model' | translate}}: {{modelFk}} + + {{'Serial Number' | translate}}: {{serialNumber}} + + + + + + + + +
diff --git a/modules/worker/front/pda/index.js b/modules/worker/front/pda/index.js new file mode 100644 index 000000000..885261e5c --- /dev/null +++ b/modules/worker/front/pda/index.js @@ -0,0 +1,53 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + const filter = { + where: {userFk: this.$params.id}, + include: {relation: 'deviceProduction'} + }; + this.$http.get('DeviceProductionUsers', {filter}). + then(res => { + if (res.data && res.data.length > 0) + this.setCurrentPDA(res.data[0]); + }); + } + + deallocatePDA() { + this.$http.post(`Workers/${this.$params.id}/deallocatePDA`, {pda: this.currentPDA.deviceProductionFk}) + .then(() => { + this.vnApp.showSuccess(this.$t('PDA deallocated')); + delete this.currentPDA; + }); + } + + allocatePDA() { + this.$http.post(`Workers/${this.$params.id}/allocatePDA`, {pda: this.newPDA}) + .then(res => { + if (res.data) + this.setCurrentPDA(res.data); + + this.vnApp.showSuccess(this.$t('PDA allocated')); + delete this.newPDA; + }); + } + + setCurrentPDA(data) { + this.currentPDA = data; + this.currentPDA.description = []; + this.currentPDA.description.push(`ID: ${this.currentPDA.deviceProductionFk}`); + this.currentPDA.description.push(`${this.$t('Model')}: ${this.currentPDA.deviceProduction.modelFk}`); + this.currentPDA.description.push(`${this.$t('Serial Number')}: ${this.currentPDA.deviceProduction.serialNumber}`); + this.currentPDA.description = this.currentPDA.description.join(' '); + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnWorkerPda', { + template: require('./index.html'), + controller: Controller, +}); diff --git a/modules/worker/front/pda/index.spec.js b/modules/worker/front/pda/index.spec.js new file mode 100644 index 000000000..a0540af45 --- /dev/null +++ b/modules/worker/front/pda/index.spec.js @@ -0,0 +1,72 @@ +import './index'; + +describe('Worker', () => { + describe('Component vnWorkerPda', () => { + let $httpBackend; + let $scope; + let $element; + let controller; + + beforeEach(ngModule('worker')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + $element = angular.element(''); + controller = $componentController('vnWorkerPda', {$element, $scope}); + $httpBackend.expectGET(`DeviceProductionUsers`).respond(); + })); + + describe('deallocatePDA()', () => { + it('should make an HTTP Post query to deallocatePDA', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + controller.currentPDA = {deviceProductionFk: 1}; + controller.$params.id = 1; + + $httpBackend + .expectPOST(`Workers/${controller.$params.id}/deallocatePDA`, + {pda: controller.currentPDA.deviceProductionFk}) + .respond(); + controller.deallocatePDA(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.currentPDA).toBeUndefined(); + }); + }); + + describe('allocatePDA()', () => { + it('should make an HTTP Post query to allocatePDA', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + controller.newPDA = 4; + controller.$params.id = 1; + + $httpBackend + .expectPOST(`Workers/${controller.$params.id}/allocatePDA`, + {pda: controller.newPDA}) + .respond(); + controller.allocatePDA(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.newPDA).toBeUndefined(); + }); + }); + + describe('setCurrentPDA()', () => { + it('should set CurrentPDA', () => { + const data = { + deviceProductionFk: 1, + deviceProduction: { + modelFk: 1, + serialNumber: 1 + } + }; + controller.setCurrentPDA(data); + + expect(controller.currentPDA).toBeDefined(); + expect(controller.currentPDA.description).toBeDefined(); + }); + }); + }); +}); diff --git a/modules/worker/front/pda/style.scss b/modules/worker/front/pda/style.scss new file mode 100644 index 000000000..4d9d70953 --- /dev/null +++ b/modules/worker/front/pda/style.scss @@ -0,0 +1,6 @@ +span.separator{ + border-left: 1px solid black; + height: 100%; + margin: 0 10px; +} + diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index dad55512b..1433485c0 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -15,6 +15,7 @@ {"state": "worker.card.calendar", "icon": "icon-calendar"}, {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.dms.index", "icon": "cloud_upload"}, + {"state": "worker.card.pda", "icon": "contact_support"}, { "icon": "icon-wiki", "external":true, @@ -141,6 +142,13 @@ "component": "vn-worker-create", "description": "New worker", "acl": ["hr"] + }, + { + "url": "/pda", + "state": "worker.card.pda", + "component": "vn-worker-pda", + "description": "PDA", + "acl": ["employee"] } ] } From 7a04b0b3de993d3ca557bfa850b5f6584138bbff Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 08:00:18 +0100 Subject: [PATCH 29/63] refs #5287 icon added --- modules/worker/front/routes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 1433485c0..329c10818 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -11,11 +11,11 @@ ], "card": [ {"state": "worker.card.basicData", "icon": "settings"}, + {"state": "worker.card.pda", "icon": "phone_android"}, {"state": "worker.card.pbx", "icon": "icon-pbx"}, {"state": "worker.card.calendar", "icon": "icon-calendar"}, {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.dms.index", "icon": "cloud_upload"}, - {"state": "worker.card.pda", "icon": "contact_support"}, { "icon": "icon-wiki", "external":true, From 96e103d76e4823c5a2d8bf7dae59815325ed1d7e Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 08:37:17 +0100 Subject: [PATCH 30/63] refs #5287 sections sorted --- modules/worker/back/methods/worker/allocatePDA.js | 2 +- modules/worker/front/routes.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/worker/back/methods/worker/allocatePDA.js b/modules/worker/back/methods/worker/allocatePDA.js index 096718c80..8d0d25d2d 100644 --- a/modules/worker/back/methods/worker/allocatePDA.js +++ b/modules/worker/back/methods/worker/allocatePDA.js @@ -2,7 +2,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('allocatePDA', { - description: 'Deallocate the worker\'s PDA', + description: 'Deallocate the PDA of the worker', accepts: [{ arg: 'id', type: 'number', diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 329c10818..b96d713ac 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -11,10 +11,10 @@ ], "card": [ {"state": "worker.card.basicData", "icon": "settings"}, + {"state": "worker.card.timeControl", "icon": "access_time"}, + {"state": "worker.card.calendar", "icon": "icon-calendar"}, {"state": "worker.card.pda", "icon": "phone_android"}, {"state": "worker.card.pbx", "icon": "icon-pbx"}, - {"state": "worker.card.calendar", "icon": "icon-calendar"}, - {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.dms.index", "icon": "cloud_upload"}, { "icon": "icon-wiki", From 5ccfe6bf900e8947fd6b249370dbfb8385bb13bb Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 11:19:41 +0100 Subject: [PATCH 31/63] refs #5160 callback added --- back/tests.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/back/tests.js b/back/tests.js index ab6893791..8f7cfd3d4 100644 --- a/back/tests.js +++ b/back/tests.js @@ -30,7 +30,10 @@ async function test() { const bootOptions = {dataSources}; const app = require('vn-loopback/server/server'); - app.boot(bootOptions); + await new Promise((resolve, reject) => { + app.boot(bootOptions, + err => err ? reject(err) : resolve()); + }); const Jasmine = require('jasmine'); const jasmine = new Jasmine(); From d5ea59e284834451385de0c1657eb93ac37b3fd3 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 12:46:48 +0100 Subject: [PATCH 32/63] =?UTF-8?q?refs=20#5287=20permisos=20a=C3=B1adidos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/changes/230801/00-workerLocker.sql | 18 ++++++++++++------ e2e/paths/03-worker/07_pda.spec.js | 2 +- modules/worker/front/pda/index.html | 3 ++- modules/worker/front/routes.json | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/db/changes/230801/00-workerLocker.sql b/db/changes/230801/00-workerLocker.sql index 1fcea50ac..0a72cca1e 100644 --- a/db/changes/230801/00-workerLocker.sql +++ b/db/changes/230801/00-workerLocker.sql @@ -1,9 +1,15 @@ ALTER TABLE `vn`.`worker` ADD locker INT UNSIGNED NULL UNIQUE; INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('DeviceProduction', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('DeviceProductionModels', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('DeviceProductionState', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('DeviceProductionUser', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('Worker', 'deallocatePDA', '*', 'ALLOW', 'ROLE', 'employee'), - ('Worker', 'allocatePDA', '*', 'ALLOW', 'ROLE', 'employee'); + ('DeviceProduction', '*', '*', 'ALLOW', 'ROLE', 'hr'), + ('DeviceProductionModels', '*', '*', 'ALLOW', 'ROLE', 'hr'), + ('DeviceProductionState', '*', '*', 'ALLOW', 'ROLE', 'hr'), + ('DeviceProductionUser', '*', '*', 'ALLOW', 'ROLE', 'hr'), + ('DeviceProduction', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('DeviceProductionModels', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('DeviceProductionState', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('DeviceProductionUser', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('Worker', 'deallocatePDA', '*', 'ALLOW', 'ROLE', 'hr'), + ('Worker', 'allocatePDA', '*', 'ALLOW', 'ROLE', 'hr'), + ('Worker', 'deallocatePDA', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('Worker', 'allocatePDA', '*', 'ALLOW', 'ROLE', 'productionAssi'); diff --git a/e2e/paths/03-worker/07_pda.spec.js b/e2e/paths/03-worker/07_pda.spec.js index f583a9e4f..2b743823e 100644 --- a/e2e/paths/03-worker/07_pda.spec.js +++ b/e2e/paths/03-worker/07_pda.spec.js @@ -7,7 +7,7 @@ describe('Worker pda path', () => { beforeAll(async() => { browser = await getBrowser(); page = browser.page; - await page.loginAndModule('employee', 'worker'); + await page.loginAndModule('hr', 'worker'); await page.accessToSearchResult('employeeNick'); await page.accessToSection('worker.card.pda'); }); diff --git a/modules/worker/front/pda/index.html b/modules/worker/front/pda/index.html index b102f616a..2f1626ba8 100644 --- a/modules/worker/front/pda/index.html +++ b/modules/worker/front/pda/index.html @@ -10,7 +10,7 @@ icon="delete" vn-tooltip="Deallocate PDA" ng-click="$ctrl.deallocatePDA()" - vn-acl="employee"> + vn-acl="hr, productionAssi"> @@ -21,6 +21,7 @@ Date: Tue, 28 Feb 2023 13:42:18 +0100 Subject: [PATCH 33/63] refs #5149 checked if ticket has refunds, added translations --- loopback/locale/en.json | 3 ++- loopback/locale/es.json | 3 ++- .../ticket/back/methods/ticket/setDeleted.js | 27 +++++++------------ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index a406b55a5..ecaee91fa 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -147,5 +147,6 @@ "The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified", "Receipt's bank was not found": "Receipt's bank was not found", "This receipt was not compensated": "This receipt was not compensated", - "Client's email was not found": "Client's email was not found" + "Client's email was not found": "Client's email was not found", + "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index d65054f37..28a2e866d 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -259,5 +259,6 @@ "Try again": "Vuelve a intentarlo", "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", "Failed to upload file": "Error al subir archivo", - "The DOCUWARE PDF document does not exists": "The DOCUWARE PDF document does not exists" + "The DOCUWARE PDF document does not exists": "The DOCUWARE PDF document does not exists", + "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}" } diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index 28488ade6..6ebc37d6e 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -42,10 +42,13 @@ module.exports = Self => { if (!isEditable) throw new UserError(`The sales of this ticket can't be modified`); - const hasRefunds = await checkRefunds(id, myOptions); - - if (hasRefunds) - throw new UserError(`You must delete the refund id %d first`, 'DELETE_REFUND_FIRST', hasRefunds); + // Check if ticket has refunds + const ticketRefunds = await models.TicketRefund.find({ + where: {originalTicketFk: id}, + fields: ['id']} + , myOptions); + if (ticketRefunds.length > 0) + throw new UserError($t('Tickets with associated refunds', {id: ticketRefunds[0].id})); // Check if has sales with shelving const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', myOptions); @@ -139,12 +142,12 @@ module.exports = Self => { await models.TicketCollection.destroyById(ticketCollection.id, myOptions); await Self.rawSql(` - DELETE sc + DELETE sc FROM vn.saleGroup sg JOIN vn.sectorCollectionSaleGroup scsg ON scsg.saleGroupFk = sg.id JOIN vn.sectorCollection sc ON sc.id = scsg.sectorCollectionFk JOIN vn.saleGroupDetail sgd ON sgd.saleGroupFk = sg.id - JOIN vn.sale s ON s.id = sgd.saleFk + JOIN vn.sale s ON s.id = sgd.saleFk WHERE s.ticketFk = ?;`, [ticket.id], myOptions); if (tx) await tx.commit(); @@ -155,16 +158,4 @@ module.exports = Self => { throw e; } }; - - async function checkRefunds(id, options) { - const models = Self.app.models; - let refunds = await models.TicketRefund.find({ - where: {ticketFk: id} - }, options); - - if (refunds.length > 0) - return refunds[0].refundTicketFk; - else - return false; - } }; From 9336d20e450a58d2d5455def95feae6bcc8dbd04 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 28 Feb 2023 13:45:36 +0100 Subject: [PATCH 34/63] refs #4975 MdbVersion/upload fixes & code clean --- modules/mdb/back/methods/mdbVersion/upload.js | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js index 864a73f52..ad158a551 100644 --- a/modules/mdb/back/methods/mdbVersion/upload.js +++ b/modules/mdb/back/methods/mdbVersion/upload.js @@ -47,7 +47,16 @@ module.exports = Self => { verb: 'POST' } }); - Self.upload = async(ctx, options) => { + Self.upload = async( + ctx, + options, + appName, + toVersion, + branch, + fromVersion, + description, + unlock + ) => { const models = Self.app.models; const myOptions = {}; const $t = ctx.req.__; // $translate @@ -55,12 +64,6 @@ module.exports = Self => { const AccessContainer = models.AccessContainer; const fileOptions = {}; let tx; - const appName = ctx.args.appName; - const toVersion = ctx.args.toVersion; - const branch = ctx.args.branch; - const fromVersion = ctx.args.fromVersion; - let description = ctx.args.description; - const unlock = ctx.args.unlock; if (typeof options == 'object') Object.assign(myOptions, options); @@ -153,11 +156,14 @@ module.exports = Self => { formatDesc += `*${appName.toUpperCase()}* v.${toVersion} `; const oldVersion = await models.MdbVersionTree.findOne({ - where: {version: fromVersion}, + where: { + version: fromVersion, + app: appName + }, fields: ['branchFk'] }, myOptions); - if (branch == oldVersion.branchFk) + if (!oldVersion || branch == oldVersion.branchFk) formatDesc += `[*${branch}*]: `; else formatDesc += `[*${oldVersion.branchFk}* » *${branch}*]: `; From b2bf7f2727405fa3164c0d22120fce7a2df5dace Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 14:29:31 +0100 Subject: [PATCH 35/63] refs #5149 fixing e2e --- db/dump/fixtures.sql | 3 ++ e2e/helpers/selectors.js | 4 +-- e2e/paths/05-ticket/21_future.spec.js | 15 ++++++++-- .../methods/ticket/specs/setDeleted.spec.js | 28 +++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 218fcb9ca..3384ec5e5 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2773,3 +2773,6 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) VALUES (1, NULL, 1); +INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) + VALUES + (1, 30); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index a1412f431..2603dbef3 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -759,8 +759,8 @@ export default { tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Future tickets"]', acceptButton: '.vn-confirm.shown button[response="accept"]', - firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', - multiCheck: 'vn-multi-check', + secondCheck: 'tbody > tr:nth-child(2) > td > vn-check', + thirdCheck: 'tbody > tr:nth-child(3) > td > vn-check', tableId: 'vn-textfield[name="id"]', tableFutureId: 'vn-textfield[name="futureId"]', tableLiters: 'vn-textfield[name="liters"]', diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 34ae3d688..a4a27587b 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -152,13 +152,22 @@ describe('Ticket Future path', () => { await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should check the three last tickets and move to the future', async() => { - await page.waitToClick(selectors.ticketFuture.multiCheck); - await page.waitToClick(selectors.ticketFuture.firstCheck); + it('should check the two tickets and move to the future', async() => { + await page.waitToClick(selectors.ticketFuture.secondCheck); + await page.waitToClick(selectors.ticketFuture.thirdCheck); await page.waitToClick(selectors.ticketFuture.moveButton); await page.waitToClick(selectors.ticketFuture.acceptButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Tickets moved successfully!'); }); + + it('should show error trying to delete a ticket with a refund', async() => { + await page.waitToClick(selectors.ticketFuture.secondCheck); + await page.waitToClick(selectors.ticketFuture.moveButton); + await page.waitToClick(selectors.ticketFuture.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets with associated refunds can\'t be deleted'); + }); }); diff --git a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js index 1c17d4d0b..133e8022e 100644 --- a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js +++ b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js @@ -101,4 +101,32 @@ describe('ticket setDeleted()', () => { throw e; } }); + + it('should show error trying to delete a ticket with a refund', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + + const ctx = { + req: { + accessToken: {userId: 9}, + headers: {origin: 'http://localhost:5000'}, + } + }; + ctx.req.__ = value => { + return value; + }; + + const ticketId = 30; + await models.Ticket.setDeleted(ctx, ticketId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toContain('Tickets with associated refunds'); + }); }); From 656685cd7eaa290e70ef952e6e00254e2bf8a987 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 28 Feb 2023 14:35:34 +0100 Subject: [PATCH 36/63] refs #4975 Minor changes --- loopback/locale/es.json | 12 ++++++------ modules/mdb/back/methods/mdbVersion/upload.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ad6d53d64..11412bf5a 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -259,10 +259,10 @@ "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", "Failed to upload file": "Error al subir archivo", "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe", - "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", - "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", - "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", + "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", + "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", + "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", - "There is no assigned email for this client": "No hay correo asignado para este cliente" -} - + "There is no assigned email for this client": "No hay correo asignado para este cliente", + "Not exist this branch": "Not exist this branch" +} \ No newline at end of file diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js index ad158a551..58fc46abb 100644 --- a/modules/mdb/back/methods/mdbVersion/upload.js +++ b/modules/mdb/back/methods/mdbVersion/upload.js @@ -49,13 +49,13 @@ module.exports = Self => { }); Self.upload = async( ctx, - options, appName, toVersion, branch, fromVersion, description, - unlock + unlock, + options ) => { const models = Self.app.models; const myOptions = {}; From 3dd6232d6adbd088de3def8eddcde8bb89cbb7f0 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Feb 2023 14:39:01 +0100 Subject: [PATCH 37/63] hotfix isTrucker was not in the params --- modules/supplier/back/methods/supplier/updateFiscalData.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/supplier/back/methods/supplier/updateFiscalData.js b/modules/supplier/back/methods/supplier/updateFiscalData.js index 4604b3f91..dff3a133b 100644 --- a/modules/supplier/back/methods/supplier/updateFiscalData.js +++ b/modules/supplier/back/methods/supplier/updateFiscalData.js @@ -64,6 +64,10 @@ module.exports = Self => { { arg: 'healthRegister', type: 'string' + }, + { + arg: 'isTrucker', + type: 'boolean' }], returns: { arg: 'res', From 15f2f46e4c0879183ec9405e8406e02bffd090d9 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 28 Feb 2023 14:48:17 +0100 Subject: [PATCH 38/63] refs #4975 Traduction no branch --- loopback/locale/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 11412bf5a..94cff1bd8 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -264,5 +264,5 @@ "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", "There is no assigned email for this client": "No hay correo asignado para este cliente", - "Not exist this branch": "Not exist this branch" + "Not exist this branch": "La rama no existe" } \ No newline at end of file From 6eab4bbe9475b3b13391686979f6eacbb3a3f6a7 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 08:15:58 +0100 Subject: [PATCH 39/63] refs #5149 fixing tests --- db/dump/fixtures.sql | 2 +- e2e/helpers/selectors.js | 6 ++++-- e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js | 12 ++++++++++++ e2e/paths/05-ticket/21_future.spec.js | 15 +++------------ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 3384ec5e5..81fadf18c 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2775,4 +2775,4 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) VALUES - (1, 30); + (1, 31); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 2603dbef3..4ed2d5719 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -22,6 +22,7 @@ export default { userConfigSecondAutocomplete: '#localBank', userConfigThirdAutocomplete: '#localCompany', acceptButton: '.vn-confirm.shown button[response=accept]', + cancelButton: '.vn-confirm.shown input[response=cancel]', searchButton: 'vn-searchbar vn-icon[icon="search"]' }, moduleIndex: { @@ -759,8 +760,8 @@ export default { tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Future tickets"]', acceptButton: '.vn-confirm.shown button[response="accept"]', - secondCheck: 'tbody > tr:nth-child(2) > td > vn-check', - thirdCheck: 'tbody > tr:nth-child(3) > td > vn-check', + firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', + multiCheck: 'vn-multi-check', tableId: 'vn-textfield[name="id"]', tableFutureId: 'vn-textfield[name="futureId"]', tableLiters: 'vn-textfield[name="liters"]', @@ -784,6 +785,7 @@ export default { tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Advance tickets"]', acceptButton: '.vn-confirm.shown button[response="accept"]', + firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', multiCheck: 'vn-multi-check', tableId: 'vn-textfield[name="id"]', tableFutureId: 'vn-textfield[name="futureId"]', 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 9d6fddbe6..ec27be496 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 @@ -226,9 +226,21 @@ describe('Ticket Edit sale path', () => { await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); await page.waitToClick(selectors.ticketSales.moreMenu); await page.waitToClick(selectors.ticketSales.moreMenuRefund); + await page.waitForSnackbar(); await page.waitForState('ticket.card.sale'); }); + it('should show error trying to delete a ticket with a refund', async() => { + await page.accessToSearchResult('16'); + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); + await page.waitToClick(selectors.globalItems.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets with associated refunds can\'t be deleted'); + await page.waitToClick(selectors.globalItems.cancelButton); + }); + it('should select the third sale and create a claim of it', async() => { await page.accessToSearchResult('16'); await page.accessToSection('ticket.card.sale'); diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index a4a27587b..34ae3d688 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -152,22 +152,13 @@ describe('Ticket Future path', () => { await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should check the two tickets and move to the future', async() => { - await page.waitToClick(selectors.ticketFuture.secondCheck); - await page.waitToClick(selectors.ticketFuture.thirdCheck); + it('should check the three last tickets and move to the future', async() => { + await page.waitToClick(selectors.ticketFuture.multiCheck); + await page.waitToClick(selectors.ticketFuture.firstCheck); await page.waitToClick(selectors.ticketFuture.moveButton); await page.waitToClick(selectors.ticketFuture.acceptButton); const message = await page.waitForSnackbar(); expect(message.text).toContain('Tickets moved successfully!'); }); - - it('should show error trying to delete a ticket with a refund', async() => { - await page.waitToClick(selectors.ticketFuture.secondCheck); - await page.waitToClick(selectors.ticketFuture.moveButton); - await page.waitToClick(selectors.ticketFuture.acceptButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Tickets with associated refunds can\'t be deleted'); - }); }); From fb940fff52408a9103cfaccd47ea1ca171890c1e Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 08:31:45 +0100 Subject: [PATCH 40/63] . --- e2e/helpers/selectors.js | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 24565f7b8..9840696c2 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -785,7 +785,6 @@ export default { moveButton: 'vn-button[vn-tooltip="Advance tickets"]', acceptButton: '.vn-confirm.shown button[response="accept"]', firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', - multiCheck: 'vn-multi-check', tableId: 'vn-textfield[name="id"]', tableFutureId: 'vn-textfield[name="futureId"]', tableLiters: 'vn-textfield[name="liters"]', From f6afed485c655f134f535fa9787f52cafd9701dd Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 1 Mar 2023 08:50:30 +0100 Subject: [PATCH 41/63] add console.log --- back/tests.js | 1 - modules/invoiceOut/back/methods/invoiceOut/downloadZip.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/back/tests.js b/back/tests.js index 591548d59..5abefd228 100644 --- a/back/tests.js +++ b/back/tests.js @@ -34,7 +34,6 @@ async function test() { const Jasmine = require('jasmine'); const jasmine = new Jasmine(); - // jasmine.seed('68436'); const SpecReporter = require('jasmine-spec-reporter').SpecReporter; jasmine.addReporter(new SpecReporter({ diff --git a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js index fe005f1ab..3410baa78 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js +++ b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js @@ -47,6 +47,7 @@ module.exports = Self => { ids = ids.split(','); for (let id of ids) { + console.log(zipConfig, totalSize, zipConfig.maxSize); if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); const invoiceOutPdf = await models.InvoiceOut.download(ctx, id, myOptions); const fileName = extractFileName(invoiceOutPdf[2]); From 915c598c0c30a25286f4bfbc7502bc6df917755e Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 09:04:53 +0100 Subject: [PATCH 42/63] fixed tests --- db/dump/fixtures.sql | 2 +- modules/ticket/back/methods/ticket/specs/setDeleted.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 403523319..5af9b9eeb 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2789,7 +2789,7 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) VALUES - (1, 31); + (1, 12); INSERT INTO `vn`.`deviceProductionModels` (`code`) VALUES diff --git a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js index 133e8022e..b2e70697a 100644 --- a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js +++ b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js @@ -118,7 +118,7 @@ describe('ticket setDeleted()', () => { return value; }; - const ticketId = 30; + const ticketId = 12; await models.Ticket.setDeleted(ctx, ticketId, options); await tx.rollback(); From 314c5c27eb3c9568f36ad7cb4286f02ab97e2247 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 09:09:05 +0100 Subject: [PATCH 43/63] refs #5149 changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3388ceb73..b1f258ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - (Trabajador -> PDA) Nueva sección ### Changed -- +- (Ticket -> Borrar ticket) Restringido el borrado de tickets con abono ### Fixed - From 4567981724da22b6c668c10ff4d1c1f8d167aa0c Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 1 Mar 2023 09:09:09 +0100 Subject: [PATCH 44/63] add console.log --- back/tests.js | 2 +- modules/invoiceOut/back/methods/invoiceOut/createPdf.js | 2 +- modules/invoiceOut/back/methods/invoiceOut/downloadZip.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/tests.js b/back/tests.js index 5abefd228..ab6893791 100644 --- a/back/tests.js +++ b/back/tests.js @@ -63,7 +63,7 @@ async function test() { jasmine.loadConfig({ spec_dir: '.', spec_files: backSpecs, - helpers: [] + helpers: [], }); await jasmine.execute(); diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index 65eaae657..71e7c1543 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -44,7 +44,7 @@ module.exports = Self => { try { const invoiceOut = await Self.findById(id, null, myOptions); const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions); - console.log(invoiceOut); + console.log(invoiceOut, !hasInvoicing); if (invoiceOut.hasPdf && !hasInvoicing) throw new UserError(`You don't have enough privileges`); diff --git a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js index 3410baa78..208d55358 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js +++ b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js @@ -47,7 +47,7 @@ module.exports = Self => { ids = ids.split(','); for (let id of ids) { - console.log(zipConfig, totalSize, zipConfig.maxSize); + console.log(zipConfig, totalSize, zipConfig ? zipConfig.maxSize : null); if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); const invoiceOutPdf = await models.InvoiceOut.download(ctx, id, myOptions); const fileName = extractFileName(invoiceOutPdf[2]); From 7aedbda98b94c73b86376507b8614c8c3e1ecb22 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 10:08:51 +0100 Subject: [PATCH 45/63] refs #5202 changed vn-tr for a --- modules/item/front/waste/index/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/item/front/waste/index/index.html b/modules/item/front/waste/index/index.html index 5da5acbf1..f1475c1b3 100644 --- a/modules/item/front/waste/index/index.html +++ b/modules/item/front/waste/index/index.html @@ -33,16 +33,16 @@
- + ng-show="$ctrl.wasteConfig[detail.buyer].hidden"> {{::waste.family}} {{::(waste.percentage / 100) | percentage: 2}} {{::waste.dwindle | currency: 'EUR'}} {{::waste.total | currency: 'EUR'}} - +
From d744cbb1a3d9ad313eb15f875088ce968dba9e10 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 12:22:01 +0100 Subject: [PATCH 46/63] hotFix itemDiary reload card conditional --- modules/item/front/diary/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/item/front/diary/index.js b/modules/item/front/diary/index.js index 9e104c8e6..03134913f 100644 --- a/modules/item/front/diary/index.js +++ b/modules/item/front/diary/index.js @@ -70,7 +70,8 @@ class Controller extends Section { } $onDestroy() { - this.card.reload(); + if (this.$state.getCurrentPath()[2].state.name === 'item') + this.card.reload(); } } From 707ae232a74e62130a58f5c4ed40056b7d339580 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 1 Mar 2023 12:24:36 +0100 Subject: [PATCH 47/63] refs #5193 ticketCreateWithUser to ticket_add --- db/tests/vn/ticketCalculateClon.spec.js | 10 ++++++---- db/tests/vn/ticketCreateWithUser.spec.js | 22 +++++++++++++--------- modules/ticket/back/methods/ticket/new.js | 3 ++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/db/tests/vn/ticketCalculateClon.spec.js b/db/tests/vn/ticketCalculateClon.spec.js index a3c790492..9116d805f 100644 --- a/db/tests/vn/ticketCalculateClon.spec.js +++ b/db/tests/vn/ticketCalculateClon.spec.js @@ -22,7 +22,7 @@ describe('ticket ticketCalculateClon()', () => { originalTicketId: 11 }; - stmt = new ParameterizedSQL('CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ + stmt = new ParameterizedSQL('CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ params.clientFk, params.shipped, params.warehouseFk, @@ -31,7 +31,8 @@ describe('ticket ticketCalculateClon()', () => { params.agencyType, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); @@ -71,7 +72,7 @@ describe('ticket ticketCalculateClon()', () => { originalTicketId: 11 }; - stmt = new ParameterizedSQL('CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ + stmt = new ParameterizedSQL('CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ params.clientFk, params.shipped, params.warehouseFk, @@ -80,7 +81,8 @@ describe('ticket ticketCalculateClon()', () => { params.agencyType, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); diff --git a/db/tests/vn/ticketCreateWithUser.spec.js b/db/tests/vn/ticketCreateWithUser.spec.js index 4aeece564..5dd84d397 100644 --- a/db/tests/vn/ticketCreateWithUser.spec.js +++ b/db/tests/vn/ticketCreateWithUser.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; -describe('ticket ticketCreateWithUser()', () => { +describe('ticket ticket_add()', () => { const today = Date.vnNew(); it('should confirm the procedure creates the expected ticket', async() => { let stmts = []; @@ -21,7 +21,7 @@ describe('ticket ticketCreateWithUser()', () => { userId: 18 }; - stmt = new ParameterizedSQL(`CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ + stmt = new ParameterizedSQL(`CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ params.clientFk, params.shipped, params.warehouseFk, @@ -30,7 +30,8 @@ describe('ticket ticketCreateWithUser()', () => { params.agencyModeFk, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); @@ -70,7 +71,7 @@ describe('ticket ticketCreateWithUser()', () => { userId: 18 }; - stmt = new ParameterizedSQL('CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)', [ + stmt = new ParameterizedSQL('CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)', [ params.clientFk, params.shipped, params.warehouseFk, @@ -79,7 +80,8 @@ describe('ticket ticketCreateWithUser()', () => { params.agencyModeFk, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); @@ -120,7 +122,7 @@ describe('ticket ticketCreateWithUser()', () => { userId: 18 }; - stmt = new ParameterizedSQL(`CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ + stmt = new ParameterizedSQL(`CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ params.clientFk, params.shipped, params.warehouseFk, @@ -129,7 +131,8 @@ describe('ticket ticketCreateWithUser()', () => { params.agencyModeFk, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); @@ -172,7 +175,7 @@ describe('ticket ticketCreateWithUser()', () => { ]); stmts.push(stmt); - stmt = new ParameterizedSQL(`CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ + stmt = new ParameterizedSQL(`CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @newTicketId)`, [ params.clientFk, params.shipped, params.warehouseFk, @@ -181,7 +184,8 @@ describe('ticket ticketCreateWithUser()', () => { params.agencyModeFk, params.routeFk, params.landed, - params.userId + params.userId, + true ]); stmts.push(stmt); stmts.push(`select @newTicketId`); diff --git a/modules/ticket/back/methods/ticket/new.js b/modules/ticket/back/methods/ticket/new.js index e6048421e..597ece3e5 100644 --- a/modules/ticket/back/methods/ticket/new.js +++ b/modules/ticket/back/methods/ticket/new.js @@ -111,7 +111,7 @@ module.exports = Self => { args.landed = landedResult && landedResult.landed; } - query = `CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result); + query = `CALL vn.ticket_add(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, @result); SELECT @result newTicketId;`; const result = await Self.rawSql(query, [ args.clientId, @@ -122,6 +122,7 @@ module.exports = Self => { args.agencyModeId || null, args.routeId || null, args.landed, + true, myUserId ], myOptions); From fdf97b1fc71dfe3c9f344773620e520d73d9099c Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 1 Mar 2023 12:59:46 +0100 Subject: [PATCH 48/63] refs #4965 Hotfix collection-label --- print/templates/reports/collection-label/collection-label.js | 3 ++- print/templates/reports/collection-label/options.json | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/print/templates/reports/collection-label/collection-label.js b/print/templates/reports/collection-label/collection-label.js index 656dde082..d8947d6e7 100644 --- a/print/templates/reports/collection-label/collection-label.js +++ b/print/templates/reports/collection-label/collection-label.js @@ -66,8 +66,9 @@ module.exports = { else value = '---'; + let routeFk = labelData.routeFk.toString(); if (labelData.routeFk) - value = `${value} [${labelData.routeFk.toString().substring(0, 3)}]`; + value = `${value} [${routeFk.substring(routeFk.length - 3)}]`; return value; }, diff --git a/print/templates/reports/collection-label/options.json b/print/templates/reports/collection-label/options.json index a555c5723..ad5ad4750 100644 --- a/print/templates/reports/collection-label/options.json +++ b/print/templates/reports/collection-label/options.json @@ -3,9 +3,9 @@ "height": "4.9cm", "margin": { "top": "0.3cm", - "right": "0.6cm", + "right": "0.3cm", "bottom": "0cm", - "left": "0cm" + "left": "0.2cm" }, "printBackground": true } \ No newline at end of file From a5d236257bc4e647c164964f9b8c8f4f0064c605 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 1 Mar 2023 14:03:47 +0100 Subject: [PATCH 49/63] refs #4965 Hotfix --- print/templates/reports/collection-label/collection-label.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/print/templates/reports/collection-label/collection-label.js b/print/templates/reports/collection-label/collection-label.js index d8947d6e7..d45ecb2bc 100644 --- a/print/templates/reports/collection-label/collection-label.js +++ b/print/templates/reports/collection-label/collection-label.js @@ -66,9 +66,10 @@ module.exports = { else value = '---'; - let routeFk = labelData.routeFk.toString(); - if (labelData.routeFk) + if (labelData.routeFk) { + let routeFk = labelData.routeFk.toString(); value = `${value} [${routeFk.substring(routeFk.length - 3)}]`; + } return value; }, From d62fbab3f1da979dff531bdc5e65e0fc48c5ab3e Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 1 Mar 2023 14:22:25 +0100 Subject: [PATCH 50/63] refs #5070 refactor and added tests --- modules/route/front/summary/index.html | 9 ++++++++- modules/route/front/summary/index.js | 15 ++++++++++++++ modules/route/front/summary/index.spec.js | 24 +++++++++++++++++++++++ modules/route/front/tickets/index.js | 24 ++++++++--------------- modules/route/front/tickets/index.spec.js | 2 +- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/modules/route/front/summary/index.html b/modules/route/front/summary/index.html index a64ad4ff7..56f7a49b9 100644 --- a/modules/route/front/summary/index.html +++ b/modules/route/front/summary/index.html @@ -93,7 +93,14 @@ {{ticket.priority | dashIfEmpty}} {{ticket.street}} - {{ticket.city}} + + {{::ticket.city}} + {{ticket.postalCode}} { + if (!response.data) + throw new UserError(`The route's vehicle doesn't have a delivery point`); + + const address = response.data + '+to:' + ticket.postalCode + ' ' + ticket.city + ' ' + ticket.street; + const url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr='; + window.open(url + encodeURI(address), '_blank'); + }); + } } ngModule.vnComponent('vnRouteSummary', { diff --git a/modules/route/front/summary/index.spec.js b/modules/route/front/summary/index.spec.js index ad300817a..cfa21aeb9 100644 --- a/modules/route/front/summary/index.spec.js +++ b/modules/route/front/summary/index.spec.js @@ -37,5 +37,29 @@ describe('Route', () => { expect(controller.packagesTotal).toEqual(4); }); }); + + describe('goToBuscaman()', () => { + it('should open buscaman with the given arguments', () => { + jest.spyOn(window, 'open').mockReturnThis(); + const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460%20Av%20Espioca%20100+to:n19%20London%20my%20street'; + controller.route = {vehicleFk: 1}; + const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`; + $httpBackend.when('GET', `Routes/1/summary`).respond(); + $httpBackend.expectGET(url).respond('46460 Av Espioca 100'); + + const ticket = { + id: 1, + checked: true, + street: 'my street', + postalCode: 'n19', + city: 'London' + }; + + controller.goToBuscaman(ticket); + $httpBackend.flush(); + + expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank'); + }); + }); }); }); diff --git a/modules/route/front/tickets/index.js b/modules/route/front/tickets/index.js index 6374d1b3a..8789708ac 100644 --- a/modules/route/front/tickets/index.js +++ b/modules/route/front/tickets/index.js @@ -74,31 +74,23 @@ class Controller extends Section { return selectedItems; } - goToBuscaman(clickedLine) { + goToBuscaman(ticket) { if (!this.route.vehicleFk) throw new UserError(`The route doesn't have a vehicle`); - let query = `Routes/${this.route.vehicleFk}/getDeliveryPoint`; - this.$http.get(query).then(response => { - if (!response.data) + this.$http.get(`Routes/${this.route.vehicleFk}/getDeliveryPoint`).then(res => { + if (!res.data) throw new UserError(`The route's vehicle doesn't have a delivery point`); - return response.data; - }).then(address => { - let addresses; - if (address) addresses = address; - let lines = this.getSelectedItems(this.tickets); - if (clickedLine) lines = [clickedLine]; - - let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr='; + let addresses = res.data; + const lines = ticket ? [ticket] : this.getSelectedItems(this.tickets); lines.forEach((line, index) => { - const previusLine = lines[index - 1] ? lines[index - 1].street : null; - if (previusLine != line.street) + const previousLine = lines[index - 1] ? lines[index - 1].street : null; + if (previousLine != line.street) addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street; }); - if (clickedLine) addresses = addresses.replace(address + '+to:', '',); - + const url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr='; window.open(url + encodeURI(addresses), '_blank'); }); } diff --git a/modules/route/front/tickets/index.spec.js b/modules/route/front/tickets/index.spec.js index f4a58154e..2c73048bd 100644 --- a/modules/route/front/tickets/index.spec.js +++ b/modules/route/front/tickets/index.spec.js @@ -136,7 +136,7 @@ describe('Route', () => { describe('goToBuscaman()', () => { it('should open buscaman with the given arguments', () => { jest.spyOn(window, 'open').mockReturnThis(); - const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460 Av Espioca 100+to:n19 London my street'; + const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460%20Av%20Espioca%20100+to:n19%20London%20my%20street'; controller.route = {vehicleFk: 1}; const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`; $httpBackend.expectGET(url).respond('46460 Av Espioca 100'); From e785c34d90c96f7e0c090d8706c2fe6d509a5463 Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 2 Mar 2023 07:52:07 +0100 Subject: [PATCH 51/63] Added next version --- CHANGELOG.md | 14 +++++++++++--- db/changes/231001/.gitkeep | 0 package.json | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 db/changes/231001/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index e5c340730..bff0feed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ 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). +## [2310.01] - 2023-03-23 + +### Added +- + +### Changed +- + +### Fixed +- + ## [2308.01] - 2023-03-09 ### Added @@ -16,9 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - (Ticket -> Borrar ticket) Restringido el borrado de tickets con abono -### Fixed -- - ## [2306.01] - 2023-02-23 ### Added diff --git a/db/changes/231001/.gitkeep b/db/changes/231001/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json index f4415f99b..30c8039ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.08.01", + "version": "23.10.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", From 57e36cebde23ee300ceb186df6b1a9208629574e Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 2 Mar 2023 09:44:45 +0100 Subject: [PATCH 52/63] fix(field): prevent input size changes when showing clear icon Refs: #5338 --- front/core/components/autocomplete/style.scss | 4 ++++ front/core/components/field/index.html | 2 +- front/core/components/field/style.scss | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/front/core/components/autocomplete/style.scss b/front/core/components/autocomplete/style.scss index 19e8362d5..201d29c1e 100755 --- a/front/core/components/autocomplete/style.scss +++ b/front/core/components/autocomplete/style.scss @@ -19,6 +19,10 @@ padding-right: 0; } } + + & > .icons.pre { + min-width: 22px + } } &.readonly > .container > .icons.post { display: none; diff --git a/front/core/components/field/index.html b/front/core/components/field/index.html index bd13f46d6..0d65c1f40 100644 --- a/front/core/components/field/index.html +++ b/front/core/components/field/index.html @@ -12,7 +12,7 @@ * -
+
.icons.pre.clearable { + min-width: 22px + } & > .underline { position: absolute; bottom: 0; From 780572a9f2649e309a0f4ec084033512b7a50a5c Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 6 Mar 2023 08:14:26 +0100 Subject: [PATCH 53/63] test fixed --- loopback/locale/en.json | 8 +++++--- modules/claim/back/methods/claim-state/isEditable.js | 2 +- .../back/methods/claim-state/specs/isEditable.spec.js | 2 +- modules/claim/front/detail/index.spec.js | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index eeb25f75d..dbe25dea3 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -147,8 +147,10 @@ "Receipt's bank was not found": "Receipt's bank was not found", "This receipt was not compensated": "This receipt was not compensated", "Client's email was not found": "Client's email was not found", - "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", + "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", - "It is not possible to modify cloned sales": "It is not possible to modify cloned sales" -} + "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", + "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", + "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2" +} \ No newline at end of file diff --git a/modules/claim/back/methods/claim-state/isEditable.js b/modules/claim/back/methods/claim-state/isEditable.js index b144f0a53..2d0a8dc44 100644 --- a/modules/claim/back/methods/claim-state/isEditable.js +++ b/modules/claim/back/methods/claim-state/isEditable.js @@ -6,7 +6,7 @@ module.exports = Self => { arg: 'id', type: 'number', required: true, - description: 'the st id', + description: 'the state id', http: {source: 'path'} }], returns: { diff --git a/modules/claim/back/methods/claim-state/specs/isEditable.spec.js b/modules/claim/back/methods/claim-state/specs/isEditable.spec.js index 4ce7af1c2..1fb8e1536 100644 --- a/modules/claim/back/methods/claim-state/specs/isEditable.spec.js +++ b/modules/claim/back/methods/claim-state/specs/isEditable.spec.js @@ -3,7 +3,7 @@ const app = require('vn-loopback/server/server'); describe('claimstate isEditable()', () => { const salesPersonId = 18; const claimManagerId = 72; - it('should return false if the given claim does not exist', async() => { + it('should return false if the given state does not exist', async() => { const tx = await app.models.Claim.beginTransaction({}); try { diff --git a/modules/claim/front/detail/index.spec.js b/modules/claim/front/detail/index.spec.js index b36f3a172..a2b177281 100644 --- a/modules/claim/front/detail/index.spec.js +++ b/modules/claim/front/detail/index.spec.js @@ -17,7 +17,7 @@ describe('claim', () => { $httpBackend = _$httpBackend_; $httpBackend.whenGET('Claims/ClaimBeginnings').respond({}); $httpBackend.whenGET(`Tickets/1/isEditable`).respond(true); - $httpBackend.whenGET(`Claims/2/isEditable`).respond(true); + $httpBackend.whenGET(`ClaimStates/2/isEditable`).respond(true); const $element = angular.element(''); controller = $componentController('vnClaimDetail', {$element, $scope}); controller.claim = { From a6bf61033f5d3e03a2e5e4af5c4d06c63ac87331 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 6 Mar 2023 12:04:16 +0100 Subject: [PATCH 54/63] refactor tests --- e2e/paths/05-ticket/21_future.spec.js | 83 +++++++++----------------- e2e/paths/05-ticket/22_advance.spec.js | 30 +++------- 2 files changed, 35 insertions(+), 78 deletions(-) diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 34ae3d688..2b8057247 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -4,12 +4,17 @@ import getBrowser from '../../helpers/puppeteer'; describe('Ticket Future path', () => { let browser; let page; + let httpRequest; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'ticket'); await page.accessToSection('ticket.future'); + page.on('request', req => { + if (req.url().includes(`Tickets/getTicketsFuture`)) + httpRequest = req.url(); + }); }); afterAll(async() => { @@ -42,114 +47,82 @@ describe('Ticket Future path', () => { it('should search with the required data', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + + expect(httpRequest).toBeDefined(); }); it('should search with the origin IPT', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.ipt); - await page.clearInput(selectors.ticketFuture.futureIpt); - await page.clearInput(selectors.ticketFuture.state); - await page.clearInput(selectors.ticketFuture.futureState); - await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + + expect(httpRequest).toContain('ipt=H'); }); 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.futureIpt); - await page.clearInput(selectors.ticketFuture.state); - await page.clearInput(selectors.ticketFuture.futureState); await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + + expect(httpRequest).toContain('futureIpt=H'); }); it('should search with the origin grouped state', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.futureIpt); - await page.clearInput(selectors.ticketFuture.state); - await page.clearInput(selectors.ticketFuture.futureState); await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 3); + + expect(httpRequest).toContain('state=FREE'); }); it('should search with the destination grouped state', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.ipt); - await page.clearInput(selectors.ticketFuture.futureIpt); await page.clearInput(selectors.ticketFuture.state); - await page.clearInput(selectors.ticketFuture.futureState); await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + + expect(httpRequest).toContain('futureState=FREE'); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.ipt); - await page.clearInput(selectors.ticketFuture.futureIpt); - await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.futureState); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); it('should search in smart-table with an ID Origin', async() => { await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableId, '13'); + await page.write(selectors.ticketFuture.tableId, '1'); await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 2); + expect(httpRequest).toContain('id'); await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - }); - - it('should search in smart-table with an ID Destination', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableFutureId, '12'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - }); - - it('should search in smart-table with an IPT Origin', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketFuture.tableIpt, 'Vertical'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); it('should search in smart-table with an IPT Destination', async() => { await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Vertical'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Horizontal'); + 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); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); it('should check the three last tickets and move to the future', async() => { diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index c92cd7a20..f8442bf12 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -4,7 +4,7 @@ import getBrowser from '../../helpers/puppeteer'; describe('Ticket Advance path', () => { let browser; let page; - const httpRequests = []; + let httpRequest; beforeAll(async() => { browser = await getBrowser(); @@ -13,7 +13,7 @@ describe('Ticket Advance path', () => { await page.accessToSection('ticket.advance'); page.on('request', req => { if (req.url().includes(`Tickets/getTicketsAdvance`)) - httpRequests.push(req.url()); + httpRequest = req.url(); }); }); @@ -49,7 +49,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.submit); - expect(httpRequests.length).toBeGreaterThan(0); + expect(httpRequest).toBeDefined(); }); it('should search with the origin IPT', async() => { @@ -57,11 +57,7 @@ describe('Ticket Advance path', () => { await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - const request = httpRequests.find(req => req.includes(('futureIpt=H'))); - - expect(request).toBeDefined(); - - httpRequests.splice(httpRequests.indexOf(request), 1); + expect(httpRequest).toContain('futureIpt=H'); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.futureIpt); @@ -73,11 +69,7 @@ describe('Ticket Advance path', () => { await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - const request = httpRequests.find(req => req.includes(('ipt=H'))); - - expect(request).toBeDefined(); - - httpRequests.splice(httpRequests.indexOf(request), 1); + expect(httpRequest).toContain('ipt=H'); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.ipt); @@ -88,11 +80,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical'); - const request = httpRequests.find(req => req.includes(('futureIpt'))); - - expect(request).toBeDefined(); - - httpRequests.splice(httpRequests.indexOf(request), 1); + expect(httpRequest).toContain('futureIpt'); await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); @@ -103,11 +91,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical'); - const request = httpRequests.find(req => req.includes(('ipt'))); - - expect(request).toBeDefined(); - - httpRequests.splice(httpRequests.indexOf(request), 1); + expect(httpRequest).toContain('ipt'); await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); From 4f091330a7276ce00c59dfce40f7a282d456cb33 Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 6 Mar 2023 12:37:37 +0100 Subject: [PATCH 55/63] feat(claimLog): added claim log section Refs: #5340 --- db/dump/fixtures.sql | 8 +- modules/claim/back/methods/claim/logs.js | 134 ++++++++++++++++++ .../back/methods/claim/specs/log.spec.js | 12 ++ modules/claim/back/models/claim.js | 1 + 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 modules/claim/back/methods/claim/logs.js create mode 100644 modules/claim/back/methods/claim/specs/log.spec.js diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5af9b9eeb..7b5a5960b 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1828,7 +1828,12 @@ INSERT INTO vn.claimRma (`id`, `code`, `created`, `workerFk`) (4, '02676A049183', DEFAULT, 1107), (5, '01837B023653', DEFAULT, 1106); - +INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`) + VALUES + (1, 18, 'update', 'Claim', '{"hasToPickUp":false}', '{"hasToPickUp":true}', 1, NULL), + (1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL), + (1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL), + (1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL); INSERT INTO `hedera`.`tpvMerchant`(`id`, `description`, `companyFk`, `bankFk`, `secretKey`) VALUES @@ -2760,7 +2765,6 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns (7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL), (7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'"); - INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); diff --git a/modules/claim/back/methods/claim/logs.js b/modules/claim/back/methods/claim/logs.js new file mode 100644 index 000000000..c7e69680b --- /dev/null +++ b/modules/claim/back/methods/claim/logs.js @@ -0,0 +1,134 @@ + +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const buildFilter = require('vn-loopback/util/filter').buildFilter; +const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter'); + +module.exports = Self => { + Self.remoteMethodCtx('logs', { + description: 'Find all claim logs of the claim entity matched by a filter', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'Number', + description: 'The claim id', + http: {source: 'path'} + }, + { + arg: 'filter', + type: 'object', + http: {source: 'query'} + }, + { + arg: 'search', + type: 'string', + http: {source: 'query'} + }, + { + arg: 'userFk', + type: 'number', + http: {source: 'query'} + }, + { + arg: 'created', + type: 'date', + http: {source: 'query'} + }, + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/:id/logs`, + verb: 'GET' + } + }); + + Self.logs = async(ctx, id, filter, options) => { + const conn = Self.dataSource.connector; + const args = ctx.args; + const myOptions = {}; + let to; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + let where = buildFilter(args, (param, value) => { + switch (param) { + case 'search': + return { + or: [ + {changedModel: {like: `%${value}%`}}, + {oldInstance: {like: `%${value}%`}} + ] + }; + case 'userFk': + return {'cl.userFk': value}; + case 'created': + value.setHours(0, 0, 0, 0); + to = new Date(value); + to.setHours(23, 59, 59, 999); + + return {creationDate: {between: [value, to]}}; + } + }); + where = mergeWhere(where, {['cl.originFk']: id}); + filter = mergeFilters(args.filter, {where}); + + const stmts = []; + + const stmt = new ParameterizedSQL( + `SELECT + cl.id, + cl.userFk, + u.name AS userName, + cl.oldInstance, + cl.newInstance, + cl.changedModel, + cl.action, + cl.creationDate AS created + FROM claimLog cl + JOIN account.user u ON u.id = cl.userFk + ` + ); + + stmt.merge(conn.makeSuffix(filter)); + stmts.push(stmt); + + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + + const logs = []; + for (const row of result) { + const changes = []; + const oldInstance = JSON.parse(row.oldInstance); + const newInstance = JSON.parse(row.newInstance); + const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)]; + const properties = new Set(mergedProperties); + for (const property of properties) { + let oldValue = oldInstance[property]; + let newValue = newInstance[property]; + + const change = { + property: property, + before: oldValue, + after: newValue, + }; + + changes.push(change); + } + + logs.push({ + model: row.changedModel, + action: row.action, + created: row.created, + userFk: row.userFk, + userName: row.userName, + changes: changes, + }); + } + + return logs; + }; +}; diff --git a/modules/claim/back/methods/claim/specs/log.spec.js b/modules/claim/back/methods/claim/specs/log.spec.js new file mode 100644 index 000000000..980bf5593 --- /dev/null +++ b/modules/claim/back/methods/claim/specs/log.spec.js @@ -0,0 +1,12 @@ +const app = require('vn-loopback/server/server'); + +describe('claim log()', () => { + const claimId = 1; + const salesPersonId = 18; + + it('should return results filtering by user id', async() => { + const result = await app.models.Claim.logs({args: {userFk: salesPersonId}}, claimId); + + expect(result.length).toBeGreaterThan(0); + }); +}); diff --git a/modules/claim/back/models/claim.js b/modules/claim/back/models/claim.js index c9d7ee7d4..12fcaa326 100644 --- a/modules/claim/back/models/claim.js +++ b/modules/claim/back/models/claim.js @@ -11,4 +11,5 @@ module.exports = Self => { require('../methods/claim/downloadFile')(Self); require('../methods/claim/claimPickupPdf')(Self); require('../methods/claim/claimPickupEmail')(Self); + require('../methods/claim/logs')(Self); }; From 9f4aed7d83d284609ea2a866fc265947b1e3738b Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 6 Mar 2023 13:44:03 +0100 Subject: [PATCH 56/63] Updated unit test --- modules/claim/back/methods/claim/specs/log.spec.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/claim/back/methods/claim/specs/log.spec.js b/modules/claim/back/methods/claim/specs/log.spec.js index 980bf5593..0ae534f1e 100644 --- a/modules/claim/back/methods/claim/specs/log.spec.js +++ b/modules/claim/back/methods/claim/specs/log.spec.js @@ -7,6 +7,17 @@ describe('claim log()', () => { it('should return results filtering by user id', async() => { const result = await app.models.Claim.logs({args: {userFk: salesPersonId}}, claimId); + const expectedObject = { + model: 'Claim', + action: 'update', + changes: [ + {property: 'hasToPickUp', before: false, after: true} + ] + }; + + const firstRow = result[0]; + expect(result.length).toBeGreaterThan(0); + expect(firstRow).toEqual(jasmine.objectContaining(expectedObject)); }); }); From 4a32c164a6f6adfe9992a321b919b0011507154a Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 7 Mar 2023 07:34:08 +0100 Subject: [PATCH 57/63] template string --- db/changes/230601/00-acl_claim.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/changes/230601/00-acl_claim.sql b/db/changes/230601/00-acl_claim.sql index ea96e130a..4e680eb4f 100644 --- a/db/changes/230601/00-acl_claim.sql +++ b/db/changes/230601/00-acl_claim.sql @@ -1,6 +1,6 @@ -INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) VALUES('ClaimBeginning', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee'); -DELETE FROM salix.ACL +DELETE FROM `salix`.`ACL` WHERE model='Claim' AND property='isEditable'; From c0ff6bea57f60e3a7102070bba8a407286871f54 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 07:47:30 +0100 Subject: [PATCH 58/63] fix(smartTable): fixed filtering with an intermediate check Refs: #5177 --- front/core/components/check/index.js | 2 +- front/core/components/smart-table/index.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/front/core/components/check/index.js b/front/core/components/check/index.js index 78b1807a5..25ec506ad 100644 --- a/front/core/components/check/index.js +++ b/front/core/components/check/index.js @@ -40,7 +40,7 @@ export default class Check extends Toggle { set tripleState(value) { this._tripleState = value; - this.field = this.field; + this.field = value; } get tripleState() { diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index ad9883950..b2380a62f 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -436,6 +436,7 @@ export default class SmartTable extends Component { if (filters && filters.userFilter) this.model.userFilter = filters.userFilter; + this.addFilter(field, this.$inputsScope.searchProps[field]); } @@ -451,7 +452,7 @@ export default class SmartTable extends Component { } addFilter(field, value) { - if (value == '') value = null; + if (value === '') value = null; let stateFilter = {tableQ: {}}; if (this.$params.q) { @@ -462,7 +463,7 @@ export default class SmartTable extends Component { } const whereParams = {[field]: value}; - if (value) { + if (value !== '' && value !== null && value !== undefined) { let where = {[field]: value}; if (this.exprBuilder) { where = buildFilter(whereParams, (param, value) => From e8e8392e5da24a34d1c86edc9b5517ed7bea0b0c Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 07:58:08 +0100 Subject: [PATCH 59/63] Updated changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bff0feed7..1cfc7e610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ### Fixed -- +- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo" ## [2308.01] - 2023-03-09 From 0d2339686cc13b39fd7b26c9f3fc67968568a482 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 08:10:52 +0100 Subject: [PATCH 60/63] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cfc7e610..cf7d8465a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo" +- (General) Al pasar el ratón por encima del icono de "Borrar" en un campo, se hacía más grande afectando a la interfaz ## [2308.01] - 2023-03-09 From 14a5c7830398d609a1757d97e7b5aa3973f5416a Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 08:13:07 +0100 Subject: [PATCH 61/63] Updated unit test --- front/core/components/check/index.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/core/components/check/index.spec.js b/front/core/components/check/index.spec.js index c9d50cab2..7ec0f12a0 100644 --- a/front/core/components/check/index.spec.js +++ b/front/core/components/check/index.spec.js @@ -45,8 +45,8 @@ describe('Component vnCheck', () => { }); it(`should set value to null and change to true when clicked`, () => { - controller.field = null; controller.tripleState = true; + controller.field = null; element.click(); expect(controller.field).toEqual(true); From 445a0b0e1fa7feec96d9de1fc8b1015a19592422 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 10:20:10 +0100 Subject: [PATCH 62/63] Claim fixes --- modules/claim/back/models/claim-beginning.js | 26 ++++++++++---------- modules/claim/front/detail/index.js | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/claim/back/models/claim-beginning.js b/modules/claim/back/models/claim-beginning.js index 4283e37e2..ba70c0bbc 100644 --- a/modules/claim/back/models/claim-beginning.js +++ b/modules/claim/back/models/claim-beginning.js @@ -29,21 +29,21 @@ module.exports = Self => { myOptions.transaction = ctx.options.transaction; const claimBeginning = await Self.findById(ctx.where.id); - + const filter = { - where: {id: claimBeginning.claimFk}, - include: [ - { - relation: 'claimState', - scope: { - fields: ['id', 'code', 'description'] - } - } - ] - }; - + where: {id: claimBeginning.claimFk}, + include: [ + { + relation: 'claimState', + scope: { + fields: ['id', 'code', 'description'] + } + } + ] + }; + const [claim] = await models.Claim.find(filter, myOptions); - const isEditable = await models.ClaimState.isEditable(httpCtx, claim.ClaimState()); + const isEditable = await models.ClaimState.isEditable(httpCtx, claim.claimState().id); if (!isEditable) throw new UserError(`The current claim can't be modified`); diff --git a/modules/claim/front/detail/index.js b/modules/claim/front/detail/index.js index 33ce1a581..833519579 100644 --- a/modules/claim/front/detail/index.js +++ b/modules/claim/front/detail/index.js @@ -100,8 +100,8 @@ class Controller extends Section { } setClaimedQuantity(id, claimedQuantity) { - let params = {id: id, quantity: claimedQuantity}; - let query = `ClaimBeginnings/`; + let params = {quantity: claimedQuantity}; + let query = `ClaimBeginnings/${id}`; this.$http.patch(query, params).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.calculateTotals(); From 3ad96b6ad73dad7697cdbe50fe6db62411a08c42 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 7 Mar 2023 11:55:13 +0100 Subject: [PATCH 63/63] Endpoint fixes --- modules/worker/back/methods/worker/filter.js | 44 +++++++++++--------- modules/worker/front/search-panel/index.html | 2 +- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/modules/worker/back/methods/worker/filter.js b/modules/worker/back/methods/worker/filter.js index d08b27a18..71a8da96f 100644 --- a/modules/worker/back/methods/worker/filter.js +++ b/modules/worker/back/methods/worker/filter.js @@ -13,55 +13,59 @@ module.exports = Self => { type: 'Object', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', http: {source: 'query'} - }, { - arg: 'tags', - type: ['Object'], - description: 'List of tags to filter with', - http: {source: 'query'} - }, { + }, + { arg: 'search', type: 'String', description: `If it's and integer searchs by id, otherwise it searchs by name`, http: {source: 'query'} - }, { + }, + { arg: 'id', type: 'Integer', description: 'The worker id', http: {source: 'query'} - }, { + }, + { arg: 'userFk', type: 'Integer', description: 'The user id', http: {source: 'query'} - }, { + }, + { arg: 'fi', type: 'String', description: 'The worker fi', http: {source: 'query'} - }, { + }, + { arg: 'departmentFk', type: 'Integer', description: 'The worker department id', http: {source: 'query'} - }, { + }, + { arg: 'extension', type: 'Integer', description: 'The worker extension id', http: {source: 'query'} - }, { + }, + { arg: 'firstName', type: 'String', description: 'The worker firstName', http: {source: 'query'} - }, { - arg: 'name', + }, + { + arg: 'lastName', type: 'String', - description: 'The worker name', + description: 'The worker lastName', http: {source: 'query'} - }, { - arg: 'nickname', + }, + { + arg: 'userName', type: 'String', - description: 'The worker nickname', + description: 'The worker user name', http: {source: 'query'} } ], @@ -93,10 +97,10 @@ module.exports = Self => { return {'w.id': value}; case 'userFk': return {'w.userFk': value}; - case 'name': - return {'w.lastName': {like: `%${value}%`}}; case 'firstName': return {'w.firstName': {like: `%${value}%`}}; + case 'lastName': + return {'w.lastName': {like: `%${value}%`}}; case 'extension': return {'p.extension': value}; case 'fi': diff --git a/modules/worker/front/search-panel/index.html b/modules/worker/front/search-panel/index.html index ca57722c8..2adb56587 100644 --- a/modules/worker/front/search-panel/index.html +++ b/modules/worker/front/search-panel/index.html @@ -30,7 +30,7 @@ + ng-model="filter.lastName">