From f7a97a8139fdc5ed72c6b53b9800e66cf904b156 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 14 Dec 2022 13:31:56 +0100 Subject: [PATCH 01/33] =?UTF-8?q?fix:=20siempre=20muestra=20el=20bot=C3=B3?= =?UTF-8?q?n=20si=20hay=20datos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/travel/front/extra-community/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 5174f8da2..3e5d5f224 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -27,7 +27,7 @@
From e6168356002e27c0104428ff60e1934056673af8 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 14 Dec 2022 13:40:28 +0100 Subject: [PATCH 02/33] delete: hasDateRange() --- modules/travel/front/extra-community/index.js | 10 ---------- modules/travel/front/extra-community/index.spec.js | 11 ----------- 2 files changed, 21 deletions(-) diff --git a/modules/travel/front/extra-community/index.js b/modules/travel/front/extra-community/index.js index a4ac487e6..2389570b9 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -43,16 +43,6 @@ class Controller extends Section { this.smartTableOptions = {}; } - get hasDateRange() { - const userParams = this.$.model.userParams; - const hasLanded = userParams.landedTo; - const hasShipped = userParams.shippedFrom; - const hasContinent = userParams.continent; - const hasWarehouseOut = userParams.warehouseOutFk; - - return hasLanded || hasShipped || hasContinent || hasWarehouseOut; - } - onDragInterval() { if (this.dragClientY > 0 && this.dragClientY < 75) this.$window.scrollTo(0, this.$window.scrollY - 10); diff --git a/modules/travel/front/extra-community/index.spec.js b/modules/travel/front/extra-community/index.spec.js index ae48b9ca1..18ddee665 100644 --- a/modules/travel/front/extra-community/index.spec.js +++ b/modules/travel/front/extra-community/index.spec.js @@ -14,17 +14,6 @@ describe('Travel Component vnTravelExtraCommunity', () => { controller.$.model.refresh = jest.fn(); })); - describe('hasDateRange()', () => { - it('should return truthy when shippedFrom or landedTo are set as userParams', () => { - const now = new Date(); - controller.$.model.userParams = {shippedFrom: now, landedTo: now}; - - const result = controller.hasDateRange; - - expect(result).toBeTruthy(); - }); - }); - describe('findDraggable()', () => { it('should find the draggable element', () => { const draggable = document.createElement('tr'); From cb9ad5d01284522c4a477202109fbd0b8150ac71 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 20 Dec 2022 08:45:14 +0100 Subject: [PATCH 03/33] refactor: show ticketId error --- back/methods/osticket/closeTicket.js | 94 +++++++++++++++------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 33fe5958b..e5cbc58f4 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -25,36 +25,36 @@ module.exports = Self => { return false; const con = mysql.createConnection({ - host: `${config.hostDb}`, - user: `${config.userDb}`, - password: `${config.passwordDb}`, - port: `${config.portDb}` + host: config.hostDb, + user: config.userDb, + password: config.passwordDb, + port: config.portDb }); const sql = `SELECT ot.ticket_id, ot.number FROM osticket.ost_ticket ot - JOIN osticket.ost_ticket_status ots ON ots.id = ot.status_id + JOIN osticket.ost_ticket_status ots ON ots.id = ot.status_id JOIN osticket.ost_thread ot2 ON ot2.object_id = ot.ticket_id AND ot2.object_type = 'T' JOIN ( SELECT ote.thread_id, MAX(ote.created) created, MAX(ote.updated) updated FROM osticket.ost_thread_entry ote - WHERE ote.staff_id != 0 AND ote.type = 'R' + WHERE ote.staff_id AND ote.type = 'R' GROUP BY ote.thread_id - ) sub ON sub.thread_id = ot2.id - WHERE ot.isanswered = 1 - AND ots.state = '${config.oldStatus}' - AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ${config.day} DAY)`; + ) sub ON sub.thread_id = ot2.id + WHERE ot.isanswered + AND ots.state = ? + AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY)`; - let ticketsId = []; + const ticketsId = []; con.connect(err => { if (err) throw err; - con.query(sql, (err, results) => { - if (err) throw err; - for (const result of results) - ticketsId.push(result.ticket_id); - }); + con.query(sql, [config.oldStatus, config.day], + (err, results) => { + if (err) throw err; + for (const result of results) + ticketsId.push(result.ticket_id); + }); }); - await getRequestToken(); async function getRequestToken() { @@ -94,6 +94,39 @@ module.exports = Self => { await close(token, secondCookie); } + async function close(token, secondCookie) { + for (const ticketId of ticketsId) { + try { + const lockCode = await getLockCode(token, secondCookie, ticketId); + let form = new FormData(); + form.append('__CSRFToken__', token); + form.append('id', ticketId); + form.append('a', config.responseType); + form.append('lockCode', lockCode); + form.append('from_email_id', config.fromEmailId); + form.append('reply-to', config.replyTo); + form.append('cannedResp', 0); + form.append('response', config.comment); + form.append('signature', 'none'); + form.append('reply_status_id', config.newStatusId); + + const ostUri = `${config.host}/tickets.php?id=${ticketId}`; + const params = { + method: 'POST', + body: form, + headers: { + 'Cookie': secondCookie + } + }; + await fetch(ostUri, params); + } catch (e) { + const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); + err.stack += e.stack; + throw err; + } + } + } + async function getLockCode(token, secondCookie, ticketId) { const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`; const params = { @@ -109,32 +142,5 @@ module.exports = Self => { return json.code; } - - async function close(token, secondCookie) { - for (const ticketId of ticketsId) { - const lockCode = await getLockCode(token, secondCookie, ticketId); - let form = new FormData(); - form.append('__CSRFToken__', token); - form.append('id', ticketId); - form.append('a', config.responseType); - form.append('lockCode', lockCode); - form.append('from_email_id', config.fromEmailId); - form.append('reply-to', config.replyTo); - form.append('cannedResp', 0); - form.append('response', config.comment); - form.append('signature', 'none'); - form.append('reply_status_id', config.newStatusId); - - const ostUri = `${config.host}/tickets.php?id=${ticketId}`; - const params = { - method: 'POST', - body: form, - headers: { - 'Cookie': secondCookie - } - }; - return fetch(ostUri, params); - } - } }; }; From 90b36bf1abb1be5c28ded97d618196a1f37ab3d3 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 20 Dec 2022 14:21:01 +0100 Subject: [PATCH 04/33] Fix missing report for the invoice electronic notification --- modules/ticket/front/descriptor-menu/index.js | 9 +++++++- .../invoice-electronic.html | 13 ++++++++++++ .../invoice-electronic/invoice-electronic.js | 21 +++++++++++++++++++ .../email/invoice-electronic/locale/en.yml | 4 ++++ .../email/invoice-electronic/locale/es.yml | 4 ++++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 print/templates/email/invoice-electronic/invoice-electronic.html create mode 100644 print/templates/email/invoice-electronic/invoice-electronic.js create mode 100644 print/templates/email/invoice-electronic/locale/en.yml create mode 100644 print/templates/email/invoice-electronic/locale/es.yml diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index f10e059ad..477eab9a3 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -254,8 +254,15 @@ class Controller extends Section { if (client.hasElectronicInvoice) { this.$http.post(`NotificationQueues`, { - notificationFk: 'invoiceElectronic', + notificationFk: 'invoice-electronic', authorFk: client.id, + params: JSON.stringify( + { + 'name': client.name, + 'email': client.email, + 'ticketId': this.id, + 'url': window.location.href + }) }).then(a => { this.vnApp.showSuccess(this.$t('Invoice sent')); }); diff --git a/print/templates/email/invoice-electronic/invoice-electronic.html b/print/templates/email/invoice-electronic/invoice-electronic.html new file mode 100644 index 000000000..fc96e0970 --- /dev/null +++ b/print/templates/email/invoice-electronic/invoice-electronic.html @@ -0,0 +1,13 @@ + + + + + + {{ $t('subject') }} + + +

{{ $t('title') }} {{name}}

+

{{ $t('clientMail') }} {{email}}

+

{{ $t('ticketId') }} {{ticketId}} + + diff --git a/print/templates/email/invoice-electronic/invoice-electronic.js b/print/templates/email/invoice-electronic/invoice-electronic.js new file mode 100644 index 000000000..2e1e739ac --- /dev/null +++ b/print/templates/email/invoice-electronic/invoice-electronic.js @@ -0,0 +1,21 @@ +module.exports = { + name: 'invoice-electronic', + props: { + name: { + type: [String], + required: true + }, + email: { + type: [String], + required: true + }, + ticketId: { + type: [Number], + required: true + }, + url: { + type: [String], + required: true + } + }, +}; diff --git a/print/templates/email/invoice-electronic/locale/en.yml b/print/templates/email/invoice-electronic/locale/en.yml new file mode 100644 index 000000000..5523a2fa3 --- /dev/null +++ b/print/templates/email/invoice-electronic/locale/en.yml @@ -0,0 +1,4 @@ +subject: A electronic invoice has been created +title: A new electronic invoice has been created for the client +clientMail: The client's email is +ticketId: The invoice's ticket is \ No newline at end of file diff --git a/print/templates/email/invoice-electronic/locale/es.yml b/print/templates/email/invoice-electronic/locale/es.yml new file mode 100644 index 000000000..2cbcfbb36 --- /dev/null +++ b/print/templates/email/invoice-electronic/locale/es.yml @@ -0,0 +1,4 @@ +subject: Se ha creado una factura electrónica +title: Se ha creado una nueva factura electrónica para el cliente +clientMail: El correo del cliente es +ticketId: El ticket de la factura es \ No newline at end of file From 7261415e16ce99d8a85bbaf95fc888919f2df5b5 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 21 Dec 2022 09:36:31 +0100 Subject: [PATCH 05/33] =?UTF-8?q?fix:=20a=C3=B1adido=20length?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/travel/front/extra-community/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 3e5d5f224..ee8dcdf98 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -27,7 +27,7 @@

From 27288d011d33ca100c03579e5d9f0399fd3c8653 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 21 Dec 2022 15:01:05 +0100 Subject: [PATCH 06/33] fix(searchBar): applyParams --- ..._smartTable_searchBar_integrations.spec.js | 32 +++++++++++++++++-- front/core/components/searchbar/searchbar.js | 6 ++-- .../components/searchbar/searchbar.spec.js | 4 +-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js index 4fc280209..f5897da2c 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('SmartTable SearchBar integration', () => { +fdescribe('SmartTable SearchBar integration', () => { let browser; let page; beforeAll(async() => { @@ -15,7 +15,7 @@ describe('SmartTable SearchBar integration', () => { await browser.close(); }); - describe('as filters', () => { + describe('as filters in smart-table section', () => { it('should search by type in searchBar', async() => { await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); @@ -47,6 +47,34 @@ describe('SmartTable SearchBar integration', () => { }); }); + describe('as filters in section without smart-table', () => { + it('go to zone section', async() => { + await page.loginAndModule('salesPerson', 'zone'); + await page.waitToClick(selectors.globalItems.searchButton); + }); + + it('should search in searchBar first time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + + it('should search in searchBar second time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + + it('should search in searchBar third time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + }); + describe('as orders', () => { it('should order by first id', async() => { await page.loginAndModule('developer', 'item'); diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index f2855d711..aefa89b5b 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -308,7 +308,7 @@ export default class Searchbar extends Component { this.tableQ = null; - const hasParams = this.$params.q && Object.keys(JSON.parse(this.$params.q)).length; + const hasParams = this.$params.q && JSON.parse(this.$params.q).tableQ; if (hasParams) { const stateFilter = JSON.parse(this.$params.q); for (let param in stateFilter) { @@ -325,8 +325,8 @@ export default class Searchbar extends Component { for (let param in stateFilter.tableQ) params[param] = stateFilter.tableQ[param]; - Object.assign(stateFilter, params); - return this.model.applyParams(params) + const newParams = Object.assign(stateFilter, params); + return this.model.applyParams(newParams) .then(() => this.model.data); } diff --git a/front/core/components/searchbar/searchbar.spec.js b/front/core/components/searchbar/searchbar.spec.js index ed8fd9d07..9998e7a7c 100644 --- a/front/core/components/searchbar/searchbar.spec.js +++ b/front/core/components/searchbar/searchbar.spec.js @@ -174,14 +174,12 @@ describe('Component vnSearchbar', () => { jest.spyOn(controller, 'doSearch'); controller.model = { refresh: jest.fn(), + applyFilter: jest.fn().mockReturnValue(Promise.resolve()), userParams: { id: 1 } }; - controller.model.applyParams = jest.fn().mockReturnValue(Promise.resolve()); - jest.spyOn(controller.model, 'applyParams'); - controller.filter = filter; controller.removeParam(0); From 05f4db7924d85b753d8e33ae3d56b922a06b9544 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 22 Dec 2022 07:16:22 +0100 Subject: [PATCH 07/33] Add requested changes to the fixtures --- db/changes/224903/00-insert_notification_invoiceE.sql | 1 - db/changes/225001/.gitkeep | 0 db/changes/225001/00-insert_notification_invoiceE.sql | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 db/changes/224903/00-insert_notification_invoiceE.sql delete mode 100644 db/changes/225001/.gitkeep create mode 100644 db/changes/225001/00-insert_notification_invoiceE.sql diff --git a/db/changes/224903/00-insert_notification_invoiceE.sql b/db/changes/224903/00-insert_notification_invoiceE.sql deleted file mode 100644 index 1d416c196..000000000 --- a/db/changes/224903/00-insert_notification_invoiceE.sql +++ /dev/null @@ -1 +0,0 @@ -insert into `util`.`notification` (`id`, `name`,`description`) values (2, 'invoiceElectronic', 'A electronic invoice has been generated'); \ No newline at end of file diff --git a/db/changes/225001/.gitkeep b/db/changes/225001/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/225001/00-insert_notification_invoiceE.sql b/db/changes/225001/00-insert_notification_invoiceE.sql new file mode 100644 index 000000000..bbce9dd01 --- /dev/null +++ b/db/changes/225001/00-insert_notification_invoiceE.sql @@ -0,0 +1 @@ +insert into `util`.`notification` (`id`, `name`,`description`) values (2, 'invoice-electronic', 'A electronic invoice has been generated'); \ No newline at end of file From 186a64f7fa8676ee6f1942ac39d29ee44c4596f0 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 22 Dec 2022 07:46:06 +0100 Subject: [PATCH 08/33] unfocus --- e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js index f5897da2c..ad558ace2 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('SmartTable SearchBar integration', () => { +describe('SmartTable SearchBar integration', () => { let browser; let page; beforeAll(async() => { From fce035298685d4388648f9cdf9e8cc3f5c3dcd67 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 22 Dec 2022 10:41:07 +0100 Subject: [PATCH 09/33] add fixtures --- db/dump/fixtures.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 92b84be43..2fd4174ea 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2685,6 +2685,7 @@ INSERT INTO `util`.`notificationConfig` INSERT INTO `util`.`notification` (`id`, `name`, `description`) VALUES (1, 'print-email', 'notification fixture one'); + (2, 'invoice-electronic', 'A electronic invoice has been generated') INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) VALUES From 93c98e05fc3bc4c0931519777d6b97caa1861045 Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 23 Dec 2022 08:27:03 +0100 Subject: [PATCH 10/33] fix(discount): handle error for a worker without business contract --- modules/ticket/back/methods/sale/usesMana.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ticket/back/methods/sale/usesMana.js b/modules/ticket/back/methods/sale/usesMana.js index 093057dca..3f55293bf 100644 --- a/modules/ticket/back/methods/sale/usesMana.js +++ b/modules/ticket/back/methods/sale/usesMana.js @@ -24,6 +24,8 @@ module.exports = Self => { const salesDepartment = await models.Department.findOne({where: {code: 'VT'}, fields: 'id'}, myOptions); const departments = await models.Department.getLeaves(salesDepartment.id, null, myOptions); const workerDepartment = await models.WorkerDepartment.findById(userId, null, myOptions); + if (!workerDepartment) return false; + const usesMana = departments.find(department => department.id == workerDepartment.departmentFk); return usesMana ? true : false; From c98b5a969d82a7f8a761734fbc89a6bddadb3f07 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 23 Dec 2022 09:16:26 +0100 Subject: [PATCH 11/33] feat: actualizada consulta intrastat --- db/changes/224903/00-invoiceOut_new.sql | 225 ++++++++++++++++++ print/templates/reports/invoice/invoice.js | 2 +- .../reports/invoice/sql/intrastat.sql | 59 ++--- 3 files changed, 249 insertions(+), 37 deletions(-) create mode 100644 db/changes/224903/00-invoiceOut_new.sql diff --git a/db/changes/224903/00-invoiceOut_new.sql b/db/changes/224903/00-invoiceOut_new.sql new file mode 100644 index 000000000..10a42d40d --- /dev/null +++ b/db/changes/224903/00-invoiceOut_new.sql @@ -0,0 +1,225 @@ +DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`; +DELIMITER $$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`( + vSerial VARCHAR(255), + vInvoiceDate DATETIME, + vTaxArea VARCHAR(25), + OUT vNewInvoiceId INT) +BEGIN +/** + * Creación de facturas emitidas. + * requiere previamente tabla ticketToInvoice(id). + * + * @param vSerial serie a la cual se hace la factura + * @param vInvoiceDate fecha de la factura + * @param vTaxArea tipo de iva en relacion a la empresa y al cliente + * @param vNewInvoiceId id de la factura que se acaba de generar + * @return vNewInvoiceId + */ + DECLARE vSpainCountryCode INT DEFAULT 1; + DECLARE vIsAnySaleToInvoice BOOL; + DECLARE vIsAnyServiceToInvoice BOOL; + DECLARE vNewRef VARCHAR(255); + DECLARE vWorker INT DEFAULT account.myUser_getId(); + DECLARE vCompany INT; + DECLARE vSupplier INT; + DECLARE vClient INT; + DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1; + DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6; + DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2; + DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R'; + DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S'; + DECLARE vNewInvoiceInId INT; + DECLARE vIsInterCompany BOOL; + + SET vInvoiceDate = IFNULL(vInvoiceDate,CURDATE()); + + SELECT t.clientFk, t.companyFk + INTO vClient, vCompany + FROM ticketToInvoice tt + JOIN ticket t ON t.id = tt.id + LIMIT 1; + + -- Eliminem de ticketToInvoice els tickets que no han de ser facturats + DELETE ti.* + FROM ticketToInvoice ti + JOIN ticket t ON t.id = ti.id + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN supplier su ON su.id = t.companyFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk + WHERE YEAR(t.shipped) < 2001 + OR c.isTaxDataChecked = FALSE + OR t.isDeleted + OR c.hasToInvoice = FALSE + OR itc.id IS NULL; + + SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id + INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice + FROM ticketToInvoice t + LEFT JOIN sale s ON s.ticketFk = t.id + LEFT JOIN ticketService ts ON ts.ticketFk = t.id; + + IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice) + AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase()) + THEN + + -- el trigger añade el siguiente Id_Factura correspondiente a la vSerial + INSERT INTO invoiceOut + ( + ref, + serial, + issued, + clientFk, + dued, + companyFk, + cplusInvoiceType477Fk + ) + SELECT + 1, + vSerial, + vInvoiceDate, + vClient, + getDueDate(vInvoiceDate, dueDay), + vCompany, + IF(vSerial = vCorrectingSerial, + vCplusCorrectingInvoiceTypeFk, + IF(vSerial = vSimplifiedSerial, + vCplusSimplifiedInvoiceTypeFk, + vCplusStandardInvoiceTypeFk)) + FROM client + WHERE id = vClient; + + + SET vNewInvoiceId = LAST_INSERT_ID(); + + SELECT `ref` + INTO vNewRef + FROM invoiceOut + WHERE id = vNewInvoiceId; + + UPDATE ticket t + JOIN ticketToInvoice ti ON ti.id = t.id + SET t.refFk = vNewRef; + + DROP TEMPORARY TABLE IF EXISTS tmp.updateInter; + CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY + SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador + FROM ticketToInvoice ti + LEFT JOIN ticketState ts ON ti.id = ts.ticket + JOIN state s + WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id); + + INSERT INTO vncontrol.inter(state_id,Id_Ticket,Id_Trabajador) + SELECT * FROM tmp.updateInter; + + INSERT INTO ticketLog (action, userFk, originFk, description) + SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef) + FROM ticketToInvoice ti; + + CALL invoiceExpenceMake(vNewInvoiceId); + CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); + + UPDATE invoiceOut io + JOIN ( + SELECT SUM(amount) AS total + FROM invoiceOutExpence + WHERE invoiceOutFk = vNewInvoiceId + ) base + JOIN ( + SELECT SUM(vat) AS total + FROM invoiceOutTax + WHERE invoiceOutFk = vNewInvoiceId + ) vat + SET io.amount = base.total + vat.total + WHERE io.id = vNewInvoiceId; + + DROP TEMPORARY TABLE tmp.updateInter; + + SELECT ios.isCEE INTO vIsInterCompany + FROM vn.ticket t + JOIN vn.invoiceOut io ON io.`ref` = t.refFk + JOIN vn.invoiceOutSerial ios ON ios.code = io.serial + WHERE t.refFk = vNewRef + LIMIT 1; + + IF (vIsInterCompany) THEN + + SELECT vCompany INTO vSupplier; + SELECT id INTO vCompany FROM company WHERE clientFk = vClient; + + INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk) + SELECT vSupplier, vNewRef, vInvoiceDate, vCompany; + + SET vNewInvoiceInId = LAST_INSERT_ID(); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket; + CREATE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM ticketToInvoice; + + CALL `ticket_getTax`('NATIONAL'); + + SET @vTaxableBaseServices := 0.00; + SET @vTaxCodeGeneral := NULL; + + INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenceFk, sub.taxTypeSageFk , sub.transactionTypeSageFk + FROM ( + SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk, @vTaxCodeGeneral := i.taxClassCodeFk + FROM tmp.ticketServiceTax tst + JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code + WHERE i.isService + HAVING taxableBase + ) sub; + + INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk + FROM tmp.ticketTax tt + JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code + WHERE !i.isService + GROUP BY tt.pgcFk + HAVING taxableBase + ORDER BY tt.priority; + + CALL invoiceInDueDay_calculate(vNewInvoiceInId); + + INSERT INTO invoiceInIntrastat ( + invoiceInFk, + intrastatFk, + amount, + stems, + countryFk, + net) + SELECT + vNewInvoiceInId invoiceInFk, + i.intrastatFk, + CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) subtotal, + CAST(SUM(IFNULL(i.stems, 1) * s.quantity) AS DECIMAL(10,2)) stems, + su.countryFk, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, i.weightByPiece) / 1000) AS DECIMAL(10,2)) netKg + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + JOIN vn.itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + JOIN intrastat ir ON ir.id = i.intrastatFk + WHERE t.refFk = vNewRef; + + DROP TEMPORARY TABLE tmp.ticket; + DROP TEMPORARY TABLE tmp.ticketAmount; + DROP TEMPORARY TABLE tmp.ticketTax; + DROP TEMPORARY TABLE tmp.ticketServiceTax; + + END IF; + + END IF; + + DROP TEMPORARY TABLE `ticketToInvoice`; +END$$ +DELIMITER ; diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 48848c079..f7011ad81 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -82,7 +82,7 @@ module.exports = { return this.rawSqlFromDef(`taxes`, [reference]); }, fetchIntrastat(reference) { - return this.rawSqlFromDef(`intrastat`, [reference, reference, reference, reference, reference]); + return this.rawSqlFromDef(`intrastat`, [reference, reference, reference]); }, fetchRectified(reference) { return this.rawSqlFromDef(`rectified`, [reference]); diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index 7f5fbdf39..f986a9564 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -1,39 +1,26 @@ SELECT * FROM invoiceOut io JOIN invoiceOutSerial ios ON io.serial = ios.code - JOIN - (SELECT - t.refFk, - ir.id code, - ir.description description, - CAST(SUM(IFNULL(i.stems, 1) * s.quantity) AS DECIMAL(10,2)) stems, - CAST(SUM(CAST(IFNULL(i.stems, 1) * s.quantity * IF(ic.grams, ic.grams, i.density * ic.cm3delivery / 1000) / 1000 AS DECIMAL(10,2)) * - IF(sub.weight, sub.weight / vn.invoiceOut_getWeight(?), 1)) AS DECIMAL(10,2)) netKg, - CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) subtotal - FROM vn.ticket t - JOIN vn.sale s ON s.ticketFk = t.id - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk - JOIN vn.intrastat ir ON ir.id = i.intrastatFk - LEFT JOIN ( - SELECT t2.weight - FROM vn.ticket t2 - WHERE refFk = ? AND weight - LIMIT 1 - ) sub ON TRUE - WHERE t.refFk = ? - AND i.intrastatFk - GROUP BY i.intrastatFk - UNION ALL - SELECT - NULL AS refFk, - NULL AS code, - NULL AS description, - 0 AS stems, - 0 AS netKg, - IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) AS subtotal - FROM vn.ticketService ts - JOIN vn.ticket t ON ts.ticketFk = t.id - WHERE t.refFk = ?) sub - WHERE io.`ref` = ? AND ios.isCEE - ORDER BY sub.code; + JOIN( + SELECT ir.id code, + ir.description, + iii.stems, + iii.net netKg, + iii.amount subtotal + FROM vn.invoiceInIntrastat iii + LEFT JOIN vn.invoiceIn ii ON ii.id = iii.invoiceInFk + LEFT JOIN vn.invoiceOut io ON io.ref = ii.supplierRef + LEFT JOIN vn.intrastat ir ON ir.id = iii.intrastatFk + WHERE io.`ref` = ? + UNION ALL + SELECT NULL code, + 'Servicios' description, + 0 stems, + 0 netKg, + IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) subtotal + FROM vn.ticketService ts + JOIN vn.ticket t ON ts.ticketFk = t.id + WHERE t.refFk = ? + ) sub + WHERE io.ref = ? AND ios.isCEE + ORDER BY sub.code; From 9468f604fff620a36d43279b74a5b02e6c88cccb Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 23 Dec 2022 10:02:21 +0100 Subject: [PATCH 12/33] move sql changes --- db/changes/{224903 => 225201}/00-invoiceOut_new.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{224903 => 225201}/00-invoiceOut_new.sql (100%) diff --git a/db/changes/224903/00-invoiceOut_new.sql b/db/changes/225201/00-invoiceOut_new.sql similarity index 100% rename from db/changes/224903/00-invoiceOut_new.sql rename to db/changes/225201/00-invoiceOut_new.sql From 29e66157ea92c9e3187e2e6d5af5e15b0670bdff Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 23 Dec 2022 12:29:28 +0100 Subject: [PATCH 13/33] fix: se excluyen los test de back que fallan intermitente --- .../back/methods/invoiceOut/specs/downloadZip.spec.js | 2 ++ .../back/methods/worker-time-control/specs/timeEntry.spec.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js index 4d1833635..3ebcf8344 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js @@ -31,6 +31,8 @@ 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; diff --git a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js index 7f652519b..2fc5c60d4 100644 --- a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js @@ -309,6 +309,8 @@ describe('workerTimeControl add/delete timeEntry()', () => { }); it('Should throw an error when trying "out" before closing a "middle" couple', async() => { + pending('https://redmine.verdnatura.es/issues/5035'); + activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; From 8696d554d66a9f989c9ea79034ebc3bfda1fdfb2 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Mon, 26 Dec 2022 07:22:59 +0100 Subject: [PATCH 14/33] Change SQL folder --- db/changes/{225001 => 225002}/00-insert_notification_invoiceE.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{225001 => 225002}/00-insert_notification_invoiceE.sql (100%) diff --git a/db/changes/225001/00-insert_notification_invoiceE.sql b/db/changes/225002/00-insert_notification_invoiceE.sql similarity index 100% rename from db/changes/225001/00-insert_notification_invoiceE.sql rename to db/changes/225002/00-insert_notification_invoiceE.sql From 7aeeddcf1813a65eca3b0cfc21e324bd1e923e4f Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 27 Dec 2022 07:23:15 +0100 Subject: [PATCH 15/33] removed the sql --- db/changes/225002/00-insert_notification_invoiceE.sql | 1 - 1 file changed, 1 deletion(-) delete mode 100644 db/changes/225002/00-insert_notification_invoiceE.sql diff --git a/db/changes/225002/00-insert_notification_invoiceE.sql b/db/changes/225002/00-insert_notification_invoiceE.sql deleted file mode 100644 index bbce9dd01..000000000 --- a/db/changes/225002/00-insert_notification_invoiceE.sql +++ /dev/null @@ -1 +0,0 @@ -insert into `util`.`notification` (`id`, `name`,`description`) values (2, 'invoice-electronic', 'A electronic invoice has been generated'); \ No newline at end of file From deb730aae7d6e41dd1cd8ff973bb9e54ac709d43 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 27 Dec 2022 09:21:02 +0100 Subject: [PATCH 16/33] solve fixture error --- db/dump/fixtures.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2fd4174ea..2b4dd4b09 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2684,8 +2684,8 @@ INSERT INTO `util`.`notificationConfig` INSERT INTO `util`.`notification` (`id`, `name`, `description`) VALUES - (1, 'print-email', 'notification fixture one'); - (2, 'invoice-electronic', 'A electronic invoice has been generated') + (1, 'print-email', 'notification fixture one'), + (2, 'invoice-electronic', 'A electronic invoice has been generated'); INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) VALUES From 3b717e54fabbc5225edd4bddcf553c9934d9bf8f Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 28 Dec 2022 13:06:00 +0100 Subject: [PATCH 17/33] refs #3571 refactor e2e worker --- e2e/paths/03-worker/01_summary.spec.js | 64 ++++----------- e2e/paths/03-worker/02_basicData.spec.js | 38 ++++----- e2e/paths/03-worker/03_pbx.spec.js | 15 ++-- e2e/paths/03-worker/04_time_control.spec.js | 85 +++++++------------- e2e/paths/03-worker/05_calendar.spec.js | 86 ++++++++------------- 5 files changed, 97 insertions(+), 191 deletions(-) diff --git a/e2e/paths/03-worker/01_summary.spec.js b/e2e/paths/03-worker/01_summary.spec.js index 4ea87481a..4e5b0cfa9 100644 --- a/e2e/paths/03-worker/01_summary.spec.js +++ b/e2e/paths/03-worker/01_summary.spec.js @@ -2,68 +2,32 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker summary path', () => { + const workerId = 3; let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'worker'); + const httpDataResponse = page.waitForResponse(response => { + return response.status() === 200 && response.url().includes(`Workers/${workerId}`); + }); await page.accessToSearchResult('agencyNick'); + await httpDataResponse; }); afterAll(async() => { await browser.close(); }); - it('should reach the employee summary section', async() => { - await page.waitForState('worker.card.summary'); - }); - - it('should check the summary contains the name and userName on the header', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.header, 'innerText'); - - expect(result).toEqual('agency agency'); - }); - - it('should check the summary contains the basic data id', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.id, 'innerText'); - - expect(result).toEqual('3'); - }); - - it('should check the summary contains the basic data email', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.email, 'innerText'); - - expect(result).toEqual('agency@verdnatura.es'); - }); - - it('should check the summary contains the basic data department', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.department, 'innerText'); - - expect(result).toEqual('CAMARA'); - }); - - it('should check the summary contains the user data id', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.userId, 'innerText'); - - expect(result).toEqual('3'); - }); - - it('should check the summary contains the user data name', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.userName, 'innerText'); - - expect(result).toEqual('agency'); - }); - - it('should check the summary contains the user data role', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.role, 'innerText'); - - expect(result).toEqual('agency'); - }); - - it('should check the summary contains the user data extension', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.extension, 'innerText'); - - expect(result).toEqual('1101'); + it('should reach the employee summary section and check all properties', async() => { + expect(await page.getProperty(selectors.workerSummary.header, 'innerText')).toEqual('agency agency'); + expect(await page.getProperty(selectors.workerSummary.id, 'innerText')).toEqual('3'); + expect(await page.getProperty(selectors.workerSummary.email, 'innerText')).toEqual('agency@verdnatura.es'); + expect(await page.getProperty(selectors.workerSummary.department, 'innerText')).toEqual('CAMARA'); + expect(await page.getProperty(selectors.workerSummary.userId, 'innerText')).toEqual('3'); + 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'); }); }); diff --git a/e2e/paths/03-worker/02_basicData.spec.js b/e2e/paths/03-worker/02_basicData.spec.js index c367c8706..66a597dd1 100644 --- a/e2e/paths/03-worker/02_basicData.spec.js +++ b/e2e/paths/03-worker/02_basicData.spec.js @@ -2,13 +2,18 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker basic data path', () => { + const workerId = 1106; let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('hr', 'worker'); + const httpDataResponse = page.waitForResponse(response => { + return response.status() === 200 && response.url().includes(`Workers/${workerId}`); + }); await page.accessToSearchResult('David Charles Haller'); + await httpDataResponse; await page.accessToSection('worker.card.basicData'); }); @@ -16,35 +21,20 @@ describe('Worker basic data path', () => { await browser.close(); }); - it('should edit the form', async() => { - await page.clearInput(selectors.workerBasicData.name); - await page.write(selectors.workerBasicData.name, 'David C.'); - await page.clearInput(selectors.workerBasicData.surname); - await page.write(selectors.workerBasicData.surname, 'H.'); - await page.clearInput(selectors.workerBasicData.phone); - await page.write(selectors.workerBasicData.phone, '444332211'); - await page.waitToClick(selectors.workerBasicData.saveButton); + it('should edit the form and then reload the section and check the data was edited', async() => { + await page.overwrite(selectors.workerBasicData.name, 'David C.'); + await page.overwrite(selectors.workerBasicData.surname, 'H.'); + await page.overwrite(selectors.workerBasicData.phone, '444332211'); + await page.click(selectors.workerBasicData.saveButton); + const message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved!'); - }); - it('should reload the section then check the name was edited', async() => { await page.reloadSection('worker.card.basicData'); - const result = await page.waitToGetProperty(selectors.workerBasicData.name, 'value'); - expect(result).toEqual('David C.'); - }); - - it('should the surname was edited', async() => { - const result = await page.waitToGetProperty(selectors.workerBasicData.surname, 'value'); - - expect(result).toEqual('H.'); - }); - - it('should the phone was edited', async() => { - const result = await page.waitToGetProperty(selectors.workerBasicData.phone, 'value'); - - expect(result).toEqual('444332211'); + 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'); }); }); diff --git a/e2e/paths/03-worker/03_pbx.spec.js b/e2e/paths/03-worker/03_pbx.spec.js index f5d2711d1..0e8003c47 100644 --- a/e2e/paths/03-worker/03_pbx.spec.js +++ b/e2e/paths/03-worker/03_pbx.spec.js @@ -16,19 +16,16 @@ describe('Worker pbx path', () => { await browser.close(); }); - it('should receive an error when the extension exceeds 4 characters', async() => { + it('should receive an error when the extension exceeds 4 characters and then sucessfully save the changes', async() => { await page.write(selectors.workerPbx.extension, '55555'); - await page.waitToClick(selectors.workerPbx.saveButton); - const message = await page.waitForSnackbar(); + await page.click(selectors.workerPbx.saveButton); + let message = await page.waitForSnackbar(); expect(message.text).toContain('Extension format is invalid'); - }); - it('should sucessfully save the changes', async() => { - await page.clearInput(selectors.workerPbx.extension); - await page.write(selectors.workerPbx.extension, '4444'); - await page.waitToClick(selectors.workerPbx.saveButton); - const message = await page.waitForSnackbar(); + await page.overwrite(selectors.workerPbx.extension, '4444'); + await page.click(selectors.workerPbx.saveButton); + message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved! User must access web'); }); diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index be8df3cf0..1222e7482 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -2,7 +2,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Worker time control path', () => { +fdescribe('Worker time control path', () => { let browser; let page; beforeAll(async() => { @@ -21,95 +21,70 @@ describe('Worker time control path', () => { const fourPm = '16:00'; const hankPymId = 1107; - it('should go to the next month', async() => { - const date = new Date(); + it(`should go to the next month, go to current month, go 1 month in the past, return error when insert 'out' of first entry, then insert 'in' monday, then insert 'out' monday, then check if Hank Pym worked 8:20 hours, remove first entry of monday, be the 'out' the first entry of monday and change week of month`, async() => { + let date = new Date(); date.setMonth(date.getMonth() + 1); - const month = date.toLocaleString('default', {month: 'long'}); + let month = date.toLocaleString('default', {month: 'long'}); - await page.waitToClick(selectors.workerTimeControl.nextMonthButton); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + await page.click(selectors.workerTimeControl.nextMonthButton); - expect(result).toContain(month); - }); + expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); - it('should go to current month', async() => { - const date = new Date(); - const month = date.toLocaleString('default', {month: 'long'}); + date = new Date(); + month = date.toLocaleString('default', {month: 'long'}); - await page.waitToClick(selectors.workerTimeControl.previousMonthButton); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + await page.click(selectors.workerTimeControl.previousMonthButton); - expect(result).toContain(month); - }); + expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); - it('should go 1 month in the past', async() => { - const date = new Date(); + date = new Date(); date.setMonth(date.getMonth() - 1); + month = date.toLocaleString('default', {month: 'long'}); const timestamp = Math.round(date.getTime() / 1000); - const month = date.toLocaleString('default', {month: 'long'}); - await page.loginAndModule('salesBoss', 'worker'); await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); + await page.click(selectors.workerTimeControl.secondWeekDay); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); - expect(result).toContain(month); - }); - - it(`should return error when insert 'out' of first entry`, async() => { - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.click(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.respondToDialog('accept'); - const message = await page.waitForSnackbar(); + let message = await page.waitForSnackbar(); expect(message.text).toBeDefined(); - }); - it(`should insert 'in' monday`, async() => { - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.click(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in'); await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); - expect(result).toEqual(eightAm); - }); + expect(await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText')).toEqual(eightAm); - it(`should insert 'out' monday`, async() => { - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.click(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText'); - expect(result).toEqual(fourPm); - }); + expect(await page.getProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText')).toEqual(fourPm); - it(`should check Hank Pym worked 8:20 hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.'); - await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.'); - }); - - it('should remove first entry of monday', async() => { - await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm); - await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm); - await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete); + expect(await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText')).toBe('08:20 h.'); + expect(await page.getProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText')).toBe('08:20 h.'); + expect(await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText')).toBe(eightAm); + expect(await page.getProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText')).toBe(fourPm); + await page.click(selectors.workerTimeControl.firstEntryOfMondayDelete); await page.respondToDialog('accept'); - const message = await page.waitForSnackbar(); + message = await page.waitForSnackbar(); expect(message.text).toContain('Entry removed'); - }); - it(`should be the 'out' the first entry of monday`, async() => { - const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); + const result = await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); expect(result).toEqual(fourPm); - }); - it('should change week of month', async() => { - await page.waitToClick(selectors.workerTimeControl.thrirdWeekDay); - await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '00:00 h.'); + await page.click(selectors.workerTimeControl.thrirdWeekDay); + + expect(await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText')).toBe('00:00 h.'); }); }); diff --git a/e2e/paths/03-worker/05_calendar.spec.js b/e2e/paths/03-worker/05_calendar.spec.js index e97b7fe7c..c310baf5a 100644 --- a/e2e/paths/03-worker/05_calendar.spec.js +++ b/e2e/paths/03-worker/05_calendar.spec.js @@ -1,16 +1,25 @@ +/* eslint-disable max-len */ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker calendar path', () => { - let reasonableTimeBetweenClicks = 400; + const reasonableTimeBetweenClicks = 300; + const date = new Date(); + const lastYear = (date.getFullYear() - 1).toString(); + let browser; let page; + + async function accessAs(user) { + await page.loginAndModule(user, 'worker'); + await page.accessToSearchResult('Charles Xavier'); + await page.accessToSection('worker.card.calendar'); + } + beforeAll(async() => { browser = await getBrowser(); page = browser.page; - await page.loginAndModule('hr', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); + accessAs('hr'); }); afterAll(async() => { @@ -21,48 +30,40 @@ describe('Worker calendar path', () => { it('should set two days as holidays on the calendar and check the total holidays increased by 1.5', async() => { await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); + await page.click(selectors.workerCalendar.penultimateMondayOfJanuary); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.absence); + await page.click(selectors.workerCalendar.absence); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.lastMondayOfMarch); + await page.click(selectors.workerCalendar.lastMondayOfMarch); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.halfHoliday); + await page.click(selectors.workerCalendar.halfHoliday); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.fistMondayOfMay); + await page.click(selectors.workerCalendar.fistMondayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.furlough); + await page.click(selectors.workerCalendar.furlough); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondTuesdayOfMay); + await page.click(selectors.workerCalendar.secondTuesdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondWednesdayOfMay); + await page.click(selectors.workerCalendar.secondWednesdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondThursdayOfMay); + await page.click(selectors.workerCalendar.secondThursdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.halfFurlough); - await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondFridayOfJun); + await page.click(selectors.workerCalendar.halfFurlough); await page.waitForTimeout(reasonableTimeBetweenClicks); + await page.click(selectors.workerCalendar.secondFridayOfJun); - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 1.5 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 1.5 '); }); }); describe(`as salesBoss`, () => { - it(`should log in and get to Charles Xavier's calendar`, async() => { - await page.loginAndModule('salesBoss', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); - }); + it(`should log in, get to Charles Xavier's calendar, undo what was done here, and check the total holidays used are back to what it was`, async() => { + accessAs('salesBoss'); - it('should undo what was done here', async() => { - await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); @@ -90,45 +91,24 @@ describe('Worker calendar path', () => { await page.waitToClick(selectors.workerCalendar.halfFurlough); await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.secondFridayOfJun); - }); - it('should check the total holidays used are back to what it was', async() => { - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 0 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); }); }); describe(`as Charles Xavier`, () => { - it(`should log in and get to his calendar`, async() => { - await page.loginAndModule('CharlesXavier', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); - }); - - it('should make a futile attempt to add holidays', async() => { - await page.waitForTimeout(reasonableTimeBetweenClicks); + it('should log in and get to his calendar, make a futile attempt to add holidays, check the total holidays used are now the initial ones and use the year selector to go to the previous year', async() => { + accessAs('CharlesXavier'); await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); - }); - it('should check the total holidays used are now the initial ones', async() => { - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); + await page.click(selectors.workerCalendar.penultimateMondayOfJanuary); - expect(result).toContain(' 0 '); - }); - - it('should use the year selector to go to the previous year', async() => { - const date = new Date(); - const lastYear = (date.getFullYear() - 1).toString(); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); await page.autocompleteSearch(selectors.workerCalendar.year, lastYear); - await page.waitForTimeout(reasonableTimeBetweenClicks); - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 0 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); }); }); }); From b2af21ba013f25c6b855636b8185e8d59988174a Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 28 Dec 2022 13:17:47 +0100 Subject: [PATCH 18/33] refs #3571 fdescribed removed --- e2e/paths/03-worker/04_time_control.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index 1222e7482..a8aea8fd4 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -2,7 +2,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Worker time control path', () => { +describe('Worker time control path', () => { let browser; let page; beforeAll(async() => { From 3514c0ac810a39dd6b6a7f9882b5deebd9f8c775 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 3 Jan 2023 09:14:25 +0100 Subject: [PATCH 19/33] refs #3571 pending tests --- e2e/paths/03-worker/04_time_control.spec.js | 79 ++++++++++++++------- 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index a8aea8fd4..bba7ced89 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -21,70 +21,99 @@ describe('Worker time control path', () => { const fourPm = '16:00'; const hankPymId = 1107; - it(`should go to the next month, go to current month, go 1 month in the past, return error when insert 'out' of first entry, then insert 'in' monday, then insert 'out' monday, then check if Hank Pym worked 8:20 hours, remove first entry of monday, be the 'out' the first entry of monday and change week of month`, async() => { + it('should go to the next month, go to current month and go 1 month in the past', async() => { let date = new Date(); date.setMonth(date.getMonth() + 1); let month = date.toLocaleString('default', {month: 'long'}); await page.click(selectors.workerTimeControl.nextMonthButton); + let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); - expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); + expect(result).toContain(month); date = new Date(); month = date.toLocaleString('default', {month: 'long'}); await page.click(selectors.workerTimeControl.previousMonthButton); + result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); - expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); + expect(result).toContain(month); date = new Date(); date.setMonth(date.getMonth() - 1); - month = date.toLocaleString('default', {month: 'long'}); const timestamp = Math.round(date.getTime() / 1000); + month = date.toLocaleString('default', {month: 'long'}); + await page.loginAndModule('salesBoss', 'worker'); await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); await page.click(selectors.workerTimeControl.secondWeekDay); - expect(await page.getProperty(selectors.workerTimeControl.monthName, 'innerText')).toContain(month); + result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); - await page.click(selectors.workerTimeControl.mondayAddTimeButton); + expect(result).toContain(month); + }); + + it(`should return error when insert 'out' of first entry`, async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.respondToDialog('accept'); - let message = await page.waitForSnackbar(); + const message = await page.waitForSnackbar(); expect(message.text).toBeDefined(); + }); - await page.click(selectors.workerTimeControl.mondayAddTimeButton); + it(`should insert 'in' monday`, async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in'); await page.respondToDialog('accept'); + const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); - expect(await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText')).toEqual(eightAm); + expect(result).toEqual(eightAm); + }); - await page.click(selectors.workerTimeControl.mondayAddTimeButton); + it(`should insert 'out' monday`, async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm); await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); await page.respondToDialog('accept'); - - expect(await page.getProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText')).toEqual(fourPm); - - expect(await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText')).toBe('08:20 h.'); - expect(await page.getProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText')).toBe('08:20 h.'); - expect(await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText')).toBe(eightAm); - expect(await page.getProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText')).toBe(fourPm); - await page.click(selectors.workerTimeControl.firstEntryOfMondayDelete); - await page.respondToDialog('accept'); - message = await page.waitForSnackbar(); - - expect(message.text).toContain('Entry removed'); - - const result = await page.getProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); + const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText'); expect(result).toEqual(fourPm); + }); + it(`should check Hank Pym worked 8:20 hours`, async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.'); + await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.'); + }); + + it('should remove first entry of monday', async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm); + await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm); + await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete); + await page.respondToDialog('accept'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Entry removed'); + }); + + it(`should be the 'out' the first entry of monday`, async() => { + pending('https://redmine.verdnatura.es/issues/4707'); + const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); + + expect(result).toEqual(fourPm); + }); + + it('should change week of month', async() => { await page.click(selectors.workerTimeControl.thrirdWeekDay); + const result = await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText'); - expect(await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText')).toBe('00:00 h.'); + expect(result).toEqual('00:00 h.'); }); }); From 030c474e06470ee7922c33fe179295e8c7e713d7 Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 4 Jan 2023 13:18:55 +0100 Subject: [PATCH 20/33] Fixed update module --- db/changes/225201/01-modules.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/changes/225201/01-modules.sql b/db/changes/225201/01-modules.sql index 82861a5e2..243d2d016 100644 --- a/db/changes/225201/01-modules.sql +++ b/db/changes/225201/01-modules.sql @@ -43,7 +43,7 @@ SET t.code = 'claim' WHERE t.code LIKE 'Claims' ESCAPE '#'; UPDATE salix.module t -SET t.code = 'user' +SET t.code = 'account' WHERE t.code LIKE 'Users' ESCAPE '#'; UPDATE salix.module t From 8f81aa2eeb61db173ec0a8e585452ae891284c5a Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 14:28:35 +0100 Subject: [PATCH 21/33] fix: salta los tickets que estan bloqueados --- back/methods/osticket/closeTicket.js | 93 +++++++++++++--------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index e5cbc58f4..cd0a2b3a2 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -25,10 +25,10 @@ module.exports = Self => { return false; const con = mysql.createConnection({ - host: config.hostDb, - user: config.userDb, - password: config.passwordDb, - port: config.portDb + host: `${config.hostDb}`, + user: `${config.userDb}`, + password: `${config.passwordDb}`, + port: `${config.portDb}` }); const sql = `SELECT ot.ticket_id, ot.number @@ -38,23 +38,23 @@ module.exports = Self => { JOIN ( SELECT ote.thread_id, MAX(ote.created) created, MAX(ote.updated) updated FROM osticket.ost_thread_entry ote - WHERE ote.staff_id AND ote.type = 'R' + WHERE ote.staff_id != 0 AND ote.type = 'R' GROUP BY ote.thread_id ) sub ON sub.thread_id = ot2.id - WHERE ot.isanswered - AND ots.state = ? - AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY)`; + WHERE ot.isanswered = 1 + AND ots.state = '${config.oldStatus}' + AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ${config.day} DAY)`; - const ticketsId = []; + let ticketsId = []; con.connect(err => { if (err) throw err; - con.query(sql, [config.oldStatus, config.day], - (err, results) => { - if (err) throw err; - for (const result of results) - ticketsId.push(result.ticket_id); - }); + con.query(sql, (err, results) => { + if (err) throw err; + for (const result of results) + ticketsId.push(result.ticket_id); + }); }); + await getRequestToken(); async function getRequestToken() { @@ -94,39 +94,6 @@ module.exports = Self => { await close(token, secondCookie); } - async function close(token, secondCookie) { - for (const ticketId of ticketsId) { - try { - const lockCode = await getLockCode(token, secondCookie, ticketId); - let form = new FormData(); - form.append('__CSRFToken__', token); - form.append('id', ticketId); - form.append('a', config.responseType); - form.append('lockCode', lockCode); - form.append('from_email_id', config.fromEmailId); - form.append('reply-to', config.replyTo); - form.append('cannedResp', 0); - form.append('response', config.comment); - form.append('signature', 'none'); - form.append('reply_status_id', config.newStatusId); - - const ostUri = `${config.host}/tickets.php?id=${ticketId}`; - const params = { - method: 'POST', - body: form, - headers: { - 'Cookie': secondCookie - } - }; - await fetch(ostUri, params); - } catch (e) { - const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); - err.stack += e.stack; - throw err; - } - } - } - async function getLockCode(token, secondCookie, ticketId) { const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`; const params = { @@ -140,7 +107,35 @@ module.exports = Self => { const body = await response.text(); const json = JSON.parse(body); - return json.code; + return json.code || json.retry; + } + + async function close(token, secondCookie) { + for (const ticketId of ticketsId) { + const lockCode = await getLockCode(token, secondCookie, ticketId); + if (lockCode == false) continue; + let form = new FormData(); + form.append('__CSRFToken__', token); + form.append('id', ticketId); + form.append('a', config.responseType); + form.append('lockCode', lockCode); + form.append('from_email_id', config.fromEmailId); + form.append('reply-to', config.replyTo); + form.append('cannedResp', 0); + form.append('response', config.comment); + form.append('signature', 'none'); + form.append('reply_status_id', config.newStatusId); + + const ostUri = `${config.host}/tickets.php?id=${ticketId}`; + const params = { + method: 'POST', + body: form, + headers: { + 'Cookie': secondCookie + } + }; + return fetch(ostUri, params); + } } }; }; From 1a74e84359cf7acc99d7927c467b4f622e347d04 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 14:32:14 +0100 Subject: [PATCH 22/33] feat: salta los tickets bloqueados --- back/methods/osticket/closeTicket.js | 92 +++++++++++++++------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index cd0a2b3a2..ad2af75b7 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -25,10 +25,10 @@ module.exports = Self => { return false; const con = mysql.createConnection({ - host: `${config.hostDb}`, - user: `${config.userDb}`, - password: `${config.passwordDb}`, - port: `${config.portDb}` + host: config.hostDb, + user: config.userDb, + password: config.passwordDb, + port: config.portDb }); const sql = `SELECT ot.ticket_id, ot.number @@ -38,23 +38,23 @@ module.exports = Self => { JOIN ( SELECT ote.thread_id, MAX(ote.created) created, MAX(ote.updated) updated FROM osticket.ost_thread_entry ote - WHERE ote.staff_id != 0 AND ote.type = 'R' + WHERE ote.staff_id AND ote.type = 'R' GROUP BY ote.thread_id ) sub ON sub.thread_id = ot2.id - WHERE ot.isanswered = 1 - AND ots.state = '${config.oldStatus}' - AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ${config.day} DAY)`; + WHERE ot.isanswered + AND ots.state = ? + AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY)`; - let ticketsId = []; + const ticketsId = []; con.connect(err => { if (err) throw err; - con.query(sql, (err, results) => { - if (err) throw err; - for (const result of results) - ticketsId.push(result.ticket_id); - }); + con.query(sql, [config.oldStatus, config.day], + (err, results) => { + if (err) throw err; + for (const result of results) + ticketsId.push(result.ticket_id); + }); }); - await getRequestToken(); async function getRequestToken() { @@ -94,6 +94,40 @@ module.exports = Self => { await close(token, secondCookie); } + async function close(token, secondCookie) { + for (const ticketId of ticketsId) { + try { + const lockCode = await getLockCode(token, secondCookie, ticketId); + if (lockCode == false) continue; + let form = new FormData(); + form.append('__CSRFToken__', token); + form.append('id', ticketId); + form.append('a', config.responseType); + form.append('lockCode', lockCode); + form.append('from_email_id', config.fromEmailId); + form.append('reply-to', config.replyTo); + form.append('cannedResp', 0); + form.append('response', config.comment); + form.append('signature', 'none'); + form.append('reply_status_id', config.newStatusId); + + const ostUri = `${config.host}/tickets.php?id=${ticketId}`; + const params = { + method: 'POST', + body: form, + headers: { + 'Cookie': secondCookie + } + }; + await fetch(ostUri, params); + } catch (e) { + const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); + err.stack += e.stack; + throw err; + } + } + } + async function getLockCode(token, secondCookie, ticketId) { const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`; const params = { @@ -109,33 +143,5 @@ module.exports = Self => { return json.code || json.retry; } - - async function close(token, secondCookie) { - for (const ticketId of ticketsId) { - const lockCode = await getLockCode(token, secondCookie, ticketId); - if (lockCode == false) continue; - let form = new FormData(); - form.append('__CSRFToken__', token); - form.append('id', ticketId); - form.append('a', config.responseType); - form.append('lockCode', lockCode); - form.append('from_email_id', config.fromEmailId); - form.append('reply-to', config.replyTo); - form.append('cannedResp', 0); - form.append('response', config.comment); - form.append('signature', 'none'); - form.append('reply_status_id', config.newStatusId); - - const ostUri = `${config.host}/tickets.php?id=${ticketId}`; - const params = { - method: 'POST', - body: form, - headers: { - 'Cookie': secondCookie - } - }; - return fetch(ostUri, params); - } - } }; }; From f356188491e5f4261199510465b93a0d38cc8763 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 14:54:43 +0100 Subject: [PATCH 23/33] feat: salta los tickets bloqueados --- back/methods/osticket/closeTicket.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index ad2af75b7..c2f6aab1e 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -98,7 +98,7 @@ module.exports = Self => { for (const ticketId of ticketsId) { try { const lockCode = await getLockCode(token, secondCookie, ticketId); - if (lockCode == false) continue; + if (!lockCode) throw new Error(`Can't get lock code`); let form = new FormData(); form.append('__CSRFToken__', token); form.append('id', ticketId); @@ -123,7 +123,7 @@ module.exports = Self => { } catch (e) { const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); err.stack += e.stack; - throw err; + console.error(err); } } } @@ -141,7 +141,7 @@ module.exports = Self => { const body = await response.text(); const json = JSON.parse(body); - return json.code || json.retry; + return json.code || null; } }; }; From a68fe26952f5e2286232fcc2178431fc61303b1c Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 15:01:20 +0100 Subject: [PATCH 24/33] refactor: machar stack --- back/methods/osticket/closeTicket.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index c2f6aab1e..601470a02 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -121,8 +121,8 @@ module.exports = Self => { }; await fetch(ostUri, params); } catch (e) { - const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); - err.stack += e.stack; + const err = new Error(`$s{ticketId} Ticket close failed: ${e.message}`); + err.stack = e.stack; console.error(err); } } From 0c6d335c4ac5fd5cdaf6b0689047c8dceefb5914 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 15:01:29 +0100 Subject: [PATCH 25/33] refactor: machacar stack --- back/methods/osticket/closeTicket.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 601470a02..98ef0aeef 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -121,7 +121,7 @@ module.exports = Self => { }; await fetch(ostUri, params); } catch (e) { - const err = new Error(`$s{ticketId} Ticket close failed: ${e.message}`); + const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); err.stack = e.stack; console.error(err); } From 201987fb992ac35220eef9d366ece37ff71228c2 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 9 Jan 2023 11:42:16 +0100 Subject: [PATCH 26/33] feat: muestra el error --- back/methods/osticket/closeTicket.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 98ef0aeef..40c0d860c 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -97,13 +97,17 @@ module.exports = Self => { async function close(token, secondCookie) { for (const ticketId of ticketsId) { try { - const lockCode = await getLockCode(token, secondCookie, ticketId); - if (!lockCode) throw new Error(`Can't get lock code`); + const lock = await getLockCode(token, secondCookie, ticketId); + if (!lock.code) { + let error = `Can't get lock code`; + if (lock.msg) error += `: ${lock.msg}`; + throw new Error(error); + } let form = new FormData(); form.append('__CSRFToken__', token); form.append('id', ticketId); form.append('a', config.responseType); - form.append('lockCode', lockCode); + form.append('lockCode', lock.code); form.append('from_email_id', config.fromEmailId); form.append('reply-to', config.replyTo); form.append('cannedResp', 0); @@ -141,7 +145,7 @@ module.exports = Self => { const body = await response.text(); const json = JSON.parse(body); - return json.code || null; + return json; } }; }; From f103931e503f69a834171d35c9af096e740eea98 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 10 Jan 2023 08:14:13 +0100 Subject: [PATCH 27/33] fix: se concatenan pq sino no muestra el id del ticket --- back/methods/osticket/closeTicket.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 40c0d860c..178b09601 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -126,7 +126,7 @@ module.exports = Self => { await fetch(ostUri, params); } catch (e) { const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); - err.stack = e.stack; + err.stack += e.stack; console.error(err); } } From ed90957ab594dcd19a6f2328839114c263817a17 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 12 Jan 2023 11:45:11 +0100 Subject: [PATCH 28/33] fix: corregida primaryKey de mdbApp --- db/changes/225202/00-mdbApp.sql | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 db/changes/225202/00-mdbApp.sql diff --git a/db/changes/225202/00-mdbApp.sql b/db/changes/225202/00-mdbApp.sql new file mode 100644 index 000000000..50c595d71 --- /dev/null +++ b/db/changes/225202/00-mdbApp.sql @@ -0,0 +1,28 @@ +ALTER TABLE `vn`.`mdbApp` DROP PRIMARY KEY; +ALTER TABLE `vn`.`mdbApp` ADD CONSTRAINT mdbApp_PK PRIMARY KEY (app,baselineBranchFk); + +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('com','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('enc','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('ent','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('eti','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('lab','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('tpv','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('com','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('enc','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('ent','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('eti','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('lab','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('tpv','dev'); + From b6de50848a634d78ff8bf0208b78a7f44406726f Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 12 Jan 2023 11:48:44 +0100 Subject: [PATCH 29/33] refs #5081 fix sms faltas --- front/salix/components/sendSms/locale/es.yml | 2 +- modules/route/front/sms/index.js | 2 +- modules/ticket/front/sale/index.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/front/salix/components/sendSms/locale/es.yml b/front/salix/components/sendSms/locale/es.yml index 64c3fcca6..94ab8e588 100644 --- a/front/salix/components/sendSms/locale/es.yml +++ b/front/salix/components/sendSms/locale/es.yml @@ -1,7 +1,7 @@ Send SMS: Enviar SMS Destination: Destinatario Message: Mensaje -SMS sent!: ¡SMS enviado! +SMS sent: ¡SMS enviado! Characters remaining: Carácteres restantes The destination can't be empty: El destinatario no puede estar vacio The message can't be empty: El mensaje no puede estar vacio diff --git a/modules/route/front/sms/index.js b/modules/route/front/sms/index.js index d8b1fc134..f466adea7 100644 --- a/modules/route/front/sms/index.js +++ b/modules/route/front/sms/index.js @@ -26,7 +26,7 @@ class Controller extends Component { throw new Error(`The message it's too long`); this.$http.post(`Routes/sendSms`, this.sms).then(res => { - this.vnApp.showMessage(this.$t('SMS sent!')); + this.vnApp.showMessage(this.$t('SMS sent')); if (res.data) this.emit('send', {response: res.data}); }); diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index c624b1a95..bb52089b3 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -441,10 +441,10 @@ - - + Date: Thu, 12 Jan 2023 11:52:27 +0100 Subject: [PATCH 30/33] fix: comprueba que hay registros --- modules/mdb/back/methods/mdbVersion/upload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js index 5dfe5d3ef..ea88c58f7 100644 --- a/modules/mdb/back/methods/mdbVersion/upload.js +++ b/modules/mdb/back/methods/mdbVersion/upload.js @@ -65,7 +65,7 @@ module.exports = Self => { try { const mdbApp = await models.MdbApp.findById(appName, null, myOptions); - if (mdbApp.locked && mdbApp.userFk != userId) { + if (mdbApp && mdbApp.locked && mdbApp.userFk != userId) { throw new UserError($t('App locked', { userId: mdbApp.userFk })); From 2678d5919167fe788f325a42954c26a279a52acb Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 12 Jan 2023 11:57:20 +0100 Subject: [PATCH 31/33] front test expected old value --- modules/route/front/sms/index.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/route/front/sms/index.spec.js b/modules/route/front/sms/index.spec.js index 42bf30931..8bf35e673 100644 --- a/modules/route/front/sms/index.spec.js +++ b/modules/route/front/sms/index.spec.js @@ -30,7 +30,7 @@ describe('Route', () => { controller.onResponse(); $httpBackend.flush(); - expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!'); + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent'); }); it('should call onResponse without the destination and show an error snackbar', () => { From d5a7691b9c16816072f9fbc23d4a583b668b5a96 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 12 Jan 2023 12:56:51 +0100 Subject: [PATCH 32/33] add controller function --- modules/ticket/front/sale/index.html | 3 ++- modules/ticket/front/sale/index.js | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index bb52089b3..d65a83c58 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -443,7 +443,8 @@ + sms="$ctrl.newSMS" + on-send="$ctrl.onSmsSend($sms)"> this.vnApp.showSuccess(this.$t('SMS sent'))); + } + /** * Inserts a new instance */ From 54356ece7d3b9fc0b0aec3e5e2eb8a0ef6b27a8b Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 12 Jan 2023 13:53:38 +0100 Subject: [PATCH 33/33] fix(monitor): refresh monitor when using ng-for track Refs: #5083 --- .../monitor/front/index/tickets/index.html | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/modules/monitor/front/index/tickets/index.html b/modules/monitor/front/index/tickets/index.html index 2f7c34e2d..b8559154e 100644 --- a/modules/monitor/front/index/tickets/index.html +++ b/modules/monitor/front/index/tickets/index.html @@ -79,51 +79,51 @@ @@ -133,64 +133,64 @@ - {{::ticket.id}} + {{ticket.id}} - {{::ticket.nickname}} + {{ticket.nickname}} - {{::ticket.userName | dashIfEmpty}} + {{ticket.userName | dashIfEmpty}} - - {{::ticket.shippedDate | date: 'dd/MM/yyyy'}} + + {{ticket.shippedDate | date: 'dd/MM/yyyy'}} - {{::ticket.zoneLanding | date: 'HH:mm'}} - {{::ticket.practicalHour | date: 'HH:mm'}} - {{::ticket.shipped | date: 'HH:mm'}} - {{::ticket.province}} + {{ticket.zoneLanding | date: 'HH:mm'}} + {{ticket.practicalHour | date: 'HH:mm'}} + {{ticket.shipped | date: 'HH:mm'}} + {{ticket.province}} - {{::ticket.refFk}} + {{ticket.refFk}} - {{::ticket.state}} + ng-show="!ticket.refFk" + class="chip {{ticket.classColor}}"> + {{ticket.state}} - {{::ticket.zoneName | dashIfEmpty}} + {{ticket.zoneName | dashIfEmpty}} - - {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} + + {{(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}