From 0afc26e20c1a65c53aca7d495ac5148673483246 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 8 Jun 2023 10:30:03 +0200 Subject: [PATCH 01/17] refs #5728 remove add, quit e2e --- e2e/paths/12-entry/07_buys.spec.js | 19 -- modules/entry/back/methods/entry/addBuy.js | 165 ------------------ .../back/methods/entry/specs/addBuy.spec.js | 42 ----- modules/entry/back/models/entry.js | 1 - modules/entry/front/buy/index/index.html | 7 - modules/entry/front/buy/index/index.js | 5 - modules/entry/front/buy/index/index.spec.js | 11 -- 7 files changed, 250 deletions(-) delete mode 100644 modules/entry/back/methods/entry/addBuy.js delete mode 100644 modules/entry/back/methods/entry/specs/addBuy.spec.js diff --git a/e2e/paths/12-entry/07_buys.spec.js b/e2e/paths/12-entry/07_buys.spec.js index e501452bc..260d1be57 100644 --- a/e2e/paths/12-entry/07_buys.spec.js +++ b/e2e/paths/12-entry/07_buys.spec.js @@ -67,25 +67,6 @@ describe('Entry import, create and edit buys path', () => { await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 1); }); - it('should add a new buy', async() => { - await page.waitToClick(selectors.entryBuys.addBuyButton); - await page.write(selectors.entryBuys.secondBuyPackingPrice, '999'); - await page.write(selectors.entryBuys.secondBuyGroupingPrice, '999'); - await page.write(selectors.entryBuys.secondBuyPrice, '999'); - await page.write(selectors.entryBuys.secondBuyGrouping, '999'); - await page.write(selectors.entryBuys.secondBuyPacking, '999'); - await page.write(selectors.entryBuys.secondBuyWeight, '999'); - await page.write(selectors.entryBuys.secondBuyStickers, '999'); - await page.autocompleteSearch(selectors.entryBuys.secondBuyPackage, '1'); - await page.write(selectors.entryBuys.secondBuyQuantity, '999'); - await page.autocompleteSearch(selectors.entryBuys.secondBuyItem, '1'); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - - await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 2); - }); - it('should edit the newest buy and check data', async() => { await page.clearInput(selectors.entryBuys.secondBuyPackingPrice); await page.waitForTimeout(250); diff --git a/modules/entry/back/methods/entry/addBuy.js b/modules/entry/back/methods/entry/addBuy.js deleted file mode 100644 index f612c1651..000000000 --- a/modules/entry/back/methods/entry/addBuy.js +++ /dev/null @@ -1,165 +0,0 @@ - -const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; - -module.exports = Self => { - Self.remoteMethodCtx('addBuy', { - description: 'Inserts a new buy for the current entry', - accessType: 'WRITE', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'The entry id', - http: {source: 'path'} - }, - { - arg: 'itemFk', - type: 'number', - required: true - }, - { - arg: 'quantity', - type: 'number', - required: true - }, - { - arg: 'packageFk', - type: 'string', - required: true - }, - { - arg: 'packing', - type: 'number', - }, - { - arg: 'grouping', - type: 'number' - }, - { - arg: 'weight', - type: 'number', - }, - { - arg: 'stickers', - type: 'number', - }, - { - arg: 'price2', - type: 'number', - }, - { - arg: 'price3', - type: 'number', - }, - { - arg: 'buyingValue', - type: 'number' - }], - returns: { - type: 'object', - root: true - }, - http: { - path: `/:id/addBuy`, - verb: 'POST' - } - }); - - Self.addBuy = async(ctx, options) => { - const conn = Self.dataSource.connector; - let tx; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - - try { - const models = Self.app.models; - - ctx.args.entryFk = ctx.args.id; - - // remove unwanted properties - delete ctx.args.id; - delete ctx.args.ctx; - - const newBuy = await models.Buy.create(ctx.args, myOptions); - - const filter = { - fields: [ - 'id', - 'itemFk', - 'stickers', - 'packing', - 'grouping', - 'quantity', - 'packageFk', - 'weight', - 'buyingValue', - 'price2', - 'price3' - ], - include: { - relation: 'item', - scope: { - fields: [ - 'id', - 'typeFk', - 'name', - 'size', - 'minPrice', - 'tag5', - 'value5', - 'tag6', - 'value6', - 'tag7', - 'value7', - 'tag8', - 'value8', - 'tag9', - 'value9', - 'tag10', - 'value10', - 'groupingMode' - ], - include: { - relation: 'itemType', - scope: { - fields: ['code', 'description'] - } - } - } - } - }; - - const stmts = []; - let stmt; - - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.buyRecalc'); - stmt = new ParameterizedSQL( - `CREATE TEMPORARY TABLE tmp.buyRecalc - (INDEX (id)) - ENGINE = MEMORY - SELECT ? AS id`, [newBuy.id]); - - stmts.push(stmt); - stmts.push('CALL buy_recalcPrices()'); - - const sql = ParameterizedSQL.join(stmts, ';'); - await conn.executeStmt(sql, myOptions); - - const buy = await models.Buy.findById(newBuy.id, filter, myOptions); - - if (tx) await tx.commit(); - - return buy; - } catch (e) { - if (tx) await tx.rollback(); - throw e; - } - }; -}; diff --git a/modules/entry/back/methods/entry/specs/addBuy.spec.js b/modules/entry/back/methods/entry/specs/addBuy.spec.js deleted file mode 100644 index ead75f2d2..000000000 --- a/modules/entry/back/methods/entry/specs/addBuy.spec.js +++ /dev/null @@ -1,42 +0,0 @@ -const models = require('vn-loopback/server/server').models; -const LoopBackContext = require('loopback-context'); - -describe('entry addBuy()', () => { - const activeCtx = { - accessToken: {userId: 18}, - }; - - const ctx = { - req: activeCtx - }; - - const entryId = 2; - it('should create a new buy for the given entry', async() => { - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - const itemId = 4; - const quantity = 10; - - ctx.args = { - id: entryId, - itemFk: itemId, - quantity: quantity, - packageFk: 3 - }; - - const tx = await models.Entry.beginTransaction({}); - const options = {transaction: tx}; - - try { - const newBuy = await models.Entry.addBuy(ctx, options); - - expect(newBuy.itemFk).toEqual(itemId); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index 0eabd70ee..6148ae559 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -3,7 +3,6 @@ module.exports = Self => { require('../methods/entry/filter')(Self); require('../methods/entry/getEntry')(Self); require('../methods/entry/getBuys')(Self); - require('../methods/entry/addBuy')(Self); require('../methods/entry/importBuys')(Self); require('../methods/entry/importBuysPreview')(Self); require('../methods/entry/lastItemBuys')(Self); diff --git a/modules/entry/front/buy/index/index.html b/modules/entry/front/buy/index/index.html index e6d1a0b76..28fdabdb4 100644 --- a/modules/entry/front/buy/index/index.html +++ b/modules/entry/front/buy/index/index.html @@ -222,13 +222,6 @@
- - { if (!res.data) return; diff --git a/modules/entry/front/buy/index/index.spec.js b/modules/entry/front/buy/index/index.spec.js index aff52bc80..0e221302c 100644 --- a/modules/entry/front/buy/index/index.spec.js +++ b/modules/entry/front/buy/index/index.spec.js @@ -25,17 +25,6 @@ describe('Entry buy', () => { controller.saveBuy(buy); $httpBackend.flush(); }); - - it(`should call the entry addBuy post route if the received buy has no ID`, () => { - controller.entry = {id: 1}; - const buy = {itemFk: 1, quantity: 1, packageFk: 1}; - - const query = `Entries/${controller.entry.id}/addBuy`; - - $httpBackend.expectPOST(query).respond(200); - controller.saveBuy(buy); - $httpBackend.flush(); - }); }); describe('deleteBuys()', () => { From 9cdaf2e51916f481cc9327f7cb5b9e39a3c812a6 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 8 Jun 2023 10:45:27 +0200 Subject: [PATCH 02/17] refs #5728 fix e2e buy --- e2e/helpers/selectors.js | 2 - e2e/paths/12-entry/07_buys.spec.js | 74 ------------------------------ 2 files changed, 76 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index fff0a2f15..ed9c9daba 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1179,8 +1179,6 @@ export default { allBuyCheckbox: 'vn-entry-buy-index thead vn-check', firstBuyCheckbox: 'vn-entry-buy-index tbody:nth-child(2) vn-check', deleteBuysButton: 'vn-entry-buy-index vn-button[icon="delete"]', - addBuyButton: 'vn-entry-buy-index vn-icon[icon="add"]', - secondBuyPackingPrice: 'vn-entry-buy-index tbody:nth-child(3) > tr:nth-child(1) vn-input-number[ng-model="buy.price3"]', secondBuyGroupingPrice: 'vn-entry-buy-index tbody:nth-child(3) > tr:nth-child(1) vn-input-number[ng-model="buy.price2"]', secondBuyPrice: 'vn-entry-buy-index tbody:nth-child(3) > tr:nth-child(1) vn-input-number[ng-model="buy.buyingValue"]', secondBuyGrouping: 'vn-entry-buy-index tbody:nth-child(3) > tr:nth-child(1) vn-input-number[ng-model="buy.grouping"]', diff --git a/e2e/paths/12-entry/07_buys.spec.js b/e2e/paths/12-entry/07_buys.spec.js index 260d1be57..28d39fb1d 100644 --- a/e2e/paths/12-entry/07_buys.spec.js +++ b/e2e/paths/12-entry/07_buys.spec.js @@ -66,78 +66,4 @@ describe('Entry import, create and edit buys path', () => { await page.waitToClick(selectors.globalItems.acceptButton); await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 1); }); - - it('should edit the newest buy and check data', async() => { - await page.clearInput(selectors.entryBuys.secondBuyPackingPrice); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyPackingPrice, '100'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyGroupingPrice); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyGroupingPrice, '200'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyPrice); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyPrice, '300'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyGrouping); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyGrouping, '400'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyPacking); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyPacking, '500'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyWeight); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyWeight, '600'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyStickers); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyStickers, '700'); - await page.keyboard.press('Enter'); - await page.waitForSnackbar(); - - await page.autocompleteSearch(selectors.entryBuys.secondBuyPackage, '94'); - await page.waitForSnackbar(); - - await page.clearInput(selectors.entryBuys.secondBuyQuantity); - await page.waitForTimeout(250); - await page.write(selectors.entryBuys.secondBuyQuantity, '800'); - await page.keyboard.press('Enter'); - - await page.reloadSection('entry.card.buy.index'); - - const secondBuyPackingPrice = await page.getValue(selectors.entryBuys.secondBuyPackingPrice); - const secondBuyGroupingPrice = await page.getValue(selectors.entryBuys.secondBuyGroupingPrice); - const secondBuyPrice = await page.getValue(selectors.entryBuys.secondBuyPrice); - const secondBuyGrouping = await page.getValue(selectors.entryBuys.secondBuyGrouping); - const secondBuyPacking = await page.getValue(selectors.entryBuys.secondBuyPacking); - const secondBuyWeight = await page.getValue(selectors.entryBuys.secondBuyWeight); - const secondBuyStickers = await page.getValue(selectors.entryBuys.secondBuyStickers); - const secondBuyPackage = await page.getValue(selectors.entryBuys.secondBuyPackage); - const secondBuyQuantity = await page.getValue(selectors.entryBuys.secondBuyQuantity); - - expect(secondBuyPackingPrice).toEqual('100'); - expect(secondBuyGroupingPrice).toEqual('200'); - expect(secondBuyPrice).toEqual('300'); - expect(secondBuyGrouping).toEqual('400'); - expect(secondBuyPacking).toEqual('500'); - expect(secondBuyWeight).toEqual('600'); - expect(secondBuyStickers).toEqual('700'); - expect(secondBuyPackage).toEqual('94'); - expect(secondBuyQuantity).toEqual('800'); - }); }); From 72b779f5c0409781b95f2722c59952e48648dd79 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 13 Jun 2023 10:26:12 +0200 Subject: [PATCH 03/17] refs #5528 fix: editar compras (seleccionar todas), cuando aplicas un filtro --- modules/entry/back/methods/entry/editLatestBuys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/entry/back/methods/entry/editLatestBuys.js b/modules/entry/back/methods/entry/editLatestBuys.js index 2642d4f4d..0da2b1625 100644 --- a/modules/entry/back/methods/entry/editLatestBuys.js +++ b/modules/entry/back/methods/entry/editLatestBuys.js @@ -75,7 +75,7 @@ module.exports = Self => { value[field] = newValue; if (filter) { - ctx.args.filter = {where: filter, limit: null}; + ctx.args = {where: filter, limit: null}; lines = await models.Buy.latestBuysFilter(ctx, null, myOptions); } From 65108943abeae3fcb9a67d0573708f43fa1e1f70 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 14 Jun 2023 12:48:14 +0200 Subject: [PATCH 04/17] refs #5528 feat: back test --- modules/entry/back/methods/entry/specs/editLatestBuys.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js index 99d2df67b..1ffe27918 100644 --- a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js +++ b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js @@ -53,7 +53,7 @@ describe('Buy editLatestsBuys()', () => { const options = {transaction: tx}; try { - const filter = {'i.typeFk': 1}; + const filter = {'categoryFk': 1}; const ctx = { args: { filter: filter From 98b270b885a061dff168408e561db8156bbc419e Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 14 Jun 2023 13:05:46 +0200 Subject: [PATCH 05/17] refs #5528 feat: add back test --- .../entry/specs/editLatestBuys.spec.js | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js index 1ffe27918..a4dd185fd 100644 --- a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js +++ b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js @@ -53,7 +53,36 @@ describe('Buy editLatestsBuys()', () => { const options = {transaction: tx}; try { - const filter = {'categoryFk': 1}; + const filter = {'categoryFk': 1, 'tags': []}; + const ctx = { + args: { + filter: filter + }, + req: {accessToken: {userId: 1}} + }; + + const field = 'size'; + const newValue = 88; + + await models.Buy.editLatestBuys(ctx, field, newValue, null, filter, options); + + const [result] = await models.Buy.latestBuysFilter(ctx, null, options); + + expect(result[field]).toEqual(newValue); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should change the value of a given column for filter tags', async() => { + const tx = await models.Buy.beginTransaction({}); + const options = {transaction: tx}; + + try { + const filter = {'tags': [{tagFk: 1, value: 'Brown'}]}; const ctx = { args: { filter: filter From a7d9bbc582abf96611fecfb3ac31aa7fdaf4b506 Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 20 Jun 2023 10:22:30 +0200 Subject: [PATCH 06/17] refs #5537 change cl c --- print/core/components/report-footer/report-footer.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/print/core/components/report-footer/report-footer.js b/print/core/components/report-footer/report-footer.js index 077ef0bde..ed718b8dc 100755 --- a/print/core/components/report-footer/report-footer.js +++ b/print/core/components/report-footer/report-footer.js @@ -5,10 +5,9 @@ module.exports = { name: 'report-footer', async serverPrefetch() { this.company = await db.findOne(` - SELECT IFNULL(ci.footnotes, cl.footnotes) as footnotes + SELECT IFNULL(ci.footnotes, c.footnotes) footnotes FROM company c - LEFT JOIN companyL10n cl ON c.id = cl.id - LEFT JOIN companyI18n ci ON ci.companyFk = cl.id + LEFT JOIN companyI18n ci ON ci.companyFk = c.id AND ci.lang = (SELECT lang FROM account.user where id = ?) WHERE c.code = ?`, [this.recipientId, this.companyCode]); From 2649db852f215a477ac0804068887c853336dfc8 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 20 Jun 2023 11:50:36 +0200 Subject: [PATCH 07/17] refs #5772 Invoice PDF size reduced --- print/templates/reports/invoice/assets/css/style.css | 6 +++++- print/templates/reports/invoice/invoice.html | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/print/templates/reports/invoice/assets/css/style.css b/print/templates/reports/invoice/assets/css/style.css index 9fda2a613..d4526ce56 100644 --- a/print/templates/reports/invoice/assets/css/style.css +++ b/print/templates/reports/invoice/assets/css/style.css @@ -16,6 +16,10 @@ h2 { font-size: 22px } +.column-oriented td, +.column-oriented th { + padding: 6px +} #nickname h2 { max-width: 400px; @@ -39,4 +43,4 @@ h2 { .phytosanitary-info { margin-top: 10px -} \ No newline at end of file +} diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index d74325dfd..32138befc 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -62,7 +62,7 @@
-
+

{{$t('deliveryNote')}}

@@ -106,6 +106,7 @@ {{sale.vatType}} {{saleImport(sale) | currency('EUR', $i18n.locale)}} + From 6f9fd9bb72109aed288fe46671ca40aa5c417c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Wed, 21 Jun 2023 09:40:14 +0200 Subject: [PATCH 08/17] refs #5772 mensajes de error --- loopback/locale/es.json | 2 +- modules/invoiceOut/front/global-invoicing/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 7e2701f95..b66a13569 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -265,7 +265,7 @@ "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", - "Exists an invoice with a previous date": "Existe una factura con fecha anterior", + "Exists an invoice with a future date": "Existe una factura con fecha posterior", "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", "Warehouse inventory not set": "El almacén inventario no está establecido", "This locker has already been assigned": "Esta taquilla ya ha sido asignada", diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 5a078dfbb..70838a5a2 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -49,7 +49,7 @@ class Controller extends Section { if (this.invoiceDate < this.maxShipped) throw new UserError('Invoice date can\'t be less than max date'); if (this.minInvoicingDate && this.invoiceDate.getTime() < this.minInvoicingDate.getTime()) - throw new UserError('Exists an invoice with a previous date'); + throw new UserError('Exists an invoice with a future date'); if (!this.companyFk) throw new UserError('Choose a valid company'); if (!this.printerFk) From 44192c0606ba7611946f21bf1189d2fa8a3e9df3 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Wed, 21 Jun 2023 11:08:28 +0200 Subject: [PATCH 09/17] refs #5667 Client translations added --- modules/client/back/locale/client/en.yml | 3 ++- modules/client/back/locale/client/es.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/client/back/locale/client/en.yml b/modules/client/back/locale/client/en.yml index 74384461c..ad21a6ce6 100644 --- a/modules/client/back/locale/client/en.yml +++ b/modules/client/back/locale/client/en.yml @@ -52,4 +52,5 @@ columns: hasInvoiceSimplified: simplified invoice typeFk: type lastSalesPersonFk: last salesperson - + rating: rating + recommendedCredit: recommended credit diff --git a/modules/client/back/locale/client/es.yml b/modules/client/back/locale/client/es.yml index 47bf896d9..b17f53b1c 100644 --- a/modules/client/back/locale/client/es.yml +++ b/modules/client/back/locale/client/es.yml @@ -52,4 +52,5 @@ columns: hasInvoiceSimplified: factura simple typeFk: tipo lastSalesPersonFk: último comercial - + rating: clasificación + recommendedCredit: crédito recomendado From d9afdccd9cd48f28ac38421967a5f5a0c2db69fc Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 21 Jun 2023 14:12:42 +0200 Subject: [PATCH 10/17] fix: acl renewToken --- back/methods/vn-user/renew-token.js | 1 + db/changes/232601/00-aclVnUser_renewToken.sql | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 db/changes/232601/00-aclVnUser_renewToken.sql diff --git a/back/methods/vn-user/renew-token.js b/back/methods/vn-user/renew-token.js index 1f3532bd6..41470dfea 100644 --- a/back/methods/vn-user/renew-token.js +++ b/back/methods/vn-user/renew-token.js @@ -3,6 +3,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('renewToken', { description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it', + accessType: 'WRITE', accepts: [], returns: { type: 'Object', diff --git a/db/changes/232601/00-aclVnUser_renewToken.sql b/db/changes/232601/00-aclVnUser_renewToken.sql new file mode 100644 index 000000000..aa20f7a82 --- /dev/null +++ b/db/changes/232601/00-aclVnUser_renewToken.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('VnUser', 'renewToken', 'WRITE', 'ALLOW', 'ROLE', 'employee') From 10a25ff59058ff198880d4e66434783196ccfe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 22 Jun 2023 07:49:35 +0200 Subject: [PATCH 11/17] refs #5772 --- loopback/locale/en.json | 2 +- loopback/locale/es.json | 8 ++- .../back/methods/invoiceOut/createPdf.js | 42 +++--------- .../back/methods/invoiceOut/download.js | 6 +- .../back/methods/invoiceOut/invoiceClient.js | 65 +++++++++++-------- .../back/methods/invoiceOut/invoiceEmail.js | 7 +- modules/invoiceOut/back/models/invoice-out.js | 33 ++++++++++ .../front/global-invoicing/index.html | 6 +- .../front/global-invoicing/index.js | 13 +++- print/core/smtp.js | 13 +++- 10 files changed, 122 insertions(+), 73 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 43ff4b86a..7a973460d 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -115,7 +115,7 @@ "This client is not invoiceable": "This client is not invoiceable", "INACTIVE_PROVIDER": "Inactive provider", "reference duplicated": "reference duplicated", - "The PDF document does not exists": "The PDF document does not exists. Try regenerating it from 'Regenerate invoice PDF' option", + "The PDF document does not exist": "The PDF document does not exists. Try regenerating it from 'Regenerate invoice PDF' option", "This item is not available": "This item is not available", "Deny buy request": "Purchase request for ticket id [{{ticketId}}]({{{url}}}) has been rejected. Reason: {{observation}}", "The type of business must be filled in basic data": "The type of business must be filled in basic data", diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b66a13569..2afe5bab5 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -211,7 +211,7 @@ "You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito", "You can't change the credit set to zero from a financialBoss": "No puedes cambiar el cŕedito establecido a cero por un jefe de finanzas", "Amounts do not match": "Las cantidades no coinciden", - "The PDF document does not exists": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'", + "The PDF document does not exist": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'", "The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos", "You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días", "The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día", @@ -293,5 +293,7 @@ "Pass expired": "La contraseña ha caducado, cambiela desde Salix", "Invalid NIF for VIES": "Invalid NIF for VIES", "Ticket does not exist": "Este ticket no existe", - "Ticket is already signed": "Este ticket ya ha sido firmado" -} + "Ticket is already signed": "Este ticket ya ha sido firmado", + "Fecha fuera de rango": "Fecha fuera de rango", + "Error while generating PDF": "Error while generating PDF" +} \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index dfdb3c1a7..8cc584c94 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -1,5 +1,4 @@ const UserError = require('vn-loopback/util/user-error'); -const print = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('createPdf', { @@ -26,9 +25,6 @@ module.exports = Self => { Self.createPdf = async function(ctx, id, options) { const models = Self.app.models; - if (process.env.NODE_ENV == 'test') - throw new UserError(`Action not allowed on the test environment`); - let tx; const myOptions = {}; @@ -41,40 +37,20 @@ module.exports = Self => { } try { - const invoiceOut = await Self.findById(id, null, myOptions); - const canCreatePdf = await models.ACL.checkAccessAcl(ctx, 'InvoiceOut', 'canCreatePdf', 'WRITE'); + const invoiceOut = await Self.findById(id, {fields: ['hasPdf']}, myOptions); - if (invoiceOut.hasPdf && !canCreatePdf) - throw new UserError(`You don't have enough privileges`); + if (invoiceOut.hasPdf) { + const canCreatePdf = await models.ACL.checkAccessAcl(ctx, 'InvoiceOut', 'canCreatePdf', 'WRITE'); + if (!canCreatePdf) + throw new UserError(`You don't have enough privileges`); + } - await invoiceOut.updateAttributes({ - hasPdf: true - }, myOptions); - - const invoiceReport = new print.Report('invoice', { - reference: invoiceOut.ref, - recipientId: invoiceOut.clientFk - }); - const buffer = await invoiceReport.toPdfStream(); - - const issued = invoiceOut.issued; - const year = issued.getFullYear().toString(); - const month = (issued.getMonth() + 1).toString(); - const day = issued.getDate().toString(); - - const fileName = `${year}${invoiceOut.ref}.pdf`; - - // Store invoice - await print.storage.write(buffer, { - type: 'invoice', - path: `${year}/${month}/${day}`, - fileName: fileName - }); + await Self.makePdf(id, myOptions); if (tx) await tx.commit(); - } catch (e) { + } catch (err) { if (tx) await tx.rollback(); - throw e; + throw err; } }; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/download.js b/modules/invoiceOut/back/methods/invoiceOut/download.js index 5c787428b..49bba046b 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/download.js +++ b/modules/invoiceOut/back/methods/invoiceOut/download.js @@ -43,7 +43,9 @@ module.exports = Self => { Object.assign(myOptions, options); try { - const invoiceOut = await models.InvoiceOut.findById(id, null, myOptions); + const invoiceOut = await models.InvoiceOut.findById(id, { + fields: ['ref', 'issued'] + }, myOptions); const issued = invoiceOut.issued; const year = issued.getFullYear().toString(); @@ -73,7 +75,7 @@ module.exports = Self => { return [stream, file.contentType, `filename="${file.name}"`]; } catch (error) { if (error.code === 'ENOENT') - throw new UserError('The PDF document does not exists'); + throw new UserError('The PDF document does not exist'); throw error; } diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 421cbaea1..ff814fea9 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -109,17 +109,22 @@ module.exports = Self => { ], myOptions); const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); - if (newInvoice.id) { - await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); + if (!newInvoice) + throw new UserError('No tickets to invoice', 'notInvoiced'); - invoiceOut = await models.InvoiceOut.findById(newInvoice.id, { - include: { - relation: 'client' + await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); + + invoiceOut = await models.InvoiceOut.findById(newInvoice.id, { + fields: ['id', 'ref', 'clientFk'], + include: { + relation: 'client', + scope: { + fields: ['email', 'isToBeMailed'] } - }, myOptions); + } + }, myOptions); - invoiceId = newInvoice.id; - } + invoiceId = newInvoice.id; if (tx) await tx.commit(); } catch (e) { @@ -127,26 +132,32 @@ module.exports = Self => { throw e; } - if (invoiceId) { - if (!invoiceOut.client().isToBeMailed) { - const query = ` - CALL vn.report_print( - 'invoice', - ?, - account.myUser_getId(), - JSON_OBJECT('refFk', ?), - 'normal' - );`; - await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref]); - } else { - ctx.args = { - reference: invoiceOut.ref, - recipientId: invoiceOut.clientFk, - recipient: invoiceOut.client().email - }; - await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); - } + try { + await Self.makePdf(invoiceId); + } catch (err) { + console.error(err); + throw new UserError('Error while generating PDF', 'pdfError'); } + + if (invoiceOut.client().isToBeMailed) { + ctx.args = { + reference: invoiceOut.ref, + recipientId: args.clientId, + recipient: invoiceOut.client().email + }; + await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); + } else { + const query = ` + CALL vn.report_print( + 'invoice', + ?, + account.myUser_getId(), + JSON_OBJECT('refFk', ?), + 'normal' + );`; + await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref]); + } + return invoiceId; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js index 83cb84881..45894e9c5 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js @@ -1,3 +1,4 @@ +const UserError = require('vn-loopback/util/user-error'); const {Email} = require('vn-print'); module.exports = Self => { @@ -74,6 +75,10 @@ module.exports = Self => { ] }; - return email.send(mailOptions); + try { + return email.send(mailOptions); + } catch(err) { + throw new UserError('Error when sending mail to client', 'mailNotSent'); + } }; }; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index 5fcef7744..bfef57f58 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -1,3 +1,5 @@ +const print = require('vn-print'); + module.exports = Self => { require('../methods/invoiceOut/filter')(Self); require('../methods/invoiceOut/summary')(Self); @@ -19,4 +21,35 @@ module.exports = Self => { require('../methods/invoiceOut/getInvoiceDate')(Self); require('../methods/invoiceOut/negativeBases')(Self); require('../methods/invoiceOut/negativeBasesCsv')(Self); + + Self.makePdf = async function(id, options) { + const fields = ['id', 'hasPdf', 'ref', 'issued']; + const invoiceOut = await Self.findById(id, {fields}, options); + + const invoiceReport = new print.Report('invoice', { + reference: invoiceOut.ref + }); + const buffer = await invoiceReport.toPdfStream(); + + const issued = invoiceOut.issued; + const year = issued.getFullYear().toString(); + const month = (issued.getMonth() + 1).toString(); + const day = issued.getDate().toString(); + + const fileName = `${year}${invoiceOut.ref}.pdf`; + + // Store invoice + + await invoiceOut.updateAttributes({ + hasPdf: true + }, options); + + if (process.env.NODE_ENV !== 'test') { + await print.storage.write(buffer, { + type: 'invoice', + path: `${year}/${month}/${day}`, + fileName: fileName + }); + } + } }; diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 3f0a10650..52bf8b619 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -55,7 +55,11 @@ {{::error.address.nickname}} - {{::error.message}} + + {{::error.message}} + diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 70838a5a2..2e4ac1888 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -108,9 +108,18 @@ class Controller extends Section { this.$http.post(`InvoiceOuts/invoiceClient`, params) .then(() => this.invoiceNext()) .catch(res => { - const message = res.data?.error?.message || res.message; if (res.status >= 400 && res.status < 500) { - this.errors.unshift({address, message}); + const error = res.data?.error; + let isWarning; + switch(error?.code) { + case 'pdfError': + case 'mailNotSent': + isWarning = true; + break; + } + + const message = error?.message || res.message; + this.errors.unshift({address, message, isWarning}); this.invoiceNext(); } else { this.invoicing = false; diff --git a/print/core/smtp.js b/print/core/smtp.js index 61b115b5a..04bede5b5 100644 --- a/print/core/smtp.js +++ b/print/core/smtp.js @@ -46,14 +46,21 @@ module.exports = { const fileNames = attachments.join(',\n'); await db.rawSql(` - INSERT INTO vn.mail (receiver, replyTo, sent, subject, body, attachment, status) - VALUES (?, ?, 1, ?, ?, ?, ?)`, [ + INSERT INTO vn.mail + SET receiver = ?, + replyTo = ?, + sent = ?, + subject = ?, + body = ?, + attachment = ?, + status = ?`, [ options.to, options.replyTo, + error ? 2 : 1, options.subject, options.text || options.html, fileNames, - error && error.message || 'Sent' + error && error.message || 'OK' ]); } From 807596f735d9684419e9757a020a0a43fad680dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 22 Jun 2023 08:50:18 +0200 Subject: [PATCH 12/17] refs #5772 --- loopback/locale/es.json | 3 ++- .../back/methods/invoiceOut/invoiceClient.js | 4 ++-- .../invoiceOut/specs/invoiceClient.spec.js | 2 +- modules/invoiceOut/back/models/invoice-out.js | 16 +++++++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 2afe5bab5..5870dcb4f 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -295,5 +295,6 @@ "Ticket does not exist": "Este ticket no existe", "Ticket is already signed": "Este ticket ya ha sido firmado", "Fecha fuera de rango": "Fecha fuera de rango", - "Error while generating PDF": "Error while generating PDF" + "Error while generating PDF": "Error al generar PDF", + "Error when sending mail to client": "Error al enviar el correo al cliente" } \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index ff814fea9..5d61bfcd0 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -131,9 +131,9 @@ module.exports = Self => { if (tx) await tx.rollback(); throw e; } - + try { - await Self.makePdf(invoiceId); + await Self.makePdf(invoiceId, myOptions); } catch (err) { console.error(err); throw new UserError('Error while generating PDF', 'pdfError'); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js index 9a0574dba..e26a0b3f1 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js @@ -23,7 +23,7 @@ describe('InvoiceOut invoiceClient()', () => { const ctx = {req: activeCtx}; it('should make a global invoicing', async() => { - spyOn(models.InvoiceOut, 'createPdf').and.returnValue(new Promise(resolve => resolve(true))); + spyOn(models.InvoiceOut, 'makePdf').and.returnValue(new Promise(resolve => resolve(true))); spyOn(models.InvoiceOut, 'invoiceEmail'); const tx = await models.InvoiceOut.beginTransaction({}); diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index bfef57f58..027ec2fb2 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -23,9 +23,19 @@ module.exports = Self => { require('../methods/invoiceOut/negativeBasesCsv')(Self); Self.makePdf = async function(id, options) { - const fields = ['id', 'hasPdf', 'ref', 'issued']; - const invoiceOut = await Self.findById(id, {fields}, options); + let tx; + const myOptions = {}; + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + const fields = ['id', 'hasPdf', 'ref', 'issued']; + const invoiceOut = await Self.findById(id, {fields}, myOptions); const invoiceReport = new print.Report('invoice', { reference: invoiceOut.ref }); @@ -42,7 +52,7 @@ module.exports = Self => { await invoiceOut.updateAttributes({ hasPdf: true - }, options); + }, myOptions); if (process.env.NODE_ENV !== 'test') { await print.storage.write(buffer, { From 9d1a181b73e7738dde3fa5cde757416e3cfd1e76 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 22 Jun 2023 11:10:56 +0200 Subject: [PATCH 13/17] refs #5772 feat: si falla al enviar el pdf, envia un rocket al comercial --- .../front/global-invoicing/index.js | 69 ++++++++++++------- .../front/global-invoicing/locale/en.yml | 1 + .../front/global-invoicing/locale/es.yml | 3 +- 3 files changed, 49 insertions(+), 24 deletions(-) create mode 100644 modules/invoiceOut/front/global-invoicing/locale/en.yml diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 2e4ac1888..36552d25b 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -7,29 +7,29 @@ class Controller extends Section { $onInit() { const date = Date.vnNew(); Object.assign(this, { - maxShipped: new Date(date.getFullYear(), date.getMonth(), 0), - clientsToInvoice: 'all', + maxShipped: new Date(date.getFullYear(), date.getMonth(), 0), + clientsToInvoice: 'all', }); this.$http.get('UserConfigs/getUserConfig') - .then(res => { - this.companyFk = res.data.companyFk; - this.getInvoiceDate(this.companyFk); - }); - } + .then(res => { + this.companyFk = res.data.companyFk; + this.getInvoiceDate(this.companyFk); + }); + } - getInvoiceDate(companyFk) { - const params = { companyFk: companyFk }; + getInvoiceDate(companyFk) { + const params = {companyFk: companyFk}; this.fetchInvoiceDate(params); - } + } - fetchInvoiceDate(params) { - this.$http.get('InvoiceOuts/getInvoiceDate', { params }) - .then(res => { - this.minInvoicingDate = res.data.issued ? new Date(res.data.issued) : null; - this.invoiceDate = this.minInvoicingDate; - }); - } + fetchInvoiceDate(params) { + this.$http.get('InvoiceOuts/getInvoiceDate', {params}) + .then(res => { + this.minInvoicingDate = res.data.issued ? new Date(res.data.issued) : null; + this.invoiceDate = this.minInvoicingDate; + }); + } stopInvoicing() { this.status = 'stopping'; @@ -111,11 +111,34 @@ class Controller extends Section { if (res.status >= 400 && res.status < 500) { const error = res.data?.error; let isWarning; - switch(error?.code) { - case 'pdfError': - case 'mailNotSent': - isWarning = true; - break; + const filter = { + where: { + id: address.clientId + } + }; + switch (error?.code) { + case 'pdfError': + isWarning = true; + break; + case 'mailNotSent': + this.$http.get(`Clients/findOne`, {filter}) + .then(res => { + const salesPersonFk = res.data.salesPersonFk; + if (!salesPersonFk) return; + + const message = this.$t('Mail not sent', { + clientId: address.clientId, + clientUrl: `${window.location.origin}/#!/client/${this.clientId}/summary` + }); + + const params = { + workerId: salesPersonFk, + message: message, + }; + this.$http.post('Chats/sendCheckingPresence', params); + }); + isWarning = true; + break; } const message = error?.message || res.message; @@ -126,7 +149,7 @@ class Controller extends Section { this.status = 'done'; throw new UserError(`Critical invoicing error, proccess stopped`); } - }) + }); } invoiceNext() { diff --git a/modules/invoiceOut/front/global-invoicing/locale/en.yml b/modules/invoiceOut/front/global-invoicing/locale/en.yml new file mode 100644 index 000000000..171822ef7 --- /dev/null +++ b/modules/invoiceOut/front/global-invoicing/locale/en.yml @@ -0,0 +1 @@ +Mail not sent: There has been an error sending the invoice to the client {{clientId}} {{clientUrl}}, please check the email address diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 5b1f7e883..4c31df729 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -18,4 +18,5 @@ Invoice out: Facturar One client: Un solo cliente Choose a valid client: Selecciona un cliente válido Stop: Parar -Critical invoicing error, proccess stopped: Error crítico al facturar, proceso detenido \ No newline at end of file +Critical invoicing error, proccess stopped: Error crítico al facturar, proceso detenido +Mail not sent: Se ha producido un fallo al enviar la factura al cliente {{clientId}} {{clientUrl}}, por favor revisa la dirección de correo electrónico From 591fc14ffaf192fea7683b63beccc64994513391 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 22 Jun 2023 12:48:50 +0200 Subject: [PATCH 14/17] refs #5772 refactor: movido codigo para enviar rocket al back --- loopback/locale/en.json | 3 +- loopback/locale/es.json | 6 ++-- .../back/methods/invoiceOut/invoiceClient.js | 34 ++++++++++++++----- .../back/methods/invoiceOut/invoiceEmail.js | 2 +- modules/invoiceOut/back/models/invoice-out.js | 17 ++-------- .../front/global-invoicing/index.js | 18 ---------- .../front/global-invoicing/locale/en.yml | 1 - .../front/global-invoicing/locale/es.yml | 1 - 8 files changed, 35 insertions(+), 47 deletions(-) delete mode 100644 modules/invoiceOut/front/global-invoicing/locale/en.yml diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 7a973460d..40df9a712 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -175,5 +175,6 @@ "Pass expired": "The password has expired, change it from Salix", "Can't transfer claimed sales": "Can't transfer claimed sales", "Invalid quantity": "Invalid quantity", - "Failed to upload delivery note": "Error to upload delivery note {{id}}" + "Failed to upload delivery note": "Error to upload delivery note {{id}}", + "Mail not sent": "There has been an error sending the invoice to the client [{{clientId}}]({{{clientUrl}}}), please check the email address" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 5870dcb4f..ce93b27ce 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -296,5 +296,7 @@ "Ticket is already signed": "Este ticket ya ha sido firmado", "Fecha fuera de rango": "Fecha fuera de rango", "Error while generating PDF": "Error al generar PDF", - "Error when sending mail to client": "Error al enviar el correo al cliente" -} \ No newline at end of file + "Error when sending mail to client": "Error al enviar el correo al cliente", + "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico" + +} diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 5d61bfcd0..d010ef631 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -51,6 +51,9 @@ module.exports = Self => { const args = ctx.args; const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; + const $t = ctx.req.__; // $translate + const origin = ctx.req.headers.origin; + let tx; if (typeof options == 'object') @@ -119,7 +122,7 @@ module.exports = Self => { include: { relation: 'client', scope: { - fields: ['email', 'isToBeMailed'] + fields: ['email', 'isToBeMailed', 'salesPersonFk'] } } }, myOptions); @@ -131,21 +134,34 @@ module.exports = Self => { if (tx) await tx.rollback(); throw e; } - + try { - await Self.makePdf(invoiceId, myOptions); + await Self.makePdf(invoiceId); } catch (err) { console.error(err); throw new UserError('Error while generating PDF', 'pdfError'); } if (invoiceOut.client().isToBeMailed) { - ctx.args = { - reference: invoiceOut.ref, - recipientId: args.clientId, - recipient: invoiceOut.client().email - }; - await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); + try { + ctx.args = { + reference: invoiceOut.ref, + recipientId: args.clientId, + recipient: invoiceOut.client().email + }; + await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); + } catch (err) { + const message = $t('Mail not sent', { + clientId: args.clientId, + clientUrl: `${origin}/#!/claim/${args.id}/summary` + }); + const salesPersonId = invoiceOut.client().salesPersonFk; + + if (salesPersonId) + await models.Chat.sendCheckingPresence(ctx, salesPersonId, message); + + throw new UserError('Error when sending mail to client', 'mailNotSent'); + } } else { const query = ` CALL vn.report_print( diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js index 45894e9c5..113526484 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js @@ -77,7 +77,7 @@ module.exports = Self => { try { return email.send(mailOptions); - } catch(err) { + } catch (err) { throw new UserError('Error when sending mail to client', 'mailNotSent'); } }; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index 027ec2fb2..0d5ed021c 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -23,19 +23,8 @@ module.exports = Self => { require('../methods/invoiceOut/negativeBasesCsv')(Self); Self.makePdf = async function(id, options) { - let tx; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - const fields = ['id', 'hasPdf', 'ref', 'issued']; - const invoiceOut = await Self.findById(id, {fields}, myOptions); + const invoiceOut = await Self.findById(id, {fields}, options); const invoiceReport = new print.Report('invoice', { reference: invoiceOut.ref }); @@ -52,7 +41,7 @@ module.exports = Self => { await invoiceOut.updateAttributes({ hasPdf: true - }, myOptions); + }, options); if (process.env.NODE_ENV !== 'test') { await print.storage.write(buffer, { @@ -61,5 +50,5 @@ module.exports = Self => { fileName: fileName }); } - } + }; }; diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 36552d25b..930dfd459 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -118,25 +118,7 @@ class Controller extends Section { }; switch (error?.code) { case 'pdfError': - isWarning = true; - break; case 'mailNotSent': - this.$http.get(`Clients/findOne`, {filter}) - .then(res => { - const salesPersonFk = res.data.salesPersonFk; - if (!salesPersonFk) return; - - const message = this.$t('Mail not sent', { - clientId: address.clientId, - clientUrl: `${window.location.origin}/#!/client/${this.clientId}/summary` - }); - - const params = { - workerId: salesPersonFk, - message: message, - }; - this.$http.post('Chats/sendCheckingPresence', params); - }); isWarning = true; break; } diff --git a/modules/invoiceOut/front/global-invoicing/locale/en.yml b/modules/invoiceOut/front/global-invoicing/locale/en.yml deleted file mode 100644 index 171822ef7..000000000 --- a/modules/invoiceOut/front/global-invoicing/locale/en.yml +++ /dev/null @@ -1 +0,0 @@ -Mail not sent: There has been an error sending the invoice to the client {{clientId}} {{clientUrl}}, please check the email address diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 4c31df729..ed61e832a 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -19,4 +19,3 @@ One client: Un solo cliente Choose a valid client: Selecciona un cliente válido Stop: Parar Critical invoicing error, proccess stopped: Error crítico al facturar, proceso detenido -Mail not sent: Se ha producido un fallo al enviar la factura al cliente {{clientId}} {{clientUrl}}, por favor revisa la dirección de correo electrónico From b7cd32f4ce2bb0a558e4ca17e887f4400f2f2b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 22 Jun 2023 13:18:16 +0200 Subject: [PATCH 15/17] refs #5772 eliminar tags en report invoice --- print/templates/reports/invoice/invoice.html | 9 --------- 1 file changed, 9 deletions(-) diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 32138befc..45b6c3934 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -106,15 +106,6 @@ {{sale.vatType}} {{saleImport(sale) | currency('EUR', $i18n.locale)}} - From 389b53ceff499dc3d186df5886b9495b5e893356 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 22 Jun 2023 13:37:43 +0200 Subject: [PATCH 16/17] refs #5772 fix: back test --- .../back/methods/invoiceOut/specs/invoiceClient.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js index e26a0b3f1..0faa8fe1a 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js @@ -18,7 +18,9 @@ describe('InvoiceOut invoiceClient()', () => { accessToken: {userId: userId}, __: value => { return value; - } + }, + headers: {origin: 'http://localhost'} + }; const ctx = {req: activeCtx}; From 344ba298f8390ebd7369dc62c989481572ff1063 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 22 Jun 2023 14:27:33 +0200 Subject: [PATCH 17/17] refs #5832 232801 init --- CHANGELOG.md | 9 +++++++++ db/changes/232801/.gitkeep | 0 package.json | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 db/changes/232801/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index fa2ebcd62..cbfc6e9e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ 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). +## [2328.01] - 2023-07-13 + +### Added + +### Changed + +### Fixed + + ## [2326.01] - 2023-06-29 ### Added diff --git a/db/changes/232801/.gitkeep b/db/changes/232801/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json index 4358c86a7..64c374841 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.26.01", + "version": "23.28.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0",