From e278491ad2bdbcf55ebc3433db74c0acc8eaab39 Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 14 Oct 2021 08:48:57 +0200 Subject: [PATCH 1/5] refactor(order): index filter optimization --- modules/order/back/methods/order/filter.js | 23 ++++++++++++---------- modules/order/front/index/index.html | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/order/back/methods/order/filter.js b/modules/order/back/methods/order/filter.js index ef6ea8a44..bd987dd5b 100644 --- a/modules/order/back/methods/order/filter.js +++ b/modules/order/back/methods/order/filter.js @@ -119,7 +119,7 @@ module.exports = Self => { case 'sourceApp': return {'o.source_app': value}; case 'ticketFk': - return {'ort.ticketFk': value}; + return {'ot.ticketFk': value}; case 'isConfirmed': return {'o.confirmed': value ? 1 : 0}; case 'myTeam': @@ -137,7 +137,10 @@ module.exports = Self => { let stmt; stmt = new ParameterizedSQL( - `SELECT + `CREATE TEMPORARY TABLE tmp.filter + (INDEX (id)) + ENGINE = MEMORY + SELECT o.id, o.total, o.date_send landed, @@ -168,20 +171,20 @@ module.exports = Self => { LEFT JOIN ticket t ON t.id = ot.ticketFk LEFT JOIN zoneEstimatedDelivery zed ON zed.zoneFk = t.zoneFk`); - if (args && args.ticketFk) { - stmt.merge({ - sql: `LEFT JOIN orderTicket ort ON ort.orderFk = o.id` - }); - } - stmt.merge(conn.makeWhere(filter.where)); - stmt.merge(`GROUP BY o.id`); stmt.merge(conn.makePagination(filter)); stmts.push(stmt); + stmt = new ParameterizedSQL(`SELECT * FROM tmp.filter`); + stmt.merge(`GROUP BY id`); + stmt.merge(conn.makeOrderBy(filter.order)); + const ordersIndex = stmts.push(stmt) - 1; + + stmts.push(`DROP TEMPORARY TABLE tmp.filter`); + const sql = ParameterizedSQL.join(stmts, ';'); const result = await conn.executeStmt(sql); - return result; + return result[ordersIndex]; }; }; diff --git a/modules/order/front/index/index.html b/modules/order/front/index/index.html index 288e81226..a2a4a5226 100644 --- a/modules/order/front/index/index.html +++ b/modules/order/front/index/index.html @@ -17,7 +17,7 @@ Landed Hour Agency - Total + Total From 85b4730c6c739a5c454bb6235da03a6959a8b8d2 Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 15 Oct 2021 10:49:23 +0200 Subject: [PATCH 2/5] feat(monitor): show client risk to future on tickets Refs: 2624 --- .../back/methods/sales-monitor/salesFilter.js | 144 ++++++++++++------ .../front/index/search-panel/index.html | 2 +- .../monitor/front/index/search-panel/index.js | 2 +- .../front/index/search-panel/index.spec.js | 4 +- .../monitor/front/index/tickets/index.html | 2 +- modules/ticket/front/search-panel/index.html | 2 +- modules/ticket/front/search-panel/index.js | 2 +- .../ticket/front/search-panel/index.spec.js | 4 +- 8 files changed, 110 insertions(+), 52 deletions(-) diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index 5d49f07df..af7ce02de 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -130,54 +130,20 @@ module.exports = Self => { const where = buildFilter(ctx.args, (param, value) => { switch (param) { - case 'search': - return /^\d+$/.test(value) - ? {'t.id': {inq: value}} - : {'t.nickname': {like: `%${value}%`}}; case 'from': return {'t.shipped': {gte: value}}; case 'to': return {'t.shipped': {lte: value}}; - case 'nickname': - return {'t.nickname': {like: `%${value}%`}}; - case 'refFk': - return {'t.refFk': value}; case 'salesPersonFk': return {'c.salesPersonFk': value}; - case 'provinceFk': - return {'a.provinceFk': value}; - case 'stateFk': - return {'ts.stateFk': value}; case 'mine': case 'myTeam': if (value) return {'c.salesPersonFk': {inq: teamMembersId}}; else return {'c.salesPersonFk': {nin: teamMembersId}}; - - case 'alertLevel': - return {'ts.alertLevel': value}; - case 'pending': - if (value) { - return {and: [ - {'st.alertLevel': 0}, - {'st.code': {nin: [ - 'OK', - 'BOARDING', - 'PRINTED', - 'PRINTED_AUTO', - 'PICKER_DESIGNED' - ]}} - ]}; - } else { - return {and: [ - {'st.alertLevel': {gt: 0}} - ]}; - } case 'id': case 'clientFk': - case 'agencyModeFk': - case 'warehouseFk': param = `t.${param}`; return {[param]: value}; } @@ -217,6 +183,7 @@ module.exports = Self => { ts.code AS alertLevelCode, u.name AS userName, c.salesPersonFk, + c.credit, z.hour AS zoneLanding, z.name AS zoneName, z.id AS zoneFk, @@ -247,6 +214,47 @@ module.exports = Self => { stmt.merge(conn.makeWhere(filter.where)); stmts.push(stmt); + // Get client debt balance + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt'); + stmts.push(` + CREATE TEMPORARY TABLE tmp.clientGetDebt + (INDEX (clientFk)) + ENGINE = MEMORY + SELECT DISTINCT clientFk FROM tmp.filter`); + + stmt = new ParameterizedSQL('CALL clientGetDebt(?)', [args.to]); + stmts.push(stmt); + stmts.push('DROP TEMPORARY TABLE tmp.clientGetDebt'); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.tickets'); + stmt = new ParameterizedSQL(` + CREATE TEMPORARY TABLE tmp.tickets + (INDEX (id)) + ENGINE = MEMORY + SELECT f.*, r.risk AS debt + FROM tmp.filter f + LEFT JOIN tmp.risk r ON f.clientFk = r.clientFk`); + stmts.push(stmt); + + // Sum risk to future + stmts.push(`SET @client:= 0`); + stmts.push('SET @risk := 0'); + stmts.push(` + UPDATE tmp.tickets + SET debt = IF(@client <> @client:= clientFk, + -totalWithVat + @risk:= - debt + totalWithVat, + -totalWithVat + @risk:= @risk + totalWithVat + ) + ORDER BY clientFk, shipped DESC + `); + + // Remove positive risks + stmts.push(` + UPDATE tmp.tickets t + SET debt = NULL + WHERE t.debt + t.credit >= 0 + `); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); stmts.push(` CREATE TEMPORARY TABLE tmp.sale_getProblems @@ -260,17 +268,20 @@ module.exports = Self => { stmts.push('CALL ticket_getProblems(FALSE)'); stmt = new ParameterizedSQL(` - SELECT f.*, tp.* - FROM tmp.filter f - LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`); + SELECT t.*, tp.*, t.debt + t.credit AS risk, + ((t.debt + t.credit) + cc.riskTolerance < 0) AS hasHighRisk + FROM tmp.tickets t + LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id + JOIN clientConfig cc`); const hasProblems = args.problems; if (hasProblems != undefined && (!args.from && !args.to)) throw new UserError('Choose a date range or days forward'); - let problemsFilter; + let finalFilter = {}; + let whereProblems; if (hasProblems === true) { - problemsFilter = {or: [ + whereProblems = {or: [ {'tp.isFreezed': true}, {'tp.risk': {gt: 0}}, {'tp.hasTicketRequest': true}, @@ -279,7 +290,7 @@ module.exports = Self => { {'tp.isAvailable': false} ]}; } else if (hasProblems === false) { - problemsFilter = {and: [ + whereProblems = {and: [ {'tp.isFreezed': false}, {'tp.risk': 0}, {'tp.hasTicketRequest': false}, @@ -289,8 +300,53 @@ module.exports = Self => { ]}; } - if (problemsFilter) - stmt.merge(conn.makeWhere(problemsFilter)); + if (whereProblems) finalFilter.where = whereProblems; + + const myWhere = buildFilter(ctx.args, (param, value) => { + switch (param) { + case 'search': + return /^\d+$/.test(value) + ? {'t.id': {inq: value}} + : {'t.nickname': {like: `%${value}%`}}; + + case 'nickname': + return {'t.nickname': {like: `%${value}%`}}; + case 'refFk': + return {'t.refFk': value}; + + case 'provinceFk': + return {'t.provinceFk': value}; + case 'stateFk': + return {'t.stateFk': value}; + case 'alertLevel': + return {'t.alertLevel': value}; + case 'pending': + if (value) { + return {and: [ + {'t.alertLevel': 0}, + {'t.alertLevelCode': {nin: [ + 'OK', + 'BOARDING', + 'PRINTED', + 'PRINTED_AUTO', + 'PICKER_DESIGNED' + ]}} + ]}; + } else { + return {and: [ + {'t.alertLevel': {gt: 0}} + ]}; + } + case 'agencyModeFk': + case 'warehouseFk': + param = `t.${param}`; + return {[param]: value}; + } + }); + + finalFilter = mergeFilters(finalFilter, {where: myWhere}); + if (finalFilter.where) + stmt.merge(conn.makeWhere(finalFilter.where)); stmt.merge(conn.makeOrderBy(filter.order)); stmt.merge(conn.makeLimit(filter)); @@ -299,7 +355,9 @@ module.exports = Self => { stmts.push( `DROP TEMPORARY TABLE tmp.filter, - tmp.ticket_problems`); + tmp.ticket_problems, + tmp.sale_getProblems, + tmp.risk`); let sql = ParameterizedSQL.join(stmts, ';'); let result = await conn.executeStmt(sql); diff --git a/modules/monitor/front/index/search-panel/index.html b/modules/monitor/front/index/search-panel/index.html index dc24c778b..5458202d2 100644 --- a/modules/monitor/front/index/search-panel/index.html +++ b/modules/monitor/front/index/search-panel/index.html @@ -70,7 +70,7 @@ diff --git a/modules/monitor/front/index/search-panel/index.js b/modules/monitor/front/index/search-panel/index.js index 057d555e4..ef6625e8a 100644 --- a/modules/monitor/front/index/search-panel/index.js +++ b/modules/monitor/front/index/search-panel/index.js @@ -14,7 +14,7 @@ class Controller extends SearchPanel { this.$http.get('AlertLevels').then(res => { for (let state of res.data) { groupedStates.push({ - alertLevel: state.alertLevel, + id: state.id, code: state.code, name: this.$t(state.code) }); diff --git a/modules/monitor/front/index/search-panel/index.spec.js b/modules/monitor/front/index/search-panel/index.spec.js index 0d19fd35f..f862e8d77 100644 --- a/modules/monitor/front/index/search-panel/index.spec.js +++ b/modules/monitor/front/index/search-panel/index.spec.js @@ -18,7 +18,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => { jest.spyOn(controller, '$t').mockReturnValue('miCodigo'); const data = [ { - alertLevel: 9999, + id: 9999, code: 'myCode' } ]; @@ -27,7 +27,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => { $httpBackend.flush(); expect(controller.groupedStates).toEqual([{ - alertLevel: 9999, + id: 9999, code: 'myCode', name: 'miCodigo' }]); diff --git a/modules/monitor/front/index/tickets/index.html b/modules/monitor/front/index/tickets/index.html index 45db04ca0..ff378adda 100644 --- a/modules/monitor/front/index/tickets/index.html +++ b/modules/monitor/front/index/tickets/index.html @@ -51,7 +51,7 @@ - + diff --git a/modules/ticket/front/search-panel/index.js b/modules/ticket/front/search-panel/index.js index 6ef47757a..ed86921e0 100644 --- a/modules/ticket/front/search-panel/index.js +++ b/modules/ticket/front/search-panel/index.js @@ -14,7 +14,7 @@ class Controller extends SearchPanel { this.$http.get('AlertLevels').then(res => { for (let state of res.data) { groupedStates.push({ - alertLevel: state.alertLevel, + id: state.id, code: state.code, name: this.$t(state.code) }); diff --git a/modules/ticket/front/search-panel/index.spec.js b/modules/ticket/front/search-panel/index.spec.js index f3a2f39ed..41c32c047 100644 --- a/modules/ticket/front/search-panel/index.spec.js +++ b/modules/ticket/front/search-panel/index.spec.js @@ -18,7 +18,7 @@ describe('Ticket Component vnTicketSearchPanel', () => { jest.spyOn(controller, '$t').mockReturnValue('miCodigo'); const data = [ { - alertLevel: 9999, + id: 9999, code: 'myCode' } ]; @@ -27,7 +27,7 @@ describe('Ticket Component vnTicketSearchPanel', () => { $httpBackend.flush(); expect(controller.groupedStates).toEqual([{ - alertLevel: 9999, + id: 9999, code: 'myCode', name: 'miCodigo' }]); From b6a9896cba900754305b50bf349afa0a9437cc9d Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 15 Oct 2021 12:10:28 +0200 Subject: [PATCH 3/5] Fixed monitor problems filter --- .../back/methods/sales-monitor/salesFilter.js | 17 +++++++++++++---- .../sales-monitor/specs/salesFilter.spec.js | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index af7ce02de..e5f992e2f 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -251,7 +251,7 @@ module.exports = Self => { // Remove positive risks stmts.push(` UPDATE tmp.tickets t - SET debt = NULL + SET debt = 0 WHERE t.debt + t.credit >= 0 `); @@ -267,9 +267,18 @@ module.exports = Self => { AND f.shipped >= CURDATE()`); stmts.push('CALL ticket_getProblems(FALSE)'); + stmts.push(` + INSERT INTO tmp.ticket_problems (ticketFk, risk, totalProblems) + SELECT t.id, t.debt + t.credit AS risk, 1 + FROM tmp.tickets t + WHERE (t.debt + t.credit) < 0 + ON DUPLICATE KEY UPDATE + risk = t.debt + t.credit, totalProblems = totalProblems + 1 + `); + stmt = new ParameterizedSQL(` - SELECT t.*, tp.*, t.debt + t.credit AS risk, - ((t.debt + t.credit) + cc.riskTolerance < 0) AS hasHighRisk + SELECT t.*, tp.*, + ((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk FROM tmp.tickets t LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id JOIN clientConfig cc`); @@ -283,7 +292,7 @@ module.exports = Self => { if (hasProblems === true) { whereProblems = {or: [ {'tp.isFreezed': true}, - {'tp.risk': {gt: 0}}, + {'tp.risk': {lt: 0}}, {'tp.hasTicketRequest': true}, {'tp.hasComponentLack': true}, {'tp.isTaxDataChecked': false}, diff --git a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js index 53cd9941e..8a5136c80 100644 --- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js +++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js @@ -23,7 +23,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await app.models.SalesMonitor.salesFilter(ctx, filter); - expect(result.length).toEqual(9); + expect(result.length).toEqual(13); }); it('should return the tickets matching the problems on false', async() => { From 629a8d25b7226841d5f57ae90a73bc657f1e0f52 Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 15 Oct 2021 13:49:41 +0200 Subject: [PATCH 4/5] Updated pagination styles --- .../10370-pickles/00-ticket_getProblems.sql | 48 +++++++++++++++++++ .../components/pagination/pagination.html | 9 ++-- front/core/components/pagination/style.scss | 6 +++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 db/changes/10370-pickles/00-ticket_getProblems.sql diff --git a/db/changes/10370-pickles/00-ticket_getProblems.sql b/db/changes/10370-pickles/00-ticket_getProblems.sql new file mode 100644 index 000000000..b58676a71 --- /dev/null +++ b/db/changes/10370-pickles/00-ticket_getProblems.sql @@ -0,0 +1,48 @@ +drop procedure `vn`.`ticket_getProblems`; + +DELIMITER $$ +$$ +create + definer = root@`%` procedure `vn`.`ticket_getProblems`(IN vIsTodayRelative tinyint(1)) +BEGIN +/** + * Calcula los problemas para un conjunto de tickets. + * Agrupados por ticket + * + * @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular + * @return tmp.ticket_problems + */ + CALL sale_getProblems(vIsTodayRelative); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket_problems; + CREATE TEMPORARY TABLE tmp.ticket_problems + (PRIMARY KEY (ticketFk)) + ENGINE = MEMORY + SELECT + ticketFk, + MAX(p.isFreezed) AS isFreezed, + MAX(p.risk) AS risk, + MAX(p.hasHighRisk) AS hasHighRisk, + MAX(p.hasTicketRequest) AS hasTicketRequest, + MIN(p.isAvailable) AS isAvailable, + MAX(p.itemShortage) AS itemShortage, + MIN(p.isTaxDataChecked) AS isTaxDataChecked, + MAX(p.hasComponentLack) AS hasComponentLack, + 0 AS totalProblems + FROM tmp.sale_problems p + GROUP BY ticketFk; + + UPDATE tmp.ticket_problems tp + SET tp.totalProblems = ( + (tp.isFreezed) + + IF(tp.risk, TRUE, FALSE) + + (tp.hasTicketRequest) + + (tp.isAvailable = 0) + + (tp.isTaxDataChecked = 0) + + (tp.hasComponentLack) + ); + + DROP TEMPORARY TABLE + tmp.sale_problems; +END;;$$ +DELIMITER ; diff --git a/front/core/components/pagination/pagination.html b/front/core/components/pagination/pagination.html index 6809018dd..72d7c31ff 100644 --- a/front/core/components/pagination/pagination.html +++ b/front/core/components/pagination/pagination.html @@ -1,9 +1,10 @@ -
- +
- + + +
diff --git a/front/core/components/pagination/style.scss b/front/core/components/pagination/style.scss index 413a6fb5f..02dcb43e4 100644 --- a/front/core/components/pagination/style.scss +++ b/front/core/components/pagination/style.scss @@ -1,7 +1,13 @@ +@import "variables"; vn-pagination { display: block; text-align: center; + color: $color-primary; + + vn-button, vn-icon { + display: block + } & > div > vn-icon-button { font-size: 2rem; From 8fabd378e75fac5bb22f3a019bd049a3c70a1a50 Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 15 Oct 2021 14:00:15 +0200 Subject: [PATCH 5/5] Removed version folder --- db/changes/10370-pickles/00-ACL.sql | 1 - .../10370-pickles/00-ticket_getProblems.sql | 48 ------------------- 2 files changed, 49 deletions(-) delete mode 100644 db/changes/10370-pickles/00-ACL.sql delete mode 100644 db/changes/10370-pickles/00-ticket_getProblems.sql diff --git a/db/changes/10370-pickles/00-ACL.sql b/db/changes/10370-pickles/00-ACL.sql deleted file mode 100644 index c5e10dec5..000000000 --- a/db/changes/10370-pickles/00-ACL.sql +++ /dev/null @@ -1 +0,0 @@ -UPDATE salix.ACL t SET t.principalId = 'employee' WHERE t.id = 269; diff --git a/db/changes/10370-pickles/00-ticket_getProblems.sql b/db/changes/10370-pickles/00-ticket_getProblems.sql deleted file mode 100644 index b58676a71..000000000 --- a/db/changes/10370-pickles/00-ticket_getProblems.sql +++ /dev/null @@ -1,48 +0,0 @@ -drop procedure `vn`.`ticket_getProblems`; - -DELIMITER $$ -$$ -create - definer = root@`%` procedure `vn`.`ticket_getProblems`(IN vIsTodayRelative tinyint(1)) -BEGIN -/** - * Calcula los problemas para un conjunto de tickets. - * Agrupados por ticket - * - * @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular - * @return tmp.ticket_problems - */ - CALL sale_getProblems(vIsTodayRelative); - - DROP TEMPORARY TABLE IF EXISTS tmp.ticket_problems; - CREATE TEMPORARY TABLE tmp.ticket_problems - (PRIMARY KEY (ticketFk)) - ENGINE = MEMORY - SELECT - ticketFk, - MAX(p.isFreezed) AS isFreezed, - MAX(p.risk) AS risk, - MAX(p.hasHighRisk) AS hasHighRisk, - MAX(p.hasTicketRequest) AS hasTicketRequest, - MIN(p.isAvailable) AS isAvailable, - MAX(p.itemShortage) AS itemShortage, - MIN(p.isTaxDataChecked) AS isTaxDataChecked, - MAX(p.hasComponentLack) AS hasComponentLack, - 0 AS totalProblems - FROM tmp.sale_problems p - GROUP BY ticketFk; - - UPDATE tmp.ticket_problems tp - SET tp.totalProblems = ( - (tp.isFreezed) + - IF(tp.risk, TRUE, FALSE) + - (tp.hasTicketRequest) + - (tp.isAvailable = 0) + - (tp.isTaxDataChecked = 0) + - (tp.hasComponentLack) - ); - - DROP TEMPORARY TABLE - tmp.sale_problems; -END;;$$ -DELIMITER ;