From 30933220aca2d32dfddd1ee4a2129aea66c58f64 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Mon, 24 Oct 2022 09:37:17 +0200 Subject: [PATCH 01/28] #4507 greuge.js/json now insert userFk @2h --- modules/client/back/models/greuge.js | 15 +++++++++++++++ modules/client/back/models/greuge.json | 4 ++++ modules/client/front/greuge/index/index.html | 2 ++ modules/client/front/greuge/index/locale/es.yml | 3 ++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/client/back/models/greuge.js b/modules/client/back/models/greuge.js index bd5f2865d..42820fd60 100644 --- a/modules/client/back/models/greuge.js +++ b/modules/client/back/models/greuge.js @@ -1,6 +1,21 @@ +const LoopBackContext = require('loopback-context'); + module.exports = function(Self) { require('../methods/greuge/sumAmount')(Self); + Self.observe('before save', function(ctx, next) { + const loopBackContext = LoopBackContext.getCurrentContext(); + + let userFk = loopBackContext.active.accessToken.userId; + + if (ctx.instance) + ctx.instance.userFk = userFk; + else + ctx.data.userFk = userFk; + + next(); + }); + Self.validatesLengthOf('description', { max: 45, message: 'Description should have maximum of 45 characters' diff --git a/modules/client/back/models/greuge.json b/modules/client/back/models/greuge.json index 918ff0ca5..e8790715a 100644 --- a/modules/client/back/models/greuge.json +++ b/modules/client/back/models/greuge.json @@ -34,6 +34,10 @@ "greugeTypeFk": { "type": "number", "required": true + }, + "userFk": { + "type": "number", + "required": true } }, diff --git a/modules/client/front/greuge/index/index.html b/modules/client/front/greuge/index/index.html index b48fe9466..cdc9c37d4 100644 --- a/modules/client/front/greuge/index/index.html +++ b/modules/client/front/greuge/index/index.html @@ -29,6 +29,7 @@ Date + Created by Comment Type Amount @@ -37,6 +38,7 @@ {{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }} + {{::greuge.userFk}} {{::greuge.description}} diff --git a/modules/client/front/greuge/index/locale/es.yml b/modules/client/front/greuge/index/locale/es.yml index 513e6ff7b..d1f202862 100644 --- a/modules/client/front/greuge/index/locale/es.yml +++ b/modules/client/front/greuge/index/locale/es.yml @@ -1,4 +1,5 @@ Date: Fecha Comment: Comentario Amount: Importe -Type: Tipo \ No newline at end of file +Type: Tipo +Created by: Creado por \ No newline at end of file From 896a7eb6f05a5764d0a0a4cd2fc685c31287f1a3 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 7 Nov 2022 15:55:17 +0100 Subject: [PATCH 02/28] refs #4700 arreglar filtro y traducciones --- .../10501-november/00-ticket_canMerge.sql | 9 + .../00-ticket_canbePostposed.sql | 75 ++++++++ loopback/locale/es.json | 3 +- .../methods/ticket-future/getTicketsFuture.js | 179 ++++++++++++++++++ .../ticket-future/moveTicketsFuture.js | 68 +++++++ modules/ticket/back/model-config.json | 3 + modules/ticket/back/models/ticket-future.json | 12 ++ modules/ticket/back/models/ticket.js | 2 + .../front/future-search-panel/index.html | 86 +++++++++ .../ticket/front/future-search-panel/index.js | 30 +++ .../front/future-search-panel/locale/en.yml | 1 + .../front/future-search-panel/locale/es.yml | 13 ++ modules/ticket/front/future/index.html | 164 ++++++++++++++++ modules/ticket/front/future/index.js | 107 +++++++++++ modules/ticket/front/future/locale/es.yml | 15 ++ modules/ticket/front/future/style.scss | 0 modules/ticket/front/index.js | 2 + modules/ticket/front/routes.json | 9 +- 18 files changed, 776 insertions(+), 2 deletions(-) create mode 100644 db/changes/10501-november/00-ticket_canMerge.sql create mode 100644 db/changes/10501-november/00-ticket_canbePostposed.sql create mode 100644 modules/ticket/back/methods/ticket-future/getTicketsFuture.js create mode 100644 modules/ticket/back/methods/ticket-future/moveTicketsFuture.js create mode 100644 modules/ticket/back/models/ticket-future.json create mode 100644 modules/ticket/front/future-search-panel/index.html create mode 100644 modules/ticket/front/future-search-panel/index.js create mode 100644 modules/ticket/front/future-search-panel/locale/en.yml create mode 100644 modules/ticket/front/future-search-panel/locale/es.yml create mode 100644 modules/ticket/front/future/index.html create mode 100644 modules/ticket/front/future/index.js create mode 100644 modules/ticket/front/future/locale/es.yml create mode 100644 modules/ticket/front/future/style.scss diff --git a/db/changes/10501-november/00-ticket_canMerge.sql b/db/changes/10501-november/00-ticket_canMerge.sql new file mode 100644 index 000000000..6db3637ac --- /dev/null +++ b/db/changes/10501-november/00-ticket_canMerge.sql @@ -0,0 +1,9 @@ +DROP PROCEDURE IF EXISTS vn.ticket_canMerge; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canMerge`(vDated DATE, vScopeDays INT, vLitersMax INT, vLinesMax INT, vWarehouseFk INT) +BEGIN + CALL vn.ticket_canbePostponed(vDated,TIMESTAMPADD(DAY, vScopeDays, vDated),vLitersMax,vLinesMax,vWarehouseFk); +END $$ +DELIMITER ; diff --git a/db/changes/10501-november/00-ticket_canbePostposed.sql b/db/changes/10501-november/00-ticket_canbePostposed.sql new file mode 100644 index 000000000..6ad9df154 --- /dev/null +++ b/db/changes/10501-november/00-ticket_canbePostposed.sql @@ -0,0 +1,75 @@ +DROP PROCEDURE IF EXISTS vn.ticket_canbePostponed; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vLitersMax INT, vLinesMax INT, vWarehouseFk INT) +BEGIN +/** + * Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro + * + * @param vOriginDated Fecha en cuestión + * @param vFutureDated Fecha en el futuro a sondear + * @param vLitersMax Volumen máximo de los tickets a catapultar + * @param vLinesMax Número máximo de lineas de los tickets a catapultar + * @param vWarehouseFk Identificador de vn.warehouse + */ + DROP TEMPORARY TABLE IF EXISTS tmp.filter; + CREATE TEMPORARY TABLE tmp.filter + (INDEX (id)) + SELECT sv.ticketFk id, + GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt, + CAST(sum(litros) AS DECIMAL(10,0)) liters, + CAST(count(*) AS DECIMAL(10,0)) `lines`, + st.name state, + sub2.id ticketFuture, + t.landed originETD, + sub2.landed destETD, + sub2.iptd tfIpt, + sub2.state tfState, + t.clientFk, + t.warehouseFk, + ts.alertLevel, + t.shipped, + sub2.shipped tfShipped, + t.workerFk + FROM vn.saleVolume sv + JOIN vn.sale s ON s.id = sv.saleFk + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.ticket t ON t.id = sv.ticketFk + JOIN vn.address a ON a.id = t.addressFk + JOIN vn.province p ON p.id = a.provinceFk + JOIN vn.country c ON c.id = p.countryFk + JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.alertLevel al ON al.id = ts.alertLevel + LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id + LEFT JOIN ( + SELECT * + FROM ( + SELECT + t.addressFk , + t.id, + t.landed, + t.shipped, + st.name state, + GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd + FROM vn.ticket t + JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.item i ON i.id = s.itemFk + WHERE t.shipped BETWEEN vFutureDated + AND util.dayend(vFutureDated) + AND t.warehouseFk = vWarehouseFk + GROUP BY t.id + ) sub + GROUP BY sub.addressFk + ) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id + WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated) + AND t.warehouseFk = vWarehouseFk + AND al.code = 'FREE' + AND tp.ticketFk IS NULL + GROUP BY sv.ticketFk + HAVING liters <= IFNULL(vLitersMax, 9999) AND `lines` <= IFNULL(vLinesMax, 9999) AND ticketFuture; +END$$ +DELIMITER ; diff --git a/loopback/locale/es.json b/loopback/locale/es.json index a41315dd1..a12cf1c09 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -237,5 +237,6 @@ "Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador", "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente", "You don't have grant privilege": "No tienes privilegios para dar privilegios", - "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario" + "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario", + "MOVE_TICKET_CONFIRMATION": "Ticket {{id}} ({{originDated}}) fusionado con {{tfId}} ({{futureDated}}) [{{fullPath}}]" } diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js new file mode 100644 index 000000000..5b83e50be --- /dev/null +++ b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js @@ -0,0 +1,179 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const buildFilter = require('vn-loopback/util/filter').buildFilter; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethodCtx('getTicketsFuture', { + description: 'Find all instances of the model matched by filter from the data source.', + accessType: 'READ', + accepts: [ + { + arg: 'originDated', + type: 'date', + description: 'The date in question', + required: true + }, + { + arg: 'futureDated', + type: 'date', + description: 'The date to probe', + required: true + }, + { + arg: 'litersMax', + type: 'number', + description: 'Maximum volume of tickets to catapult', + required: true + }, + { + arg: 'linesMax', + type: 'number', + description: 'Maximum number of lines of tickets to catapult', + required: true + }, + { + arg: 'warehouseFk', + type: 'number', + description: 'Warehouse identifier', + required: true + }, + { + arg: 'filter', + type: 'object', + description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/getTicketsFuture`, + verb: 'GET' + } + }); + + Self.getTicketsFuture = async (ctx, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + const conn = Self.dataSource.connector; + const args = ctx.args; + const stmts = []; + let stmt; + + stmt = new ParameterizedSQL( + `CALL vn.ticket_canbePostponed(?,?,?,?,?)`, + [args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]); + + stmts.push(stmt); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); + + stmt = new ParameterizedSQL(` + CREATE TEMPORARY TABLE tmp.sale_getProblems + (INDEX (ticketFk)) + ENGINE = MEMORY + SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped + FROM tmp.filter f + LEFT JOIN alertLevel al ON al.id = f.alertLevel + WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`); + stmts.push(stmt); + + 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`); + + if (args.problems != undefined && (!args.from && !args.to)) + throw new UserError('Choose a date range or days forward'); + + const myWhere = buildFilter(ctx.args, (param, value) => { + switch (param) { + // case 'search': + // return /^\d+$/.test(value) + // ? {'t.id': {inq: value}} + // : {'t.nickname': {like: `%${value}%`}}; + case 'shipped': + return {'shipped': {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}; + } + }); + let finalFilter = {}; + finalFilter = mergeFilters(finalFilter, {where: myWhere}); + if (finalFilter.where) + stmt.merge(conn.makeWhere(finalFilter.where)); + + let condition; + let hasProblem; + let range; + let hasWhere; + switch (args.problems) { + case true: + condition = `or`; + hasProblem = true; + range = {neq: null}; + hasWhere = true; + break; + + case false: + condition = `and`; + hasProblem = null; + range = null; + hasWhere = true; + break; + } + + const problems = {[condition]: [ + {'tp.isFreezed': hasProblem}, + {'tp.risk': hasProblem}, + {'tp.hasTicketRequest': hasProblem}, + {'tp.itemShortage': range} + ]}; + + if (hasWhere) + stmt.merge(conn.makeWhere(problems)); + + const ticketsIndex = stmts.push(stmt) - 1; + + stmts.push( + `DROP TEMPORARY TABLE + tmp.filter, + tmp.ticket_problems`); + + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + return result[ticketsIndex]; + }; +}; \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket-future/moveTicketsFuture.js b/modules/ticket/back/methods/ticket-future/moveTicketsFuture.js new file mode 100644 index 000000000..940a83c33 --- /dev/null +++ b/modules/ticket/back/methods/ticket-future/moveTicketsFuture.js @@ -0,0 +1,68 @@ +const LoopBackContext = require('loopback-context'); + +module.exports = Self => { + Self.remoteMethodCtx('moveTicketsFuture', { + description: 'Move specified tickets to the future', + accessType: 'WRITE', + accepts: [ + { + arg: 'tickets', + type: ['object'], + description: 'The array of tickets', + required: false + } + ], + returns: { + type: 'string', + root: true + }, + http: { + path: `/moveTicketsFuture`, + verb: 'POST' + } + }); + + Self.moveTicketsFuture = async (ctx, tickets, options) => { + const loopBackContext = LoopBackContext.getCurrentContext(); + const httpCtx = {req: loopBackContext.active}; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + for (let ticket of tickets) { + console.log(ticket); + try { + if(!ticket.id || !ticket.ticketFuture) continue; + await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions); + await models.Ticket.setDeleted(ctx, ticket.id, myOptions); + if (tx) + { + const httpRequest = httpCtx.req.http.req; + const $t = httpRequest.__; + const origin = httpRequest.headers.origin; + const fullPath = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; + const message = $t('MOVE_TICKET_CONFIRMATION', { + originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), + futureDated: new Date(ticket.destETD).toLocaleDateString('es-ES'), + id: ticket.id, + tfId: ticket.ticketFuture, + fullPath + }); + await tx.commit(); + await models.Chat.sendCheckingPresence(httpCtx, ticket.workerFk, message); + } + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; + }; +}; \ No newline at end of file diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json index 21e800b36..82d8e3b1a 100644 --- a/modules/ticket/back/model-config.json +++ b/modules/ticket/back/model-config.json @@ -91,5 +91,8 @@ }, "TicketConfig": { "dataSource": "vn" + }, + "TicketFuture": { + "dataSource": "vn" } } diff --git a/modules/ticket/back/models/ticket-future.json b/modules/ticket/back/models/ticket-future.json new file mode 100644 index 000000000..5d0b24dbc --- /dev/null +++ b/modules/ticket/back/models/ticket-future.json @@ -0,0 +1,12 @@ +{ + "name": "TicketFuture", + "base": "PersistedModel", + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] + } \ No newline at end of file diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index c05130552..649a83160 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -4,6 +4,8 @@ const LoopBackContext = require('loopback-context'); module.exports = Self => { // Methods require('./ticket-methods')(Self); + require('../methods/ticket-future/getTicketsFuture')(Self); + require('../methods/ticket-future/moveTicketsFuture')(Self); Self.observe('before save', async function(ctx) { const loopBackContext = LoopBackContext.getCurrentContext(); diff --git a/modules/ticket/front/future-search-panel/index.html b/modules/ticket/front/future-search-panel/index.html new file mode 100644 index 000000000..4f5486d62 --- /dev/null +++ b/modules/ticket/front/future-search-panel/index.html @@ -0,0 +1,86 @@ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js new file mode 100644 index 000000000..bbc2148e7 --- /dev/null +++ b/modules/ticket/front/future-search-panel/index.js @@ -0,0 +1,30 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +class Controller extends SearchPanel { + constructor($, $element) { + super($, $element); + this.filter = this.$.filter; + } + + get from() { + return this._from; + } + + set from(value) { + this._from = value; + } + + get to() { + return this._to; + } + + set to(value) { + this._to = value; + } +} + +ngModule.vnComponent('vnFutureTicketSearchPanel', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/ticket/front/future-search-panel/locale/en.yml b/modules/ticket/front/future-search-panel/locale/en.yml new file mode 100644 index 000000000..0440752c5 --- /dev/null +++ b/modules/ticket/front/future-search-panel/locale/en.yml @@ -0,0 +1 @@ +Future tickets: Tickets a futuro \ No newline at end of file diff --git a/modules/ticket/front/future-search-panel/locale/es.yml b/modules/ticket/front/future-search-panel/locale/es.yml new file mode 100644 index 000000000..e459c3cd9 --- /dev/null +++ b/modules/ticket/front/future-search-panel/locale/es.yml @@ -0,0 +1,13 @@ +Future tickets: Tickets a futuro +Origin date: Fecha origen +Destination date: Fecha destino +Origin ETD: ETD origen +Destination ETD: ETD destino +Max Lines Origin: Líneas máx. origen +Max Liters Origin: Litros máx. origen +Origin ITP: ITP origen +Destination ITP: ITP destino +With problems: Con problemas +Warehouse: Almacén +Origin Agrupated State: Estado agrupado origen +Destination Agrupated State: Estado agrupado destino diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html new file mode 100644 index 000000000..9dbb5a4ca --- /dev/null +++ b/modules/ticket/front/future/index.html @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Problems + + Origin ID + + Origin ETD + + Origin State + + IPT + + Liters + + Available Lines + + Destination ID + + Destination ETD + + Destination State + + IPT +
+ + + + + + + + + + + + + + + + + {{::ticket.id}} + + {{::ticket.originETD | date: 'dd/MM/yyyy'}} + + {{::ticket.state}} + {{::ticket.ipt}}{{::ticket.liters}}{{::ticket.lines}} + {{::ticket.ticketFuture}} + + {{::ticket.destETD | date: 'dd/MM/yyyy'}} + + {{::ticket.tfState}} + {{::ticket.tfIpt}}
+
+
+
+ + + + \ No newline at end of file diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js new file mode 100644 index 000000000..6dda5812d --- /dev/null +++ b/modules/ticket/front/future/index.js @@ -0,0 +1,107 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.$checkAll = false; + + const originDated = new Date(); + const futureDated = new Date(); + const warehouseFk = 1; + const litersMax = 9999; + const linesMax = 9999; + + this.defaultFilter = { + originDated, + futureDated, + warehouseFk, + litersMax, + linesMax + }; + + this.smartTableOptions = { + activeButtons: { + search: true + }, + columns: [{ + field:'problems', + searchable: false + }, + { + field:'ETD', + searchable: false + }, + { + field:'tfETD', + searchable: false + }] + }; + } + + get checked() { + const tickets = this.$.model.data || []; + const checkedLines = []; + for (let ticket of tickets) { + if (ticket.checked) + checkedLines.push(ticket); + } + + return checkedLines; + } + + moveTicketsFuture() + { + let params = { + tickets: this.checked + }; + this.$http.post('Tickets/moveTicketsFuture', params); + this.reload(); + } + + compareDate(date) { + let today = new Date(); + today.setHours(0, 0, 0, 0); + let timeTicket = new Date(date); + timeTicket.setHours(0, 0, 0, 0); + + let comparation = today - timeTicket; + + if (comparation == 0) + return 'warning'; + if (comparation < 0) + return 'success'; + } + + stateColor(state) { + if (state === 'OK') + return 'success'; + else if (state === 'FREE') + return 'notice'; + } + + exprBuilder(param, value) { + switch (param) { + case 'shipped': + return {'shipped': {like: `%${value}%`}}; + } + } + + dateRange(value) { + const minHour = new Date(value); + minHour.setHours(0, 0, 0, 0); + const maxHour = new Date(value); + maxHour.setHours(23, 59, 59, 59); + + return [minHour, maxHour]; + } + + reload() { + this.$.model.refresh(); + } +} + +ngModule.vnComponent('vnTicketFuture', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/ticket/front/future/locale/es.yml b/modules/ticket/front/future/locale/es.yml new file mode 100644 index 000000000..946611e66 --- /dev/null +++ b/modules/ticket/front/future/locale/es.yml @@ -0,0 +1,15 @@ +Future tickets: Tickets a futuro +Search tickets: Buscar tickets +Search future tickets by date: Buscar tickets por fecha +Problems: Problemas +Origin ID: ID origen +Closing: Cierre +Origin State: Estado origen +Destination State: Estado destino +Liters: Litros +Available Lines: Líneas disponibles +Destination ID: ID destino +Destination ETD: ETD Destino +Origin ETD: ETD Origen +Move tickets: Mover tickets +Move confirmation: ¿Desea mover {0} tickets hacia el futuro? diff --git a/modules/ticket/front/future/style.scss b/modules/ticket/front/future/style.scss new file mode 100644 index 000000000..e69de29bb diff --git a/modules/ticket/front/index.js b/modules/ticket/front/index.js index 0558d251d..6106a22eb 100644 --- a/modules/ticket/front/index.js +++ b/modules/ticket/front/index.js @@ -34,3 +34,5 @@ import './dms/create'; import './dms/edit'; import './sms'; import './boxing'; +import './future'; +import './future-search-panel'; diff --git a/modules/ticket/front/routes.json b/modules/ticket/front/routes.json index 4be8e2183..62f43a098 100644 --- a/modules/ticket/front/routes.json +++ b/modules/ticket/front/routes.json @@ -7,7 +7,8 @@ "menus": { "main": [ {"state": "ticket.index", "icon": "icon-ticket"}, - {"state": "ticket.weekly.index", "icon": "schedule"} + {"state": "ticket.weekly.index", "icon": "schedule"}, + {"state": "ticket.future", "icon": "double_arrow"} ], "card": [ {"state": "ticket.card.basicData.stepOne", "icon": "settings"}, @@ -283,6 +284,12 @@ "params": { "ticket": "$ctrl.ticket" } + }, + { + "url": "/future", + "state": "ticket.future", + "component": "vn-ticket-future", + "description": "Future tickets" } ] } From ff000661385eb8c6e496bc4a971f2da7e61c383f Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 8 Nov 2022 15:56:58 +0100 Subject: [PATCH 03/28] refs #4700 tests front y fixtures --- db/dump/fixtures.sql | 10 +- .../sales-monitor/specs/salesFilter.spec.js | 10 +- .../methods/ticket-future/getTicketsFuture.js | 173 +++++++++++------- .../spec/getTicketsFuture.spec.js | 165 +++++++++++++++++ .../moveTicketsFuture.js => ticket/merge.js} | 13 +- .../back/methods/ticket/specs/filter.spec.js | 12 +- .../ticket/specs/priceDifference.spec.js | 2 +- modules/ticket/back/models/ticket-methods.js | 2 + modules/ticket/back/models/ticket.js | 2 - .../front/future-search-panel/index.html | 8 +- .../ticket/front/future-search-panel/index.js | 16 -- .../front/future-search-panel/locale/es.yml | 4 +- modules/ticket/front/future/index.html | 56 +++--- modules/ticket/front/future/index.js | 65 ++++--- modules/ticket/front/future/index.spec.js | 113 ++++++++++++ modules/ticket/front/future/locale/en.yml | 1 + modules/ticket/front/future/locale/es.yml | 3 +- modules/ticket/front/future/style.scss | 0 18 files changed, 486 insertions(+), 169 deletions(-) create mode 100644 modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js rename modules/ticket/back/methods/{ticket-future/moveTicketsFuture.js => ticket/merge.js} (89%) create mode 100644 modules/ticket/front/future/index.spec.js create mode 100644 modules/ticket/front/future/locale/en.yml delete mode 100644 modules/ticket/front/future/style.scss diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5cadaf77c..2cd0c425e 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -686,7 +686,10 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF (24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE()), (25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()), - (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()); + (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()), + (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), + (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), + (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()); INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES @@ -984,7 +987,10 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric (30, 4, 18, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (31, 2, 23, 'Melee weapon combat fist 15cm', -5, 7.08, 0, 0, 0, util.VN_CURDATE()), (32, 1, 24, 'Ranged weapon longbow 2m', -1, 8.07, 0, 0, 0, util.VN_CURDATE()), - (33, 5, 14, 'Ranged weapon pistol 9mm', 50, 1.79, 0, 0, 0, util.VN_CURDATE()); + (33, 5, 14, 'Ranged weapon pistol 9mm', 50, 1.79, 0, 0, 0, util.VN_CURDATE()), + (34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), + (35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), + (36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()); INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) VALUES 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 0682cef09..9fcbf028f 100644 --- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js +++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js @@ -11,7 +11,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {order: 'id DESC'}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(27); + expect(result.length).toEqual(30); await tx.rollback(); } catch (e) { @@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(16); + expect(result.length).toEqual(19); await tx.rollback(); } catch (e) { @@ -87,7 +87,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(27); + expect(result.length).toEqual(30); await tx.rollback(); } catch (e) { @@ -130,7 +130,7 @@ describe('SalesMonitor salesFilter()', () => { const length = result.length; const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; - expect(length).toEqual(10); + expect(length).toEqual(13); expect(anyResult.state).toMatch(/(Libre|Arreglar)/); await tx.rollback(); @@ -171,7 +171,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(23); + expect(result.length).toEqual(26); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js index 5b83e50be..0b21a9202 100644 --- a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js +++ b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js @@ -1,10 +1,11 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const buildFilter = require('vn-loopback/util/filter').buildFilter; const mergeFilters = require('vn-loopback/util/filter').mergeFilters; +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('getTicketsFuture', { - description: 'Find all instances of the model matched by filter from the data source.', + description: 'Find all tickets that can be moved to the future', accessType: 'READ', accepts: [ { @@ -37,6 +38,60 @@ module.exports = Self => { description: 'Warehouse identifier', required: true }, + { + arg: 'shipped', + type: 'date', + description: 'Origin shipped', + required: false + }, + { + arg: 'tfShipped', + type: 'date', + description: 'Destination shipped', + required: false + }, + { + arg: 'ipt', + type: 'string', + description: 'Origin Item Packaging Type', + required: false + }, + { + arg: 'tfIpt', + type: 'string', + description: 'Destination Item Packaging Type', + required: false + }, + { + arg: 'id', + type: 'number', + description: 'Origin id', + required: false + }, + { + arg: 'tfId', + type: 'number', + description: 'Destination id', + required: false + }, + { + arg: 'state', + type: 'string', + description: 'Origin state', + required: false + }, + { + arg: 'tfState', + type: 'string', + description: 'Destination state', + required: false + }, + { + arg: 'problems', + type: 'boolean', + description: `Whether to show only tickets with problems`, + required: false + }, { arg: 'filter', type: 'object', @@ -53,11 +108,11 @@ module.exports = Self => { } }); - Self.getTicketsFuture = async (ctx, options) => { + Self.getTicketsFuture = async (ctx, filter, options) => { const myOptions = {}; if (typeof options == 'object') - Object.assign(myOptions, options); + Object.assign(myOptions, options); const conn = Self.dataSource.connector; const args = ctx.args; const stmts = []; @@ -71,10 +126,10 @@ module.exports = Self => { stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); stmt = new ParameterizedSQL(` - CREATE TEMPORARY TABLE tmp.sale_getProblems + CREATE TEMPORARY TABLE tmp.sale_getProblems (INDEX (ticketFk)) ENGINE = MEMORY - SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped + SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped FROM tmp.filter f LEFT JOIN alertLevel al ON al.id = f.alertLevel WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`); @@ -87,80 +142,64 @@ module.exports = Self => { FROM tmp.filter f LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`); - if (args.problems != undefined && (!args.from && !args.to)) + if (args.problems != undefined && (!args.originDated && !args.futureDated)) throw new UserError('Choose a date range or days forward'); - const myWhere = buildFilter(ctx.args, (param, value) => { + const searchBarWhere = buildFilter(args, (param, value) => { switch (param) { - // case 'search': - // return /^\d+$/.test(value) - // ? {'t.id': {inq: value}} - // : {'t.nickname': {like: `%${value}%`}}; - case 'shipped': - return {'shipped': {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}; + case 'id': + return { 'f.id': value }; + case 'tfId': + return { 'f.ticketFuture': value }; + case 'shipped': + return { 'f.shipped': value }; + case 'tfShipped': + return { 'f.tfShipped': value }; + case 'ipt': + return { 'f.ipt': value }; + case 'tfIpt': + return { 'f.tfIpt': value }; + case 'state': + return { 'f.state': { like: `%${value}%` } }; + case 'tfState': + return { 'f.tfState': { like: `%${value}%` } }; } }); - let finalFilter = {}; - finalFilter = mergeFilters(finalFilter, {where: myWhere}); - if (finalFilter.where) - stmt.merge(conn.makeWhere(finalFilter.where)); + + filter = mergeFilters(args.filter, { where: searchBarWhere }); + stmt.merge(conn.makeSuffix(filter)); let condition; let hasProblem; let range; let hasWhere; switch (args.problems) { - case true: - condition = `or`; - hasProblem = true; - range = {neq: null}; - hasWhere = true; - break; + case true: + condition = `or`; + hasProblem = true; + range = { neq: null }; + hasWhere = true; + break; - case false: - condition = `and`; - hasProblem = null; - range = null; - hasWhere = true; - break; + case false: + condition = `and`; + hasProblem = null; + range = null; + hasWhere = true; + break; } - const problems = {[condition]: [ - {'tp.isFreezed': hasProblem}, - {'tp.risk': hasProblem}, - {'tp.hasTicketRequest': hasProblem}, - {'tp.itemShortage': range} - ]}; + const problems = { + [condition]: [ + { 'tp.isFreezed': hasProblem }, + { 'tp.risk': hasProblem }, + { 'tp.hasTicketRequest': hasProblem }, + { 'tp.itemShortage': range }, + { 'tp.hasComponentLack': hasProblem }, + { 'tp.isTaxDataChecked': !hasProblem }, + { 'tp.isTooLittle': hasProblem } + ] + }; if (hasWhere) stmt.merge(conn.makeWhere(problems)); @@ -168,7 +207,7 @@ module.exports = Self => { const ticketsIndex = stmts.push(stmt) - 1; stmts.push( - `DROP TEMPORARY TABLE + `DROP TEMPORARY TABLE tmp.filter, tmp.ticket_problems`); @@ -176,4 +215,4 @@ module.exports = Self => { const result = await conn.executeStmt(sql, myOptions); return result[ticketsIndex]; }; -}; \ No newline at end of file +}; diff --git a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js new file mode 100644 index 000000000..0bab7a98a --- /dev/null +++ b/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js @@ -0,0 +1,165 @@ +const models = require('vn-loopback/server/server').models; + +fdescribe('TicketFuture getTicketsFuture()', () => { + const today = new Date(); + today.setHours(0, 0, 0, 0); + + it('should return the tickets passing the required data', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the problems on true', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + problems: true + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the problems on false', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + problems: false + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the problems on null', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + problems: null + }; + + const ctx = {req: {accessToken: {userId: 9}}, args}; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the correct origin shipped', async() => { + let tomorrow = new Date(today.getDate() + 1); + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + shipped: today + }; + + const ctx = {req: {accessToken: {userId: 9}}, args}; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + // try { + // const options = {transaction: tx}; + + // const args = { + // originDated: today, + // futureDated: today, + // litersMax: 9999, + // linesMax: 9999, + // warehouseFk: 1, + // shipped: tomorrow + // }; + + // const ctx = {req: {accessToken: {userId: 9}}, args}; + // const result = await models.Ticket.getTicketsFuture(ctx, options); + + // expect(result.length).toEqual(0); + + // await tx.rollback(); + // } catch (e) { + // await tx.rollback(); + // throw e; + // } + }); + + +}); diff --git a/modules/ticket/back/methods/ticket-future/moveTicketsFuture.js b/modules/ticket/back/methods/ticket/merge.js similarity index 89% rename from modules/ticket/back/methods/ticket-future/moveTicketsFuture.js rename to modules/ticket/back/methods/ticket/merge.js index 940a83c33..da1a150c8 100644 --- a/modules/ticket/back/methods/ticket-future/moveTicketsFuture.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -1,8 +1,8 @@ const LoopBackContext = require('loopback-context'); module.exports = Self => { - Self.remoteMethodCtx('moveTicketsFuture', { - description: 'Move specified tickets to the future', + Self.remoteMethodCtx('merge', { + description: 'Merge one ticket into another', accessType: 'WRITE', accepts: [ { @@ -17,12 +17,12 @@ module.exports = Self => { root: true }, http: { - path: `/moveTicketsFuture`, + path: `/merge`, verb: 'POST' } }); - Self.moveTicketsFuture = async (ctx, tickets, options) => { + Self.merge = async (ctx, tickets, options) => { const loopBackContext = LoopBackContext.getCurrentContext(); const httpCtx = {req: loopBackContext.active}; const models = Self.app.models; @@ -36,9 +36,8 @@ module.exports = Self => { tx = await Self.beginTransaction({}); myOptions.transaction = tx; } - + for (let ticket of tickets) { - console.log(ticket); try { if(!ticket.id || !ticket.ticketFuture) continue; await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions); @@ -65,4 +64,4 @@ module.exports = Self => { } }; }; -}; \ No newline at end of file +}; diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index c3dc40092..e2ab43aea 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -11,7 +11,7 @@ describe('ticket filter()', () => { const filter = {order: 'id DESC'}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(27); + expect(result.length).toEqual(30); await tx.rollback(); } catch (e) { @@ -87,7 +87,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(27); + expect(result.length).toEqual(30); await tx.rollback(); } catch (e) { @@ -130,7 +130,7 @@ describe('ticket filter()', () => { const length = result.length; const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; - expect(length).toEqual(10); + expect(length).toEqual(13); expect(anyResult.state).toMatch(/(Libre|Arreglar)/); await tx.rollback(); @@ -175,7 +175,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(23); + expect(result.length).toEqual(26); await tx.rollback(); } catch (e) { @@ -232,7 +232,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(22); + expect(result.length).toEqual(25); await tx.rollback(); } catch (e) { @@ -270,7 +270,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(27); + expect(result.length).toEqual(30); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js index d8c785baa..96d29c46f 100644 --- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js +++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js @@ -87,7 +87,7 @@ describe('sale priceDifference()', () => { const secondtItem = result.items[1]; expect(firstItem.movable).toEqual(410); - expect(secondtItem.movable).toEqual(1870); + expect(secondtItem.movable).toEqual(1810); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js index 9255e52e6..92036d77f 100644 --- a/modules/ticket/back/models/ticket-methods.js +++ b/modules/ticket/back/models/ticket-methods.js @@ -33,4 +33,6 @@ module.exports = function(Self) { require('../methods/ticket/closeByTicket')(Self); require('../methods/ticket/closeByAgency')(Self); require('../methods/ticket/closeByRoute')(Self); + require('../methods/ticket-future/getTicketsFuture')(Self); + require('../methods/ticket/merge')(Self); }; diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index 649a83160..c05130552 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -4,8 +4,6 @@ const LoopBackContext = require('loopback-context'); module.exports = Self => { // Methods require('./ticket-methods')(Self); - require('../methods/ticket-future/getTicketsFuture')(Self); - require('../methods/ticket-future/moveTicketsFuture')(Self); Self.observe('before save', async function(ctx) { const loopBackContext = LoopBackContext.getCurrentContext(); diff --git a/modules/ticket/front/future-search-panel/index.html b/modules/ticket/front/future-search-panel/index.html index 4f5486d62..d69b1ba9e 100644 --- a/modules/ticket/front/future-search-panel/index.html +++ b/modules/ticket/front/future-search-panel/index.html @@ -44,13 +44,13 @@ + label="Origin IPT" + ng-model="filter.ipt"> + label="Destination IPT" + ng-model="filter.tfIpt"> diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js index bbc2148e7..c747af62c 100644 --- a/modules/ticket/front/future-search-panel/index.js +++ b/modules/ticket/front/future-search-panel/index.js @@ -6,22 +6,6 @@ class Controller extends SearchPanel { super($, $element); this.filter = this.$.filter; } - - get from() { - return this._from; - } - - set from(value) { - this._from = value; - } - - get to() { - return this._to; - } - - set to(value) { - this._to = value; - } } ngModule.vnComponent('vnFutureTicketSearchPanel', { diff --git a/modules/ticket/front/future-search-panel/locale/es.yml b/modules/ticket/front/future-search-panel/locale/es.yml index e459c3cd9..413f9e5f9 100644 --- a/modules/ticket/front/future-search-panel/locale/es.yml +++ b/modules/ticket/front/future-search-panel/locale/es.yml @@ -5,8 +5,8 @@ Origin ETD: ETD origen Destination ETD: ETD destino Max Lines Origin: Líneas máx. origen Max Liters Origin: Litros máx. origen -Origin ITP: ITP origen -Destination ITP: ITP destino +Origin IPT: IPT origen +Destination IPT: IPT destino With problems: Con problemas Warehouse: Almacén Origin Agrupated State: Estado agrupado origen diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 9dbb5a4ca..021fc1390 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -12,13 +12,13 @@ info="Search future tickets by date" auto-state="false" model="model" - filter="$ctrl.defaultFilter"> + filter="::$ctrl.filter"> - Origin ID - + Origin ETD @@ -62,7 +62,7 @@ Destination ID - + Destination ETD @@ -76,7 +76,7 @@ - @@ -119,33 +119,43 @@ icon="icon-components"> - {{::ticket.id}} - {{::ticket.originETD | date: 'dd/MM/yyyy'}} + + {{::ticket.originETD | date: 'dd/MM/yyyy'}} + - + - {{::ticket.state}} - + {{::ticket.state}} + + {{::ticket.ipt}} {{::ticket.liters}} {{::ticket.lines}} - + - {{::ticket.ticketFuture}} - - - {{::ticket.destETD | date: 'dd/MM/yyyy'}} + {{::ticket.ticketFuture}} + - + + {{::ticket.destETD | date: 'dd/MM/yyyy'}} + + + + - {{::ticket.tfState}} - + {{::ticket.tfState}} + + {{::ticket.tfIpt}} @@ -156,9 +166,9 @@ - - \ No newline at end of file + diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index 6dda5812d..479d4b000 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -25,40 +25,20 @@ export default class Controller extends Section { search: true }, columns: [{ - field:'problems', + field: 'problems', searchable: false }, { - field:'ETD', + field: 'originETD', searchable: false }, { - field:'tfETD', + field: 'destETD', searchable: false }] }; } - get checked() { - const tickets = this.$.model.data || []; - const checkedLines = []; - for (let ticket of tickets) { - if (ticket.checked) - checkedLines.push(ticket); - } - - return checkedLines; - } - - moveTicketsFuture() - { - let params = { - tickets: this.checked - }; - this.$http.post('Tickets/moveTicketsFuture', params); - this.reload(); - } - compareDate(date) { let today = new Date(); today.setHours(0, 0, 0, 0); @@ -73,20 +53,24 @@ export default class Controller extends Section { return 'success'; } + get checked() { + const tickets = this.$.model.data || []; + const checkedLines = []; + for (let ticket of tickets) { + if (ticket.checked) + checkedLines.push(ticket); + } + + return checkedLines; + } + stateColor(state) { if (state === 'OK') return 'success'; else if (state === 'FREE') return 'notice'; } - - exprBuilder(param, value) { - switch (param) { - case 'shipped': - return {'shipped': {like: `%${value}%`}}; - } - } - + dateRange(value) { const minHour = new Date(value); minHour.setHours(0, 0, 0, 0); @@ -96,11 +80,26 @@ export default class Controller extends Section { return [minHour, maxHour]; } - reload() { - this.$.model.refresh(); + get confirmationMessage() { + if (!this.$.model) return 0; + + return this.$t(`Move confirmation`, { + checked: this.checked.length + }); + } + + moveTicketsFuture() { + let params = { tickets: this.checked }; + return this.$http.post('Tickets/merge', params) + .then(() => { + this.$.model.refresh(); + this.vnApp.showSuccess(this.$t('Success')); + }); } } +Controller.$inject = ['$element', '$scope']; + ngModule.vnComponent('vnTicketFuture', { template: require('./index.html'), controller: Controller diff --git a/modules/ticket/front/future/index.spec.js b/modules/ticket/front/future/index.spec.js new file mode 100644 index 000000000..003b277ee --- /dev/null +++ b/modules/ticket/front/future/index.spec.js @@ -0,0 +1,113 @@ +import './index.js'; +import crudModel from 'core/mocks/crud-model'; + +describe('Component vnTicketFuture', () => { + let controller; + let $httpBackend; + let $window; + + beforeEach(ngModule('ticket') + ); + + beforeEach(inject(($componentController, _$window_, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $window = _$window_; + const $element = angular.element(''); + controller = $componentController('vnTicketFuture', { $element }); + controller.$.model = crudModel; + controller.$.model.data = [{ + id: 1, + checked: true, + state: "OK" + }, { + id: 2, + checked: true, + state: "FREE" + }]; + })); + + describe('compareDate()', () => { + it('should return warning when the date is the present', () => { + let today = new Date(); + let result = controller.compareDate(today); + + expect(result).toEqual('warning'); + }); + + it('should return sucess when the date is in the future', () => { + let futureDate = new Date(); + futureDate = futureDate.setDate(futureDate.getDate() + 10); + let result = controller.compareDate(futureDate); + + expect(result).toEqual('success'); + }); + + it('should return undefined when the date is in the past', () => { + let pastDate = new Date(); + pastDate = pastDate.setDate(pastDate.getDate() - 10); + let result = controller.compareDate(pastDate); + + expect(result).toEqual(undefined); + }); + }); + + describe('checked()', () => { + it('should return an array of checked tickets', () => { + const result = controller.checked; + const firstRow = result[0]; + const secondRow = result[1]; + + expect(result.length).toEqual(2); + expect(firstRow.id).toEqual(1); + expect(secondRow.id).toEqual(2); + }); + }); + + describe('stateColor()', () => { + it('should return success to the OK tickets', () => { + const ok = controller.stateColor(controller.$.model.data[0].state); + const notOk = controller.stateColor(controller.$.model.data[1].state); + expect(ok).toEqual('success'); + expect(notOk).not.toEqual('success'); + }); + + it('should return success to the FREE tickets', () => { + const notFree = controller.stateColor(controller.$.model.data[0].state); + const free = controller.stateColor(controller.$.model.data[1].state); + expect(free).toEqual('notice'); + expect(notFree).not.toEqual('notice'); + }); + }); + + describe('dateRange()', () => { + it('should return two dates with the hours at the start and end of the given date', () => { + const now = new Date(); + + const today = now.getDate(); + + const dateRange = controller.dateRange(now); + const start = dateRange[0].toString(); + const end = dateRange[1].toString(); + + expect(start).toContain(today); + expect(start).toContain('00:00:00'); + + expect(end).toContain(today); + expect(end).toContain('23:59:59'); + }); + }); + + describe('moveTicketsFuture()', () => { + it('should make an HTTP Post query', () => { + jest.spyOn(controller.$.model, 'refresh'); + jest.spyOn(controller.vnApp, 'showSuccess'); + + $httpBackend.expectPOST(`Tickets/merge`).respond(); + controller.moveTicketsFuture(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.$.model.refresh).toHaveBeenCalledWith(); + }); + }); +}); diff --git a/modules/ticket/front/future/locale/en.yml b/modules/ticket/front/future/locale/en.yml new file mode 100644 index 000000000..7b0a377b8 --- /dev/null +++ b/modules/ticket/front/future/locale/en.yml @@ -0,0 +1 @@ +Move confirmation: Do you want to move {{checked}} tickets to the future? diff --git a/modules/ticket/front/future/locale/es.yml b/modules/ticket/front/future/locale/es.yml index 946611e66..937f206e9 100644 --- a/modules/ticket/front/future/locale/es.yml +++ b/modules/ticket/front/future/locale/es.yml @@ -12,4 +12,5 @@ Destination ID: ID destino Destination ETD: ETD Destino Origin ETD: ETD Origen Move tickets: Mover tickets -Move confirmation: ¿Desea mover {0} tickets hacia el futuro? +Move confirmation: ¿Desea mover {{checked}} tickets hacia el futuro? +Success: Tickets movidos correctamente diff --git a/modules/ticket/front/future/style.scss b/modules/ticket/front/future/style.scss deleted file mode 100644 index e69de29bb..000000000 From 1327f0ae9ddb550c8b0536f4f34eb4375851feac Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 10 Nov 2022 08:18:05 +0100 Subject: [PATCH 04/28] Added requested changes, refs #4507 @1:20h --- .../10502-november/00-greuge.userFK_userFk.sql | 1 + modules/client/back/models/greuge.json | 16 ++++++++-------- modules/client/front/greuge/index/index.html | 2 +- modules/client/front/greuge/index/index.js | 6 ++++++ 4 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 db/changes/10502-november/00-greuge.userFK_userFk.sql diff --git a/db/changes/10502-november/00-greuge.userFK_userFk.sql b/db/changes/10502-november/00-greuge.userFK_userFk.sql new file mode 100644 index 000000000..2a5323fa3 --- /dev/null +++ b/db/changes/10502-november/00-greuge.userFK_userFk.sql @@ -0,0 +1 @@ +ALTER TABLE vn.greuge CHANGE userFK userFk int(10) unsigned DEFAULT NULL NULL; \ No newline at end of file diff --git a/modules/client/back/models/greuge.json b/modules/client/back/models/greuge.json index e8790715a..a694c7552 100644 --- a/modules/client/back/models/greuge.json +++ b/modules/client/back/models/greuge.json @@ -2,9 +2,9 @@ "name": "Greuge", "base": "Loggable", "log": { - "model": "ClientLog", - "relation": "client", - "showField": "description" + "model": "ClientLog", + "relation": "client", + "showField": "description" }, "options": { "mysql": { @@ -34,12 +34,7 @@ "greugeTypeFk": { "type": "number", "required": true - }, - "userFk": { - "type": "number", - "required": true } - }, "relations": { "client": { @@ -56,6 +51,11 @@ "type": "belongsTo", "model": "GreugeType", "foreignKey": "greugeTypeFk" + }, + "user": { + "type": "belongsTo", + "model": "Account", + "foreignKey": "userFK" } } } \ No newline at end of file diff --git a/modules/client/front/greuge/index/index.html b/modules/client/front/greuge/index/index.html index cdc9c37d4..44074ed1a 100644 --- a/modules/client/front/greuge/index/index.html +++ b/modules/client/front/greuge/index/index.html @@ -38,7 +38,7 @@ {{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }} - {{::greuge.userFk}} + {{::greuge.user.name}} {{::greuge.description}} diff --git a/modules/client/front/greuge/index/index.js b/modules/client/front/greuge/index/index.js index 2451167a4..7a5ccc531 100644 --- a/modules/client/front/greuge/index/index.js +++ b/modules/client/front/greuge/index/index.js @@ -8,6 +8,12 @@ class Controller extends Section { include: [ { relation: 'greugeType', + scope: { + fields: ['id', 'name'] + }, + }, + { + relation: 'user', scope: { fields: ['id', 'name'] } From c53e309071cadb12f1deca6fa7700248ba8d6afa Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 10 Nov 2022 08:19:54 +0100 Subject: [PATCH 05/28] Fix typo --- modules/client/back/models/greuge.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/client/back/models/greuge.json b/modules/client/back/models/greuge.json index a694c7552..625bf4e28 100644 --- a/modules/client/back/models/greuge.json +++ b/modules/client/back/models/greuge.json @@ -55,7 +55,7 @@ "user": { "type": "belongsTo", "model": "Account", - "foreignKey": "userFK" + "foreignKey": "userFk" } } } \ No newline at end of file From 8dd6012b1f8e50cc98ae398e96d127fced675e86 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 10 Nov 2022 08:27:47 +0100 Subject: [PATCH 06/28] Added worker descriptor popover --- modules/client/front/greuge/index/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/client/front/greuge/index/index.html b/modules/client/front/greuge/index/index.html index 44074ed1a..80e41e915 100644 --- a/modules/client/front/greuge/index/index.html +++ b/modules/client/front/greuge/index/index.html @@ -38,7 +38,8 @@ {{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }} - {{::greuge.user.name}} + {{::greuge.user.name}} {{::greuge.description}} @@ -59,3 +60,4 @@ vn-bind="+" fixed-bottom-right> + \ No newline at end of file From 8b06243041112365aa58f2f17470af11068c9357 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 10 Nov 2022 08:36:26 +0100 Subject: [PATCH 07/28] Fix link being the whole column --- modules/client/front/greuge/index/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/client/front/greuge/index/index.html b/modules/client/front/greuge/index/index.html index 80e41e915..459d92fc7 100644 --- a/modules/client/front/greuge/index/index.html +++ b/modules/client/front/greuge/index/index.html @@ -38,8 +38,8 @@ {{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }} - {{::greuge.user.name}} + {{::greuge.user.name}} {{::greuge.description}} From 117e2c03f517041e992087de85b4385488a3b271 Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 10 Nov 2022 15:54:00 +0100 Subject: [PATCH 08/28] refs #4700 tests back y empezando e2e --- .../10501-november/00-ticket_canMerge.sql | 2 +- .../00-ticket_canbePostposed.sql | 25 +- e2e/helpers/selectors.js | 21 ++ e2e/paths/05-ticket/20_future.spec.js | 126 +++++++ .../methods/ticket-future/getTicketsFuture.js | 84 ++--- .../spec/getTicketsFuture.spec.js | 335 ++++++++++++++++-- modules/ticket/back/methods/ticket/merge.js | 28 +- .../back/methods/ticket/specs/merge.spec.js | 58 +++ .../front/future-search-panel/index.html | 69 ++-- .../ticket/front/future-search-panel/index.js | 30 ++ .../front/future-search-panel/locale/en.yml | 10 +- .../front/future-search-panel/locale/es.yml | 18 +- modules/ticket/front/future/index.html | 9 +- modules/ticket/front/future/index.js | 62 +++- modules/ticket/front/future/locale/en.yml | 4 + modules/ticket/front/future/locale/es.yml | 6 + 16 files changed, 739 insertions(+), 148 deletions(-) create mode 100644 e2e/paths/05-ticket/20_future.spec.js create mode 100644 modules/ticket/back/methods/ticket/specs/merge.spec.js diff --git a/db/changes/10501-november/00-ticket_canMerge.sql b/db/changes/10501-november/00-ticket_canMerge.sql index 6db3637ac..7e01f2fab 100644 --- a/db/changes/10501-november/00-ticket_canMerge.sql +++ b/db/changes/10501-november/00-ticket_canMerge.sql @@ -4,6 +4,6 @@ DELIMITER $$ $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canMerge`(vDated DATE, vScopeDays INT, vLitersMax INT, vLinesMax INT, vWarehouseFk INT) BEGIN - CALL vn.ticket_canbePostponed(vDated,TIMESTAMPADD(DAY, vScopeDays, vDated),vLitersMax,vLinesMax,vWarehouseFk); + CALL vn.ticket_canbePostponed(vDated,TIMESTAMPADD(DAY, vScopeDays, vDated),vLitersMax,vLinesMax,vWarehouseFk); END $$ DELIMITER ; diff --git a/db/changes/10501-november/00-ticket_canbePostposed.sql b/db/changes/10501-november/00-ticket_canbePostposed.sql index 6ad9df154..113b09324 100644 --- a/db/changes/10501-november/00-ticket_canbePostposed.sql +++ b/db/changes/10501-november/00-ticket_canbePostposed.sql @@ -3,7 +3,7 @@ DROP PROCEDURE IF EXISTS vn.ticket_canbePostponed; DELIMITER $$ $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vLitersMax INT, vLinesMax INT, vWarehouseFk INT) -BEGIN +BEGIN /** * Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro * @@ -13,25 +13,27 @@ BEGIN * @param vLinesMax Número máximo de lineas de los tickets a catapultar * @param vWarehouseFk Identificador de vn.warehouse */ - DROP TEMPORARY TABLE IF EXISTS tmp.filter; - CREATE TEMPORARY TABLE tmp.filter + DROP TEMPORARY TABLE IF EXISTS tmp.filter; + CREATE TEMPORARY TABLE tmp.filter (INDEX (id)) SELECT sv.ticketFk id, GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt, CAST(sum(litros) AS DECIMAL(10,0)) liters, - CAST(count(*) AS DECIMAL(10,0)) `lines`, - st.name state, - sub2.id ticketFuture, + CAST(count(*) AS DECIMAL(10,0)) `lines`, + st.name state, + sub2.id ticketFuture, t.landed originETD, sub2.landed destETD, sub2.iptd tfIpt, sub2.state tfState, t.clientFk, - t.warehouseFk, - ts.alertLevel, + t.warehouseFk, + ts.alertLevel, t.shipped, sub2.shipped tfShipped, - t.workerFk + t.workerFk, + st.code code, + sub2.code tfCode FROM vn.saleVolume sv JOIN vn.sale s ON s.id = sv.saleFk JOIN vn.item i ON i.id = s.itemFk @@ -39,7 +41,7 @@ BEGIN JOIN vn.address a ON a.id = t.addressFk JOIN vn.province p ON p.id = a.provinceFk JOIN vn.country c ON c.id = p.countryFk - JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.ticketState ts ON ts.ticketFk = t.id JOIN vn.state st ON st.id = ts.stateFk JOIN vn.alertLevel al ON al.id = ts.alertLevel LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id @@ -52,6 +54,7 @@ BEGIN t.landed, t.shipped, st.name state, + st.code code, GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd FROM vn.ticket t JOIN vn.ticketState ts ON ts.ticketFk = t.id @@ -67,7 +70,7 @@ BEGIN ) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated) AND t.warehouseFk = vWarehouseFk - AND al.code = 'FREE' + AND al.code = 'FREE' AND tp.ticketFk IS NULL GROUP BY sv.ticketFk HAVING liters <= IFNULL(vLitersMax, 9999) AND `lines` <= IFNULL(vLinesMax, 9999) AND ticketFuture; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index cd6d39795..749e243d0 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -712,6 +712,27 @@ export default { saveImport: 'button[response="accept"]', anyDocument: 'vn-ticket-dms-index > vn-data-viewer vn-tbody vn-tr' }, + ticketFuture: { + openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]', + originDated: 'vn-date-picker[label="Origin ETD"]', + futureDated: 'vn-date-picker[label="Destination ETD"]', + shipped: 'vn-date-picker[label="Origin date"]', + tfShipped: 'vn-date-picker[label="Destination date"]', + linesMax: 'vn-textfield[label="Max Lines"]', + litersMax: 'vn-textfield[label="Max Liters"]', + ipt: 'vn-autocomplete[label="Origin IPT"]', + tfIpt: 'vn-autocomplete[label="Destination IPT"]', + state: 'vn-autocomplete[label="Origin Grouped State"]', + tfState: 'vn-autocomplete[label="Destination Grouped State"]', + warehouseFk: 'vn-autocomplete[label="Warehouse"]', + problems: 'vn-check[label="With problems"]', + tableButtonSearch: 'vn-button[vn-tooltip="Search"]', + moveButton: 'vn-button[vn-tooltip="Future tickets"]', + tableId: 'vn-textfield[ng-model="searchProps[\'id\']"]', + tableTfId: 'vn-textfield[ng-model="searchProps[\'ticketFuture\']"]', + submit: 'vn-submit[label="Search"]', + table: 'tbody > tr:not(.empty-rows, #searchRow)', + }, createStateView: { state: 'vn-autocomplete[ng-model="$ctrl.stateFk"]', worker: 'vn-autocomplete[ng-model="$ctrl.workerFk"]', diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/20_future.spec.js new file mode 100644 index 000000000..c9c4559a7 --- /dev/null +++ b/e2e/paths/05-ticket/20_future.spec.js @@ -0,0 +1,126 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Future path', () => { + let browser; + let page; + + beforeAll(async () => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSection('ticket.future'); + }); + + afterAll(async () => { + await browser.close(); + }); + + const now = new Date(); + const tomorrow = new Date(now.getDate() + 1); + it('should search with the required data', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.originDated, now); + await page.pickDate(selectors.ticketFuture.futureDated, now); + await page.waitToClick(selectors.ticketFuture.linesMax); + await page.write(selectors.ticketFuture.linesMax, '9999'); + await page.write(selectors.ticketFuture.litersMax, '9999'); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, 'Warehouse One'); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search with the origin shipped today', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.shipped, now); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search with the origin shipped tomorrow', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.shipped, tomorrow); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with the destination shipped today', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.shipped); + await page.pickDate(selectors.ticketFuture.tfShipped, now); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search with the destination shipped tomorrow', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.tfShipped, tomorrow); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with the origin IPT', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.tfShipped); + await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with the destination IPT', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.ipt); + await page.autocompleteSearch(selectors.ticketFuture.tfIpt, 'Horizontal'); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with the origin grouped state', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.tfIpt); + await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 3); + }); + + it('should search with the destination grouped state', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.state); + await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with problems selected', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.tfState); + await page.waitToClick(selectors.ticketFuture.problems); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search with no problems selected', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.problems); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + }); + + it('should search with an ID Origin', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.problems); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.write(selectors.ticketFuture.tableId, "13"); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + }); + it('should search with an ID Destination', async () => { + await page.clearInput(selectors.ticketFuture.tableId); + await page.write(selectors.ticketFuture.tableTfId, "12"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + }); + + + // const message = await page.waitForSnackbar(); +}); diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js index 0b21a9202..132df064f 100644 --- a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js +++ b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js @@ -108,44 +108,15 @@ module.exports = Self => { } }); - Self.getTicketsFuture = async (ctx, filter, options) => { + Self.getTicketsFuture = async (ctx, options) => { + const args = ctx.args; + const conn = Self.dataSource.connector; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const conn = Self.dataSource.connector; - const args = ctx.args; - const stmts = []; - let stmt; - stmt = new ParameterizedSQL( - `CALL vn.ticket_canbePostponed(?,?,?,?,?)`, - [args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]); - - stmts.push(stmt); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); - - stmt = new ParameterizedSQL(` - CREATE TEMPORARY TABLE tmp.sale_getProblems - (INDEX (ticketFk)) - ENGINE = MEMORY - SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped - FROM tmp.filter f - LEFT JOIN alertLevel al ON al.id = f.alertLevel - WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`); - stmts.push(stmt); - - 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`); - - if (args.problems != undefined && (!args.originDated && !args.futureDated)) - throw new UserError('Choose a date range or days forward'); - - const searchBarWhere = buildFilter(args, (param, value) => { + const where = buildFilter(ctx.args, (param, value) => { switch (param) { case 'id': return { 'f.id': value }; @@ -160,14 +131,43 @@ module.exports = Self => { case 'tfIpt': return { 'f.tfIpt': value }; case 'state': - return { 'f.state': { like: `%${value}%` } }; + return { 'f.code': { like: `%${value}%` } }; case 'tfState': - return { 'f.tfState': { like: `%${value}%` } }; + return { 'f.tfCode': { like: `%${value}%` } }; } }); - filter = mergeFilters(args.filter, { where: searchBarWhere }); - stmt.merge(conn.makeSuffix(filter)); + let filter = mergeFilters(ctx.args.filter, { where }); + const stmts = []; + let stmt; + + stmt = new ParameterizedSQL( + `CALL vn.ticket_canbePostponed(?,?,?,?,?)`, + [args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]); + + stmts.push(stmt); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); + + stmt = new ParameterizedSQL(` + CREATE TEMPORARY TABLE tmp.sale_getProblems + (INDEX (ticketFk)) + ENGINE = MEMORY + SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped + FROM tmp.filter f + LEFT JOIN alertLevel al ON al.id = f.alertLevel + WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`); + stmts.push(stmt); + + 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`); + + if (args.problems != undefined && (!args.originDated && !args.futureDated)) + throw new UserError('Choose a date range or days forward'); let condition; let hasProblem; @@ -196,13 +196,15 @@ module.exports = Self => { { 'tp.hasTicketRequest': hasProblem }, { 'tp.itemShortage': range }, { 'tp.hasComponentLack': hasProblem }, - { 'tp.isTaxDataChecked': !hasProblem }, { 'tp.isTooLittle': hasProblem } ] }; - if (hasWhere) - stmt.merge(conn.makeWhere(problems)); + if (hasWhere) { + filter = mergeFilters(filter, { where: problems }); + } + stmt.merge(conn.makeWhere(filter.where)); + const ticketsIndex = stmts.push(stmt) - 1; @@ -212,7 +214,9 @@ module.exports = Self => { tmp.ticket_problems`); const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + return result[ticketsIndex]; }; }; diff --git a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js index 0bab7a98a..502ea3074 100644 --- a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js +++ b/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js @@ -1,8 +1,9 @@ const models = require('vn-loopback/server/server').models; -fdescribe('TicketFuture getTicketsFuture()', () => { +describe('TicketFuture getTicketsFuture()', () => { const today = new Date(); today.setHours(0, 0, 0, 0); + const tomorrow = new Date(today.getDate() + 1); it('should return the tickets passing the required data', async () => { const tx = await models.Ticket.beginTransaction({}); @@ -83,11 +84,11 @@ fdescribe('TicketFuture getTicketsFuture()', () => { } }); - it('should return the tickets matching the problems on null', async() => { + it('should return the tickets matching the problems on null', async () => { const tx = await models.Ticket.beginTransaction({}); try { - const options = {transaction: tx}; + const options = { transaction: tx }; const args = { originDated: today, @@ -98,7 +99,7 @@ fdescribe('TicketFuture getTicketsFuture()', () => { problems: null }; - const ctx = {req: {accessToken: {userId: 9}}, args}; + const ctx = { req: { accessToken: { userId: 9 } }, args }; const result = await models.Ticket.getTicketsFuture(ctx, options); expect(result.length).toEqual(4); @@ -110,12 +111,11 @@ fdescribe('TicketFuture getTicketsFuture()', () => { } }); - it('should return the tickets matching the correct origin shipped', async() => { - let tomorrow = new Date(today.getDate() + 1); + it('should return the tickets matching the correct origin shipped', async () => { const tx = await models.Ticket.beginTransaction({}); try { - const options = {transaction: tx}; + const options = { transaction: tx }; const args = { originDated: today, @@ -126,7 +126,7 @@ fdescribe('TicketFuture getTicketsFuture()', () => { shipped: today }; - const ctx = {req: {accessToken: {userId: 9}}, args}; + const ctx = { req: { accessToken: { userId: 9 } }, args }; const result = await models.Ticket.getTicketsFuture(ctx, options); expect(result.length).toEqual(4); @@ -136,30 +136,303 @@ fdescribe('TicketFuture getTicketsFuture()', () => { await tx.rollback(); throw e; } - - // try { - // const options = {transaction: tx}; - - // const args = { - // originDated: today, - // futureDated: today, - // litersMax: 9999, - // linesMax: 9999, - // warehouseFk: 1, - // shipped: tomorrow - // }; - - // const ctx = {req: {accessToken: {userId: 9}}, args}; - // const result = await models.Ticket.getTicketsFuture(ctx, options); - - // expect(result.length).toEqual(0); - - // await tx.rollback(); - // } catch (e) { - // await tx.rollback(); - // throw e; - // } }); + it('should return the tickets matching the an incorrect origin shipped', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + shipped: tomorrow + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the correct destination shipped', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfShipped: today + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the an incorrect destination shipped', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfShipped: tomorrow + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the OK State in origin date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + state: "OK" + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(1); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the OK State in destination date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfState: "OK" + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the correct IPT in origin date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + ipt: null + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the incorrect IPT in origin date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + ipt: 0 + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the correct IPT in destination date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfIpt: null + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the incorrect IPT in destination date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfIpt: 0 + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the ID in origin date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + id: 13 + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(1); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets matching the ID in destination date', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const args = { + originDated: today, + futureDated: today, + litersMax: 9999, + linesMax: 9999, + warehouseFk: 1, + tfId: 12 + }; + + const ctx = { req: { accessToken: { userId: 9 } }, args }; + const result = await models.Ticket.getTicketsFuture(ctx, options); + + expect(result.length).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index da1a150c8..356259a26 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -1,5 +1,3 @@ -const LoopBackContext = require('loopback-context'); - module.exports = Self => { Self.remoteMethodCtx('merge', { description: 'Merge one ticket into another', @@ -23,8 +21,9 @@ module.exports = Self => { }); Self.merge = async (ctx, tickets, options) => { - const loopBackContext = LoopBackContext.getCurrentContext(); - const httpCtx = {req: loopBackContext.active}; + const httpRequest = ctx.req; + const $t = httpRequest.__; + const origin = httpRequest.headers.origin; const models = Self.app.models; const myOptions = {}; let tx; @@ -39,24 +38,21 @@ module.exports = Self => { for (let ticket of tickets) { try { + const fullPath = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; + const message = $t('MOVE_TICKET_CONFIRMATION', { + originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), + futureDated: new Date(ticket.destETD).toLocaleDateString('es-ES'), + id: ticket.id, + tfId: ticket.ticketFuture, + fullPath + }); if(!ticket.id || !ticket.ticketFuture) continue; await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions); await models.Ticket.setDeleted(ctx, ticket.id, myOptions); + await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); if (tx) { - const httpRequest = httpCtx.req.http.req; - const $t = httpRequest.__; - const origin = httpRequest.headers.origin; - const fullPath = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; - const message = $t('MOVE_TICKET_CONFIRMATION', { - originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), - futureDated: new Date(ticket.destETD).toLocaleDateString('es-ES'), - id: ticket.id, - tfId: ticket.ticketFuture, - fullPath - }); await tx.commit(); - await models.Chat.sendCheckingPresence(httpCtx, ticket.workerFk, message); } } catch (e) { if (tx) await tx.rollback(); diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js new file mode 100644 index 000000000..713f86ad6 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js @@ -0,0 +1,58 @@ +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); + +describe('ticket merge()', () => { + const tickets = [{ + id: 13, + ticketFuture: 12, + workerFk: 1, + originETD: new Date(), + destETD: new Date() + }]; + + const activeCtx = { + accessToken: { userId: 9 }, + }; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + const ctx = { + req: { + accessToken: { userId: 9 }, + headers: { origin: 'http://localhost:5000' }, + } + }; + ctx.req.__ = value => { + return value; + }; + + it('should merge two tickets', async () => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = { transaction: tx }; + const chatNotificationBeforeMerge = await models.Chat.find(); + + await models.Ticket.merge(ctx, tickets, options); + + const createdTicketLog = await models.TicketLog.find({ where: { originFk: tickets[0].id } }, options); + const deletedTicket = await models.Ticket.findOne({ where: { id: tickets[0].id } }, options); + const salesTicketFuture = await models.Sale.find({ where: { ticketFk: tickets[0].ticketFuture } }, options); + const chatNotificationAfterMerge = await models.Chat.find(); + + expect(createdTicketLog.length).toEqual(1); + expect(deletedTicket.isDeleted).toEqual(true); + expect(salesTicketFuture.length).toEqual(2); + expect(chatNotificationBeforeMerge.length).toEqual(chatNotificationAfterMerge.length - 2); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/ticket/front/future-search-panel/index.html b/modules/ticket/front/future-search-panel/index.html index d69b1ba9e..1b3ae453e 100644 --- a/modules/ticket/front/future-search-panel/index.html +++ b/modules/ticket/front/future-search-panel/index.html @@ -18,52 +18,76 @@ vn-one label="Origin ETD" ng-model="filter.originDated" - required="true"> + required="true" + info="ETD"> + required="true" + info="ETD"> - - - + + {{name}} + + + - + value-field="code" + show-field="name" + ng-model="filter.tfIpt" + info="IPT"> + + {{name}} + + - - - + {{name}} + + + - + + {{name}} + + - - + diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js index c747af62c..1a1f0e4c5 100644 --- a/modules/ticket/front/future-search-panel/index.js +++ b/modules/ticket/front/future-search-panel/index.js @@ -5,6 +5,36 @@ class Controller extends SearchPanel { constructor($, $element) { super($, $element); this.filter = this.$.filter; + this.getGroupedStates(); + this.getItemPackingTypes(); + } + + getGroupedStates() { + let groupedStates = []; + this.$http.get('AlertLevels').then(res => { + for (let state of res.data) { + groupedStates.push({ + id: state.id, + code: state.code, + name: this.$t(state.code) + }); + } + this.groupedStates = groupedStates; + }); + } + + getItemPackingTypes() { + let itemPackingTypes = []; + this.$http.get('ItemPackingTypes').then(res => { + for (let ipt of res.data) { + itemPackingTypes.push({ + id: ipt.id, + code: ipt.code, + name: this.$t(ipt.code) + }); + } + this.itemPackingTypes = itemPackingTypes; + }); } } diff --git a/modules/ticket/front/future-search-panel/locale/en.yml b/modules/ticket/front/future-search-panel/locale/en.yml index 0440752c5..fe71865cb 100644 --- a/modules/ticket/front/future-search-panel/locale/en.yml +++ b/modules/ticket/front/future-search-panel/locale/en.yml @@ -1 +1,9 @@ -Future tickets: Tickets a futuro \ No newline at end of file +Future tickets: Tickets a futuro +FREE: Free +DELIVERED: Delivered +ON_PREPARATION: On preparation +PACKED: Packed +F: Fruits and vegetables +V: Vertical +H: Horizontal +P: Feed diff --git a/modules/ticket/front/future-search-panel/locale/es.yml b/modules/ticket/front/future-search-panel/locale/es.yml index 413f9e5f9..82deba538 100644 --- a/modules/ticket/front/future-search-panel/locale/es.yml +++ b/modules/ticket/front/future-search-panel/locale/es.yml @@ -3,11 +3,21 @@ Origin date: Fecha origen Destination date: Fecha destino Origin ETD: ETD origen Destination ETD: ETD destino -Max Lines Origin: Líneas máx. origen -Max Liters Origin: Litros máx. origen +Max Lines: Líneas máx. +Max Liters: Litros máx. Origin IPT: IPT origen Destination IPT: IPT destino With problems: Con problemas Warehouse: Almacén -Origin Agrupated State: Estado agrupado origen -Destination Agrupated State: Estado agrupado destino +Origin Grouped State: Estado agrupado origen +Destination Grouped State: Estado agrupado destino +FREE: Libre +DELIVERED: Servido +ON_PREPARATION: En preparacion +PACKED: Encajado +F: Frutas y verduras +V: Vertical +H: Horizontal +P: Pienso +ETD: Tiempo estimado de entrega +IPT: Encajado diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 021fc1390..31d4ae0d9 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -1,7 +1,6 @@ @@ -11,14 +10,14 @@ placeholder="Search tickets" info="Search future tickets by date" auto-state="false" - model="model" - filter="::$ctrl.filter"> + model="model"> IPT - + Liters - + Available Lines diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index 479d4b000..7c9b6122e 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -6,23 +6,9 @@ export default class Controller extends Section { super($element, $); this.$checkAll = false; - const originDated = new Date(); - const futureDated = new Date(); - const warehouseFk = 1; - const litersMax = 9999; - const linesMax = 9999; - - this.defaultFilter = { - originDated, - futureDated, - warehouseFk, - litersMax, - linesMax - }; - this.smartTableOptions = { activeButtons: { - search: true + search: true, }, columns: [{ field: 'problems', @@ -35,7 +21,32 @@ export default class Controller extends Section { { field: 'destETD', searchable: false - }] + }, + { + field: 'state', + searchable: false + }, + { + field: 'tfState', + searchable: false + }, + { + field: 'ipt', + autocomplete: { + url: 'ItemPackingTypes', + showField: 'description', + valueField: 'code' + } + }, + { + field: 'tfIpt', + autocomplete: { + url: 'ItemPackingTypes', + showField: 'description', + valueField: 'code' + } + }, + ] }; } @@ -67,7 +78,7 @@ export default class Controller extends Section { stateColor(state) { if (state === 'OK') return 'success'; - else if (state === 'FREE') + else if (state === 'Libre') return 'notice'; } @@ -96,6 +107,23 @@ export default class Controller extends Section { this.vnApp.showSuccess(this.$t('Success')); }); } + + exprBuilder(param, value) { + switch (param) { + case 'id': + return { 'id': value }; + case 'ticketFuture': + return { 'ticketFuture': value }; + case 'litersMax': + return { 'liters': value }; + case 'linesMax': + return { 'lines': value }; + case 'ipt': + return { 'ipt': value }; + case 'tfIpt': + return { 'tfIpt': value }; + } + } } Controller.$inject = ['$element', '$scope']; diff --git a/modules/ticket/front/future/locale/en.yml b/modules/ticket/front/future/locale/en.yml index 7b0a377b8..8e2340a0b 100644 --- a/modules/ticket/front/future/locale/en.yml +++ b/modules/ticket/front/future/locale/en.yml @@ -1 +1,5 @@ Move confirmation: Do you want to move {{checked}} tickets to the future? +FREE: Free +DELIVERED: Delivered +ON_PREPARATION: On preparation +PACKED: Packed diff --git a/modules/ticket/front/future/locale/es.yml b/modules/ticket/front/future/locale/es.yml index 937f206e9..9be0be6a4 100644 --- a/modules/ticket/front/future/locale/es.yml +++ b/modules/ticket/front/future/locale/es.yml @@ -14,3 +14,9 @@ Origin ETD: ETD Origen Move tickets: Mover tickets Move confirmation: ¿Desea mover {{checked}} tickets hacia el futuro? Success: Tickets movidos correctamente +ETD: Tiempo estimado de entrega +IPT: Encajado +FREE: Libre +DELIVERED: Servido +ON_PREPARATION: En preparacion +PACKED: Encajado From c16210dd8a4106ed1acc2c77d9e8e25ccd7f94c6 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 11 Nov 2022 15:58:11 +0100 Subject: [PATCH 09/28] refs #4700 working on e2e --- .../00-ticket_canMerge.sql | 0 .../00-ticket_canbePostposed.sql | 0 e2e/helpers/selectors.js | 13 +- e2e/paths/04-item/08_regularize.spec.js | 4 +- .../05-ticket/01-sale/02_edit_sale.spec.js | 2 +- e2e/paths/05-ticket/20_future.spec.js | 205 ++++++++++++++++-- loopback/locale/en.json | 7 +- modules/ticket/back/methods/ticket/merge.js | 23 +- modules/ticket/front/future/index.spec.js | 2 +- modules/ticket/front/future/locale/en.yml | 1 + 10 files changed, 220 insertions(+), 37 deletions(-) rename db/changes/{10501-november => 10503-november}/00-ticket_canMerge.sql (100%) rename db/changes/{10501-november => 10503-november}/00-ticket_canbePostposed.sql (100%) diff --git a/db/changes/10501-november/00-ticket_canMerge.sql b/db/changes/10503-november/00-ticket_canMerge.sql similarity index 100% rename from db/changes/10501-november/00-ticket_canMerge.sql rename to db/changes/10503-november/00-ticket_canMerge.sql diff --git a/db/changes/10501-november/00-ticket_canbePostposed.sql b/db/changes/10503-november/00-ticket_canbePostposed.sql similarity index 100% rename from db/changes/10501-november/00-ticket_canbePostposed.sql rename to db/changes/10503-november/00-ticket_canbePostposed.sql diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 749e243d0..52ea34950 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -722,16 +722,23 @@ export default { litersMax: 'vn-textfield[label="Max Liters"]', ipt: 'vn-autocomplete[label="Origin IPT"]', tfIpt: 'vn-autocomplete[label="Destination IPT"]', + tableIpt: 'vn-autocomplete[name="ipt"]', + tableTfIpt: 'vn-autocomplete[name="tfIpt"]', state: 'vn-autocomplete[label="Origin Grouped State"]', tfState: 'vn-autocomplete[label="Destination Grouped State"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]', problems: 'vn-check[label="With problems"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Future tickets"]', - tableId: 'vn-textfield[ng-model="searchProps[\'id\']"]', - tableTfId: 'vn-textfield[ng-model="searchProps[\'ticketFuture\']"]', + acceptButton: '.vn-confirm.shown button[response="accept"]', + firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', + multiCheck: 'vn-multi-check', + tableId: 'vn-textfield[name="id"]', + tableTfId: 'vn-textfield[name="ticketFuture"]', + tableLiters: 'vn-textfield[name="litersMax"]', + tableLines: 'vn-textfield[name="linesMax"]', submit: 'vn-submit[label="Search"]', - table: 'tbody > tr:not(.empty-rows, #searchRow)', + table: 'tbody > tr:not(.empty-rows)' }, createStateView: { state: 'vn-autocomplete[ng-model="$ctrl.stateFk"]', diff --git a/e2e/paths/04-item/08_regularize.spec.js b/e2e/paths/04-item/08_regularize.spec.js index 400df666f..2e09a9f63 100644 --- a/e2e/paths/04-item/08_regularize.spec.js +++ b/e2e/paths/04-item/08_regularize.spec.js @@ -127,8 +127,8 @@ describe('Item regularize path', () => { await page.waitForState('ticket.index'); }); - it('should search for the ticket with id 28 once again', async() => { - await page.accessToSearchResult('28'); + it('should search for the ticket with id 31 once again', async() => { + await page.accessToSearchResult('31'); await page.waitForState('ticket.card.summary'); }); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index d776f417d..67dfd83bf 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -291,7 +291,7 @@ describe('Ticket Edit sale path', () => { it('should confirm the transfered quantity is the correct one', async() => { const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); - expect(result).toContain('10'); + expect(result).toContain('20'); }); it('should go back to the original ticket sales section', async() => { diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/20_future.spec.js index c9c4559a7..9572ac746 100644 --- a/e2e/paths/05-ticket/20_future.spec.js +++ b/e2e/paths/05-ticket/20_future.spec.js @@ -18,14 +18,69 @@ describe('Ticket Future path', () => { const now = new Date(); const tomorrow = new Date(now.getDate() + 1); + const ticket = { + originDated: now, + futureDated: now, + linesMax: '9999', + litersMax: '9999', + warehouseFk: 'Warehouse One' + }; + + it('should show errors snackbar because of the required data', async () => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); + await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); + await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); + await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); + + await page.waitToClick(selectors.ticketFuture.submit); + let message = await page.waitForSnackbar(); + expect(message.text).toContain('warehouseFk is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); + await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); + await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + expect(message.text).toContain('litersMax is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); + await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); + await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + expect(message.text).toContain('linesMax is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); + await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); + await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + expect(message.text).toContain('futureDated is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); + await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); + await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + expect(message.text).toContain('originDated is a required argument'); + }); + it('should search with the required data', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, now); - await page.pickDate(selectors.ticketFuture.futureDated, now); - await page.waitToClick(selectors.ticketFuture.linesMax); - await page.write(selectors.ticketFuture.linesMax, '9999'); - await page.write(selectors.ticketFuture.litersMax, '9999'); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, 'Warehouse One'); + await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); + await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); + await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); + await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); + await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); @@ -61,7 +116,14 @@ describe('Ticket Future path', () => { it('should search with the origin IPT', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.shipped); await page.clearInput(selectors.ticketFuture.tfShipped); + await page.clearInput(selectors.ticketFuture.ipt); + await page.clearInput(selectors.ticketFuture.tfIpt); + await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.tfState); + await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); @@ -69,7 +131,14 @@ describe('Ticket Future path', () => { it('should search with the destination IPT', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.shipped); + await page.clearInput(selectors.ticketFuture.tfShipped); await page.clearInput(selectors.ticketFuture.ipt); + await page.clearInput(selectors.ticketFuture.tfIpt); + await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.tfState); + await page.autocompleteSearch(selectors.ticketFuture.tfIpt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); @@ -77,7 +146,14 @@ describe('Ticket Future path', () => { it('should search with the origin grouped state', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.shipped); + await page.clearInput(selectors.ticketFuture.tfShipped); + await page.clearInput(selectors.ticketFuture.ipt); await page.clearInput(selectors.ticketFuture.tfIpt); + await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.tfState); + await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 3); @@ -85,7 +161,14 @@ describe('Ticket Future path', () => { it('should search with the destination grouped state', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.shipped); + await page.clearInput(selectors.ticketFuture.tfShipped); + await page.clearInput(selectors.ticketFuture.ipt); + await page.clearInput(selectors.ticketFuture.tfIpt); await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.tfState); + await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free'); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); @@ -93,7 +176,14 @@ describe('Ticket Future path', () => { it('should search with problems selected', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.shipped); + await page.clearInput(selectors.ticketFuture.tfShipped); + await page.clearInput(selectors.ticketFuture.ipt); + await page.clearInput(selectors.ticketFuture.tfIpt); + await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.tfState); + await page.waitToClick(selectors.ticketFuture.problems); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); @@ -104,23 +194,108 @@ describe('Ticket Future path', () => { await page.waitToClick(selectors.ticketFuture.problems); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.problems); + await page.waitToClick(selectors.ticketFuture.submit); }); - it('should search with an ID Origin', async () => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.problems); - await page.waitToClick(selectors.ticketFuture.submit); + it('should search in smart-table with an ID Origin', async () => { await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.write(selectors.ticketFuture.tableId, "13"); await page.keyboard.press("Enter"); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 2); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should search with an ID Destination', async () => { - await page.clearInput(selectors.ticketFuture.tableId); + + it('should search in smart-table with an ID Destination', async () => { + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.write(selectors.ticketFuture.tableTfId, "12"); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); + it('should search in smart-table with an IPT Origin', async () => { + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.autocompleteSearch(selectors.ticketFuture.tableIpt, 'Vertical'); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search in smart-table with an IPT Destination', async () => { + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.autocompleteSearch(selectors.ticketFuture.tableTfIpt, 'Vertical'); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search in smart-table with especified Lines', async () => { + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.write(selectors.ticketFuture.tableLines, "0"); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.write(selectors.ticketFuture.tableLines, "1"); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should search in smart-table with especified Liters', async () => { + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.write(selectors.ticketFuture.tableLiters, "0"); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.write(selectors.ticketFuture.tableLiters, "28"); + await page.keyboard.press("Enter"); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); + + await page.waitToClick(selectors.ticketFuture.tableButtonSearch); + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); + }); + + it('should check the second ticket and move to the future', async () => { + await page.waitToClick(selectors.ticketFuture.multiCheck); + await page.waitToClick(selectors.ticketFuture.firstCheck); + await page.waitToClick(selectors.ticketFuture.moveButton); + await page.waitToClick(selectors.ticketFuture.acceptButton); + const message = await page.waitForSnackbar(); + expect(message.text).toContain('Tickets moved successfully!'); + }); - // const message = await page.waitForSnackbar(); }); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 1e151294f..8ec38e425 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -134,6 +134,7 @@ "Password does not meet requirements": "Password does not meet requirements", "You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies", "Not enough privileges to edit a client": "Not enough privileges to edit a client", - "You don't have grant privilege": "You don't have grant privilege", - "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user" -} + "You don't have grant privilege": "You don't have grant privilege", + "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", + "MOVE_TICKET_CONFIRMATION": "MOVE_TICKET_CONFIRMATION" +} \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index 356259a26..e7f815128 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -36,8 +36,8 @@ module.exports = Self => { myOptions.transaction = tx; } - for (let ticket of tickets) { - try { + try { + for (let ticket of tickets) { const fullPath = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; const message = $t('MOVE_TICKET_CONFIRMATION', { originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), @@ -46,18 +46,17 @@ module.exports = Self => { tfId: ticket.ticketFuture, fullPath }); - if(!ticket.id || !ticket.ticketFuture) continue; - await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions); + if (!ticket.id || !ticket.ticketFuture) continue; + await models.Sale.updateAll({ ticketFk: ticket.id }, { ticketFk: ticket.ticketFuture }, myOptions); await models.Ticket.setDeleted(ctx, ticket.id, myOptions); await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); - if (tx) - { - await tx.commit(); - } - } catch (e) { - if (tx) await tx.rollback(); - throw e; + }; + if (tx) { + await tx.commit(); } - }; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } }; }; diff --git a/modules/ticket/front/future/index.spec.js b/modules/ticket/front/future/index.spec.js index 003b277ee..63deebc4f 100644 --- a/modules/ticket/front/future/index.spec.js +++ b/modules/ticket/front/future/index.spec.js @@ -22,7 +22,7 @@ describe('Component vnTicketFuture', () => { }, { id: 2, checked: true, - state: "FREE" + state: "Libre" }]; })); diff --git a/modules/ticket/front/future/locale/en.yml b/modules/ticket/front/future/locale/en.yml index 8e2340a0b..66d3ce269 100644 --- a/modules/ticket/front/future/locale/en.yml +++ b/modules/ticket/front/future/locale/en.yml @@ -3,3 +3,4 @@ FREE: Free DELIVERED: Delivered ON_PREPARATION: On preparation PACKED: Packed +Success: Tickets moved successfully! From 0ef64481b9d4a57799acfc503ead59113c7083c3 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 14 Nov 2022 08:51:15 +0100 Subject: [PATCH 10/28] refs #4700 e2e finished --- e2e/paths/05-ticket/20_future.spec.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/20_future.spec.js index 9572ac746..23c2db77a 100644 --- a/e2e/paths/05-ticket/20_future.spec.js +++ b/e2e/paths/05-ticket/20_future.spec.js @@ -172,11 +172,8 @@ describe('Ticket Future path', () => { await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free'); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); - }); - it('should search with problems selected', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.shipped); await page.clearInput(selectors.ticketFuture.tfShipped); await page.clearInput(selectors.ticketFuture.ipt); @@ -184,21 +181,10 @@ describe('Ticket Future path', () => { await page.clearInput(selectors.ticketFuture.state); await page.clearInput(selectors.ticketFuture.tfState); - await page.waitToClick(selectors.ticketFuture.problems); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should search with no problems selected', async () => { - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.problems); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.clearInput(selectors.ticketFuture.problems); - await page.waitToClick(selectors.ticketFuture.submit); - }); - it('should search in smart-table with an ID Origin', async () => { await page.waitToClick(selectors.ticketFuture.tableButtonSearch); await page.write(selectors.ticketFuture.tableId, "13"); @@ -289,7 +275,7 @@ describe('Ticket Future path', () => { await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should check the second ticket and move to the future', async () => { + it('should check the three last tickets and move to the future', async () => { await page.waitToClick(selectors.ticketFuture.multiCheck); await page.waitToClick(selectors.ticketFuture.firstCheck); await page.waitToClick(selectors.ticketFuture.moveButton); From 03ea2b4f1130b4ce607176b6e64e1315e26b4fc9 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 14 Nov 2022 08:55:27 +0100 Subject: [PATCH 11/28] refs #4700 translations --- loopback/locale/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 8ec38e425..84ca88a64 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -136,5 +136,5 @@ "Not enough privileges to edit a client": "Not enough privileges to edit a client", "You don't have grant privilege": "You don't have grant privilege", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", - "MOVE_TICKET_CONFIRMATION": "MOVE_TICKET_CONFIRMATION" -} \ No newline at end of file + "MOVE_TICKET_CONFIRMATION": "Ticket {{id}} ({{originDated}}) merged with {{tfId}} ({{futureDated}}) [{{fullPath}}]" +} From 7dd87b1ea8532d2a9c7073a811569edbd1db7d82 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 14 Nov 2022 09:56:23 +0100 Subject: [PATCH 12/28] refs #4700 icons future --- .../styles/fonts/MaterialIcons-Regular.woff2 | Bin 94744 -> 125116 bytes modules/ticket/front/future/index.html | 2 +- modules/ticket/front/routes.json | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/front/core/styles/fonts/MaterialIcons-Regular.woff2 b/front/core/styles/fonts/MaterialIcons-Regular.woff2 index 9d1dfcc70d7c7c0fc78aec9d6a46fb4ca50564f9..2eb4fb4997c4987aa93c222b053a22d23e45f03c 100644 GIT binary patch literal 125116 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 literal 94744 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 diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 31d4ae0d9..ecb521032 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -21,7 +21,7 @@ > diff --git a/modules/ticket/front/routes.json b/modules/ticket/front/routes.json index 62f43a098..2963d54c4 100644 --- a/modules/ticket/front/routes.json +++ b/modules/ticket/front/routes.json @@ -8,7 +8,7 @@ "main": [ {"state": "ticket.index", "icon": "icon-ticket"}, {"state": "ticket.weekly.index", "icon": "schedule"}, - {"state": "ticket.future", "icon": "double_arrow"} + {"state": "ticket.future", "icon": "keyboard_double_arrow_right"} ], "card": [ {"state": "ticket.card.basicData.stepOne", "icon": "settings"}, From 5c249dcbccacd95131642ddb93f1c58778077ea1 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 15 Nov 2022 08:24:10 +0100 Subject: [PATCH 13/28] refs #4767 @1h30m --- modules/route/front/descriptor/index.html | 7 +++++++ modules/route/front/descriptor/index.js | 8 ++++++++ modules/route/front/descriptor/index.spec.js | 16 ++++++++++++++++ modules/route/front/descriptor/locale/es.yml | 2 ++ 4 files changed, 33 insertions(+) diff --git a/modules/route/front/descriptor/index.html b/modules/route/front/descriptor/index.html index fc1d3419c..6d6fb082e 100644 --- a/modules/route/front/descriptor/index.html +++ b/modules/route/front/descriptor/index.html @@ -20,6 +20,13 @@ translate> Update volume + + Delete route +

diff --git a/modules/route/front/descriptor/index.js b/modules/route/front/descriptor/index.js index 2dc512b67..aa47044b1 100644 --- a/modules/route/front/descriptor/index.js +++ b/modules/route/front/descriptor/index.js @@ -34,6 +34,14 @@ class Controller extends Descriptor { }); } + deleteCurrentRoute() { + this.$http.delete(`Routes/${this.id}`) + .then(() => { + this.vnApp.showSuccess(this.$t('Route deleted')); + this.$state.go('route.index'); + }); + } + loadData() { const filter = { fields: [ diff --git a/modules/route/front/descriptor/index.spec.js b/modules/route/front/descriptor/index.spec.js index ab996d9b0..f43666c8b 100644 --- a/modules/route/front/descriptor/index.spec.js +++ b/modules/route/front/descriptor/index.spec.js @@ -23,4 +23,20 @@ describe('vnRouteDescriptorPopover', () => { expect(controller.route).toEqual(response); }); }); + + describe('deleteCurrentRoute()', () => { + it(`should perform a delete query to delete the current route`, () => { + const id = 1; + + jest.spyOn(controller.vnApp, 'showSuccess'); + + controller._id = id; + $httpBackend.expectDELETE(`Routes/${id}`).respond(200); + controller.deleteCurrentRoute(); + $httpBackend.flush(); + + expect(controller.route).toBeUndefined(); + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Route deleted'); + }); + }); }); diff --git a/modules/route/front/descriptor/locale/es.yml b/modules/route/front/descriptor/locale/es.yml index 63fa7202b..23068fbf8 100644 --- a/modules/route/front/descriptor/locale/es.yml +++ b/modules/route/front/descriptor/locale/es.yml @@ -4,4 +4,6 @@ Send route report: Enviar informe de ruta Show route report: Ver informe de ruta Update volume: Actualizar volumen Volume updated: Volumen actualizado +Delete route: Borrar ruta +Route deleted: Ruta borrada Are you sure you want to update the volume?: Estas seguro que quieres actualizar el volumen? \ No newline at end of file From 5acbaf036a521cb6dcd2e971d933dcea7e56665d Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 15 Nov 2022 09:30:36 +0100 Subject: [PATCH 14/28] refs #3557 back and test done --- .../10503-november/00-sale_missingTrash.sql | 23 ++++++ .../ticket/back/methods/sale/missingTrash.js | 70 +++++++++++++++++++ .../methods/sale/specs/missingTrash.spec.js | 35 ++++++++++ modules/ticket/back/models/sale.js | 1 + 4 files changed, 129 insertions(+) create mode 100644 db/changes/10503-november/00-sale_missingTrash.sql create mode 100644 modules/ticket/back/methods/sale/missingTrash.js create mode 100644 modules/ticket/back/methods/sale/specs/missingTrash.spec.js diff --git a/db/changes/10503-november/00-sale_missingTrash.sql b/db/changes/10503-november/00-sale_missingTrash.sql new file mode 100644 index 000000000..f0de6d5cd --- /dev/null +++ b/db/changes/10503-november/00-sale_missingTrash.sql @@ -0,0 +1,23 @@ +DROP PROCEDURE IF EXISTS vn.sale_missingTrash; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_missingTrash`( + vSaleFk BIGINT, + vQuantity INT, + vIsTrash BOOLEAN, + vWarehouseFk INT, + vNewQuantity INT) +/** + * Modifica la cantidad de una sale tirándola a faltas o basura + * + * @param vSaleFk el id de la sale + * @param vQuantity cantidad que se va a tirar a faltas o basura + * @param vIsTrash true si es basura, false si es faltas + * @param vWarehouseFk id warehouse + * @param vNewQuantity cantidad que se queda en el ticket original + */ +BEGIN + CALL vn.collection_missingTrash(vSaleFk ,vQuantity ,vIsTrash ,vWarehouseFk ,vNewQuantity); +END$$ +DELIMITER ; diff --git a/modules/ticket/back/methods/sale/missingTrash.js b/modules/ticket/back/methods/sale/missingTrash.js new file mode 100644 index 000000000..6d4f69178 --- /dev/null +++ b/modules/ticket/back/methods/sale/missingTrash.js @@ -0,0 +1,70 @@ +module.exports = Self => { + Self.remoteMethodCtx('missingTrash', { + description: 'Modify the amount of a sale by throwing it to faults or garbage', + accessType: 'WRITE', + accepts: [ + { + arg: 'saleFk', + type: 'number', + required: true, + description: 'The sale id' + }, + { + arg: 'quantity', + type: 'number', + required: true, + description: 'Quantity that is going to be thrown away' + }, + { + arg: 'isTrash', + type: 'boolean', + required: true, + description: 'True if garbage, false if fault' + }, + { + arg: 'warehouseFk', + type: 'number', + required: true, + description: 'The warehouse id' + }, + { + arg: 'newQuantity', + type: 'number', + required: true, + description: 'Amount remaining on the original ticket' + }, + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/missingTrash`, + verb: 'POST' + } + }); + + Self.missingTrash = async function (ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options) { + const myOptions = {}; + let tx; + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const missingTrash = await Self.rawSql(`CALL vn.sale_missingTrash(?, ?, ?, ?, ?)`, + [saleFk, quantity, isTrash, warehouseFk, newQuantity], myOptions); + + if (tx) await tx.commit(); + + return missingTrash; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js new file mode 100644 index 000000000..62fd74343 --- /dev/null +++ b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js @@ -0,0 +1,35 @@ +const models = require('vn-loopback/server/server').models; + +fdescribe('sale missingTrash()', () => { + it('should modify the amount of a sale by throwing it to faults or garbage', async () => { + const tx = await models.Sale.beginTransaction({}); + + try { + const options = { transaction: tx }; + + const saleFk = 1; + const quantity = 3; + const isTrash = true; + const warehouseFk = 1; + const newQuantity = 2; + + const ctx = { req: { accessToken: { userId: 9 } } }; + + let sale = await models.Sale.findById(saleFk, null, options); + expect(sale.quantity).toEqual(5); + expect(sale.originalQuantity).toBe(null); + + await models.Sale.missingTrash(ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options); + + sale = await models.Sale.findById(saleFk, null, options); + expect(sale.quantity).toEqual(2); + expect(sale.originalQuantity).toBe(5); + + await tx.rollback(); + + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index ae247fc24..cb8814e67 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -9,6 +9,7 @@ module.exports = Self => { require('../methods/sale/refund')(Self); require('../methods/sale/canEdit')(Self); require('../methods/sale/usesMana')(Self); + require('../methods/sale/missingTrash')(Self); Self.validatesPresenceOf('concept', { message: `Concept cannot be blank` From 3dd43d21aef8412f511839d5ef4f3147c613a8ce Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 15 Nov 2022 09:37:26 +0100 Subject: [PATCH 15/28] fix test --- modules/ticket/back/methods/sale/specs/missingTrash.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js index 62fd74343..4dbe2588c 100644 --- a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js +++ b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js @@ -1,6 +1,6 @@ const models = require('vn-loopback/server/server').models; -fdescribe('sale missingTrash()', () => { +describe('sale missingTrash()', () => { it('should modify the amount of a sale by throwing it to faults or garbage', async () => { const tx = await models.Sale.beginTransaction({}); From 01607c71b68a876f99f16aed689928cfb4412668 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 15 Nov 2022 13:03:55 +0100 Subject: [PATCH 16/28] fix rocket message and order table --- loopback/locale/en.json | 2 +- loopback/locale/es.json | 2 +- .../ticket/back/methods/ticket-future/getTicketsFuture.js | 4 +++- modules/ticket/back/methods/ticket/merge.js | 8 +++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 84ca88a64..0f625a23d 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -136,5 +136,5 @@ "Not enough privileges to edit a client": "Not enough privileges to edit a client", "You don't have grant privilege": "You don't have grant privilege", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", - "MOVE_TICKET_CONFIRMATION": "Ticket {{id}} ({{originDated}}) merged with {{tfId}} ({{futureDated}}) [{{fullPath}}]" + "MOVE_TICKET_CONFIRMATION": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index a12cf1c09..965bc97c1 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -238,5 +238,5 @@ "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente", "You don't have grant privilege": "No tienes privilegios para dar privilegios", "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario", - "MOVE_TICKET_CONFIRMATION": "Ticket {{id}} ({{originDated}}) fusionado con {{tfId}} ({{futureDated}}) [{{fullPath}}]" + "MOVE_TICKET_CONFIRMATION": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" } diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js index 132df064f..0fcc21182 100644 --- a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js +++ b/modules/ticket/back/methods/ticket-future/getTicketsFuture.js @@ -203,8 +203,10 @@ module.exports = Self => { if (hasWhere) { filter = mergeFilters(filter, { where: problems }); } - stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(conn.makeOrderBy(filter.order)); + stmt.merge(conn.makeLimit(filter)); const ticketsIndex = stmts.push(stmt) - 1; diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index e7f815128..306993814 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -38,18 +38,20 @@ module.exports = Self => { try { for (let ticket of tickets) { - const fullPath = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; + const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`; + const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; const message = $t('MOVE_TICKET_CONFIRMATION', { originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), futureDated: new Date(ticket.destETD).toLocaleDateString('es-ES'), id: ticket.id, tfId: ticket.ticketFuture, - fullPath + fullPath, + fullPathFuture }); if (!ticket.id || !ticket.ticketFuture) continue; await models.Sale.updateAll({ ticketFk: ticket.id }, { ticketFk: ticket.ticketFuture }, myOptions); await models.Ticket.setDeleted(ctx, ticket.id, myOptions); - await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); + await models.Chat.sendCheckingPresence(ctx, 1, message); }; if (tx) { await tx.commit(); From 97a6aff499ed09315a8a9679031b84ccc3946cf5 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 15 Nov 2022 13:08:06 +0100 Subject: [PATCH 17/28] fix workerFk --- modules/ticket/back/methods/ticket/merge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index 306993814..879136c46 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -51,7 +51,7 @@ module.exports = Self => { if (!ticket.id || !ticket.ticketFuture) continue; await models.Sale.updateAll({ ticketFk: ticket.id }, { ticketFk: ticket.ticketFuture }, myOptions); await models.Ticket.setDeleted(ctx, ticket.id, myOptions); - await models.Chat.sendCheckingPresence(ctx, 1, message); + await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); }; if (tx) { await tx.commit(); From c200e1af32f7ec464d2906323359f7a3925e7b02 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 15 Nov 2022 15:09:41 +0100 Subject: [PATCH 18/28] refactor: optimizado select --- .../00-timeBusiness_calculate.sql | 88 +++++++++++++++++++ .../specs/sendMail.spec.js | 9 -- 2 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 db/changes/10503-november/00-timeBusiness_calculate.sql diff --git a/db/changes/10503-november/00-timeBusiness_calculate.sql b/db/changes/10503-november/00-timeBusiness_calculate.sql new file mode 100644 index 000000000..ea13c4a8a --- /dev/null +++ b/db/changes/10503-november/00-timeBusiness_calculate.sql @@ -0,0 +1,88 @@ +DROP PROCEDURE IF EXISTS `vn`.`timeBusiness_calculate`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`timeBusiness_calculate`(vDatedFrom DATETIME, vDatedTo DATETIME) +BEGIN +/** + * Horas que debe trabajar un empleado según contrato y día. + * @param vDatedFrom workerTimeControl + * @param vDatedTo workerTimeControl + * @table tmp.user(userFk) + * @return tmp.timeBusinessCalculate + */ + DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate; + CREATE TEMPORARY TABLE tmp.timeBusinessCalculate + (INDEX (departmentFk)) + SELECT dated, + businessFk, + userFk, + departmentFk, + hourStart, + hourEnd, + timeTable, + timeWorkSeconds, + SEC_TO_TIME(timeWorkSeconds) timeWorkSexagesimal, + timeWorkSeconds / 3600 timeWorkDecimal, + timeWorkSeconds timeBusinessSeconds, + SEC_TO_TIME(timeWorkSeconds) timeBusinessSexagesimal, + timeWorkSeconds / 3600 timeBusinessDecimal, + name type, + permissionRate, + hoursWeek, + discountRate, + isAllowedToWork + FROM(SELECT t.dated, + b.id businessFk, + w.userFk, + b.departmentFk, + IF(j.start = NULL, NULL, GROUP_CONCAT(DISTINCT LEFT(j.start,5) ORDER BY j.start ASC SEPARATOR ' - ')) hourStart , + IF(j.start = NULL, NULL, GROUP_CONCAT(DISTINCT LEFT(j.end,5) ORDER BY j.end ASC SEPARATOR ' - ')) hourEnd, + IF(j.start = NULL, NULL, GROUP_CONCAT(DISTINCT LEFT(j.start,5), " - ", LEFT(j.end,5) ORDER BY j.end ASC SEPARATOR ' - ')) timeTable, + IF(j.start = NULL, 0, IFNULL(SUM(TIME_TO_SEC(j.end)) - SUM(TIME_TO_SEC(j.start)), 0)) timeWorkSeconds, + at2.name, + at2.permissionRate, + at2.discountRate, + cl.hours_week hoursWeek, + at2.isAllowedToWork + FROM time t + LEFT JOIN business b ON t.dated BETWEEN b.started AND IFNULL(b.ended, vDatedTo) + LEFT JOIN worker w ON w.id = b.workerFk + JOIN tmp.`user` u ON u.userFK = w.userFK + LEFT JOIN workCenter wc ON wc.id = b.workcenterFK + LEFT JOIN postgresql.calendar_labour_type cl ON cl.calendar_labour_type_id = b.calendarTypeFk + LEFT JOIN postgresql.journey j ON j.business_id = b.id AND j.day_id = WEEKDAY(t.dated) + 1 + LEFT JOIN postgresql.calendar_employee ce ON ce.businessFk = b.id AND ce.date = t.dated + LEFT JOIN absenceType at2 ON at2.id = ce.calendar_state_id + WHERE t.dated BETWEEN vDatedFrom AND vDatedTo + GROUP BY w.userFk, t.dated + )sub; + + UPDATE tmp.timeBusinessCalculate t + LEFT JOIN postgresql.journey j ON j.business_id = t.businessFk + SET t.timeWorkSeconds = t.hoursWeek / 5 * 3600, + t.timeWorkSexagesimal = SEC_TO_TIME( t.hoursWeek / 5 * 3600), + t.timeWorkDecimal = t.hoursWeek / 5, + t.timeBusinessSeconds = t.hoursWeek / 5 * 3600, + t.timeBusinessSexagesimal = SEC_TO_TIME( t.hoursWeek / 5 * 3600), + t.timeBusinessDecimal = t.hoursWeek / 5 + WHERE DAYOFWEEK(t.dated) IN(2,3,4,5,6) AND j.journey_id IS NULL ; + + UPDATE tmp.timeBusinessCalculate t + SET t.timeWorkSeconds = t.timeWorkSeconds - (t.timeWorkSeconds * permissionRate) , + t.timeWorkSexagesimal = SEC_TO_TIME ((t.timeWorkDecimal - (t.timeWorkDecimal * permissionRate)) * 3600), + t.timeWorkDecimal = t.timeWorkDecimal - (t.timeWorkDecimal * permissionRate) + WHERE permissionRate <> 0; + + UPDATE tmp.timeBusinessCalculate t + JOIN calendarHolidays ch ON ch.dated = t.dated + JOIN business b ON b.id = t.businessFk + AND b.workcenterFk = ch.workcenterFk + SET t.timeWorkSeconds = 0, + t.timeWorkSexagesimal = 0, + t.timeWorkDecimal = 0, + t.permissionrate = 1, + t.type = 'Festivo' + WHERE t.type IS NULL; +END$$ +DELIMITER ; diff --git a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js index d0afd45b9..4cc6e54e3 100644 --- a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js @@ -12,11 +12,6 @@ describe('workerTimeControl sendMail()', () => { }; - beforeAll(function() { - originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; - jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; - }); - it('should fill time control of a worker without records in Journey and with rest', async() => { const tx = await models.WorkerTimeControl.beginTransaction({}); @@ -124,9 +119,5 @@ describe('workerTimeControl sendMail()', () => { throw e; } }); - - afterAll(function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; - }); }); From 7b3a1bfb22bff5082626b9929ba1bb8b7b3354a0 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Wed, 16 Nov 2022 08:28:12 +0100 Subject: [PATCH 19/28] requested changes --- db/changes/10502-november/00-greuge.userFK_userFk.sql | 1 - db/changes/10503-november/00-greuge.userFK_userFk.sql | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 db/changes/10502-november/00-greuge.userFK_userFk.sql create mode 100644 db/changes/10503-november/00-greuge.userFK_userFk.sql diff --git a/db/changes/10502-november/00-greuge.userFK_userFk.sql b/db/changes/10502-november/00-greuge.userFK_userFk.sql deleted file mode 100644 index 2a5323fa3..000000000 --- a/db/changes/10502-november/00-greuge.userFK_userFk.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE vn.greuge CHANGE userFK userFk int(10) unsigned DEFAULT NULL NULL; \ No newline at end of file diff --git a/db/changes/10503-november/00-greuge.userFK_userFk.sql b/db/changes/10503-november/00-greuge.userFK_userFk.sql new file mode 100644 index 000000000..ec4bf3146 --- /dev/null +++ b/db/changes/10503-november/00-greuge.userFK_userFk.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`greuge` CHANGE `userFK` `userFk` int(10) unsigned DEFAULT NULL NULL; \ No newline at end of file From 78dc7db7a7e8627f7e7bff48a62647b218fce163 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 16 Nov 2022 09:46:35 +0100 Subject: [PATCH 20/28] correcciones --- db/changes/10503-november/00-ticket_canMerge.sql | 2 +- db/changes/10503-november/00-ticket_canbePostposed.sql | 2 +- .../methods/sales-monitor/specs/salesFilter.spec.js | 10 +++++----- modules/ticket/back/methods/ticket/merge.js | 6 ++++-- .../ticket/back/methods/ticket/specs/filter.spec.js | 10 +++++----- modules/ticket/back/models/ticket-future.json | 4 ++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/db/changes/10503-november/00-ticket_canMerge.sql b/db/changes/10503-november/00-ticket_canMerge.sql index 7e01f2fab..cb0e5cfe8 100644 --- a/db/changes/10503-november/00-ticket_canMerge.sql +++ b/db/changes/10503-november/00-ticket_canMerge.sql @@ -1,4 +1,4 @@ -DROP PROCEDURE IF EXISTS vn.ticket_canMerge; +DROP PROCEDURE IF EXISTS `vn`.`ticket_canMerge`; DELIMITER $$ $$ diff --git a/db/changes/10503-november/00-ticket_canbePostposed.sql b/db/changes/10503-november/00-ticket_canbePostposed.sql index 113b09324..905d267a4 100644 --- a/db/changes/10503-november/00-ticket_canbePostposed.sql +++ b/db/changes/10503-november/00-ticket_canbePostposed.sql @@ -1,4 +1,4 @@ -DROP PROCEDURE IF EXISTS vn.ticket_canbePostponed; +DROP PROCEDURE IF EXISTS `vn`.`ticket_canbePostponed`; DELIMITER $$ $$ 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 9fcbf028f..d2e1a5bec 100644 --- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js +++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js @@ -11,7 +11,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {order: 'id DESC'}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(30); + expect(result.length).toBeGreaterThan(25); await tx.rollback(); } catch (e) { @@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(19); + expect(result.length).toBeGreaterThan(15); await tx.rollback(); } catch (e) { @@ -87,7 +87,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(30); + expect(result.length).toBeGreaterThan(20); await tx.rollback(); } catch (e) { @@ -130,7 +130,7 @@ describe('SalesMonitor salesFilter()', () => { const length = result.length; const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; - expect(length).toEqual(13); + expect(length).toBeGreaterThan(10); expect(anyResult.state).toMatch(/(Libre|Arreglar)/); await tx.rollback(); @@ -171,7 +171,7 @@ describe('SalesMonitor salesFilter()', () => { const filter = {}; const result = await models.SalesMonitor.salesFilter(ctx, filter, options); - expect(result.length).toEqual(26); + expect(result.length).toBeGreaterThan(20); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index 879136c46..0f1fa38bf 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -1,3 +1,5 @@ +const dateUtil = require('vn-loopback/util/date'); + module.exports = Self => { Self.remoteMethodCtx('merge', { description: 'Merge one ticket into another', @@ -41,8 +43,8 @@ module.exports = Self => { const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`; const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; const message = $t('MOVE_TICKET_CONFIRMATION', { - originDated: new Date(ticket.originETD).toLocaleDateString('es-ES'), - futureDated: new Date(ticket.destETD).toLocaleDateString('es-ES'), + originDated: dateUtil.toString(new Date(ticket.originETD)), + futureDated: dateUtil.toString(new Date(ticket.destETD)), id: ticket.id, tfId: ticket.ticketFuture, fullPath, diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index e2ab43aea..008068ff2 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -11,7 +11,7 @@ describe('ticket filter()', () => { const filter = {order: 'id DESC'}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(30); + expect(result.length).toBeGreaterThan(25); await tx.rollback(); } catch (e) { @@ -87,7 +87,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(30); + expect(result.length).toBeGreaterThan(25); await tx.rollback(); } catch (e) { @@ -130,7 +130,7 @@ describe('ticket filter()', () => { const length = result.length; const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; - expect(length).toEqual(13); + expect(length).toBeGreaterThan(10); expect(anyResult.state).toMatch(/(Libre|Arreglar)/); await tx.rollback(); @@ -232,7 +232,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(25); + expect(result.length).toBeGreaterThan(20); await tx.rollback(); } catch (e) { @@ -270,7 +270,7 @@ describe('ticket filter()', () => { const filter = {}; const result = await models.Ticket.filter(ctx, filter, options); - expect(result.length).toEqual(30); + expect(result.length).toBeGreaterThan(25); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/models/ticket-future.json b/modules/ticket/back/models/ticket-future.json index 5d0b24dbc..2a1b45def 100644 --- a/modules/ticket/back/models/ticket-future.json +++ b/modules/ticket/back/models/ticket-future.json @@ -5,8 +5,8 @@ { "accessType": "READ", "principalType": "ROLE", - "principalId": "$everyone", + "principalId": "$authenticated", "permission": "ALLOW" } ] - } \ No newline at end of file + } From 489df60afc9d15cacde1f3b3307860a3e9c654f3 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 16 Nov 2022 11:10:00 +0100 Subject: [PATCH 21/28] suggested filter added --- e2e/paths/05-ticket/20_future.spec.js | 33 +++++--------------------- modules/ticket/front/future/index.html | 1 + modules/ticket/front/future/index.js | 13 ++++++++++ 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/20_future.spec.js index 23c2db77a..7502d3617 100644 --- a/e2e/paths/05-ticket/20_future.spec.js +++ b/e2e/paths/05-ticket/20_future.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Ticket Future path', () => { +fdescribe('Ticket Future path', () => { let browser; let page; @@ -28,47 +28,31 @@ describe('Ticket Future path', () => { it('should show errors snackbar because of the required data', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); - await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); - await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); - await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); - + await page.clearInput(selectors.ticketFuture.warehouseFk); await page.waitToClick(selectors.ticketFuture.submit); let message = await page.waitForSnackbar(); expect(message.text).toContain('warehouseFk is a required argument'); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); - await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); - await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.clearInput(selectors.ticketFuture.litersMax); await page.waitToClick(selectors.ticketFuture.submit); message = await page.waitForSnackbar(); expect(message.text).toContain('litersMax is a required argument'); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); - await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); - await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.clearInput(selectors.ticketFuture.linesMax); await page.waitToClick(selectors.ticketFuture.submit); message = await page.waitForSnackbar(); expect(message.text).toContain('linesMax is a required argument'); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); - await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); - await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.clearInput(selectors.ticketFuture.futureDated); await page.waitToClick(selectors.ticketFuture.submit); message = await page.waitForSnackbar(); expect(message.text).toContain('futureDated is a required argument'); await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); - await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); - await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); + await page.clearInput(selectors.ticketFuture.originDated); await page.waitToClick(selectors.ticketFuture.submit); message = await page.waitForSnackbar(); expect(message.text).toContain('originDated is a required argument'); @@ -76,11 +60,6 @@ describe('Ticket Future path', () => { it('should search with the required data', async () => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.pickDate(selectors.ticketFuture.originDated, ticket.originDated); - await page.pickDate(selectors.ticketFuture.futureDated, ticket.futureDated); - await page.write(selectors.ticketFuture.linesMax, ticket.linesMax); - await page.write(selectors.ticketFuture.litersMax, ticket.litersMax); - await page.autocompleteSearch(selectors.ticketFuture.warehouseFk, ticket.warehouseFk); await page.waitToClick(selectors.ticketFuture.submit); await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index ecb521032..d30cbaf19 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -9,6 +9,7 @@ panel="vn-future-ticket-search-panel" placeholder="Search tickets" info="Search future tickets by date" + suggested-filter="$ctrl.filterParams" auto-state="false" model="model"> diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index 7c9b6122e..311b9c307 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -48,6 +48,19 @@ export default class Controller extends Section { }, ] }; + this.setDefaultFilter(); + } + + setDefaultFilter() { + const today = new Date(); + + this.filterParams = { + originDated: today, + futureDated: today, + linesMax: '9999', + litersMax: '9999', + warehouseFk: 1 + }; } compareDate(date) { From edb495c744e945b044dfebb09a2fded3510df1f2 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 16 Nov 2022 11:52:35 +0100 Subject: [PATCH 22/28] fix describe --- e2e/paths/05-ticket/20_future.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/20_future.spec.js index 7502d3617..4fee9523b 100644 --- a/e2e/paths/05-ticket/20_future.spec.js +++ b/e2e/paths/05-ticket/20_future.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Ticket Future path', () => { +describe('Ticket Future path', () => { let browser; let page; From e4a6585b6af91fff3192cf1819a6b4b27d9c3fb0 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 16 Nov 2022 13:46:16 +0100 Subject: [PATCH 23/28] fix test back --- .../10503-november/00-sale_missingTrash.sql | 4 ++++ db/changes/10503-november/delete.keep | 0 .../methods/sale/specs/missingTrash.spec.js | 21 +++++++++---------- 3 files changed, 14 insertions(+), 11 deletions(-) delete mode 100644 db/changes/10503-november/delete.keep diff --git a/db/changes/10503-november/00-sale_missingTrash.sql b/db/changes/10503-november/00-sale_missingTrash.sql index f0de6d5cd..8c1bcaed3 100644 --- a/db/changes/10503-november/00-sale_missingTrash.sql +++ b/db/changes/10503-november/00-sale_missingTrash.sql @@ -21,3 +21,7 @@ BEGIN CALL vn.collection_missingTrash(vSaleFk ,vQuantity ,vIsTrash ,vWarehouseFk ,vNewQuantity); END$$ DELIMITER ; + +INSERT INTO `salix`.`ACL` +(model, property, accessType, permission, principalType, principalId) +VALUES('Sale', 'missingTrash', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/10503-november/delete.keep b/db/changes/10503-november/delete.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js index 4dbe2588c..490ad7e0e 100644 --- a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js +++ b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js @@ -7,23 +7,22 @@ describe('sale missingTrash()', () => { try { const options = { transaction: tx }; - const saleFk = 1; - const quantity = 3; + const quantity = 1; const isTrash = true; - const warehouseFk = 1; - const newQuantity = 2; const ctx = { req: { accessToken: { userId: 9 } } }; - let sale = await models.Sale.findById(saleFk, null, options); - expect(sale.quantity).toEqual(5); - expect(sale.originalQuantity).toBe(null); + const sale = await models.Sale.findOne({fields: ['id','quantity', 'originalQuantity', 'ticketFk']}, options); + console.log(sale); + const ticket = await models.Ticket.findById(sale.ticketFk, {fields: ['warehouseFk']}, options); + console.log(ticket); + const newQuantity = sale.quantity-quantity; - await models.Sale.missingTrash(ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options); + await models.Sale.missingTrash(ctx, sale.id, quantity, isTrash, ticket.warehouseFk, newQuantity, options); - sale = await models.Sale.findById(saleFk, null, options); - expect(sale.quantity).toEqual(2); - expect(sale.originalQuantity).toBe(5); + const saleAfter = await models.Sale.findById(sale.id, {fields: ['quantity', 'originalQuantity']}, options); + expect(saleAfter.quantity).toEqual(newQuantity); + expect(saleAfter.originalQuantity).toBe(sale.quantity); await tx.rollback(); From 153cb48ff0fa25e505a4825a94408a4372c0318d Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 17 Nov 2022 08:55:35 +0100 Subject: [PATCH 24/28] fix test --- db/dump/fixtures.sql | 4 +-- .../ticket/back/methods/sale/missingTrash.js | 2 +- .../methods/sale/specs/missingTrash.spec.js | 35 ++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 49cf639ef..98c15075e 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -333,7 +333,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city (1109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'), (1110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'), (1111, 'Missing', NULL, 'Missing man', 'Anton', 'The space, Universe far away', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL), - (1112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city, Underground', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL); + (1112, 'Trash', '12345678Z', 'Garbage man', 'Unknown name', 'New York city, Underground', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL); INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1 @@ -2701,7 +2701,7 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) VALUES (1, 9); - + INSERT INTO `vn`.`productionConfig` (`isPreviousPreparationRequired`, `ticketPrintedMax`, `ticketTrolleyMax`, `rookieDays`, `notBuyingMonths`, `id`, `isZoneClosedByExpeditionActivated`, `maxNotReadyCollections`, `minTicketsToCloseZone`, `movingTicketDelRoute`, `defaultZone`, `defautlAgencyMode`, `hasUniqueCollectionTime`, `maxCollectionWithoutUser`, `pendingCollectionsOrder`, `pendingCollectionsAge`) VALUES (0, 8, 80, 0, 0, 1, 0, 15, 25, -1, 697, 1328, 0, 1, 8, 6); diff --git a/modules/ticket/back/methods/sale/missingTrash.js b/modules/ticket/back/methods/sale/missingTrash.js index 6d4f69178..4ff37eb1f 100644 --- a/modules/ticket/back/methods/sale/missingTrash.js +++ b/modules/ticket/back/methods/sale/missingTrash.js @@ -44,7 +44,7 @@ module.exports = Self => { } }); - Self.missingTrash = async function (ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options) { + Self.missingTrash = async function(ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options) { const myOptions = {}; let tx; if (typeof options == 'object') diff --git a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js index 490ad7e0e..dcc59333d 100644 --- a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js +++ b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js @@ -1,31 +1,50 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale missingTrash()', () => { - it('should modify the amount of a sale by throwing it to faults or garbage', async () => { + const activeCtx = { + accessToken: {userId: 9}, + headers: {origin: 'localhost:5000'}, + __: () => {} + }; + + const ctx = { + req: activeCtx + }; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + it('should modify the amount of a sale by throwing it to faults or garbage', async() => { const tx = await models.Sale.beginTransaction({}); try { - const options = { transaction: tx }; + const options = {transaction: tx}; const quantity = 1; const isTrash = true; - const ctx = { req: { accessToken: { userId: 9 } } }; + const trashClient = await models.Client.findOne({where: {name: 'Trash'}}, options); + await trashClient.updateAttribute('name', 'BASURA', options); + + const sale = await models.Sale.findOne({fields: ['id', 'quantity', 'originalQuantity', 'ticketFk']} + , options); - const sale = await models.Sale.findOne({fields: ['id','quantity', 'originalQuantity', 'ticketFk']}, options); - console.log(sale); const ticket = await models.Ticket.findById(sale.ticketFk, {fields: ['warehouseFk']}, options); - console.log(ticket); - const newQuantity = sale.quantity-quantity; + + const newQuantity = sale.quantity - quantity; await models.Sale.missingTrash(ctx, sale.id, quantity, isTrash, ticket.warehouseFk, newQuantity, options); const saleAfter = await models.Sale.findById(sale.id, {fields: ['quantity', 'originalQuantity']}, options); + expect(saleAfter.quantity).toEqual(newQuantity); expect(saleAfter.originalQuantity).toBe(sale.quantity); await tx.rollback(); - } catch (e) { await tx.rollback(); throw e; From fd58eaf8388daa990a071e19a876461a2c20f484 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 18 Nov 2022 09:36:38 +0100 Subject: [PATCH 25/28] drop procedure --- .../00-collection_missingTrash.sql | 1 + .../10503-november/00-sale_missingTrash.sql | 27 ------- db/dump/fixtures.sql | 2 +- .../ticket/back/methods/sale/missingTrash.js | 70 ------------------- .../methods/sale/specs/missingTrash.spec.js | 53 -------------- modules/ticket/back/models/sale.js | 1 - 6 files changed, 2 insertions(+), 152 deletions(-) create mode 100644 db/changes/10503-november/00-collection_missingTrash.sql delete mode 100644 db/changes/10503-november/00-sale_missingTrash.sql delete mode 100644 modules/ticket/back/methods/sale/missingTrash.js delete mode 100644 modules/ticket/back/methods/sale/specs/missingTrash.spec.js diff --git a/db/changes/10503-november/00-collection_missingTrash.sql b/db/changes/10503-november/00-collection_missingTrash.sql new file mode 100644 index 000000000..d4467c699 --- /dev/null +++ b/db/changes/10503-november/00-collection_missingTrash.sql @@ -0,0 +1 @@ +DROP PROCEDURE IF EXISTS `vn`.`collection_missingTrash`; diff --git a/db/changes/10503-november/00-sale_missingTrash.sql b/db/changes/10503-november/00-sale_missingTrash.sql deleted file mode 100644 index 8c1bcaed3..000000000 --- a/db/changes/10503-november/00-sale_missingTrash.sql +++ /dev/null @@ -1,27 +0,0 @@ -DROP PROCEDURE IF EXISTS vn.sale_missingTrash; - -DELIMITER $$ -$$ -CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_missingTrash`( - vSaleFk BIGINT, - vQuantity INT, - vIsTrash BOOLEAN, - vWarehouseFk INT, - vNewQuantity INT) -/** - * Modifica la cantidad de una sale tirándola a faltas o basura - * - * @param vSaleFk el id de la sale - * @param vQuantity cantidad que se va a tirar a faltas o basura - * @param vIsTrash true si es basura, false si es faltas - * @param vWarehouseFk id warehouse - * @param vNewQuantity cantidad que se queda en el ticket original - */ -BEGIN - CALL vn.collection_missingTrash(vSaleFk ,vQuantity ,vIsTrash ,vWarehouseFk ,vNewQuantity); -END$$ -DELIMITER ; - -INSERT INTO `salix`.`ACL` -(model, property, accessType, permission, principalType, principalId) -VALUES('Sale', 'missingTrash', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 98c15075e..a436c7572 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -333,7 +333,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city (1109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'), (1110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'), (1111, 'Missing', NULL, 'Missing man', 'Anton', 'The space, Universe far away', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL), - (1112, 'Trash', '12345678Z', 'Garbage man', 'Unknown name', 'New York city, Underground', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL); + (1112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city, Underground', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL); INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1 diff --git a/modules/ticket/back/methods/sale/missingTrash.js b/modules/ticket/back/methods/sale/missingTrash.js deleted file mode 100644 index 4ff37eb1f..000000000 --- a/modules/ticket/back/methods/sale/missingTrash.js +++ /dev/null @@ -1,70 +0,0 @@ -module.exports = Self => { - Self.remoteMethodCtx('missingTrash', { - description: 'Modify the amount of a sale by throwing it to faults or garbage', - accessType: 'WRITE', - accepts: [ - { - arg: 'saleFk', - type: 'number', - required: true, - description: 'The sale id' - }, - { - arg: 'quantity', - type: 'number', - required: true, - description: 'Quantity that is going to be thrown away' - }, - { - arg: 'isTrash', - type: 'boolean', - required: true, - description: 'True if garbage, false if fault' - }, - { - arg: 'warehouseFk', - type: 'number', - required: true, - description: 'The warehouse id' - }, - { - arg: 'newQuantity', - type: 'number', - required: true, - description: 'Amount remaining on the original ticket' - }, - ], - returns: { - type: ['object'], - root: true - }, - http: { - path: `/missingTrash`, - verb: 'POST' - } - }); - - Self.missingTrash = async function(ctx, saleFk, quantity, isTrash, warehouseFk, newQuantity, options) { - const myOptions = {}; - let tx; - if (typeof options == 'object') - Object.assign(myOptions, options); - - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - - try { - const missingTrash = await Self.rawSql(`CALL vn.sale_missingTrash(?, ?, ?, ?, ?)`, - [saleFk, quantity, isTrash, warehouseFk, newQuantity], myOptions); - - if (tx) await tx.commit(); - - return missingTrash; - } catch (e) { - if (tx) await tx.rollback(); - throw e; - } - }; -}; diff --git a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js b/modules/ticket/back/methods/sale/specs/missingTrash.spec.js deleted file mode 100644 index dcc59333d..000000000 --- a/modules/ticket/back/methods/sale/specs/missingTrash.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -const models = require('vn-loopback/server/server').models; -const LoopBackContext = require('loopback-context'); - -describe('sale missingTrash()', () => { - const activeCtx = { - accessToken: {userId: 9}, - headers: {origin: 'localhost:5000'}, - __: () => {} - }; - - const ctx = { - req: activeCtx - }; - - beforeEach(() => { - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - }); - - it('should modify the amount of a sale by throwing it to faults or garbage', async() => { - const tx = await models.Sale.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const quantity = 1; - const isTrash = true; - - const trashClient = await models.Client.findOne({where: {name: 'Trash'}}, options); - await trashClient.updateAttribute('name', 'BASURA', options); - - const sale = await models.Sale.findOne({fields: ['id', 'quantity', 'originalQuantity', 'ticketFk']} - , options); - - const ticket = await models.Ticket.findById(sale.ticketFk, {fields: ['warehouseFk']}, options); - - const newQuantity = sale.quantity - quantity; - - await models.Sale.missingTrash(ctx, sale.id, quantity, isTrash, ticket.warehouseFk, newQuantity, options); - - const saleAfter = await models.Sale.findById(sale.id, {fields: ['quantity', 'originalQuantity']}, options); - - expect(saleAfter.quantity).toEqual(newQuantity); - expect(saleAfter.originalQuantity).toBe(sale.quantity); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index cb8814e67..ae247fc24 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -9,7 +9,6 @@ module.exports = Self => { require('../methods/sale/refund')(Self); require('../methods/sale/canEdit')(Self); require('../methods/sale/usesMana')(Self); - require('../methods/sale/missingTrash')(Self); Self.validatesPresenceOf('concept', { message: `Concept cannot be blank` From 67f03469807df1e1025720c9414d4c63b6534fdd Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 18 Nov 2022 09:37:38 +0100 Subject: [PATCH 26/28] space fixtures --- db/dump/fixtures.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index a436c7572..c766bdee5 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2701,7 +2701,6 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) VALUES (1, 9); - INSERT INTO `vn`.`productionConfig` (`isPreviousPreparationRequired`, `ticketPrintedMax`, `ticketTrolleyMax`, `rookieDays`, `notBuyingMonths`, `id`, `isZoneClosedByExpeditionActivated`, `maxNotReadyCollections`, `minTicketsToCloseZone`, `movingTicketDelRoute`, `defaultZone`, `defautlAgencyMode`, `hasUniqueCollectionTime`, `maxCollectionWithoutUser`, `pendingCollectionsOrder`, `pendingCollectionsAge`) VALUES (0, 8, 80, 0, 0, 1, 0, 15, 25, -1, 697, 1328, 0, 1, 8, 6); From a952fc0330b61fed1fdd5df994bbe62296c61823 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 18 Nov 2022 09:38:22 +0100 Subject: [PATCH 27/28] space fixtures --- db/dump/fixtures.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index c766bdee5..a436c7572 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2701,6 +2701,7 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) VALUES (1, 9); + INSERT INTO `vn`.`productionConfig` (`isPreviousPreparationRequired`, `ticketPrintedMax`, `ticketTrolleyMax`, `rookieDays`, `notBuyingMonths`, `id`, `isZoneClosedByExpeditionActivated`, `maxNotReadyCollections`, `minTicketsToCloseZone`, `movingTicketDelRoute`, `defaultZone`, `defautlAgencyMode`, `hasUniqueCollectionTime`, `maxCollectionWithoutUser`, `pendingCollectionsOrder`, `pendingCollectionsAge`) VALUES (0, 8, 80, 0, 0, 1, 0, 15, 25, -1, 697, 1328, 0, 1, 8, 6); From 463e56b631b2eefbc6776ce802d6d080605fb719 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 21 Nov 2022 11:41:17 +0100 Subject: [PATCH 28/28] corrections --- db/changes/10503-november/00-ticket_canMerge.sql | 5 +++++ ...anbePostposed.sql => 00-ticket_canbePostponed.sql} | 1 + loopback/locale/en.json | 2 +- loopback/locale/es.json | 2 +- modules/ticket/back/methods/ticket/merge.js | 11 +++++------ modules/ticket/back/models/ticket-future.json | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) rename db/changes/10503-november/{00-ticket_canbePostposed.sql => 00-ticket_canbePostponed.sql} (99%) diff --git a/db/changes/10503-november/00-ticket_canMerge.sql b/db/changes/10503-november/00-ticket_canMerge.sql index cb0e5cfe8..843237b64 100644 --- a/db/changes/10503-november/00-ticket_canMerge.sql +++ b/db/changes/10503-november/00-ticket_canMerge.sql @@ -7,3 +7,8 @@ BEGIN CALL vn.ticket_canbePostponed(vDated,TIMESTAMPADD(DAY, vScopeDays, vDated),vLitersMax,vLinesMax,vWarehouseFk); END $$ DELIMITER ; + +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) +VALUES + ('Ticket', 'getTicketsFuture', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'merge', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/10503-november/00-ticket_canbePostposed.sql b/db/changes/10503-november/00-ticket_canbePostponed.sql similarity index 99% rename from db/changes/10503-november/00-ticket_canbePostposed.sql rename to db/changes/10503-november/00-ticket_canbePostponed.sql index 905d267a4..c691fa4bd 100644 --- a/db/changes/10503-november/00-ticket_canbePostposed.sql +++ b/db/changes/10503-november/00-ticket_canbePostponed.sql @@ -76,3 +76,4 @@ BEGIN HAVING liters <= IFNULL(vLitersMax, 9999) AND `lines` <= IFNULL(vLinesMax, 9999) AND ticketFuture; END$$ DELIMITER ; + diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 0f625a23d..07a6d7a64 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -136,5 +136,5 @@ "Not enough privileges to edit a client": "Not enough privileges to edit a client", "You don't have grant privilege": "You don't have grant privilege", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", - "MOVE_TICKET_CONFIRMATION": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" + "Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 965bc97c1..18d2218c9 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -238,5 +238,5 @@ "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente", "You don't have grant privilege": "No tienes privilegios para dar privilegios", "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario", - "MOVE_TICKET_CONFIRMATION": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" + "Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})" } diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index 0f1fa38bf..04f8d83af 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -22,7 +22,7 @@ module.exports = Self => { } }); - Self.merge = async (ctx, tickets, options) => { + Self.merge = async(ctx, tickets, options) => { const httpRequest = ctx.req; const $t = httpRequest.__; const origin = httpRequest.headers.origin; @@ -42,7 +42,7 @@ module.exports = Self => { for (let ticket of tickets) { const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`; const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`; - const message = $t('MOVE_TICKET_CONFIRMATION', { + const message = $t('Ticket merged', { originDated: dateUtil.toString(new Date(ticket.originETD)), futureDated: dateUtil.toString(new Date(ticket.destETD)), id: ticket.id, @@ -51,13 +51,12 @@ module.exports = Self => { fullPathFuture }); if (!ticket.id || !ticket.ticketFuture) continue; - await models.Sale.updateAll({ ticketFk: ticket.id }, { ticketFk: ticket.ticketFuture }, myOptions); + await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions); await models.Ticket.setDeleted(ctx, ticket.id, myOptions); await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); - }; - if (tx) { - await tx.commit(); } + if (tx) + await tx.commit(); } catch (e) { if (tx) await tx.rollback(); throw e; diff --git a/modules/ticket/back/models/ticket-future.json b/modules/ticket/back/models/ticket-future.json index 2a1b45def..00277ab8a 100644 --- a/modules/ticket/back/models/ticket-future.json +++ b/modules/ticket/back/models/ticket-future.json @@ -5,7 +5,7 @@ { "accessType": "READ", "principalType": "ROLE", - "principalId": "$authenticated", + "principalId": "employee", "permission": "ALLOW" } ]