From b45b0ff8260ee221da6902cd7cff4e557fd33533 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 20 Apr 2023 08:23:46 +0200 Subject: [PATCH 001/130] refs #5066 copy project from the other --- db/changes/231601/00-ACLgetVehiclesSorted.sql | 3 ++ .../back/methods/vehicle/getVehiclesSorted.js | 28 +++++++++++++++++++ modules/route/back/models/vehicle.js | 3 ++ modules/route/front/basic-data/index.html | 5 +++- modules/route/front/basic-data/index.js | 13 +++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 db/changes/231601/00-ACLgetVehiclesSorted.sql create mode 100644 modules/route/back/methods/vehicle/getVehiclesSorted.js create mode 100644 modules/route/back/models/vehicle.js diff --git a/db/changes/231601/00-ACLgetVehiclesSorted.sql b/db/changes/231601/00-ACLgetVehiclesSorted.sql new file mode 100644 index 000000000..5d3ec454d --- /dev/null +++ b/db/changes/231601/00-ACLgetVehiclesSorted.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) + VALUES + ('Vehicle','getVehiclesSorted','WRITE','ALLOW','employee'); \ No newline at end of file diff --git a/modules/route/back/methods/vehicle/getVehiclesSorted.js b/modules/route/back/methods/vehicle/getVehiclesSorted.js new file mode 100644 index 000000000..b785e5dc8 --- /dev/null +++ b/modules/route/back/methods/vehicle/getVehiclesSorted.js @@ -0,0 +1,28 @@ +module.exports = Self => { + Self.remoteMethod('getVehiclesSorted', { + description: 'Sort the vehicles by a warehouse', + accessType: 'WRITE', + accepts: [{ + arg: 'warehouseFk', + type: 'number' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/getVehiclesSorted`, + verb: `POST` + } + }); + + Self.getVehiclesSorted = async warehouseFk => { + const vehicles = await Self.rawSql(` + SELECT v.id, v.numberPlate, w.name + FROM vehicle v + JOIN warehouse w ON w.id = v.warehouseFk + ORDER BY v.warehouseFk = ? DESC, v.numberPlate ASC`, [warehouseFk]); + + return vehicles; + }; +}; diff --git a/modules/route/back/models/vehicle.js b/modules/route/back/models/vehicle.js new file mode 100644 index 000000000..459afe1c2 --- /dev/null +++ b/modules/route/back/models/vehicle.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/vehicle/getVehiclesSorted')(Self); +}; diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 831599ae8..9888a6859 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -24,10 +24,13 @@ + + {{numberPlate}} - {{name}} + diff --git a/modules/route/front/basic-data/index.js b/modules/route/front/basic-data/index.js index b8602ed12..80626e97e 100644 --- a/modules/route/front/basic-data/index.js +++ b/modules/route/front/basic-data/index.js @@ -7,6 +7,19 @@ class Controller extends Section { this.card.reload() ); } + constructor($element, $) { + super($element, $); + this.$http.get(`UserConfigs/getUserConfig`) + .then(res => { + if (res && res.data) { + this.$http.post(`Vehicles/getVehiclesSorted`, {warehouseFk: res.data.warehouseFk}) + .then(res => { + if (res && res.data) + this.vehicles = res.data; + }); + } + }); + } } ngModule.vnComponent('vnRouteBasicData', { From 16fdfa00fda86e5fe2cba3f57ec581f36d18152b Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 20 Apr 2023 09:09:48 +0200 Subject: [PATCH 002/130] refs #5066 e2e solve --- e2e/paths/08-route/02_basic_data.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index ff8361499..6132d5e23 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -46,7 +46,7 @@ describe('Route basic Data path', () => { it('should confirm the vehicle was edited', async() => { const vehicle = await page.waitToGetProperty(selectors.routeBasicData.vehicle, 'value'); - expect(vehicle).toEqual('1111-IMK'); + expect(vehicle).toEqual('1111-IMK - Warehouse One'); }); it('should confirm the km start was edited', async() => { From 237c83c6f551d7b8d188a0045c9be108eee3b2fa Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 20 Apr 2023 10:20:15 +0200 Subject: [PATCH 003/130] refs #5066 getVehicleSorted small mod --- modules/route/back/methods/vehicle/getVehiclesSorted.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/route/back/methods/vehicle/getVehiclesSorted.js b/modules/route/back/methods/vehicle/getVehiclesSorted.js index b785e5dc8..9dad8b80a 100644 --- a/modules/route/back/methods/vehicle/getVehiclesSorted.js +++ b/modules/route/back/methods/vehicle/getVehiclesSorted.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethod('getVehiclesSorted', { - description: 'Sort the vehicles by a warehouse', + description: 'Sort the vehicles by warehouse', accessType: 'WRITE', accepts: [{ arg: 'warehouseFk', From 91edc09057b9660fada62e4d243fa8836be12820 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 29 May 2023 10:24:37 +0200 Subject: [PATCH 004/130] refs #5066 move sql --- db/changes/232401/00-ACLgetVehiclesSorted.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 db/changes/232401/00-ACLgetVehiclesSorted.sql diff --git a/db/changes/232401/00-ACLgetVehiclesSorted.sql b/db/changes/232401/00-ACLgetVehiclesSorted.sql new file mode 100644 index 000000000..5d3ec454d --- /dev/null +++ b/db/changes/232401/00-ACLgetVehiclesSorted.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) + VALUES + ('Vehicle','getVehiclesSorted','WRITE','ALLOW','employee'); \ No newline at end of file From d8e7c2700a110bde087ae5bee817fe6fc997acfb Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 29 May 2023 12:42:27 +0200 Subject: [PATCH 005/130] refs #5066 fix autocomplete --- e2e/paths/08-route/02_basic_data.spec.js | 2 +- front/core/components/autocomplete/index.js | 14 +++++++++++++- .../back/methods/vehicle/getVehiclesSorted.js | 10 ++++++---- modules/route/front/basic-data/index.html | 8 +++----- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index 6008b0482..7ab7dda42 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -24,7 +24,7 @@ describe('Route basic Data path', () => { const form = 'vn-route-basic-data form'; const values = { worker: 'adminBossNick', - vehicle: '1111-IMK - Warehouse One', + vehicle: '1111-IMK', created: nextMonth, kmStart: 1, kmEnd: 2, diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 2539c4ef4..52491f7e0 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -174,6 +174,7 @@ export default class Autocomplete extends Field { refreshDisplayed() { let display = ''; + let hasTemplate = this.$transclude && this.$transclude.isSlotFilled('tplItem'); if (this._selection && this.showField) { if (this.multiple && Array.isArray(this._selection)) { @@ -181,8 +182,19 @@ export default class Autocomplete extends Field { if (display.length > 0) display += ', '; display += item[this.showField]; } - } else + } else { display = this._selection[this.showField]; + if (hasTemplate) { + let template = this.$transclude(() => {}, null, 'tplItem'); + const element = template[0]; + const description = element.querySelector('.text-secondary'); + if (description) description.remove(); + + const displayElement = angular.element(element); + const displayText = displayElement.text(); + display = this.$interpolate(displayText)(this._selection); + } + } } this.input.value = display; diff --git a/modules/route/back/methods/vehicle/getVehiclesSorted.js b/modules/route/back/methods/vehicle/getVehiclesSorted.js index 9dad8b80a..384d89391 100644 --- a/modules/route/back/methods/vehicle/getVehiclesSorted.js +++ b/modules/route/back/methods/vehicle/getVehiclesSorted.js @@ -18,11 +18,13 @@ module.exports = Self => { Self.getVehiclesSorted = async warehouseFk => { const vehicles = await Self.rawSql(` - SELECT v.id, v.numberPlate, w.name + SELECT ROW_NUMBER() OVER (ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate) AS 'order', + v.id, + v.warehouseFk, + CONCAT(v.numberPlate, ' - ', w.name) as description FROM vehicle v - JOIN warehouse w ON w.id = v.warehouseFk - ORDER BY v.warehouseFk = ? DESC, v.numberPlate ASC`, [warehouseFk]); - + JOIN warehouse w ON w.id = v.warehouseFk + ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate ASC`, [warehouseFk, warehouseFk]); return vehicles; }; }; diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 0f62dc107..1ba84583f 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -25,19 +25,17 @@ - - {{numberPlate}} - {{name}} - + vn-name="created"> Date: Mon, 29 May 2023 13:49:32 +0200 Subject: [PATCH 006/130] refs #5066 e2e fixs, change name sorted --- db/changes/232401/00-ACLgetVehiclesSorted.sql | 2 +- e2e/paths/08-route/02_basic_data.spec.js | 2 +- front/core/components/autocomplete/index.js | 14 +------------- .../vehicle/{getVehiclesSorted.js => sorted.js} | 6 +++--- modules/route/back/models/vehicle.js | 2 +- modules/route/front/basic-data/index.html | 3 ++- modules/route/front/basic-data/index.js | 2 +- 7 files changed, 10 insertions(+), 21 deletions(-) rename modules/route/back/methods/vehicle/{getVehiclesSorted.js => sorted.js} (85%) diff --git a/db/changes/232401/00-ACLgetVehiclesSorted.sql b/db/changes/232401/00-ACLgetVehiclesSorted.sql index 5d3ec454d..6625f0d5c 100644 --- a/db/changes/232401/00-ACLgetVehiclesSorted.sql +++ b/db/changes/232401/00-ACLgetVehiclesSorted.sql @@ -1,3 +1,3 @@ INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) VALUES - ('Vehicle','getVehiclesSorted','WRITE','ALLOW','employee'); \ No newline at end of file + ('Vehicle','sorted','WRITE','ALLOW','employee'); \ No newline at end of file diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index 7ab7dda42..6008b0482 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -24,7 +24,7 @@ describe('Route basic Data path', () => { const form = 'vn-route-basic-data form'; const values = { worker: 'adminBossNick', - vehicle: '1111-IMK', + vehicle: '1111-IMK - Warehouse One', created: nextMonth, kmStart: 1, kmEnd: 2, diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 52491f7e0..2539c4ef4 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -174,7 +174,6 @@ export default class Autocomplete extends Field { refreshDisplayed() { let display = ''; - let hasTemplate = this.$transclude && this.$transclude.isSlotFilled('tplItem'); if (this._selection && this.showField) { if (this.multiple && Array.isArray(this._selection)) { @@ -182,19 +181,8 @@ export default class Autocomplete extends Field { if (display.length > 0) display += ', '; display += item[this.showField]; } - } else { + } else display = this._selection[this.showField]; - if (hasTemplate) { - let template = this.$transclude(() => {}, null, 'tplItem'); - const element = template[0]; - const description = element.querySelector('.text-secondary'); - if (description) description.remove(); - - const displayElement = angular.element(element); - const displayText = displayElement.text(); - display = this.$interpolate(displayText)(this._selection); - } - } } this.input.value = display; diff --git a/modules/route/back/methods/vehicle/getVehiclesSorted.js b/modules/route/back/methods/vehicle/sorted.js similarity index 85% rename from modules/route/back/methods/vehicle/getVehiclesSorted.js rename to modules/route/back/methods/vehicle/sorted.js index 384d89391..4231b77cb 100644 --- a/modules/route/back/methods/vehicle/getVehiclesSorted.js +++ b/modules/route/back/methods/vehicle/sorted.js @@ -1,5 +1,5 @@ module.exports = Self => { - Self.remoteMethod('getVehiclesSorted', { + Self.remoteMethod('sorted', { description: 'Sort the vehicles by warehouse', accessType: 'WRITE', accepts: [{ @@ -11,12 +11,12 @@ module.exports = Self => { root: true }, http: { - path: `/getVehiclesSorted`, + path: `/sorted`, verb: `POST` } }); - Self.getVehiclesSorted = async warehouseFk => { + Self.sorted = async warehouseFk => { const vehicles = await Self.rawSql(` SELECT ROW_NUMBER() OVER (ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate) AS 'order', v.id, diff --git a/modules/route/back/models/vehicle.js b/modules/route/back/models/vehicle.js index 459afe1c2..73e321443 100644 --- a/modules/route/back/models/vehicle.js +++ b/modules/route/back/models/vehicle.js @@ -1,3 +1,3 @@ module.exports = Self => { - require('../methods/vehicle/getVehiclesSorted')(Self); + require('../methods/vehicle/sorted')(Self); }; diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 1ba84583f..1d6e260a9 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -28,7 +28,8 @@ show-field="description" order="order" value-field="id" - label="Vehicle"> + label="Vehicle" + vn-name="vehicle"> diff --git a/modules/route/front/basic-data/index.js b/modules/route/front/basic-data/index.js index 80626e97e..a147a451c 100644 --- a/modules/route/front/basic-data/index.js +++ b/modules/route/front/basic-data/index.js @@ -12,7 +12,7 @@ class Controller extends Section { this.$http.get(`UserConfigs/getUserConfig`) .then(res => { if (res && res.data) { - this.$http.post(`Vehicles/getVehiclesSorted`, {warehouseFk: res.data.warehouseFk}) + this.$http.post(`Vehicles/sorted`, {warehouseFk: res.data.warehouseFk}) .then(res => { if (res && res.data) this.vehicles = res.data; From b60cd2539a205433a24e41d38ae19d0ca81922e3 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 29 May 2023 15:21:37 +0200 Subject: [PATCH 007/130] refs #5712 feat(workerDms): docuware integration --- back/methods/docuware/checkFile.js | 50 ++++---- back/methods/docuware/core.js | 113 ++++++++++++++---- back/methods/docuware/download.js | 4 +- db/changes/232401/00-workerDocuware.sql | 3 + .../back/methods/worker-dms/docuware.js | 46 +++++++ .../worker/back/methods/worker-dms/filter.js | 39 +++++- modules/worker/back/models/worker-dms.js | 1 + modules/worker/front/dms/index/index.html | 12 +- modules/worker/front/dms/index/index.js | 3 +- 9 files changed, 219 insertions(+), 52 deletions(-) create mode 100644 db/changes/232401/00-workerDocuware.sql create mode 100644 modules/worker/back/methods/worker-dms/docuware.js diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js index c0a4e8ef3..447efa760 100644 --- a/back/methods/docuware/checkFile.js +++ b/back/methods/docuware/checkFile.js @@ -1,7 +1,7 @@ const axios = require('axios'); module.exports = Self => { - Self.remoteMethodCtx('checkFile', { + Self.remoteMethod('checkFile', { description: 'Check if exist docuware file', accessType: 'READ', accepts: [ @@ -20,8 +20,14 @@ module.exports = Self => { { arg: 'signed', type: 'boolean', - required: true, + required: false, description: 'If pdf is necessary to be signed' + }, + { + arg: 'filter', + type: 'object', + required: false, + description: 'The filter' } ], returns: { @@ -34,7 +40,7 @@ module.exports = Self => { } }); - Self.checkFile = async function(ctx, id, fileCabinet, signed) { + Self.checkFile = async function(id, fileCabinet, signed, filter) { const models = Self.app.models; const action = 'find'; @@ -44,35 +50,39 @@ module.exports = Self => { action: action } }); - - const searchFilter = { - condition: [ - { - DBName: docuwareInfo.findById, - - Value: [id] - } - ], - sortOrder: [ - { - Field: 'FILENAME', - Direction: 'Desc' - } - ] - }; + console.log(id, fileCabinet, signed, filter); + if (!filter) { + filter = { + condition: [ + { + DBName: docuwareInfo.findById, + Value: [id] + } + ], + sortOrder: [ + { + Field: 'FILENAME', + Direction: 'Desc' + } + ] + }; + } try { const options = await Self.getOptions(); const fileCabinetId = await Self.getFileCabinet(fileCabinet); const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); + console.log('FILTER', filter); const response = await axios.post( `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, - searchFilter, + filter, options.headers ); const [documents] = response.data.Items; + console.log(response); + console.log(response.data); if (!documents) return false; const state = documents.Fields.find(field => field.FieldName == 'ESTADO'); diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js index 2053ddf85..ac04c1958 100644 --- a/back/methods/docuware/core.js +++ b/back/methods/docuware/core.js @@ -1,6 +1,28 @@ const axios = require('axios'); module.exports = Self => { + /** + * Returns basic headers + * + * @param {string} cookie - The docuware cookie + * @return {object} - The headers + */ + Self.getOptions = async() => { + const docuwareConfig = await Self.app.models.DocuwareConfig.findOne(); + const headers = { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Cookie': docuwareConfig.cookie + } + }; + + return { + url: docuwareConfig.url, + headers + }; + }; + /** * Returns the dialog id * @@ -20,9 +42,6 @@ module.exports = Self => { const options = await Self.getOptions(); - if (!process.env.NODE_ENV) - return Math.round(); - const response = await axios.get(`${options.url}/FileCabinets/${fileCabinetId}/dialogs`, options.headers); const dialogs = response.data.Dialog; const dialogId = dialogs.find(dialogs => dialogs.DisplayName === docuwareInfo.dialogName).Id; @@ -44,9 +63,6 @@ module.exports = Self => { } }); - if (!process.env.NODE_ENV) - return Math.round(); - const fileCabinetResponse = await axios.get(`${options.url}/FileCabinets`, options.headers); const fileCabinets = fileCabinetResponse.data.FileCabinet; const fileCabinetId = fileCabinets.find(fileCabinet => fileCabinet.Name === docuwareInfo.fileCabinetName).Id; @@ -55,24 +71,81 @@ module.exports = Self => { }; /** - * Returns basic headers + * Returns docuware data * - * @param {string} cookie - The docuware cookie - * @return {object} - The headers + * @param {string} code - The fileCabinet code + * @param {object} filter - The filter for docuware + * @param {object} parse - The fields parsed + * @return {object} - The data */ - Self.getOptions = async() => { - const docuwareConfig = await Self.app.models.DocuwareConfig.findOne(); - const headers = { - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Cookie': docuwareConfig.cookie + Self.get = async(code, filter, parse) => { + const options = await Self.getOptions(); + const fileCabinetId = await Self.getFileCabinet(code); + const dialogId = await Self.getDialog(code, 'find', fileCabinetId); + + const {data} = await axios.post( + `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, + filter, + options.headers + ); + + return parser(data, parse); + }; + + /** + * Returns docuware data + * + * @param {string} code - The fileCabinet code + * @param {any} id - The id of docuware + * @param {object} parse - The fields parsed + * @return {object} - The data + */ + Self.getById = async(code, id, parse) => { + const docuwareInfo = await Self.app.models.Docuware.findOne({ + fields: ['findById'], + where: { + code: code, + action: 'find' } + }); + const filter = { + condition: [ + { + DBName: docuwareInfo.findById, + Value: [id] + } + ] }; - return { - url: docuwareConfig.url, - headers - }; + return Self.get(code, filter, parse); }; + + /** + * Returns docuware data filtered + * + * @param {array} data - The data + * @param {object} parse - The fields parsed + * @return {object} - The data parsed + */ + function parser(data, parse) { + if (!(data && data.Items)) return data; + + const parsed = []; + for (item of data.Items) { + const itemParsed = {}; + item.Fields.map(field => { + if (field.ItemElementName.includes('Date')) field.Item = toDate(field.Item); + if (!parse) return itemParsed[field.FieldLabel] = field.Item; + if (parse[field.FieldLabel]) + itemParsed[parse[field.FieldLabel]] = field.Item; + }); + parsed.push(itemParsed); + } + return parsed; + } + + function toDate(value) { + if (!value) return; + return new Date(Number(value.substring(6, 19))); + } }; diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js index 56d006ee7..b9c646adb 100644 --- a/back/methods/docuware/download.js +++ b/back/methods/docuware/download.js @@ -41,8 +41,10 @@ module.exports = Self => { } }); - Self.download = async function(ctx, id, fileCabinet) { + Self.download = async function(ctx, id, fileCabinet, filter) { const models = Self.app.models; + + // REVIEW const docuwareFile = await models.Docuware.checkFile(ctx, id, fileCabinet, true); if (!docuwareFile) throw new UserError('The DOCUWARE PDF document does not exists'); diff --git a/db/changes/232401/00-workerDocuware.sql b/db/changes/232401/00-workerDocuware.sql new file mode 100644 index 000000000..45d64bd78 --- /dev/null +++ b/db/changes/232401/00-workerDocuware.sql @@ -0,0 +1,3 @@ +INSERT INTO `vn`.`docuware` +(code, fileCabinetName, `action`, dialogName, findById) +VALUES('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO'); diff --git a/modules/worker/back/methods/worker-dms/docuware.js b/modules/worker/back/methods/worker-dms/docuware.js new file mode 100644 index 000000000..ff5902e8f --- /dev/null +++ b/modules/worker/back/methods/worker-dms/docuware.js @@ -0,0 +1,46 @@ +module.exports = Self => { + Self.remoteMethodCtx('docuwareDownload', { + description: 'Download a worker document', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'Number', + description: 'The document id', + http: {source: 'path'} + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'String', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'String', + http: {target: 'header'} + } + ], + http: { + path: `/:id/docuwareDownload`, + verb: 'GET' + } + }); + + Self.docuwareDownload = async function(ctx, id) { + // CHECK ROLE? + const filter = { + condition: [ + { + DBName: 'FILENAME', + Value: [id] + } + ] + }; + return await Self.app.models.Docuware.download(ctx, id, 'hr', false, filter); + }; +}; diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index c16b2bbb1..7de838311 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -5,6 +5,12 @@ module.exports = Self => { description: 'Find all instances of the model matched by filter from the data source.', accessType: 'READ', accepts: [ + { + arg: 'id', + type: 'Number', + description: 'The worker id', + http: {source: 'path'} + }, { arg: 'filter', type: 'Object', @@ -17,16 +23,17 @@ module.exports = Self => { root: true }, http: { - path: `/filter`, + path: `/:id/filter`, verb: 'GET' } }); - Self.filter = async(ctx, filter) => { + Self.filter = async(ctx, id, filter) => { const conn = Self.dataSource.connector; const userId = ctx.req.accessToken.userId; + const models = Self.app.models; - const account = await Self.app.models.VnUser.findById(userId); + const account = await models.VnUser.findById(userId); const stmt = new ParameterizedSQL( `SELECT d.id dmsFk, d.reference, d.description, d.file, d.created, d.hardCopyNumber, d.hasFile FROM workerDocument wd @@ -47,7 +54,31 @@ module.exports = Self => { }] }, oldWhere]}; stmt.merge(conn.makeSuffix(filter)); + const workerDms = await conn.executeStmt(stmt); - return await conn.executeStmt(stmt); + // Get docuware info + const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); + const docuwareParse = { + 'Document ID': 'dmsFk', + 'Tipo Documento': 'description', + 'Stored on': 'created', + }; + const workerDocuware = await models.Docuware.getById('hr', 'BONO MOLA XAVIER', docuwareParse);// worker.lastName + worker.firstName); + + for (document of workerDocuware) { + const defaultData = { + file: document.dmsFk + '.png', + isDocuware: true, + hardCopyNumber: null, + hasFile: false, + reference: worker.fi + }; + + document = Object.assign(document, defaultData); + } + console.log(workerDocuware); + console.log(workerDms); + + return workerDms.concat(workerDocuware); }; }; diff --git a/modules/worker/back/models/worker-dms.js b/modules/worker/back/models/worker-dms.js index b9d6f9a77..1712383b3 100644 --- a/modules/worker/back/models/worker-dms.js +++ b/modules/worker/back/models/worker-dms.js @@ -2,6 +2,7 @@ module.exports = Self => { require('../methods/worker-dms/downloadFile')(Self); require('../methods/worker-dms/removeFile')(Self); require('../methods/worker-dms/filter')(Self); + require('../methods/worker-dms/docuware')(Self); Self.isMine = async function(ctx, dmsId) { const myUserId = ctx.req.accessToken.userId; diff --git a/modules/worker/front/dms/index/index.html b/modules/worker/front/dms/index/index.html index 1404336a2..6ed3a6f15 100644 --- a/modules/worker/front/dms/index/index.html +++ b/modules/worker/front/dms/index/index.html @@ -1,6 +1,6 @@ - + ng-click="$ctrl.downloadFile(document.dmsFk, document.isDocuware)"> {{::document.file}} @@ -63,7 +63,7 @@ + ng-click="$ctrl.downloadFile(document.dmsFk, document.isDocuware)"> @@ -91,9 +91,9 @@ fixed-bottom-right> - - \ No newline at end of file + diff --git a/modules/worker/front/dms/index/index.js b/modules/worker/front/dms/index/index.js index 9bb3c896a..ae2d51a17 100644 --- a/modules/worker/front/dms/index/index.js +++ b/modules/worker/front/dms/index/index.js @@ -17,7 +17,8 @@ class Controller extends Component { }); } - downloadFile(dmsId) { + downloadFile(dmsId, isDocuware) { + if (isDocuware) return this.vnFile.download(`api/workerDms/${dmsId}/docuwareDownload`); this.vnFile.download(`api/workerDms/${dmsId}/downloadFile`); } } From 0661bf8fa98cead2a07a4ee16b499520e771be0c Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 30 May 2023 12:21:44 +0200 Subject: [PATCH 008/130] refs #5066 remake sql without ROW_ORDER --- modules/route/back/methods/vehicle/sorted.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/modules/route/back/methods/vehicle/sorted.js b/modules/route/back/methods/vehicle/sorted.js index 4231b77cb..5c4c305cc 100644 --- a/modules/route/back/methods/vehicle/sorted.js +++ b/modules/route/back/methods/vehicle/sorted.js @@ -17,14 +17,11 @@ module.exports = Self => { }); Self.sorted = async warehouseFk => { - const vehicles = await Self.rawSql(` - SELECT ROW_NUMBER() OVER (ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate) AS 'order', - v.id, - v.warehouseFk, - CONCAT(v.numberPlate, ' - ', w.name) as description - FROM vehicle v - JOIN warehouse w ON w.id = v.warehouseFk - ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate ASC`, [warehouseFk, warehouseFk]); - return vehicles; + return Self.rawSql(` + SELECT v.id, v.warehouseFk, CONCAT(v.numberPlate, ' - ', w.name) as description + FROM vehicle v + JOIN warehouse w ON w.id = v.warehouseFk + ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate ASC; + `, [warehouseFk]); }; }; From c23d8282ebf9433d69e75ad45c12323128349f9f Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 30 May 2023 15:34:11 +0200 Subject: [PATCH 009/130] refs #5712 feat(workerDms): docuware download --- back/methods/docuware/checkFile.js | 31 +++++------ back/methods/docuware/core.js | 6 +- back/methods/docuware/download.js | 17 +++--- back/methods/docuware/upload.js | 5 -- db/changes/232401/00-workerDocuware.sql | 6 +- .../back/methods/ticket/docuwareDownload.js | 55 +++++++++++++++++++ .../ticket/front/descriptor-menu/index.html | 7 +-- modules/ticket/front/descriptor-menu/index.js | 4 ++ .../back/methods/worker-dms/docuware.js | 3 +- .../worker/back/methods/worker-dms/filter.js | 3 +- modules/worker/front/dms/index/index.html | 20 +++++-- 11 files changed, 111 insertions(+), 46 deletions(-) create mode 100644 modules/ticket/back/methods/ticket/docuwareDownload.js diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js index 447efa760..803755d09 100644 --- a/back/methods/docuware/checkFile.js +++ b/back/methods/docuware/checkFile.js @@ -17,18 +17,16 @@ module.exports = Self => { required: true, description: 'The fileCabinet name' }, - { - arg: 'signed', - type: 'boolean', - required: false, - description: 'If pdf is necessary to be signed' - }, { arg: 'filter', type: 'object', - required: false, description: 'The filter' - } + }, + { + arg: 'signed', + type: 'boolean', + description: 'If pdf is necessary to be signed' + }, ], returns: { type: 'object', @@ -40,7 +38,7 @@ module.exports = Self => { } }); - Self.checkFile = async function(id, fileCabinet, signed, filter) { + Self.checkFile = async function(id, fileCabinet, filter, signed) { const models = Self.app.models; const action = 'find'; @@ -50,7 +48,8 @@ module.exports = Self => { action: action } }); - console.log(id, fileCabinet, signed, filter); + console.log('ENTRY'); + console.log(filter, signed); if (!filter) { filter = { condition: [ @@ -67,13 +66,18 @@ module.exports = Self => { ] }; } + if (signed) { + filter.condition.push({ + DBName: 'ESTADO', + Value: ['Firmado'] + }); + } try { const options = await Self.getOptions(); const fileCabinetId = await Self.getFileCabinet(fileCabinet); const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); - console.log('FILTER', filter); const response = await axios.post( `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, @@ -81,13 +85,8 @@ module.exports = Self => { options.headers ); const [documents] = response.data.Items; - console.log(response); - console.log(response.data); if (!documents) return false; - const state = documents.Fields.find(field => field.FieldName == 'ESTADO'); - if (signed && state.Item != 'Firmado') return false; - return {id: documents.Id}; } catch (error) { return false; diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js index ac04c1958..f13b69b13 100644 --- a/back/methods/docuware/core.js +++ b/back/methods/docuware/core.js @@ -83,13 +83,13 @@ module.exports = Self => { const fileCabinetId = await Self.getFileCabinet(code); const dialogId = await Self.getDialog(code, 'find', fileCabinetId); - const {data} = await axios.post( + const data = await axios.post( `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, filter, options.headers ); - - return parser(data, parse); + console.log(data.data); + return parser(data.data, parse); }; /** diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js index b9c646adb..a0d72ce01 100644 --- a/back/methods/docuware/download.js +++ b/back/methods/docuware/download.js @@ -3,7 +3,7 @@ const axios = require('axios'); const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethodCtx('download', { + Self.remoteMethod('download', { description: 'Download an docuware PDF', accessType: 'READ', accepts: [ @@ -16,8 +16,12 @@ module.exports = Self => { { arg: 'fileCabinet', type: 'string', - description: 'The file cabinet', - http: {source: 'path'} + description: 'The file cabinet' + }, + { + arg: 'filter', + type: 'object', + description: 'The filter' } ], returns: [ @@ -36,16 +40,15 @@ module.exports = Self => { } ], http: { - path: `/:id/download/:fileCabinet`, + path: `/:id/download`, verb: 'GET' } }); - Self.download = async function(ctx, id, fileCabinet, filter) { + Self.download = async function(id, fileCabinet, filter) { const models = Self.app.models; - // REVIEW - const docuwareFile = await models.Docuware.checkFile(ctx, id, fileCabinet, true); + const docuwareFile = await models.Docuware.checkFile(id, fileCabinet, filter); if (!docuwareFile) throw new UserError('The DOCUWARE PDF document does not exists'); const fileCabinetId = await Self.getFileCabinet(fileCabinet); diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index ea9ee3622..9dd1f2103 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -16,11 +16,6 @@ module.exports = Self => { arg: 'fileCabinet', type: 'string', description: 'The file cabinet' - }, - { - arg: 'dialog', - type: 'string', - description: 'The dialog' } ], returns: [], diff --git a/db/changes/232401/00-workerDocuware.sql b/db/changes/232401/00-workerDocuware.sql index 45d64bd78..fbacb23f9 100644 --- a/db/changes/232401/00-workerDocuware.sql +++ b/db/changes/232401/00-workerDocuware.sql @@ -1,3 +1,3 @@ -INSERT INTO `vn`.`docuware` -(code, fileCabinetName, `action`, dialogName, findById) -VALUES('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO'); +INSERT INTO `vn`.`docuware` (code, fileCabinetName, `action`, dialogName, findById) + VALUES + ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO'); diff --git a/modules/ticket/back/methods/ticket/docuwareDownload.js b/modules/ticket/back/methods/ticket/docuwareDownload.js new file mode 100644 index 000000000..bc74e0d21 --- /dev/null +++ b/modules/ticket/back/methods/ticket/docuwareDownload.js @@ -0,0 +1,55 @@ +module.exports = Self => { + Self.remoteMethodCtx('docuwareDownload', { + description: 'Download a ticket delivery note document', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'Number', + description: 'The document id', + http: {source: 'path'} + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'String', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'String', + http: {target: 'header'} + } + ], + http: { + path: `/:id/docuwareDownload`, + verb: 'GET' + } + }); + + Self.docuwareDownload = async function(ctx, id) { + const filter = { + condition: [ + { + DBName: docuwareInfo.findById, + Value: [id] + }, + { + DBName: 'ESTADO', + Value: ['Firmado'] + } + ], + sortOrder: [ + { + Field: 'FILENAME', + Direction: 'Desc' + } + ] + }; + return await Self.app.models.Docuware.download(id, 'deliveryNote', filter); + }; +}; diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index c2ebc3e3a..b645005be 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -36,13 +36,12 @@ translate> as PDF without prices - as PDF signed - + diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 987d6a3f1..bcb08c565 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -336,6 +336,10 @@ class Controller extends Section { this.vnApp.showSuccess(this.$t('PDF sent!')); }); } + + docuwareDownload() { + this.vnFile.download(`api/Ticket/${this.ticket.id}/docuwareDownload`); + } } Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail']; diff --git a/modules/worker/back/methods/worker-dms/docuware.js b/modules/worker/back/methods/worker-dms/docuware.js index ff5902e8f..764b7633c 100644 --- a/modules/worker/back/methods/worker-dms/docuware.js +++ b/modules/worker/back/methods/worker-dms/docuware.js @@ -32,7 +32,6 @@ module.exports = Self => { }); Self.docuwareDownload = async function(ctx, id) { - // CHECK ROLE? const filter = { condition: [ { @@ -41,6 +40,6 @@ module.exports = Self => { } ] }; - return await Self.app.models.Docuware.download(ctx, id, 'hr', false, filter); + return await Self.app.models.Docuware.download(id, 'hr', filter); }; }; diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 7de838311..eaefe67d3 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -59,12 +59,11 @@ module.exports = Self => { // Get docuware info const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); const docuwareParse = { - 'Document ID': 'dmsFk', + 'Filename': 'dmsFk', 'Tipo Documento': 'description', 'Stored on': 'created', }; const workerDocuware = await models.Docuware.getById('hr', 'BONO MOLA XAVIER', docuwareParse);// worker.lastName + worker.firstName); - for (document of workerDocuware) { const defaultData = { file: document.dmsFk + '.png', diff --git a/modules/worker/front/dms/index/index.html b/modules/worker/front/dms/index/index.html index 6ed3a6f15..9d2d5b25d 100644 --- a/modules/worker/front/dms/index/index.html +++ b/modules/worker/front/dms/index/index.html @@ -60,19 +60,31 @@ {{::document.created | date:'dd/MM/yyyy HH:mm'}} - + - - + + - + + + + + Date: Wed, 31 May 2023 10:04:34 +0200 Subject: [PATCH 010/130] refs #5066 sorted without CONCAT, order=false --- modules/route/back/methods/vehicle/sorted.js | 2 +- modules/route/front/basic-data/index.html | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/route/back/methods/vehicle/sorted.js b/modules/route/back/methods/vehicle/sorted.js index 5c4c305cc..b379743bc 100644 --- a/modules/route/back/methods/vehicle/sorted.js +++ b/modules/route/back/methods/vehicle/sorted.js @@ -18,7 +18,7 @@ module.exports = Self => { Self.sorted = async warehouseFk => { return Self.rawSql(` - SELECT v.id, v.warehouseFk, CONCAT(v.numberPlate, ' - ', w.name) as description + SELECT v.id, v.warehouseFk, v.numberPlate, w.name FROM vehicle v JOIN warehouse w ON w.id = v.warehouseFk ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate ASC; diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 1d6e260a9..bf7bf672c 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -22,14 +22,14 @@
{{::name}}
- + order="false"> + {{::numberPlate}} - {{::name}}
From d18137bce0c97552ab8628d4458d5f346678ce9e Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 31 May 2023 10:20:13 +0200 Subject: [PATCH 011/130] refs #5066 not dense --- modules/route/front/basic-data/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index bf7bf672c..514c535a2 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -22,7 +22,7 @@
{{::name}}
- Date: Wed, 31 May 2023 11:32:37 +0200 Subject: [PATCH 012/130] refs #5712 openDocuware --- back/methods/docuware/checkFile.js | 3 +-- back/methods/docuware/core.js | 1 - db/changes/232401/00-workerDocuware.sql | 4 ++++ front/core/services/app.js | 6 +++++- front/core/services/locale/es.yml | 3 ++- .../worker/back/methods/worker-dms/filter.js | 4 +--- modules/worker/front/dms/index/index.html | 20 +++++++------------ modules/worker/front/dms/index/index.js | 5 +++++ 8 files changed, 25 insertions(+), 21 deletions(-) diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js index 803755d09..18d169085 100644 --- a/back/methods/docuware/checkFile.js +++ b/back/methods/docuware/checkFile.js @@ -48,8 +48,7 @@ module.exports = Self => { action: action } }); - console.log('ENTRY'); - console.log(filter, signed); + if (!filter) { filter = { condition: [ diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js index f13b69b13..7bb3e617a 100644 --- a/back/methods/docuware/core.js +++ b/back/methods/docuware/core.js @@ -88,7 +88,6 @@ module.exports = Self => { filter, options.headers ); - console.log(data.data); return parser(data.data, parse); }; diff --git a/db/changes/232401/00-workerDocuware.sql b/db/changes/232401/00-workerDocuware.sql index fbacb23f9..c8d4e4f23 100644 --- a/db/changes/232401/00-workerDocuware.sql +++ b/db/changes/232401/00-workerDocuware.sql @@ -1,3 +1,7 @@ INSERT INTO `vn`.`docuware` (code, fileCabinetName, `action`, dialogName, findById) VALUES ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO'); + +INSERT INTO `salix`.`url` (appName, environment, url) + VALUES + ('docuware', 'production', 'https://verdnatura.docuware.cloud/DocuWare/Platform/'); diff --git a/front/core/services/app.js b/front/core/services/app.js index fb0a08777..6c80fafcc 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -66,7 +66,11 @@ export default class App { return this.logger.$http.get('Urls/findOne', {filter}) .then(res => { - return res.data.url + route; + if (res && res.data) + return res.data.url + route; + }) + .catch(() => { + this.showError('Direction not found'); }); } } diff --git a/front/core/services/locale/es.yml b/front/core/services/locale/es.yml index cf8801b52..e9811e38f 100644 --- a/front/core/services/locale/es.yml +++ b/front/core/services/locale/es.yml @@ -3,4 +3,5 @@ Could not contact the server: No se ha podido contactar con el servidor, asegura Please enter your username: Por favor introduce tu nombre de usuario It seems that the server has fall down: Parece que el servidor se ha caído, espera unos minutos e inténtalo de nuevo Session has expired: Tu sesión ha expirado, por favor vuelve a iniciar sesión -Access denied: Acción no permitida \ No newline at end of file +Access denied: Acción no permitida +Direction not found: Dirección no encontrada diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index eaefe67d3..0b89cc883 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -63,7 +63,7 @@ module.exports = Self => { 'Tipo Documento': 'description', 'Stored on': 'created', }; - const workerDocuware = await models.Docuware.getById('hr', 'BONO MOLA XAVIER', docuwareParse);// worker.lastName + worker.firstName); + const workerDocuware = await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse); for (document of workerDocuware) { const defaultData = { file: document.dmsFk + '.png', @@ -75,8 +75,6 @@ module.exports = Self => { document = Object.assign(document, defaultData); } - console.log(workerDocuware); - console.log(workerDms); return workerDms.concat(workerDocuware); }; diff --git a/modules/worker/front/dms/index/index.html b/modules/worker/front/dms/index/index.html index 9d2d5b25d..aefbbcf34 100644 --- a/modules/worker/front/dms/index/index.html +++ b/modules/worker/front/dms/index/index.html @@ -60,11 +60,13 @@ {{::document.created | date:'dd/MM/yyyy HH:mm'}} - + + + @@ -76,19 +78,11 @@ tabindex="-1"> - - - - - + diff --git a/modules/worker/front/dms/index/index.js b/modules/worker/front/dms/index/index.js index ae2d51a17..489fe1732 100644 --- a/modules/worker/front/dms/index/index.js +++ b/modules/worker/front/dms/index/index.js @@ -21,6 +21,11 @@ class Controller extends Component { if (isDocuware) return this.vnFile.download(`api/workerDms/${dmsId}/docuwareDownload`); this.vnFile.download(`api/workerDms/${dmsId}/downloadFile`); } + + async openDocuware() { + const url = await this.vnApp.getUrl(`WebClient`, 'docuware'); + if (url) window.open(url).focus(); + } } Controller.$inject = ['$element', '$scope', 'vnFile']; From cc27d1fa97df7d7ce648a9b0d4019618525bbb85 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 7 Jun 2023 08:30:37 +0200 Subject: [PATCH 013/130] refs #5066 fix vehicle res.data --- modules/route/front/basic-data/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/route/front/basic-data/index.js b/modules/route/front/basic-data/index.js index a147a451c..d7f178985 100644 --- a/modules/route/front/basic-data/index.js +++ b/modules/route/front/basic-data/index.js @@ -11,10 +11,10 @@ class Controller extends Section { super($element, $); this.$http.get(`UserConfigs/getUserConfig`) .then(res => { - if (res && res.data) { + if (res.data) { this.$http.post(`Vehicles/sorted`, {warehouseFk: res.data.warehouseFk}) .then(res => { - if (res && res.data) + if (res.data) this.vehicles = res.data; }); } From 0cc5781f3fc2b562ee1fd617a40f35402be2fd6d Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 13 Jun 2023 15:05:37 +0200 Subject: [PATCH 014/130] =?UTF-8?q?refs=20#4734=20feat:=20a=C3=B1adido=20m?= =?UTF-8?q?=C3=A9todo=20putExpedicionInternacional=20de=20viaexpress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../putExpedicionInternacional.js | 135 ++++++++++++++++++ back/model-config.json | 3 + back/models/viaexpress-config.js | 3 + back/models/viaexpress-config.json | 34 +++++ db/changes/232601/00-acl_viaexpressConfig.sql | 3 + db/changes/232601/00-viaexpress.sql | 13 ++ db/dump/fixtures.sql | 12 +- 7 files changed, 197 insertions(+), 6 deletions(-) create mode 100644 back/methods/viaexpress-config/putExpedicionInternacional.js create mode 100644 back/models/viaexpress-config.js create mode 100644 back/models/viaexpress-config.json create mode 100644 db/changes/232601/00-acl_viaexpressConfig.sql create mode 100644 db/changes/232601/00-viaexpress.sql diff --git a/back/methods/viaexpress-config/putExpedicionInternacional.js b/back/methods/viaexpress-config/putExpedicionInternacional.js new file mode 100644 index 000000000..dc1df3218 --- /dev/null +++ b/back/methods/viaexpress-config/putExpedicionInternacional.js @@ -0,0 +1,135 @@ +const axios = require('axios'); + +module.exports = Self => { + Self.remoteMethod('putExpedicionInternacional', { + description: 'Returns the lastest campaigns', + accessType: 'WRITE', + accepts: [{ + arg: 'expeditionFk', + type: 'number', + required: true + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/putExpedicionInternacional`, + verb: 'POST' + } + }); + + Self.putExpedicionInternacional = async(expeditionFk, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const [data] = await Self.rawSql(` + SELECT urlAccess, + clientViaexpress, + userViaexpress, + passwordViaexpress, + defaultWeight, + DATE_FORMAT(t.shipped, '%Y-%m-%d') shipped, + deliveryType, + cv.socialName senderName, + av.street senderStreet, + av.postalCode senderPostalCode, + av.city senderCity, + pv.name senderProvince, + IFNULL(av.mobile, IFNULL(av.phone, IFNULL(cv.mobile, cv.phone))) senderPhone, + SUBSTRING_INDEX(cv.email, ',', 1) senderEmail, + a.nickname receiverName, + a.street receiverStreet, + a.postalCode receiverPostalCode, + a.city receiverCity, + p.name receiverProvince, + IFNULL(a.mobile, IFNULL(a.phone, IFNULL(c.mobile, c.phone))) receiverPhone, + SUBSTRING_INDEX(c.email, ',', 1) receiverEmail, + c2.code receiverCountry + FROM vn.viaexpressConfig + JOIN vn.expedition e ON e.id = ? + JOIN vn.ticket t ON t.id = e.ticketFk + JOIN vn.address a ON a.id = t.addressFk + JOIN vn.province p ON p.id = a.provinceFk + JOIN vn.client c ON c.id = t.clientFk + JOIN vn.company co ON co.id = t.companyFk + JOIN vn.client cv ON cv.id = co.clientFk + JOIN vn.address av ON av.id = cv.defaultAddressFk + JOIN vn.province pv ON pv.id = av.provinceFk + JOIN vn.country c2 ON c2.id = p.countryFk`, [expeditionFk], myOptions); + + const xmlData = ` + + + + + ${data.defaultWeight} + 1 + 0 + ${data.shipped} + 0 + ${data.deliveryType} + 0 + 0 + 0 + 0 + 0 + + + 0 + + + + ${data.senderName} + ${data.senderStreet} + ${data.senderPostalCode} + ${data.senderCity} + ${data.senderProvince} + + ${data.senderPhone} + ${data.senderEmail} + + + ${data.receiverName} + ${data.receiverStreet} + ${data.receiverPostalCode} + ${data.receiverCity} + + ${data.receiverProvince} + + ${data.receiverPhone} + ${data.receiverEmail} + ${data.receiverCountry} + + + ${data.clientViaexpress} + ${data.userViaexpress} + ${data.passwordViaexpress} + + + + + `; + + const url = 'http://82.223.6.71:82/ServicioVxClientes.asmx'; + try { + const response = await axios.post(url, xmlData, { + headers: { + 'Content-Type': 'application/soap+xml; charset=utf-8' + } + }); + + const startTag = ''; + const endTag = ''; + const startIndex = response.data.indexOf(startTag) + startTag.length; + const endIndex = response.data.indexOf(endTag); + const referenciaVx = response.data.substring(startIndex, endIndex); + + return referenciaVx; + } catch (error) { + throw Error(error.response.data); + } + }; +}; diff --git a/back/model-config.json b/back/model-config.json index ff2bf5850..ec126455b 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -139,6 +139,9 @@ }, "PrintConfig": { "dataSource": "vn" + }, + "ViaexpressConfig": { + "dataSource": "vn" } } diff --git a/back/models/viaexpress-config.js b/back/models/viaexpress-config.js new file mode 100644 index 000000000..712bde60d --- /dev/null +++ b/back/models/viaexpress-config.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/viaexpress-config/putExpedicionInternacional')(Self); +}; diff --git a/back/models/viaexpress-config.json b/back/models/viaexpress-config.json new file mode 100644 index 000000000..ed150a448 --- /dev/null +++ b/back/models/viaexpress-config.json @@ -0,0 +1,34 @@ +{ + "name": "ViaexpressConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "viaexpressConfig" + } + }, + "properties": { + "id": { + "type": "number", + "required": true + }, + "urlAccess": { + "type": "string", + "required": true + }, + "clientViaexpress": { + "type": "date" + }, + "userViaexpress": { + "type": "number" + }, + "passwordViaexpress": { + "type": "number" + }, + "defaultWeight": { + "type": "number" + }, + "deliveryType": { + "type": "number" + } + } +} diff --git a/db/changes/232601/00-acl_viaexpressConfig.sql b/db/changes/232601/00-acl_viaexpressConfig.sql new file mode 100644 index 000000000..837185262 --- /dev/null +++ b/db/changes/232601/00-acl_viaexpressConfig.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('ViaexpressConfig', 'putExpedicionInternacional', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/232601/00-viaexpress.sql b/db/changes/232601/00-viaexpress.sql new file mode 100644 index 000000000..1313135f9 --- /dev/null +++ b/db/changes/232601/00-viaexpress.sql @@ -0,0 +1,13 @@ +CREATE TABLE `vn`.`viaexpressConfig` ( + id int auto_increment NOT NULL, + urlAccess varchar(100) NOT NULL, + clientViaexpress varchar(100) NOT NULL, + userViaexpress varchar(100) NOT NULL, + passwordViaexpress varchar(100) NOT NULL, + defaultWeight decimal(10,2) NOT NULL, + deliveryType varchar(5) NOT NULL, + CONSTRAINT viaexpressConfig_PK PRIMARY KEY (id) +) +ENGINE=InnoDB +DEFAULT CHARSET=utf8mb3 +COLLATE=utf8mb3_unicode_ci; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index a6557ff89..eddb1f6a9 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -566,13 +566,13 @@ INSERT INTO `vn`.`supplierAccount`(`id`, `supplierFk`, `iban`, `bankEntityFk`) VALUES (241, 442, 'ES111122333344111122221111', 128); -INSERT INTO `vn`.`company`(`id`, `code`, `supplierAccountFk`, `workerManagerFk`, `companyCode`, `sage200Company`, `expired`, `companyGroupFk`, `phytosanitary`) +INSERT INTO `vn`.`company`(`id`, `code`, `supplierAccountFk`, `workerManagerFk`, `companyCode`, `sage200Company`, `expired`, `companyGroupFk`, `phytosanitary` , `clientFk`) VALUES - (69 , 'CCs', NULL, 30, NULL, 0, NULL, 1, NULL), - (442 , 'VNL', 241, 30, 2 , 1, NULL, 2, 'VNL Company - Plant passport'), - (567 , 'VNH', NULL, 30, NULL, 4, NULL, 1, 'VNH Company - Plant passport'), - (791 , 'FTH', NULL, 30, NULL, 3, '2015-11-30', 1, NULL), - (1381, 'ORN', NULL, 30, NULL, 7, NULL, 1, 'ORN Company - Plant passport'); + (69 , 'CCs', NULL, 30, NULL, 0, NULL, 1, NULL , NULL), + (442 , 'VNL', 241, 30, 2 , 1, NULL, 2, 'VNL Company - Plant passport' , 1101), + (567 , 'VNH', NULL, 30, NULL, 4, NULL, 1, 'VNH Company - Plant passport' , NULL), + (791 , 'FTH', NULL, 30, NULL, 3, '2015-11-30', 1, NULL , NULL), + (1381, 'ORN', NULL, 30, NULL, 7, NULL, 1, 'ORN Company - Plant passport' , NULL); INSERT INTO `vn`.`taxArea` (`code`, `claveOperacionFactura`, `CodigoTransaccion`) VALUES From 0a9bdc6f891b050c95f1806857681c4119dd5ff8 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 13:25:45 +0200 Subject: [PATCH 015/130] test: jenkins test secuenciales --- Jenkinsfile | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index cf9b8cd67..1fe2cfc9b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,19 +54,17 @@ pipeline { NODE_ENV = "" TZ = 'Europe/Madrid' } - parallel { - stage('Frontend') { - steps { - nodejs('node-v20') { - sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' - } + stage('Frontend') { + steps { + nodejs('node-v20') { + sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' } } - stage('Backend') { - steps { - nodejs('node-v20') { - sh 'npm run test:back:ci' - } + } + stage('Backend') { + steps { + nodejs('node-v20') { + sh 'npm run test:back:ci' } } } From 1f4e98075cfa5d36ed309246870b8e6572e97f6b Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 13:27:35 +0200 Subject: [PATCH 016/130] fix: test secuendiales --- Jenkinsfile | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1fe2cfc9b..72d70dc97 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,17 +54,19 @@ pipeline { NODE_ENV = "" TZ = 'Europe/Madrid' } - stage('Frontend') { - steps { - nodejs('node-v20') { - sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' + steps { + stage('Frontend') { + steps { + nodejs('node-v20') { + sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' + } } } - } - stage('Backend') { - steps { - nodejs('node-v20') { - sh 'npm run test:back:ci' + stage('Backend') { + steps { + nodejs('node-v20') { + sh 'npm run test:back:ci' + } } } } From a31b735d3cef087646a8d7ea1d498741cfb942cd Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 13:29:00 +0200 Subject: [PATCH 017/130] fix --- Jenkinsfile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 72d70dc97..5345b6dfe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -55,17 +55,18 @@ pipeline { TZ = 'Europe/Madrid' } steps { - stage('Frontend') { - steps { - nodejs('node-v20') { - sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' + script { + if (!env.BRANCH_NAME.equals('test') && !env.BRANCH_NAME.equals('master')) { + stage('Frontend') { + nodejs('node-v20') { + sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' + } } - } - } - stage('Backend') { - steps { - nodejs('node-v20') { - sh 'npm run test:back:ci' + + stage('Backend') { + nodejs('node-v20') { + sh 'npm run test:back:ci' + } } } } From 2da54ac3d72175c28cb7b11972dcba43fa0e6cc7 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 13:39:05 +0200 Subject: [PATCH 018/130] test secuenciales --- Jenkinsfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5345b6dfe..897bf4f3e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -57,17 +57,17 @@ pipeline { steps { script { if (!env.BRANCH_NAME.equals('test') && !env.BRANCH_NAME.equals('master')) { - stage('Frontend') { - nodejs('node-v20') { - sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' - } - } - stage('Backend') { nodejs('node-v20') { sh 'npm run test:back:ci' } } + + stage('Frontend') { + nodejs('node-v20') { + sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' + } + } } } } From 998597dfcc53f90f4fe5bc4334f87045c2d5f05b Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 13:49:21 +0200 Subject: [PATCH 019/130] refs #4734 recator: cambiado nombre ruta --- ...onInternacional.js => internationalExpedition.js} | 12 ++++++------ back/models/viaexpress-config.js | 2 +- back/models/viaexpress-config.json | 2 +- db/changes/232601/00-acl_viaexpressConfig.sql | 2 +- db/changes/232601/00-viaexpress.sql | 7 ++----- 5 files changed, 11 insertions(+), 14 deletions(-) rename back/methods/viaexpress-config/{putExpedicionInternacional.js => internationalExpedition.js} (94%) diff --git a/back/methods/viaexpress-config/putExpedicionInternacional.js b/back/methods/viaexpress-config/internationalExpedition.js similarity index 94% rename from back/methods/viaexpress-config/putExpedicionInternacional.js rename to back/methods/viaexpress-config/internationalExpedition.js index dc1df3218..99a4197c7 100644 --- a/back/methods/viaexpress-config/putExpedicionInternacional.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -1,7 +1,7 @@ const axios = require('axios'); module.exports = Self => { - Self.remoteMethod('putExpedicionInternacional', { + Self.remoteMethod('internationalExpedition', { description: 'Returns the lastest campaigns', accessType: 'WRITE', accepts: [{ @@ -14,19 +14,20 @@ module.exports = Self => { root: true }, http: { - path: `/putExpedicionInternacional`, + path: `/internationalExpedition`, verb: 'POST' } }); - Self.putExpedicionInternacional = async(expeditionFk, options) => { + Self.internationalExpedition = async(expeditionFk, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const [data] = await Self.rawSql(` - SELECT urlAccess, + SELECT + url, clientViaexpress, userViaexpress, passwordViaexpress, @@ -113,9 +114,8 @@ module.exports = Self => { `; - const url = 'http://82.223.6.71:82/ServicioVxClientes.asmx'; try { - const response = await axios.post(url, xmlData, { + const response = await axios.post(`${data.url}ServicioVxClientes.asmx`, xmlData, { headers: { 'Content-Type': 'application/soap+xml; charset=utf-8' } diff --git a/back/models/viaexpress-config.js b/back/models/viaexpress-config.js index 712bde60d..72424f806 100644 --- a/back/models/viaexpress-config.js +++ b/back/models/viaexpress-config.js @@ -1,3 +1,3 @@ module.exports = Self => { - require('../methods/viaexpress-config/putExpedicionInternacional')(Self); + require('../methods/viaexpress-config/internationalExpedition')(Self); }; diff --git a/back/models/viaexpress-config.json b/back/models/viaexpress-config.json index ed150a448..5927cee3f 100644 --- a/back/models/viaexpress-config.json +++ b/back/models/viaexpress-config.json @@ -11,7 +11,7 @@ "type": "number", "required": true }, - "urlAccess": { + "url": { "type": "string", "required": true }, diff --git a/db/changes/232601/00-acl_viaexpressConfig.sql b/db/changes/232601/00-acl_viaexpressConfig.sql index 837185262..91a7e3c5b 100644 --- a/db/changes/232601/00-acl_viaexpressConfig.sql +++ b/db/changes/232601/00-acl_viaexpressConfig.sql @@ -1,3 +1,3 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('ViaexpressConfig', 'putExpedicionInternacional', 'WRITE', 'ALLOW', 'ROLE', 'employee'); + ('ViaexpressConfig', 'internationalExpedition', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/232601/00-viaexpress.sql b/db/changes/232601/00-viaexpress.sql index 1313135f9..9e3baa9fd 100644 --- a/db/changes/232601/00-viaexpress.sql +++ b/db/changes/232601/00-viaexpress.sql @@ -1,13 +1,10 @@ CREATE TABLE `vn`.`viaexpressConfig` ( id int auto_increment NOT NULL, - urlAccess varchar(100) NOT NULL, + url varchar(100) NOT NULL, clientViaexpress varchar(100) NOT NULL, userViaexpress varchar(100) NOT NULL, passwordViaexpress varchar(100) NOT NULL, defaultWeight decimal(10,2) NOT NULL, deliveryType varchar(5) NOT NULL, CONSTRAINT viaexpressConfig_PK PRIMARY KEY (id) -) -ENGINE=InnoDB -DEFAULT CHARSET=utf8mb3 -COLLATE=utf8mb3_unicode_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; From 1027e0753e399e4e7ed39d35468c1c5197945623 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 14:06:36 +0200 Subject: [PATCH 020/130] test in paralel --- Jenkinsfile | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 897bf4f3e..cf9b8cd67 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -54,19 +54,18 @@ pipeline { NODE_ENV = "" TZ = 'Europe/Madrid' } - steps { - script { - if (!env.BRANCH_NAME.equals('test') && !env.BRANCH_NAME.equals('master')) { - stage('Backend') { - nodejs('node-v20') { - sh 'npm run test:back:ci' - } + parallel { + stage('Frontend') { + steps { + nodejs('node-v20') { + sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' } - - stage('Frontend') { - nodejs('node-v20') { - sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=2' - } + } + } + stage('Backend') { + steps { + nodejs('node-v20') { + sh 'npm run test:back:ci' } } } From 90ce0d1c275e1f508bceb8a13224aef97262ada4 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 14:24:47 +0200 Subject: [PATCH 021/130] refs #4734 refactor: consulta con loopback --- .../internationalExpedition.js | 95 +++++++++++++++++-- back/models/company.json | 7 ++ 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index 99a4197c7..fd8d69e6d 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -20,6 +20,7 @@ module.exports = Self => { }); Self.internationalExpedition = async(expeditionFk, options) => { + const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') @@ -27,13 +28,13 @@ module.exports = Self => { const [data] = await Self.rawSql(` SELECT - url, - clientViaexpress, - userViaexpress, - passwordViaexpress, - defaultWeight, + -- url, + -- clientViaexpress, + -- userViaexpress, + -- passwordViaexpress, + -- defaultWeight, + -- deliveryType, DATE_FORMAT(t.shipped, '%Y-%m-%d') shipped, - deliveryType, cv.socialName senderName, av.street senderStreet, av.postalCode senderPostalCode, @@ -61,6 +62,88 @@ module.exports = Self => { JOIN vn.province pv ON pv.id = av.provinceFk JOIN vn.country c2 ON c2.id = p.countryFk`, [expeditionFk], myOptions); + const expedition = await models.Expedition.findOne({ + fields: ['id', 'ticketFk'], + where: {id: expeditionFk}, + include: [ + { + relation: 'ticket', + scope: { + fields: ['shipped', 'addressFk', 'clientFk', 'companyFk'], + include: [ + { + relation: 'client', + scope: { + fields: ['mobile', 'phone', 'email'] + } + }, + { + relation: 'address', + scope: { + fields: [ + 'nickname', + 'street', + 'postalCode', + 'city', + 'mobile', + 'phone', + 'provinceFk' + ], + include: { + relation: 'province', + scope: { + fields: ['name', 'countryFk'], + include: { + relation: 'country', + scope: { + fields: ['code'], + } + } + + } + } + } + }, + { + relation: 'company', + scope: { + fields: ['clientFk'], + include: { + relation: 'client', + scope: { + fields: ['socialName', 'mobile', 'phone', 'email', 'defaultAddressFk'], + include: { + relation: 'defaultAddress', + scope: { + fields: [ + 'street', + 'postalCode', + 'city', + 'mobile', + 'phone', + 'provinceFk' + ], + include: { + relation: 'province', + scope: { + fields: ['name'] + } + } + } + } + } + } + } + } + ] + } + + } + ] + }, myOptions); + console.log(data); + console.log(expedition); + const xmlData = ` diff --git a/back/models/company.json b/back/models/company.json index f16c5762f..53266e38a 100644 --- a/back/models/company.json +++ b/back/models/company.json @@ -24,5 +24,12 @@ "where" :{ "expired": null } + }, + "relations": { + "client": { + "type": "belongsTo", + "model": "Client", + "foreignKey": "clientFk" + } } } From ab68cb7165a0ae7a34074c6699f716a1476600e1 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 14:27:29 +0200 Subject: [PATCH 022/130] refs #4734 fix: manejo errores --- back/methods/viaexpress-config/internationalExpedition.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index fd8d69e6d..dd46ff794 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -212,7 +212,8 @@ module.exports = Self => { return referenciaVx; } catch (error) { - throw Error(error.response.data); + if (error?.response?.data) throw Error(error.response.data); + throw Error(error); } }; }; From 219ad75172ad57a6e76fa4ae84c718f249f0f3b6 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 16 Jun 2023 14:30:33 +0200 Subject: [PATCH 023/130] a --- .../viaexpress-config/internationalExpedition.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index dd46ff794..23b62e845 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -28,12 +28,12 @@ module.exports = Self => { const [data] = await Self.rawSql(` SELECT - -- url, - -- clientViaexpress, - -- userViaexpress, - -- passwordViaexpress, - -- defaultWeight, - -- deliveryType, + url, + clientViaexpress, + userViaexpress, + passwordViaexpress, + defaultWeight, + deliveryType, DATE_FORMAT(t.shipped, '%Y-%m-%d') shipped, cv.socialName senderName, av.street senderStreet, From 303be74382a9bc38f931e994db15027df9e890f7 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 19 Jun 2023 11:55:07 +0200 Subject: [PATCH 024/130] refs #4734 refactor: use loopback instead of --- .../internationalExpedition.js | 92 +++++++------------ back/models/viaexpress-config.json | 8 +- 2 files changed, 36 insertions(+), 64 deletions(-) diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index 23b62e845..70a68acd6 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -26,42 +26,6 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const [data] = await Self.rawSql(` - SELECT - url, - clientViaexpress, - userViaexpress, - passwordViaexpress, - defaultWeight, - deliveryType, - DATE_FORMAT(t.shipped, '%Y-%m-%d') shipped, - cv.socialName senderName, - av.street senderStreet, - av.postalCode senderPostalCode, - av.city senderCity, - pv.name senderProvince, - IFNULL(av.mobile, IFNULL(av.phone, IFNULL(cv.mobile, cv.phone))) senderPhone, - SUBSTRING_INDEX(cv.email, ',', 1) senderEmail, - a.nickname receiverName, - a.street receiverStreet, - a.postalCode receiverPostalCode, - a.city receiverCity, - p.name receiverProvince, - IFNULL(a.mobile, IFNULL(a.phone, IFNULL(c.mobile, c.phone))) receiverPhone, - SUBSTRING_INDEX(c.email, ',', 1) receiverEmail, - c2.code receiverCountry - FROM vn.viaexpressConfig - JOIN vn.expedition e ON e.id = ? - JOIN vn.ticket t ON t.id = e.ticketFk - JOIN vn.address a ON a.id = t.addressFk - JOIN vn.province p ON p.id = a.provinceFk - JOIN vn.client c ON c.id = t.clientFk - JOIN vn.company co ON co.id = t.companyFk - JOIN vn.client cv ON cv.id = co.clientFk - JOIN vn.address av ON av.id = cv.defaultAddressFk - JOIN vn.province pv ON pv.id = av.provinceFk - JOIN vn.country c2 ON c2.id = p.countryFk`, [expeditionFk], myOptions); - const expedition = await models.Expedition.findOne({ fields: ['id', 'ticketFk'], where: {id: expeditionFk}, @@ -141,20 +105,28 @@ module.exports = Self => { } ] }, myOptions); - console.log(data); - console.log(expedition); + + const viaexpressConfig = await models.ViaexpressConfig.findOne({ + fields: ['url', 'clientViaexpress', 'userViaexpress', 'passwordViaexpress', 'defaultWeight', 'deliveryType'] + }, myOptions); + + const shipped = expedition.ticket().shipped; + const year = shipped.getFullYear(); + const month = shipped.getMonth() + 1; + const day = shipped.getDate(); + const date = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`; const xmlData = ` - ${data.defaultWeight} + ${viaexpressConfig.defaultWeight} 1 0 - ${data.shipped} + ${date} 0 - ${data.deliveryType} + ${viaexpressConfig.deliveryType} 0 0 0 @@ -166,31 +138,31 @@ module.exports = Self => { - ${data.senderName} - ${data.senderStreet} - ${data.senderPostalCode} - ${data.senderCity} - ${data.senderProvince} + ${expedition.ticket().company().client().socialName} + ${expedition.ticket().company().client().defaultAddress().street} + ${expedition.ticket().company().client().defaultAddress().postalCode} + ${expedition.ticket().company().client().defaultAddress().city} + ${expedition.ticket().company().client().defaultAddress().province().name} - ${data.senderPhone} - ${data.senderEmail} + ${expedition.ticket().company().client().defaultAddress().mobile || expedition.ticket().company().client().defaultAddress().phone || expedition.ticket().company().client().mobile || expedition.ticket().company().client().phone} + ${expedition.ticket().company().client().email} - ${data.receiverName} - ${data.receiverStreet} - ${data.receiverPostalCode} - ${data.receiverCity} + ${expedition.ticket().address().nickname} + ${expedition.ticket().address().street} + ${expedition.ticket().address().postalCode} + ${expedition.ticket().address().city} - ${data.receiverProvince} + ${expedition.ticket().address().province().name} - ${data.receiverPhone} - ${data.receiverEmail} - ${data.receiverCountry} + ${expedition.ticket().address().mobile || expedition.ticket().address().phone || expedition.ticket().client().mobile || expedition.ticket().client().phone} + ${expedition.ticket().client().email} + ${expedition.ticket().address().province().country().code} - ${data.clientViaexpress} - ${data.userViaexpress} - ${data.passwordViaexpress} + ${viaexpressConfig.clientViaexpress} + ${viaexpressConfig.userViaexpress} + ${viaexpressConfig.passwordViaexpress} @@ -198,7 +170,7 @@ module.exports = Self => { `; try { - const response = await axios.post(`${data.url}ServicioVxClientes.asmx`, xmlData, { + const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, xmlData, { headers: { 'Content-Type': 'application/soap+xml; charset=utf-8' } diff --git a/back/models/viaexpress-config.json b/back/models/viaexpress-config.json index 5927cee3f..26d6c8e37 100644 --- a/back/models/viaexpress-config.json +++ b/back/models/viaexpress-config.json @@ -16,19 +16,19 @@ "required": true }, "clientViaexpress": { - "type": "date" + "type": "string" }, "userViaexpress": { - "type": "number" + "type": "string" }, "passwordViaexpress": { - "type": "number" + "type": "string" }, "defaultWeight": { "type": "number" }, "deliveryType": { - "type": "number" + "type": "string" } } } From cfe340eeff471d70d188e5f1b5573179b38941b1 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 19 Jun 2023 14:27:24 +0200 Subject: [PATCH 025/130] refs #4734 feat: xml en otro archivo --- .../internationalExpedition.js | 232 ++++++------------ back/methods/viaexpress-config/renderer.js | 162 ++++++++++++ back/methods/viaexpress-config/template.xml | 52 ++++ back/models/viaexpress-config.js | 1 + package.json | 1 + 5 files changed, 285 insertions(+), 163 deletions(-) create mode 100644 back/methods/viaexpress-config/renderer.js create mode 100644 back/methods/viaexpress-config/template.xml diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index 70a68acd6..cbb1c2c67 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -1,4 +1,5 @@ const axios = require('axios'); +const fs = require('fs'); module.exports = Self => { Self.remoteMethod('internationalExpedition', { @@ -19,173 +20,78 @@ module.exports = Self => { } }); - Self.internationalExpedition = async(expeditionFk, options) => { + Self.internationalExpedition = async expeditionFk => { const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const expedition = await models.Expedition.findOne({ - fields: ['id', 'ticketFk'], - where: {id: expeditionFk}, - include: [ - { - relation: 'ticket', - scope: { - fields: ['shipped', 'addressFk', 'clientFk', 'companyFk'], - include: [ - { - relation: 'client', - scope: { - fields: ['mobile', 'phone', 'email'] - } - }, - { - relation: 'address', - scope: { - fields: [ - 'nickname', - 'street', - 'postalCode', - 'city', - 'mobile', - 'phone', - 'provinceFk' - ], - include: { - relation: 'province', - scope: { - fields: ['name', 'countryFk'], - include: { - relation: 'country', - scope: { - fields: ['code'], - } - } - - } - } - } - }, - { - relation: 'company', - scope: { - fields: ['clientFk'], - include: { - relation: 'client', - scope: { - fields: ['socialName', 'mobile', 'phone', 'email', 'defaultAddressFk'], - include: { - relation: 'defaultAddress', - scope: { - fields: [ - 'street', - 'postalCode', - 'city', - 'mobile', - 'phone', - 'provinceFk' - ], - include: { - relation: 'province', - scope: { - fields: ['name'] - } - } - } - } - } - } - } - } - ] - } - - } - ] - }, myOptions); const viaexpressConfig = await models.ViaexpressConfig.findOne({ - fields: ['url', 'clientViaexpress', 'userViaexpress', 'passwordViaexpress', 'defaultWeight', 'deliveryType'] - }, myOptions); + fields: ['url'] + }); - const shipped = expedition.ticket().shipped; - const year = shipped.getFullYear(); - const month = shipped.getMonth() + 1; - const day = shipped.getDate(); - const date = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`; + const renderedXml = await models.ViaexpressConfig.renderer(expeditionFk); + // const renderedXml = ` + // + // + // + // + // 10 + // 1 + // 0 + // 2023-06-12 + // 0 + // E + // 0 + // 0 + // 0 + // 0 + // 0 + // + // + // 0 + // + // + // + // VERDNATURA LEVANTE SL + // FENOLLARS, 2 + // 46680 + // Algemesi + // Valencia + // + // 963677177 + // pako.natek@gmail.com + // + // + // ROSAMARY FLORISTERIA + // C SANTA ROSA,25 + // 03802 + // ALCOY + // ALCOY + // Alicante + // + // 653967489 + // correo@floristeriarosamary.com + // ES + // + // + // 16092 + // B97367486 + // VERDNA22 + // + // + // + // + // `; + const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, renderedXml, { + headers: { + 'Content-Type': 'application/soap+xml; charset=utf-8' + } + }); + console.log(response); + const startTag = ''; + const endTag = ''; + const startIndex = response.data.indexOf(startTag) + startTag.length; + const endIndex = response.data.indexOf(endTag); + const referenciaVx = response.data.substring(startIndex, endIndex); - const xmlData = ` - - - - - ${viaexpressConfig.defaultWeight} - 1 - 0 - ${date} - 0 - ${viaexpressConfig.deliveryType} - 0 - 0 - 0 - 0 - 0 - - - 0 - - - - ${expedition.ticket().company().client().socialName} - ${expedition.ticket().company().client().defaultAddress().street} - ${expedition.ticket().company().client().defaultAddress().postalCode} - ${expedition.ticket().company().client().defaultAddress().city} - ${expedition.ticket().company().client().defaultAddress().province().name} - - ${expedition.ticket().company().client().defaultAddress().mobile || expedition.ticket().company().client().defaultAddress().phone || expedition.ticket().company().client().mobile || expedition.ticket().company().client().phone} - ${expedition.ticket().company().client().email} - - - ${expedition.ticket().address().nickname} - ${expedition.ticket().address().street} - ${expedition.ticket().address().postalCode} - ${expedition.ticket().address().city} - - ${expedition.ticket().address().province().name} - - ${expedition.ticket().address().mobile || expedition.ticket().address().phone || expedition.ticket().client().mobile || expedition.ticket().client().phone} - ${expedition.ticket().client().email} - ${expedition.ticket().address().province().country().code} - - - ${viaexpressConfig.clientViaexpress} - ${viaexpressConfig.userViaexpress} - ${viaexpressConfig.passwordViaexpress} - - - - - `; - - try { - const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, xmlData, { - headers: { - 'Content-Type': 'application/soap+xml; charset=utf-8' - } - }); - - const startTag = ''; - const endTag = ''; - const startIndex = response.data.indexOf(startTag) + startTag.length; - const endIndex = response.data.indexOf(endTag); - const referenciaVx = response.data.substring(startIndex, endIndex); - - return referenciaVx; - } catch (error) { - if (error?.response?.data) throw Error(error.response.data); - throw Error(error); - } + return referenciaVx; }; }; diff --git a/back/methods/viaexpress-config/renderer.js b/back/methods/viaexpress-config/renderer.js new file mode 100644 index 000000000..79dab21c9 --- /dev/null +++ b/back/methods/viaexpress-config/renderer.js @@ -0,0 +1,162 @@ +const fs = require('fs'); +const handlebars = require('handlebars'); + +module.exports = Self => { + Self.remoteMethod('renderer', { + description: 'Returns the lastest campaigns', + accessType: 'READ', + accepts: [{ + arg: 'expeditionFk', + type: 'number', + required: true + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/renderer`, + verb: 'GET' + } + }); + + Self.renderer = async expeditionFk => { + const models = Self.app.models; + + const viaexpressConfig = await models.ViaexpressConfig.findOne({ + fields: ['clientViaexpress', 'userViaexpress', 'passwordViaexpress', 'defaultWeight', 'deliveryType'] + }); + + const expedition = await models.Expedition.findOne({ + fields: ['id', 'ticketFk'], + where: {id: expeditionFk}, + include: [ + { + relation: 'ticket', + scope: { + fields: ['shipped', 'addressFk', 'clientFk', 'companyFk'], + include: [ + { + relation: 'client', + scope: { + fields: ['mobile', 'phone', 'email'] + } + }, + { + relation: 'address', + scope: { + fields: [ + 'nickname', + 'street', + 'postalCode', + 'city', + 'mobile', + 'phone', + 'provinceFk' + ], + include: { + relation: 'province', + scope: { + fields: ['name', 'countryFk'], + include: { + relation: 'country', + scope: { + fields: ['code'], + } + } + + } + } + } + }, + { + relation: 'company', + scope: { + fields: ['clientFk'], + include: { + relation: 'client', + scope: { + fields: ['socialName', 'mobile', 'phone', 'email', 'defaultAddressFk'], + include: { + relation: 'defaultAddress', + scope: { + fields: [ + 'street', + 'postalCode', + 'city', + 'mobile', + 'phone', + 'provinceFk' + ], + include: { + relation: 'province', + scope: { + fields: ['name'] + } + } + } + } + } + } + } + } + ] + } + + } + ] + }); + + const shipped = expedition.ticket().shipped; + const year = shipped.getFullYear(); + const month = shipped.getMonth() + 1; + const day = shipped.getDate(); + const date = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`; + + const data = { + defaultWeight: viaexpressConfig.defaultWeight, + date: date, // const date = new Date().toISOString(); + deliveryType: viaexpressConfig.deliveryType, + senderName: expedition.ticket().company().client().socialName, + senderStreet: expedition.ticket().company().client().defaultAddress().street, + senderPostalCode: expedition.ticket().company().client().defaultAddress().postalCode, + senderCity: expedition.ticket().company().client().defaultAddress().city, + senderProvince: expedition.ticket().company().client().defaultAddress().province().name, + senderPhone: expedition.ticket().company().client().defaultAddress().mobile + || expedition.ticket().company().client().defaultAddress().phone + || expedition.ticket().company().client().mobile + || expedition.ticket().company().client().phone, + senderEmail: expedition.ticket().company().client().email, + receiverName: expedition.ticket().address().nickname, + receiverStreet: expedition.ticket().address().street, + receiverPostalCode: expedition.ticket().address().postalCode, + receiverCity: expedition.ticket().address().city, + receiverProvince: expedition.ticket().address().province().name, + receiverPhone: expedition.ticket().address().mobile + || expedition.ticket().address().phone + || expedition.ticket().client().mobile + || expedition.ticket().client().phone, + receiverEmail: expedition.ticket().client().email, + receiverCountry: expedition.ticket().address().province().country().code, + clientViaexpress: viaexpressConfig.clientViaexpress, + userViaexpress: viaexpressConfig.userViaexpress, + passwordViaexpress: viaexpressConfig.passwordViaexpress + }; + + const templateXml = fs.readFileSync(__dirname + '/template.xml', 'utf-8'); + + // // Crea una instancia de Vue con los datos + // const vueInstance = new Vue({ + // data: data, + // template: templateXml, + // }); + + // // Renderiza la plantilla con los datos utilizando vue-server-renderer + // const renderer = createRenderer(); + // return renderer.renderToString(vueInstance); + + const compiledTemplate = handlebars.compile(templateXml); + const renderedHtml = compiledTemplate(data); + return renderedHtml; + }; +}; diff --git a/back/methods/viaexpress-config/template.xml b/back/methods/viaexpress-config/template.xml new file mode 100644 index 000000000..141fb939a --- /dev/null +++ b/back/methods/viaexpress-config/template.xml @@ -0,0 +1,52 @@ + + + + + + {{ defaultWeight }} + 1 + 0 + {{ date }} + 0 + {{ deliveryType }} + 0 + 0 + 0 + 0 + 0 + + + 0 + + + + {{ senderName }} + {{ senderStreet }} + {{ senderPostalCode }} + {{ senderCity }} + {{ senderProvince }} + + {{ senderPhone }} + {{ senderEmail }} + + + {{ receiverName }} + {{ receiverStreet }} + {{ receiverPostalCode }} + {{ receiverCity }} + + {{ receiverProvince }} + + {{ receiverPhone }} + {{ receiverEmail }} + {{ receiverCountry }} + + + {{ clientViaexpress }} + {{ userViaexpress }} + {{ passwordViaexpress }} + + + + + diff --git a/back/models/viaexpress-config.js b/back/models/viaexpress-config.js index 72424f806..d0335b28b 100644 --- a/back/models/viaexpress-config.js +++ b/back/models/viaexpress-config.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/viaexpress-config/internationalExpedition')(Self); + require('../methods/viaexpress-config/renderer')(Self); }; diff --git a/package.json b/package.json index 4358c86a7..857a7c172 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "ftps": "^1.2.0", "gm": "^1.25.0", "got": "^10.7.0", + "handlebars": "^4.7.7", "helmet": "^3.21.2", "i18n": "^0.8.4", "image-type": "^4.1.0", From 1ba19714da1d8c14d5ee54ca4cbe044cae8a86d5 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 20 Jun 2023 07:11:45 +0200 Subject: [PATCH 026/130] refs #4734 feat: add acl --- db/changes/232601/00-acl_viaexpressConfig.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/changes/232601/00-acl_viaexpressConfig.sql b/db/changes/232601/00-acl_viaexpressConfig.sql index 91a7e3c5b..d4c186dd4 100644 --- a/db/changes/232601/00-acl_viaexpressConfig.sql +++ b/db/changes/232601/00-acl_viaexpressConfig.sql @@ -1,3 +1,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('ViaexpressConfig', 'internationalExpedition', 'WRITE', 'ALLOW', 'ROLE', 'employee'); + ('ViaexpressConfig', 'internationalExpedition', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('ViaexpressConfig', 'renderer', 'READ', 'ALLOW', 'ROLE', 'employee'); From c3af2e3c925186e56f31a0f80f33b4095604770b Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 20 Jun 2023 07:19:32 +0200 Subject: [PATCH 027/130] refs #4734 refactor: actualizada descripcion --- back/methods/viaexpress-config/internationalExpedition.js | 3 +-- back/methods/viaexpress-config/renderer.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index cbb1c2c67..75f44401f 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -1,9 +1,8 @@ const axios = require('axios'); -const fs = require('fs'); module.exports = Self => { Self.remoteMethod('internationalExpedition', { - description: 'Returns the lastest campaigns', + description: 'Create an expedition and return a label', accessType: 'WRITE', accepts: [{ arg: 'expeditionFk', diff --git a/back/methods/viaexpress-config/renderer.js b/back/methods/viaexpress-config/renderer.js index 79dab21c9..7308b482e 100644 --- a/back/methods/viaexpress-config/renderer.js +++ b/back/methods/viaexpress-config/renderer.js @@ -3,7 +3,7 @@ const handlebars = require('handlebars'); module.exports = Self => { Self.remoteMethod('renderer', { - description: 'Returns the lastest campaigns', + description: 'Renders the data from an XML', accessType: 'READ', accepts: [{ arg: 'expeditionFk', From 13e95bcd35920d28fa170b97b2d317cf4cee918d Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 20 Jun 2023 11:25:47 +0200 Subject: [PATCH 028/130] add vue commented code --- back/methods/viaexpress-config/renderer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/back/methods/viaexpress-config/renderer.js b/back/methods/viaexpress-config/renderer.js index 7308b482e..588733174 100644 --- a/back/methods/viaexpress-config/renderer.js +++ b/back/methods/viaexpress-config/renderer.js @@ -1,5 +1,7 @@ const fs = require('fs'); const handlebars = require('handlebars'); +// const Vue = require('vue'); +// const renderer = require('vue-server-renderer').createRenderer(); module.exports = Self => { Self.remoteMethod('renderer', { From 4444b45b08e5e5427408d15f57b7ff80b87bce1e Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 20 Jun 2023 14:07:36 +0200 Subject: [PATCH 029/130] refs #4734 feat: se utiliza la libreria ejs y xmldom --- .../internationalExpedition.js | 65 ++----------------- back/methods/viaexpress-config/renderer.js | 28 ++------ back/methods/viaexpress-config/template.ejs | 52 +++++++++++++++ back/methods/viaexpress-config/template.xml | 52 --------------- 4 files changed, 64 insertions(+), 133 deletions(-) create mode 100644 back/methods/viaexpress-config/template.ejs delete mode 100644 back/methods/viaexpress-config/template.xml diff --git a/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js index 75f44401f..698bb1dac 100644 --- a/back/methods/viaexpress-config/internationalExpedition.js +++ b/back/methods/viaexpress-config/internationalExpedition.js @@ -1,4 +1,5 @@ const axios = require('axios'); +const {DOMParser} = require('xmldom'); module.exports = Self => { Self.remoteMethod('internationalExpedition', { @@ -27,69 +28,17 @@ module.exports = Self => { }); const renderedXml = await models.ViaexpressConfig.renderer(expeditionFk); - // const renderedXml = ` - // - // - // - // - // 10 - // 1 - // 0 - // 2023-06-12 - // 0 - // E - // 0 - // 0 - // 0 - // 0 - // 0 - // - // - // 0 - // - // - // - // VERDNATURA LEVANTE SL - // FENOLLARS, 2 - // 46680 - // Algemesi - // Valencia - // - // 963677177 - // pako.natek@gmail.com - // - // - // ROSAMARY FLORISTERIA - // C SANTA ROSA,25 - // 03802 - // ALCOY - // ALCOY - // Alicante - // - // 653967489 - // correo@floristeriarosamary.com - // ES - // - // - // 16092 - // B97367486 - // VERDNA22 - // - // - // - // - // `; const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, renderedXml, { headers: { 'Content-Type': 'application/soap+xml; charset=utf-8' } }); - console.log(response); - const startTag = ''; - const endTag = ''; - const startIndex = response.data.indexOf(startTag) + startTag.length; - const endIndex = response.data.indexOf(endTag); - const referenciaVx = response.data.substring(startIndex, endIndex); + + const xmlString = response.data; + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(xmlString, 'text/xml'); + const referenciaVxElement = xmlDoc.getElementsByTagName('ReferenciaVx')[0]; + const referenciaVx = referenciaVxElement.textContent; return referenciaVx; }; diff --git a/back/methods/viaexpress-config/renderer.js b/back/methods/viaexpress-config/renderer.js index 588733174..4014dd42d 100644 --- a/back/methods/viaexpress-config/renderer.js +++ b/back/methods/viaexpress-config/renderer.js @@ -1,7 +1,5 @@ const fs = require('fs'); -const handlebars = require('handlebars'); -// const Vue = require('vue'); -// const renderer = require('vue-server-renderer').createRenderer(); +const ejs = require('ejs'); module.exports = Self => { Self.remoteMethod('renderer', { @@ -110,14 +108,10 @@ module.exports = Self => { }); const shipped = expedition.ticket().shipped; - const year = shipped.getFullYear(); - const month = shipped.getMonth() + 1; - const day = shipped.getDate(); - const date = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`; const data = { defaultWeight: viaexpressConfig.defaultWeight, - date: date, // const date = new Date().toISOString(); + date: shipped.toISOString(), // const date = new Date().toISOString(); deliveryType: viaexpressConfig.deliveryType, senderName: expedition.ticket().company().client().socialName, senderStreet: expedition.ticket().company().client().defaultAddress().street, @@ -145,20 +139,8 @@ module.exports = Self => { passwordViaexpress: viaexpressConfig.passwordViaexpress }; - const templateXml = fs.readFileSync(__dirname + '/template.xml', 'utf-8'); - - // // Crea una instancia de Vue con los datos - // const vueInstance = new Vue({ - // data: data, - // template: templateXml, - // }); - - // // Renderiza la plantilla con los datos utilizando vue-server-renderer - // const renderer = createRenderer(); - // return renderer.renderToString(vueInstance); - - const compiledTemplate = handlebars.compile(templateXml); - const renderedHtml = compiledTemplate(data); - return renderedHtml; + const template = fs.readFileSync(__dirname + '/template.ejs', 'utf-8'); + const renderedXml = ejs.render(template, data); + return renderedXml; }; }; diff --git a/back/methods/viaexpress-config/template.ejs b/back/methods/viaexpress-config/template.ejs new file mode 100644 index 000000000..e8b1f1977 --- /dev/null +++ b/back/methods/viaexpress-config/template.ejs @@ -0,0 +1,52 @@ + + + + + + <%= defaultWeight %> + 1 + 0 + <%= date %> + 0 + <%= deliveryType %> + 0 + 0 + 0 + 0 + 0 + + + 0 + + + + <%= senderName %> + <%= senderStreet %> + <%= senderPostalCode %> + <%= senderCity %> + <%= senderProvince %> + + <%= senderPhone %> + <%= senderEmail %> + + + <%= receiverName %> + <%= receiverStreet %> + <%= receiverPostalCode %> + <%= receiverCity %> + + <%= receiverProvince %> + + <%= receiverPhone %> + <%= receiverEmail %> + <%= receiverCountry %> + + + <%= clientViaexpress %> + <%= userViaexpress %> + <%= passwordViaexpress %> + + + + + diff --git a/back/methods/viaexpress-config/template.xml b/back/methods/viaexpress-config/template.xml deleted file mode 100644 index 141fb939a..000000000 --- a/back/methods/viaexpress-config/template.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - {{ defaultWeight }} - 1 - 0 - {{ date }} - 0 - {{ deliveryType }} - 0 - 0 - 0 - 0 - 0 - - - 0 - - - - {{ senderName }} - {{ senderStreet }} - {{ senderPostalCode }} - {{ senderCity }} - {{ senderProvince }} - - {{ senderPhone }} - {{ senderEmail }} - - - {{ receiverName }} - {{ receiverStreet }} - {{ receiverPostalCode }} - {{ receiverCity }} - - {{ receiverProvince }} - - {{ receiverPhone }} - {{ receiverEmail }} - {{ receiverCountry }} - - - {{ clientViaexpress }} - {{ userViaexpress }} - {{ passwordViaexpress }} - - - - - From dcbe8c5f7a36c29ed985705c07f0a80a4c17556a Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 26 Jun 2023 06:28:35 +0200 Subject: [PATCH 030/130] refs #5066 quit if --- modules/route/front/basic-data/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/route/front/basic-data/index.js b/modules/route/front/basic-data/index.js index d7f178985..e6be796ce 100644 --- a/modules/route/front/basic-data/index.js +++ b/modules/route/front/basic-data/index.js @@ -14,8 +14,7 @@ class Controller extends Section { if (res.data) { this.$http.post(`Vehicles/sorted`, {warehouseFk: res.data.warehouseFk}) .then(res => { - if (res.data) - this.vehicles = res.data; + this.vehicles = res.data; }); } }); From eff46c1cec81cf0d12a6e775e4749098481025fc Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 26 Jun 2023 07:43:36 +0200 Subject: [PATCH 031/130] refs #5066 e2e fix, vnConfig --- e2e/paths/08-route/02_basic_data.spec.js | 2 +- modules/route/front/basic-data/index.html | 3 ++- modules/route/front/basic-data/index.js | 19 +++++++------------ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index 6008b0482..7ab7dda42 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -24,7 +24,7 @@ describe('Route basic Data path', () => { const form = 'vn-route-basic-data form'; const values = { worker: 'adminBossNick', - vehicle: '1111-IMK - Warehouse One', + vehicle: '1111-IMK', created: nextMonth, kmStart: 1, kmEnd: 2, diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 514c535a2..ade9230e8 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -28,7 +28,8 @@ data="$ctrl.vehicles" show-field="numberPlate" value-field="id" - order="false"> + order="false" + vn-name="vehicle"> {{::numberPlate}} - {{::name}}
diff --git a/modules/route/front/basic-data/index.js b/modules/route/front/basic-data/index.js index e6be796ce..f051e23c5 100644 --- a/modules/route/front/basic-data/index.js +++ b/modules/route/front/basic-data/index.js @@ -2,23 +2,18 @@ import ngModule from '../module'; import Section from 'salix/components/section'; class Controller extends Section { + $onInit() { + this.$http.post(`Vehicles/sorted`, {warehouseFk: this.vnConfig.warehouseFk}) + .then(res => { + this.vehicles = res.data; + }); + } + onSubmit() { this.$.watcher.submit().then(() => this.card.reload() ); } - constructor($element, $) { - super($element, $); - this.$http.get(`UserConfigs/getUserConfig`) - .then(res => { - if (res.data) { - this.$http.post(`Vehicles/sorted`, {warehouseFk: res.data.warehouseFk}) - .then(res => { - this.vehicles = res.data; - }); - } - }); - } } ngModule.vnComponent('vnRouteBasicData', { From 549235429c06bfb12cd7fa9a67f7b91baa2da00e Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 27 Jun 2023 07:18:36 +0200 Subject: [PATCH 032/130] refs #5640 oldBranch --- e2e/paths/02-client/03_edit_fiscal_data.spec.js | 4 ++-- e2e/paths/02-client/12_lock_of_verified_data.spec.js | 6 +++--- modules/client/front/fiscal-data/index.html | 2 ++ modules/client/front/fiscal-data/index.js | 6 ++++++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/e2e/paths/02-client/03_edit_fiscal_data.spec.js b/e2e/paths/02-client/03_edit_fiscal_data.spec.js index 0babb5396..9098e816f 100644 --- a/e2e/paths/02-client/03_edit_fiscal_data.spec.js +++ b/e2e/paths/02-client/03_edit_fiscal_data.spec.js @@ -61,7 +61,7 @@ describe('Client Edit fiscalData path', () => { await page.clearInput(selectors.clientFiscalData.fiscalId); await page.write(selectors.clientFiscalData.fiscalId, 'INVALID!'); await page.clearInput(selectors.clientFiscalData.address); - await page.write(selectors.clientFiscalData.address, 'Somewhere edited'); + await page.write(selectors.clientFiscalData.address, 'SOMEWHERE EDITED'); await page.autocompleteSearch(selectors.clientFiscalData.country, 'España'); await page.autocompleteSearch(selectors.clientFiscalData.province, 'Province one'); await page.clearInput(selectors.clientFiscalData.city); @@ -190,7 +190,7 @@ describe('Client Edit fiscalData path', () => { const verifiedData = await page.checkboxState(selectors.clientFiscalData.verifiedDataCheckbox); expect(fiscalId).toEqual('94980061C'); - expect(address).toEqual('Somewhere edited'); + expect(address).toEqual('SOMEWHERE EDITED'); expect(postcode).toContain('46000'); expect(sageTax).toEqual('Operaciones no sujetas'); expect(sageTransaction).toEqual('Regularización de inversiones'); diff --git a/e2e/paths/02-client/12_lock_of_verified_data.spec.js b/e2e/paths/02-client/12_lock_of_verified_data.spec.js index 139af0cea..7abe15460 100644 --- a/e2e/paths/02-client/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client/12_lock_of_verified_data.spec.js @@ -39,7 +39,7 @@ describe('Client lock verified data path', () => { await page.reloadSection('client.card.fiscalData'); const result = await page.waitToGetProperty(selectors.clientFiscalData.socialName, 'value'); - expect(result).toEqual('Captain America Civil War'); + expect(result).toEqual('CAPTAIN AMERICA CIVIL WAR'); }); }); @@ -88,7 +88,7 @@ describe('Client lock verified data path', () => { await page.reloadSection('client.card.fiscalData'); const result = await page.waitToGetProperty(selectors.clientFiscalData.socialName, 'value'); - expect(result).toEqual('Ant man and the Wasp'); + expect(result).toEqual('ANT MAN AND THE WASP'); }); }); @@ -142,7 +142,7 @@ describe('Client lock verified data path', () => { await page.reloadSection('client.card.fiscalData'); const result = await page.waitToGetProperty(selectors.clientFiscalData.socialName, 'value'); - expect(result).toEqual('new social name edition'); + expect(result).toEqual('NEW SOCIAL NAME EDITION'); }); }); diff --git a/modules/client/front/fiscal-data/index.html b/modules/client/front/fiscal-data/index.html index d232d6dab..4d001e226 100644 --- a/modules/client/front/fiscal-data/index.html +++ b/modules/client/front/fiscal-data/index.html @@ -33,6 +33,7 @@ ng-model="$ctrl.client.socialName" info="Only letters, numbers and spaces can be used" required="true" + ng-keyup="$ctrl.mayus($event)" rule> diff --git a/modules/client/front/fiscal-data/index.js b/modules/client/front/fiscal-data/index.js index acad38185..1599c917b 100644 --- a/modules/client/front/fiscal-data/index.js +++ b/modules/client/front/fiscal-data/index.js @@ -177,6 +177,12 @@ export default class Controller extends Section { this.client.provinceFk = response.provinceFk; this.client.countryFk = response.countryFk; } + + mayus(event) { + let input = event.target; + let inputValue = input.value; + input.value = inputValue.toUpperCase(); + } } ngModule.vnComponent('vnClientFiscalData', { From 783d4c60c4d7e81e5cf99369944947fac7624502 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 28 Jun 2023 13:02:47 +0200 Subject: [PATCH 033/130] refs #4734 delete module handlebars from package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 857a7c172..4358c86a7 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "ftps": "^1.2.0", "gm": "^1.25.0", "got": "^10.7.0", - "handlebars": "^4.7.7", "helmet": "^3.21.2", "i18n": "^0.8.4", "image-type": "^4.1.0", From d03df4c5ccd1821c9576ba8f708e4c3b1e4bad18 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 3 Jul 2023 11:38:38 +0200 Subject: [PATCH 034/130] refs #5690 ticketproblems --- modules/ticket/back/methods/ticket/filter.js | 3 ++- modules/ticket/back/methods/ticket/getTicketsFuture.js | 3 ++- modules/ticket/front/future/index.html | 5 +++++ modules/ticket/front/index/index.html | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index 262b3fd74..ea77b7677 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -339,7 +339,8 @@ module.exports = Self => { {'tp.isFreezed': hasProblem}, {'tp.risk': hasProblem}, {'tp.hasTicketRequest': hasProblem}, - {'tp.itemShortage': range} + {'tp.itemShortage': range}, + {'tp.hasRounding': hasProblem} ]}; if (hasWhere) diff --git a/modules/ticket/back/methods/ticket/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js index 901e546f7..fa24cc379 100644 --- a/modules/ticket/back/methods/ticket/getTicketsFuture.js +++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js @@ -194,7 +194,8 @@ module.exports = Self => { {'tp.hasTicketRequest': hasProblem}, {'tp.itemShortage': range}, {'tp.hasComponentLack': hasProblem}, - {'tp.isTooLittle': hasProblem} + {'tp.isTooLittle': hasProblem}, + {'tp.hasRounding': hasProblem} ] }; diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 78b0f9864..742143b27 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -123,6 +123,11 @@ class="bright" icon="icon-components"> + + + + {{::ticket.id}} From 4f616397a2d1c513f5e051872fb7468de28e5978 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 3 Jul 2023 15:05:39 +0200 Subject: [PATCH 035/130] refs #5712 use dmsType readRole --- db/changes/232401/00-workerDocuware.sql | 7 ---- db/changes/232801/00-workerDocuware.sql | 10 +++++ .../{docuware.js => docuwareDownload.js} | 0 .../worker/back/methods/worker-dms/filter.js | 38 +++++++++++-------- modules/worker/back/models/worker-dms.js | 2 +- 5 files changed, 34 insertions(+), 23 deletions(-) delete mode 100644 db/changes/232401/00-workerDocuware.sql create mode 100644 db/changes/232801/00-workerDocuware.sql rename modules/worker/back/methods/worker-dms/{docuware.js => docuwareDownload.js} (100%) diff --git a/db/changes/232401/00-workerDocuware.sql b/db/changes/232401/00-workerDocuware.sql deleted file mode 100644 index c8d4e4f23..000000000 --- a/db/changes/232401/00-workerDocuware.sql +++ /dev/null @@ -1,7 +0,0 @@ -INSERT INTO `vn`.`docuware` (code, fileCabinetName, `action`, dialogName, findById) - VALUES - ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO'); - -INSERT INTO `salix`.`url` (appName, environment, url) - VALUES - ('docuware', 'production', 'https://verdnatura.docuware.cloud/DocuWare/Platform/'); diff --git a/db/changes/232801/00-workerDocuware.sql b/db/changes/232801/00-workerDocuware.sql new file mode 100644 index 000000000..2d0ce3c33 --- /dev/null +++ b/db/changes/232801/00-workerDocuware.sql @@ -0,0 +1,10 @@ +ALTER TABLE `vn`.`docuware` ADD dmsTypeFk INT(11) DEFAULT NULL NULL; +ALTER TABLE `vn`.`docuware` ADD CONSTRAINT docuware_FK FOREIGN KEY (dmsTypeFk) REFERENCES `vn`.`dmsType`(id) ON DELETE RESTRICT ON UPDATE CASCADE; +INSERT INTO `vn`.`docuware` (code, fileCabinetName, `action`, dialogName, findById, dmsTypeFk) + VALUES + ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO', NULL); + +INSERT INTO `salix`.`url` (appName, environment, url) + VALUES + ('docuware', 'production', 'https://verdnatura.docuware.cloud/DocuWare/Platform/'); + diff --git a/modules/worker/back/methods/worker-dms/docuware.js b/modules/worker/back/methods/worker-dms/docuwareDownload.js similarity index 100% rename from modules/worker/back/methods/worker-dms/docuware.js rename to modules/worker/back/methods/worker-dms/docuwareDownload.js diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 0b89cc883..1343038b7 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -57,23 +57,31 @@ module.exports = Self => { const workerDms = await conn.executeStmt(stmt); // Get docuware info - const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); - const docuwareParse = { - 'Filename': 'dmsFk', - 'Tipo Documento': 'description', - 'Stored on': 'created', - }; - const workerDocuware = await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse); - for (document of workerDocuware) { - const defaultData = { - file: document.dmsFk + '.png', - isDocuware: true, - hardCopyNumber: null, - hasFile: false, - reference: worker.fi + const docuware = await models.Docuware.findOne({ + fields: ['dmsTypeFk'], + where: {code: 'hr', action: 'find'} + }); + const docuwareDmsType = docuware.dmsTypeFk; + if (!(docuwareDmsType && !await models.DmsType.hasReadRole(ctx, docuwareDmsType))) { + const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); + const docuwareParse = { + 'Filename': 'dmsFk', + 'Tipo Documento': 'description', + 'Stored on': 'created', }; + const workerDocuware = + await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse); + for (document of workerDocuware) { + const defaultData = { + file: document.dmsFk + '.png', + isDocuware: true, + hardCopyNumber: null, + hasFile: false, + reference: worker.fi + }; - document = Object.assign(document, defaultData); + document = Object.assign(document, defaultData); + } } return workerDms.concat(workerDocuware); diff --git a/modules/worker/back/models/worker-dms.js b/modules/worker/back/models/worker-dms.js index 1712383b3..6343e902e 100644 --- a/modules/worker/back/models/worker-dms.js +++ b/modules/worker/back/models/worker-dms.js @@ -2,7 +2,7 @@ module.exports = Self => { require('../methods/worker-dms/downloadFile')(Self); require('../methods/worker-dms/removeFile')(Self); require('../methods/worker-dms/filter')(Self); - require('../methods/worker-dms/docuware')(Self); + require('../methods/worker-dms/docuwareDownload')(Self); Self.isMine = async function(ctx, dmsId) { const myUserId = ctx.req.accessToken.userId; From 1a18ba66a940959bdae82335289ccd1a39a1fac8 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 4 Jul 2023 15:18:57 +0200 Subject: [PATCH 036/130] refs #5712 fix(workerDms): filter --- back/models/docuware.json | 7 +++++++ modules/worker/back/methods/worker-dms/filter.js | 9 ++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/back/models/docuware.json b/back/models/docuware.json index dec20eede..b1a6a8bce 100644 --- a/back/models/docuware.json +++ b/back/models/docuware.json @@ -28,5 +28,12 @@ "findById": { "type": "string" } + }, + "relations": { + "dmsType": { + "type": "belongsTo", + "model": "DmsType", + "foreignKey": "dmsTypeFk" + } } } diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 1343038b7..e19010988 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -62,22 +62,25 @@ module.exports = Self => { where: {code: 'hr', action: 'find'} }); const docuwareDmsType = docuware.dmsTypeFk; + let workerDocuware; if (!(docuwareDmsType && !await models.DmsType.hasReadRole(ctx, docuwareDmsType))) { const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); const docuwareParse = { 'Filename': 'dmsFk', 'Tipo Documento': 'description', 'Stored on': 'created', + 'Document ID': 'id' }; - const workerDocuware = + workerDocuware = await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse); for (document of workerDocuware) { const defaultData = { - file: document.dmsFk + '.png', + file: 'dw' + document.id + '.png', isDocuware: true, hardCopyNumber: null, hasFile: false, - reference: worker.fi + reference: worker.fi, + dmsFk: 'DW' + document.id }; document = Object.assign(document, defaultData); From 444b08c566c18e0b716b38ff4f6f45b76116f921 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 5 Jul 2023 12:09:52 +0200 Subject: [PATCH 037/130] refs #5712 test(docuware) --- back/methods/docuware/checkFile.js | 15 +- back/methods/docuware/core.js | 18 ++- back/methods/docuware/specs/checkFile.spec.js | 74 ++-------- back/methods/docuware/specs/core.spec.js | 135 ++++++++++++++++++ back/methods/docuware/specs/download.spec.js | 2 +- db/changes/232801/00-workerDocuware.sql | 2 +- .../back/methods/ticket/docuwareDownload.js | 6 +- .../methods/worker-dms/docuwareDownload.js | 6 +- .../worker/back/methods/worker-dms/filter.js | 5 +- 9 files changed, 176 insertions(+), 87 deletions(-) create mode 100644 back/methods/docuware/specs/core.spec.js diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js index 18d169085..19224057c 100644 --- a/back/methods/docuware/checkFile.js +++ b/back/methods/docuware/checkFile.js @@ -1,5 +1,3 @@ -const axios = require('axios'); - module.exports = Self => { Self.remoteMethod('checkFile', { description: 'Check if exist docuware file', @@ -73,17 +71,8 @@ module.exports = Self => { } try { - const options = await Self.getOptions(); - - const fileCabinetId = await Self.getFileCabinet(fileCabinet); - const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); - - const response = await axios.post( - `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, - filter, - options.headers - ); - const [documents] = response.data.Items; + const response = await Self.get(fileCabinet, filter); + const [documents] = response.Items; if (!documents) return false; return {id: documents.Id}; diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js index 7bb3e617a..74d922236 100644 --- a/back/methods/docuware/core.js +++ b/back/methods/docuware/core.js @@ -32,10 +32,13 @@ module.exports = Self => { * @return {number} - The fileCabinet id */ Self.getDialog = async(code, action, fileCabinetId) => { + if (!process.env.NODE_ENV) + return Math.floor(Math.random() + 100); + const docuwareInfo = await Self.app.models.Docuware.findOne({ where: { - code: code, - action: action + code, + action } }); if (!fileCabinetId) fileCabinetId = await Self.getFileCabinet(code); @@ -56,10 +59,13 @@ module.exports = Self => { * @return {number} - The fileCabinet id */ Self.getFileCabinet = async code => { + if (!process.env.NODE_ENV) + return Math.floor(Math.random() + 100); + const options = await Self.getOptions(); const docuwareInfo = await Self.app.models.Docuware.findOne({ where: { - code: code + code } }); @@ -79,6 +85,8 @@ module.exports = Self => { * @return {object} - The data */ Self.get = async(code, filter, parse) => { + if (!process.env.NODE_ENV) return; + const options = await Self.getOptions(); const fileCabinetId = await Self.getFileCabinet(code); const dialogId = await Self.getDialog(code, 'find', fileCabinetId); @@ -100,10 +108,12 @@ module.exports = Self => { * @return {object} - The data */ Self.getById = async(code, id, parse) => { + if (!process.env.NODE_ENV) return; + const docuwareInfo = await Self.app.models.Docuware.findOne({ fields: ['findById'], where: { - code: code, + code, action: 'find' } }); diff --git a/back/methods/docuware/specs/checkFile.spec.js b/back/methods/docuware/specs/checkFile.spec.js index dd11951cc..8460bb561 100644 --- a/back/methods/docuware/specs/checkFile.spec.js +++ b/back/methods/docuware/specs/checkFile.spec.js @@ -1,57 +1,15 @@ const models = require('vn-loopback/server/server').models; -const axios = require('axios'); describe('docuware download()', () => { const ticketId = 1; - const userId = 9; - const ctx = { - req: { - - accessToken: {userId: userId}, - headers: {origin: 'http://localhost:5000'}, - } - }; const docuwareModel = models.Docuware; const fileCabinetName = 'deliveryNote'; - beforeAll(() => { - spyOn(docuwareModel, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); - spyOn(docuwareModel, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); - }); - it('should return false if there are no documents', async() => { - const response = { - data: { - Items: [] - } - }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(response))); + spyOn(docuwareModel, 'get').and.returnValue((new Promise(resolve => resolve({Items: []})))); - const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, true); - - expect(result).toEqual(false); - }); - - it('should return false if the document is unsigned', async() => { - const response = { - data: { - Items: [ - { - Id: 1, - Fields: [ - { - FieldName: 'ESTADO', - Item: 'Unsigned' - } - ] - } - ] - } - }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(response))); - - const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, true); + const result = await models.Docuware.checkFile(ticketId, fileCabinetName, null, true); expect(result).toEqual(false); }); @@ -59,23 +17,21 @@ describe('docuware download()', () => { it('should return the document data', async() => { const docuwareId = 1; const response = { - data: { - Items: [ - { - Id: docuwareId, - Fields: [ - { - FieldName: 'ESTADO', - Item: 'Firmado' - } - ] - } - ] - } + Items: [ + { + Id: docuwareId, + Fields: [ + { + FieldName: 'ESTADO', + Item: 'Firmado' + } + ] + } + ] }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(response))); + spyOn(docuwareModel, 'get').and.returnValue((new Promise(resolve => resolve(response)))); - const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, true); + const result = await models.Docuware.checkFile(ticketId, fileCabinetName, null, true); expect(result.id).toEqual(docuwareId); }); diff --git a/back/methods/docuware/specs/core.spec.js b/back/methods/docuware/specs/core.spec.js new file mode 100644 index 000000000..cdf8a3b62 --- /dev/null +++ b/back/methods/docuware/specs/core.spec.js @@ -0,0 +1,135 @@ +const axios = require('axios'); +const models = require('vn-loopback/server/server').models; + +describe('Docuware core', () => { + beforeAll(() => { + process.env.NODE_ENV = 'testing'; + }); + + afterAll(() => { + delete process.env.NODE_ENV; + }); + + describe('getOptions()', () => { + it('should return url and headers', async() => { + const result = await models.Docuware.getOptions(); + + expect(result.url).toBeDefined(); + expect(result.headers).toBeDefined(); + }); + }); + + describe('getDialog()', () => { + it('should return dialogId', async() => { + const dialogs = { + data: { + Dialog: [ + { + DisplayName: 'find', + Id: 'getDialogTest' + } + ] + } + }; + spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs))); + const result = await models.Docuware.getDialog('deliveryNote', 'find', 'randomFileCabinetId'); + + expect(result).toEqual('getDialogTest'); + }); + }); + + describe('getFileCabinet()', () => { + it('should return fileCabinetId', async() => { + const code = 'deliveryNote'; + const docuwareInfo = await models.Docuware.findOne({ + where: { + code + } + }); + const dialogs = { + data: { + FileCabinet: [ + { + Name: docuwareInfo.fileCabinetName, + Id: 'getFileCabinetTest' + } + ] + } + }; + spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs))); + const result = await models.Docuware.getFileCabinet(code); + + expect(result).toEqual('getFileCabinetTest'); + }); + }); + + describe('get()', () => { + it('should return data without parse', async() => { + spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); + spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); + const data = { + data: { + id: 1 + } + }; + spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); + const result = await models.Docuware.get('deliveryNote'); + + expect(result.id).toEqual(1); + }); + + it('should return data with parse', async() => { + spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); + spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); + const data = { + data: { + Items: [{ + Fields: [ + { + ItemElementName: 'integer', + FieldLabel: 'firstRequiredField', + Item: 1 + }, + { + ItemElementName: 'string', + FieldLabel: 'secondRequiredField', + Item: 'myName' + }, + { + ItemElementName: 'integer', + FieldLabel: 'notRequiredField', + Item: 2 + } + ] + }] + } + }; + const parse = { + 'firstRequiredField': 'id', + 'secondRequiredField': 'name', + }; + spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); + const [result] = await models.Docuware.get('deliveryNote', null, parse); + + expect(result.id).toEqual(1); + expect(result.name).toEqual('myName'); + expect(result.notRequiredField).not.toBeDefined(); + }); + }); + + describe('getById()', () => { + it('should return data', async() => { + spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); + spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); + const data = { + data: { + id: 1 + } + }; + spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); + const result = await models.Docuware.getById('deliveryNote', 1); + + expect(result.id).toEqual(1); + }); + }); +}); diff --git a/back/methods/docuware/specs/download.spec.js b/back/methods/docuware/specs/download.spec.js index fcc1671a6..bc580a079 100644 --- a/back/methods/docuware/specs/download.spec.js +++ b/back/methods/docuware/specs/download.spec.js @@ -39,7 +39,7 @@ describe('docuware download()', () => { spyOn(docuwareModel, 'checkFile').and.returnValue({}); spyOn(axios, 'get').and.returnValue(new stream.PassThrough({objectMode: true})); - const result = await models.Docuware.download(ctx, ticketId, fileCabinetName); + const result = await models.Docuware.download(ticketId, fileCabinetName); expect(result[1]).toEqual('application/pdf'); expect(result[2]).toEqual(`filename="${ticketId}.pdf"`); diff --git a/db/changes/232801/00-workerDocuware.sql b/db/changes/232801/00-workerDocuware.sql index 2d0ce3c33..2f2c4a1cd 100644 --- a/db/changes/232801/00-workerDocuware.sql +++ b/db/changes/232801/00-workerDocuware.sql @@ -2,7 +2,7 @@ ALTER TABLE `vn`.`docuware` ADD dmsTypeFk INT(11) DEFAULT NULL NULL; ALTER TABLE `vn`.`docuware` ADD CONSTRAINT docuware_FK FOREIGN KEY (dmsTypeFk) REFERENCES `vn`.`dmsType`(id) ON DELETE RESTRICT ON UPDATE CASCADE; INSERT INTO `vn`.`docuware` (code, fileCabinetName, `action`, dialogName, findById, dmsTypeFk) VALUES - ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO', NULL); + ('hr', 'RRHH', 'find', 'Búsqueda', 'N__DOCUMENTO', NULL); -- set dmsTypeFk 3 when deploy in production INSERT INTO `salix`.`url` (appName, environment, url) VALUES diff --git a/modules/ticket/back/methods/ticket/docuwareDownload.js b/modules/ticket/back/methods/ticket/docuwareDownload.js index bc74e0d21..e9b74b1a9 100644 --- a/modules/ticket/back/methods/ticket/docuwareDownload.js +++ b/modules/ticket/back/methods/ticket/docuwareDownload.js @@ -1,5 +1,5 @@ module.exports = Self => { - Self.remoteMethodCtx('docuwareDownload', { + Self.remoteMethod('docuwareDownload', { description: 'Download a ticket delivery note document', accessType: 'READ', accepts: [ @@ -31,7 +31,7 @@ module.exports = Self => { } }); - Self.docuwareDownload = async function(ctx, id) { + Self.docuwareDownload = async id => { const filter = { condition: [ { @@ -50,6 +50,6 @@ module.exports = Self => { } ] }; - return await Self.app.models.Docuware.download(id, 'deliveryNote', filter); + return Self.app.models.Docuware.download(id, 'deliveryNote', filter); }; }; diff --git a/modules/worker/back/methods/worker-dms/docuwareDownload.js b/modules/worker/back/methods/worker-dms/docuwareDownload.js index 764b7633c..c64c159ed 100644 --- a/modules/worker/back/methods/worker-dms/docuwareDownload.js +++ b/modules/worker/back/methods/worker-dms/docuwareDownload.js @@ -1,5 +1,5 @@ module.exports = Self => { - Self.remoteMethodCtx('docuwareDownload', { + Self.remoteMethod('docuwareDownload', { description: 'Download a worker document', accessType: 'READ', accepts: [ @@ -31,7 +31,7 @@ module.exports = Self => { } }); - Self.docuwareDownload = async function(ctx, id) { + Self.docuwareDownload = async id => { const filter = { condition: [ { @@ -40,6 +40,6 @@ module.exports = Self => { } ] }; - return await Self.app.models.Docuware.download(id, 'hr', filter); + return Self.app.models.Docuware.download(id, 'hr', filter); }; }; diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index e19010988..55db68d5d 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -62,8 +62,8 @@ module.exports = Self => { where: {code: 'hr', action: 'find'} }); const docuwareDmsType = docuware.dmsTypeFk; - let workerDocuware; - if (!(docuwareDmsType && !await models.DmsType.hasReadRole(ctx, docuwareDmsType))) { + let workerDocuware = []; + if (!docuwareDmsType || (docuwareDmsType && await models.DmsType.hasReadRole(ctx, docuwareDmsType))) { const worker = await models.Worker.findById(id, {fields: ['fi', 'firstName', 'lastName']}); const docuwareParse = { 'Filename': 'dmsFk', @@ -86,7 +86,6 @@ module.exports = Self => { document = Object.assign(document, defaultData); } } - return workerDms.concat(workerDocuware); }; }; From 5d933da28af0c03b33095375748664c9424b7612 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 5 Jul 2023 12:14:26 +0200 Subject: [PATCH 038/130] refs #5712 fix empty data --- modules/worker/back/methods/worker-dms/filter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 55db68d5d..5f55f1bd7 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -72,7 +72,7 @@ module.exports = Self => { 'Document ID': 'id' }; workerDocuware = - await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse); + await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse) ?? []; for (document of workerDocuware) { const defaultData = { file: 'dw' + document.id + '.png', From 510b78c7035eabcef9d51c78816fe3349968f9c5 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 12 Jul 2023 13:08:46 +0200 Subject: [PATCH 039/130] refs #6006 mod dias anteriores --- modules/travel/front/search-panel/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/travel/front/search-panel/index.js b/modules/travel/front/search-panel/index.js index 089953127..f53c15ca8 100644 --- a/modules/travel/front/search-panel/index.js +++ b/modules/travel/front/search-panel/index.js @@ -38,10 +38,12 @@ class Controller extends SearchPanel { applyFilters(param) { if (typeof this.filter.scopeDays === 'number') { - const shippedFrom = Date.vnNew(); + const today = Date.vnNew(); + const shippedFrom = new Date(today.getTime()); + shippedFrom.setDate(today.getDate() - 30); shippedFrom.setHours(0, 0, 0, 0); - const shippedTo = new Date(shippedFrom.getTime()); + const shippedTo = new Date(today.getTime()); shippedTo.setDate(shippedTo.getDate() + this.filter.scopeDays); shippedTo.setHours(23, 59, 59, 999); Object.assign(this.filter, {shippedFrom, shippedTo}); From 551d06ee8358554f2c83dbeaf6a1f054e634e2af Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 12 Jul 2023 13:55:57 +0200 Subject: [PATCH 040/130] =?UTF-8?q?refs=20#5887=20para=20eliminar=20sigue?= =?UTF-8?q?=20las=20mismas=20reglas=20que=20para=20a=C3=B1adir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/methods/vn-user/specs/addAlias.spec.js | 8 +-- back/models/vn-user.js | 2 - db/changes/232402/00-hotFix_travelConfig.sql | 32 +++++------ db/changes/232601/00-aclAddAlias.sql | 12 ++--- loopback/locale/es.json | 2 +- .../methods/mail-alias-account}/addAlias.js | 25 +-------- .../mail-alias-account}/removeAlias.js | 6 +-- .../account/back/models/mail-alias-account.js | 53 +++++++++++++++++++ modules/account/front/aliases/index.js | 4 +- modules/account/front/aliases/index.spec.js | 4 +- 10 files changed, 83 insertions(+), 65 deletions(-) rename {back/methods/vn-user => modules/account/back/methods/mail-alias-account}/addAlias.js (58%) rename {back/methods/vn-user => modules/account/back/methods/mail-alias-account}/removeAlias.js (83%) create mode 100644 modules/account/back/models/mail-alias-account.js diff --git a/back/methods/vn-user/specs/addAlias.spec.js b/back/methods/vn-user/specs/addAlias.spec.js index ef657a3a8..880c08139 100644 --- a/back/methods/vn-user/specs/addAlias.spec.js +++ b/back/methods/vn-user/specs/addAlias.spec.js @@ -14,7 +14,7 @@ describe('VnUser addAlias()', () => { try { const options = {transaction: tx}; - await models.VnUser.addAlias(ctx, employeeId, mailAlias, options); + await models.MailAliasAccount.addAlias(ctx, employeeId, mailAlias, options); await tx.rollback(); } catch (e) { @@ -33,7 +33,7 @@ describe('VnUser addAlias()', () => { try { const options = {transaction: tx}; - await models.VnUser.addAlias(ctx, employeeId, mailAlias, options); + await models.MailAliasAccount.addAlias(ctx, employeeId, mailAlias, options); await tx.rollback(); } catch (e) { @@ -41,7 +41,7 @@ describe('VnUser addAlias()', () => { await tx.rollback(); } - expect(error.message).toContain(`You cannot assign an alias that you are not assigned to`); + expect(error.message).toContain(`You cannot assign/remove an alias that you are not assigned to`); }); it('should add an alias', async() => { @@ -55,7 +55,7 @@ describe('VnUser addAlias()', () => { const user = await models.VnUser.findById(developerId, null, options); await user.updateAttribute('hasGrant', true, options); - result = await models.VnUser.addAlias(ctx, customerId, mailAlias, options); + result = await models.MailAliasAccount.addAlias(ctx, customerId, mailAlias, options); await tx.rollback(); } catch (e) { diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 12aab585c..b58395acc 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -11,8 +11,6 @@ module.exports = function(Self) { require('../methods/vn-user/validate-token')(Self); require('../methods/vn-user/privileges')(Self); require('../methods/vn-user/renew-token')(Self); - require('../methods/vn-user/addAlias')(Self); - require('../methods/vn-user/removeAlias')(Self); Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create'); diff --git a/db/changes/232402/00-hotFix_travelConfig.sql b/db/changes/232402/00-hotFix_travelConfig.sql index 65450a74d..2691999dc 100644 --- a/db/changes/232402/00-hotFix_travelConfig.sql +++ b/db/changes/232402/00-hotFix_travelConfig.sql @@ -1,19 +1,19 @@ -CREATE TABLE `vn`.`travelConfig` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen', - `warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino', - `agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto', - `companyFk` int(10) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto', - PRIMARY KEY (`id`), - KEY `travelConfig_FK` (`warehouseInFk`), - KEY `travelConfig_FK_1` (`warehouseOutFk`), - KEY `travelConfig_FK_2` (`agencyFk`), - KEY `travelConfig_FK_3` (`companyFk`), - CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +-- CREATE TABLE `vn`.`travelConfig` ( +-- `id` int(11) unsigned NOT NULL AUTO_INCREMENT, +-- `warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen', +-- `warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino', +-- `agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto', +-- `companyFk` int(10) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto', +-- PRIMARY KEY (`id`), +-- KEY `travelConfig_FK` (`warehouseInFk`), +-- KEY `travelConfig_FK_1` (`warehouseOutFk`), +-- KEY `travelConfig_FK_2` (`agencyFk`), +-- KEY `travelConfig_FK_3` (`companyFk`), +-- CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, +-- CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, +-- CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, +-- CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES diff --git a/db/changes/232601/00-aclAddAlias.sql b/db/changes/232601/00-aclAddAlias.sql index cc96f5ad8..db2100bed 100644 --- a/db/changes/232601/00-aclAddAlias.sql +++ b/db/changes/232601/00-aclAddAlias.sql @@ -1,11 +1,5 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) VALUES - ('VnUser', 'addAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'); - -INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) - VALUES - ('VnUser', 'removeAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'); - -INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) - VALUES - ('VnUser', 'canRemoveAlias', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); + ('MailAliasAccount', 'addAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', 'removeAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', 'canEditAlias', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 809ed5874..4408b48b5 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -299,5 +299,5 @@ "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico", "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", - "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado" + "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado" } diff --git a/back/methods/vn-user/addAlias.js b/modules/account/back/methods/mail-alias-account/addAlias.js similarity index 58% rename from back/methods/vn-user/addAlias.js rename to modules/account/back/methods/mail-alias-account/addAlias.js index 9fe43e713..74624b63c 100644 --- a/back/methods/vn-user/addAlias.js +++ b/modules/account/back/methods/mail-alias-account/addAlias.js @@ -1,5 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); - module.exports = Self => { Self.remoteMethod('addAlias', { description: 'Add an alias if the user has the grant', @@ -32,33 +30,12 @@ module.exports = Self => { Self.addAlias = async function(ctx, id, mailAlias, options) { const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions); - - if (!user.hasGrant) - throw new UserError(`You don't have grant privilege`); - - const account = await models.Account.findById(userId, { - fields: ['id'], - include: { - relation: 'aliases', - scope: { - fields: ['mailAlias'] - } - } - }, myOptions); - - const aliases = account.aliases().map(alias => alias.mailAlias); - - const hasAlias = aliases.includes(mailAlias); - if (!hasAlias) - throw new UserError(`You cannot assign an alias that you are not assigned to`); + await Self.hasGrant(ctx, mailAlias, myOptions); return models.MailAliasAccount.create({ mailAlias: mailAlias, diff --git a/back/methods/vn-user/removeAlias.js b/modules/account/back/methods/mail-alias-account/removeAlias.js similarity index 83% rename from back/methods/vn-user/removeAlias.js rename to modules/account/back/methods/mail-alias-account/removeAlias.js index 0424c3e96..c32911f4d 100644 --- a/back/methods/vn-user/removeAlias.js +++ b/modules/account/back/methods/mail-alias-account/removeAlias.js @@ -32,16 +32,12 @@ module.exports = Self => { Self.removeAlias = async function(ctx, id, mailAlias, options) { const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const canRemoveAlias = await models.ACL.checkAccessAcl(ctx, 'VnUser', 'canRemoveAlias', 'WRITE'); - - if (userId != id && !canRemoveAlias) throw new UserError(`You don't have grant privilege`); + await Self.hasGrant(ctx, mailAlias, myOptions); const mailAliasAccount = await models.MailAliasAccount.findOne({ where: { diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js new file mode 100644 index 000000000..21c70c32e --- /dev/null +++ b/modules/account/back/models/mail-alias-account.js @@ -0,0 +1,53 @@ + +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + require('../methods/account/sync')(Self); + require('../methods/account/sync-by-id')(Self); + require('../methods/account/sync-all')(Self); + require('../methods/account/login')(Self); + require('../methods/account/logout')(Self); + require('../methods/account/change-password')(Self); + require('../methods/account/set-password')(Self); + require('../methods/mail-alias-account/addAlias')(Self); + require('../methods/mail-alias-account/removeAlias')(Self); + + /** + * Checks if current user has + * read privileges over a dms + * + * @param {Object} ctx - Request context + * @param {Interger} mailAlias - mailAlias id + * @param {Object} options - Query options + * @return {Boolean} True for user with grant + */ + Self.hasGrant = async function(ctx, mailAlias, options) { + const models = Self.app.models; + const userId = ctx.req.accessToken.userId; + + const canEditAlias = await models.ACL.checkAccessAcl(ctx, 'MailAliasAccount', 'canEditAlias', 'WRITE'); + if (canEditAlias) return true; + + const user = await models.VnUser.findById(userId, {fields: ['hasGrant']}, options); + if (!user.hasGrant) + throw new UserError(`You don't have grant privilege`); + + const account = await models.Account.findById(userId, { + fields: ['id'], + include: { + relation: 'aliases', + scope: { + fields: ['mailAlias'] + } + } + }, options); + + const aliases = account.aliases().map(alias => alias.mailAlias); + + const hasAlias = aliases.includes(mailAlias); + if (!hasAlias) + throw new UserError(`You cannot assign/remove an alias that you are not assigned to`); + + return true; + }; +}; diff --git a/modules/account/front/aliases/index.js b/modules/account/front/aliases/index.js index e0c738ee4..b4ada07e5 100644 --- a/modules/account/front/aliases/index.js +++ b/modules/account/front/aliases/index.js @@ -25,7 +25,7 @@ export default class Controller extends Section { } onAddSave() { - return this.$http.post(`VnUsers/${this.$params.id}/addAlias`, this.addData) + return this.$http.post(`MailAliasAccounts/${this.$params.id}/addAlias`, this.addData) .then(() => this.refresh()) .then(() => this.vnApp.showSuccess( this.$t('Subscribed to alias!')) @@ -36,7 +36,7 @@ export default class Controller extends Section { const params = { mailAlias: row.mailAlias }; - return this.$http.post(`VnUsers/${this.$params.id}/removeAlias`, params) + return this.$http.post(`MailAliasAccounts/${this.$params.id}/removeAlias`, params) .then(() => this.refresh()) .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); } diff --git a/modules/account/front/aliases/index.spec.js b/modules/account/front/aliases/index.spec.js index 61f71949c..f72c06ab4 100644 --- a/modules/account/front/aliases/index.spec.js +++ b/modules/account/front/aliases/index.spec.js @@ -27,7 +27,7 @@ describe('component vnUserAliases', () => { controller.addData = {account: 1}; controller.$params = {id: 1}; - $httpBackend.expectPOST('VnUsers/1/addAlias').respond(); + $httpBackend.expectPOST('MailAliasAccounts/1/addAlias').respond(); $httpBackend.expectGET('MailAliasAccounts').respond('foo'); controller.onAddSave(); $httpBackend.flush(); @@ -44,7 +44,7 @@ describe('component vnUserAliases', () => { ]; controller.$params = {id: 1}; - $httpBackend.expectPOST('VnUsers/1/removeAlias').respond(); + $httpBackend.expectPOST('MailAliasAccounts/1/removeAlias').respond(); $httpBackend.expectGET('MailAliasAccounts').respond(controller.$.data[1]); controller.onRemove(controller.$.data[0]); $httpBackend.flush(); From aea5133f399837a4281c446e059f910be9b0530b Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 12 Jul 2023 14:01:39 +0200 Subject: [PATCH 041/130] refs #5877 fix: aply changes --- db/changes/232601/{00-aclAddAlias.sql => 01-aclAddAlias.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/232601/{00-aclAddAlias.sql => 01-aclAddAlias.sql} (100%) diff --git a/db/changes/232601/00-aclAddAlias.sql b/db/changes/232601/01-aclAddAlias.sql similarity index 100% rename from db/changes/232601/00-aclAddAlias.sql rename to db/changes/232601/01-aclAddAlias.sql From c0d329edcab295b2277b1bece04bd344b661a1ab Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 12 Jul 2023 14:04:17 +0200 Subject: [PATCH 042/130] a --- db/changes/232402/00-hotFix_travelConfig.sql | 32 +++++++++---------- .../account/back/models/mail-alias-account.js | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/db/changes/232402/00-hotFix_travelConfig.sql b/db/changes/232402/00-hotFix_travelConfig.sql index 2691999dc..65450a74d 100644 --- a/db/changes/232402/00-hotFix_travelConfig.sql +++ b/db/changes/232402/00-hotFix_travelConfig.sql @@ -1,19 +1,19 @@ --- CREATE TABLE `vn`.`travelConfig` ( --- `id` int(11) unsigned NOT NULL AUTO_INCREMENT, --- `warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen', --- `warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino', --- `agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto', --- `companyFk` int(10) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto', --- PRIMARY KEY (`id`), --- KEY `travelConfig_FK` (`warehouseInFk`), --- KEY `travelConfig_FK_1` (`warehouseOutFk`), --- KEY `travelConfig_FK_2` (`agencyFk`), --- KEY `travelConfig_FK_3` (`companyFk`), --- CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, --- CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, --- CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, --- CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE --- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +CREATE TABLE `vn`.`travelConfig` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen', + `warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino', + `agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto', + `companyFk` int(10) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto', + PRIMARY KEY (`id`), + KEY `travelConfig_FK` (`warehouseInFk`), + KEY `travelConfig_FK_1` (`warehouseOutFk`), + KEY `travelConfig_FK_2` (`agencyFk`), + KEY `travelConfig_FK_3` (`companyFk`), + CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 21c70c32e..78ec75326 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -14,7 +14,7 @@ module.exports = Self => { /** * Checks if current user has - * read privileges over a dms + * grant to add/remove alias * * @param {Object} ctx - Request context * @param {Interger} mailAlias - mailAlias id From ef6a2ae578988ac536f91fcc7994a0483318983e Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 12 Jul 2023 14:06:28 +0200 Subject: [PATCH 043/130] refs #5887 fix: delete requires --- modules/account/back/models/mail-alias-account.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 78ec75326..0875bf79a 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -2,13 +2,6 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - require('../methods/account/sync')(Self); - require('../methods/account/sync-by-id')(Self); - require('../methods/account/sync-all')(Self); - require('../methods/account/login')(Self); - require('../methods/account/logout')(Self); - require('../methods/account/change-password')(Self); - require('../methods/account/set-password')(Self); require('../methods/mail-alias-account/addAlias')(Self); require('../methods/mail-alias-account/removeAlias')(Self); From 7aaaf5492cebb382e1474ad6a6384843f9ca17e1 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 12 Jul 2023 15:07:06 +0200 Subject: [PATCH 044/130] refs #5887 refacotr: move code to hook --- back/methods/vn-user/specs/addAlias.spec.js | 68 ------------------- db/changes/232601/01-aclAddAlias.sql | 7 +- .../methods/mail-alias-account/addAlias.js | 45 ------------ .../methods/mail-alias-account/removeAlias.js | 51 -------------- .../account/back/models/mail-alias-account.js | 25 ++++--- modules/account/front/aliases/index.js | 14 ++-- modules/account/front/aliases/index.spec.js | 9 +-- 7 files changed, 32 insertions(+), 187 deletions(-) delete mode 100644 back/methods/vn-user/specs/addAlias.spec.js delete mode 100644 modules/account/back/methods/mail-alias-account/addAlias.js delete mode 100644 modules/account/back/methods/mail-alias-account/removeAlias.js diff --git a/back/methods/vn-user/specs/addAlias.spec.js b/back/methods/vn-user/specs/addAlias.spec.js deleted file mode 100644 index 880c08139..000000000 --- a/back/methods/vn-user/specs/addAlias.spec.js +++ /dev/null @@ -1,68 +0,0 @@ -const {models} = require('vn-loopback/server/server'); - -describe('VnUser addAlias()', () => { - const employeeId = 1; - const sysadminId = 66; - const developerId = 9; - const customerId = 2; - const mailAlias = 1; - it('should throw an error when user not has privileges', async() => { - const ctx = {req: {accessToken: {userId: employeeId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let error; - try { - const options = {transaction: tx}; - - await models.MailAliasAccount.addAlias(ctx, employeeId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toContain(`You don't have grant privilege`); - }); - - it('should throw an error when user has privileges but not has the role from user', async() => { - const ctx = {req: {accessToken: {userId: sysadminId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let error; - try { - const options = {transaction: tx}; - - await models.MailAliasAccount.addAlias(ctx, employeeId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toContain(`You cannot assign/remove an alias that you are not assigned to`); - }); - - it('should add an alias', async() => { - const ctx = {req: {accessToken: {userId: developerId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let result; - try { - const options = {transaction: tx}; - - const user = await models.VnUser.findById(developerId, null, options); - await user.updateAttribute('hasGrant', true, options); - - result = await models.MailAliasAccount.addAlias(ctx, customerId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - } - - expect(result.mailAlias).toBe(mailAlias); - expect(result.account).toBe(customerId); - }); -}); diff --git a/db/changes/232601/01-aclAddAlias.sql b/db/changes/232601/01-aclAddAlias.sql index db2100bed..d4df3cd44 100644 --- a/db/changes/232601/01-aclAddAlias.sql +++ b/db/changes/232601/01-aclAddAlias.sql @@ -1,5 +1,8 @@ +DELETE FROM `salix`.`ACL` WHERE model = 'MailAliasAccount'; + INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) VALUES - ('MailAliasAccount', 'addAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'), - ('MailAliasAccount', 'removeAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', 'create', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'employee'), ('MailAliasAccount', 'canEditAlias', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/modules/account/back/methods/mail-alias-account/addAlias.js b/modules/account/back/methods/mail-alias-account/addAlias.js deleted file mode 100644 index 74624b63c..000000000 --- a/modules/account/back/methods/mail-alias-account/addAlias.js +++ /dev/null @@ -1,45 +0,0 @@ -module.exports = Self => { - Self.remoteMethod('addAlias', { - description: 'Add an alias if the user has the grant', - accessType: 'WRITE', - accepts: [ - { - arg: 'ctx', - type: 'Object', - http: {source: 'context'} - }, - { - arg: 'id', - type: 'number', - required: true, - description: 'The user id', - http: {source: 'path'} - }, - { - arg: 'mailAlias', - type: 'number', - description: 'The new alias for user', - required: true - } - ], - http: { - path: `/:id/addAlias`, - verb: 'POST' - } - }); - - Self.addAlias = async function(ctx, id, mailAlias, options) { - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - await Self.hasGrant(ctx, mailAlias, myOptions); - - return models.MailAliasAccount.create({ - mailAlias: mailAlias, - account: id - }, myOptions); - }; -}; diff --git a/modules/account/back/methods/mail-alias-account/removeAlias.js b/modules/account/back/methods/mail-alias-account/removeAlias.js deleted file mode 100644 index c32911f4d..000000000 --- a/modules/account/back/methods/mail-alias-account/removeAlias.js +++ /dev/null @@ -1,51 +0,0 @@ -const UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.remoteMethod('removeAlias', { - description: 'Remove alias if the user has the grant', - accessType: 'WRITE', - accepts: [ - { - arg: 'ctx', - type: 'Object', - http: {source: 'context'} - }, - { - arg: 'id', - type: 'number', - required: true, - description: 'The user id', - http: {source: 'path'} - }, - { - arg: 'mailAlias', - type: 'number', - description: 'The alias to delete', - required: true - } - ], - http: { - path: `/:id/removeAlias`, - verb: 'POST' - } - }); - - Self.removeAlias = async function(ctx, id, mailAlias, options) { - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - await Self.hasGrant(ctx, mailAlias, myOptions); - - const mailAliasAccount = await models.MailAliasAccount.findOne({ - where: { - mailAlias: mailAlias, - account: id - } - }, myOptions); - - await mailAliasAccount.destroy(myOptions); - }; -}; diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 0875bf79a..6f5213f24 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -2,8 +2,17 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - require('../methods/mail-alias-account/addAlias')(Self); - require('../methods/mail-alias-account/removeAlias')(Self); + Self.observe('before save', async ctx => { + const changes = ctx.currentInstance || ctx.instance; + + await Self.hasGrant(ctx, changes.mailAlias); + }); + + Self.observe('before delete', async ctx => { + const mailAliasAccount = await Self.findById(ctx.where.id); + + await Self.hasGrant(ctx, mailAliasAccount.mailAlias); + }); /** * Checks if current user has @@ -11,17 +20,17 @@ module.exports = Self => { * * @param {Object} ctx - Request context * @param {Interger} mailAlias - mailAlias id - * @param {Object} options - Query options * @return {Boolean} True for user with grant */ - Self.hasGrant = async function(ctx, mailAlias, options) { + Self.hasGrant = async function(ctx, mailAlias) { const models = Self.app.models; - const userId = ctx.req.accessToken.userId; + const accessToken = {req: {accessToken: ctx.options.accessToken}}; + const userId = accessToken.req.accessToken.userId; - const canEditAlias = await models.ACL.checkAccessAcl(ctx, 'MailAliasAccount', 'canEditAlias', 'WRITE'); + const canEditAlias = await models.ACL.checkAccessAcl(accessToken, 'MailAliasAccount', 'canEditAlias', 'WRITE'); if (canEditAlias) return true; - const user = await models.VnUser.findById(userId, {fields: ['hasGrant']}, options); + const user = await models.VnUser.findById(userId, {fields: ['hasGrant']}); if (!user.hasGrant) throw new UserError(`You don't have grant privilege`); @@ -33,7 +42,7 @@ module.exports = Self => { fields: ['mailAlias'] } } - }, options); + }); const aliases = account.aliases().map(alias => alias.mailAlias); diff --git a/modules/account/front/aliases/index.js b/modules/account/front/aliases/index.js index b4ada07e5..0fc806a71 100644 --- a/modules/account/front/aliases/index.js +++ b/modules/account/front/aliases/index.js @@ -21,11 +21,12 @@ export default class Controller extends Section { } onAddClick() { + this.addData = {account: this.$params.id}; this.$.dialog.show(); } onAddSave() { - return this.$http.post(`MailAliasAccounts/${this.$params.id}/addAlias`, this.addData) + return this.$http.post(`MailAliasAccounts`, this.addData) .then(() => this.refresh()) .then(() => this.vnApp.showSuccess( this.$t('Subscribed to alias!')) @@ -33,12 +34,11 @@ export default class Controller extends Section { } onRemove(row) { - const params = { - mailAlias: row.mailAlias - }; - return this.$http.post(`MailAliasAccounts/${this.$params.id}/removeAlias`, params) - .then(() => this.refresh()) - .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); + return this.$http.delete(`MailAliasAccounts/${row.id}`) + .then(() => { + this.$.data.splice(this.$.data.indexOf(row), 1); + this.vnApp.showSuccess(this.$t('Unsubscribed from alias!')); + }); } } diff --git a/modules/account/front/aliases/index.spec.js b/modules/account/front/aliases/index.spec.js index f72c06ab4..466f1e1e9 100644 --- a/modules/account/front/aliases/index.spec.js +++ b/modules/account/front/aliases/index.spec.js @@ -25,9 +25,8 @@ describe('component vnUserAliases', () => { describe('onAddSave()', () => { it('should add the new row', () => { controller.addData = {account: 1}; - controller.$params = {id: 1}; - $httpBackend.expectPOST('MailAliasAccounts/1/addAlias').respond(); + $httpBackend.expectPOST('MailAliasAccounts').respond(); $httpBackend.expectGET('MailAliasAccounts').respond('foo'); controller.onAddSave(); $httpBackend.flush(); @@ -42,14 +41,12 @@ describe('component vnUserAliases', () => { {id: 1, alias: 'foo'}, {id: 2, alias: 'bar'} ]; - controller.$params = {id: 1}; - $httpBackend.expectPOST('MailAliasAccounts/1/removeAlias').respond(); - $httpBackend.expectGET('MailAliasAccounts').respond(controller.$.data[1]); + $httpBackend.expectDELETE('MailAliasAccounts/1').respond(); controller.onRemove(controller.$.data[0]); $httpBackend.flush(); - expect(controller.$.data).toEqual({id: 2, alias: 'bar'}); + expect(controller.$.data).toEqual([{id: 2, alias: 'bar'}]); expect(controller.vnApp.showSuccess).toHaveBeenCalled(); }); }); From 69c3a49cce42c1f0d2d07c5b1a24b245a004d3e5 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 13 Jul 2023 08:05:10 +0200 Subject: [PATCH 046/130] warnFix: smtp prevents the sending of emails depending on the condition --- print/core/smtp.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/print/core/smtp.js b/print/core/smtp.js index 276b85401..8c07e7eca 100644 --- a/print/core/smtp.js +++ b/print/core/smtp.js @@ -10,16 +10,17 @@ module.exports = { async send(options) { options.from = `${config.app.senderName} <${config.app.senderEmail}>`; - if (!process.env.NODE_ENV) - options.to = config.app.senderEmail; + const env = process.env.NODE_ENV; + const canSend = env === 'production' || !env || options.force; - if (process.env.NODE_ENV !== 'production' && !options.force) { + if (!canSend || !config.smtp.auth.user) { const notProductionError = {message: 'This not production, this email not sended'}; await this.mailLog(options, notProductionError); + return Promise.resolve(true); } - if (!config.smtp.auth.user) - return Promise.resolve(true); + if (!env) + options.to = config.app.senderEmail; let res; let error; From 3a61bc6052a2137f6590e7092aac6a9d8c4f76b3 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 13 Jul 2023 08:21:17 +0200 Subject: [PATCH 047/130] refs #5887 move changes sql --- db/changes/{232601 => 232602}/01-aclAddAlias.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{232601 => 232602}/01-aclAddAlias.sql (100%) diff --git a/db/changes/232601/01-aclAddAlias.sql b/db/changes/232602/01-aclAddAlias.sql similarity index 100% rename from db/changes/232601/01-aclAddAlias.sql rename to db/changes/232602/01-aclAddAlias.sql From 337ce56a60e7296e49143455f2784de28fe0b68d Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 13 Jul 2023 08:37:11 +0200 Subject: [PATCH 048/130] refs #5887 test exlcuido --- modules/ticket/back/methods/ticket/specs/filter.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index 6cc1a3ad2..510446cab 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -141,6 +141,7 @@ describe('ticket filter()', () => { }); it('should return the tickets that are not pending', async() => { + pending('#6010 test intermitente'); const tx = await models.Ticket.beginTransaction({}); try { From 112d7a84e336b6242ff04a845faf256bb81b71b2 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 13 Jul 2023 09:32:08 +0200 Subject: [PATCH 049/130] solved test --- back/methods/vn-user/specs/addAlias.spec.js | 68 ------------------- modules/ticket/front/descriptor-menu/index.js | 2 +- 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 back/methods/vn-user/specs/addAlias.spec.js diff --git a/back/methods/vn-user/specs/addAlias.spec.js b/back/methods/vn-user/specs/addAlias.spec.js deleted file mode 100644 index ef657a3a8..000000000 --- a/back/methods/vn-user/specs/addAlias.spec.js +++ /dev/null @@ -1,68 +0,0 @@ -const {models} = require('vn-loopback/server/server'); - -describe('VnUser addAlias()', () => { - const employeeId = 1; - const sysadminId = 66; - const developerId = 9; - const customerId = 2; - const mailAlias = 1; - it('should throw an error when user not has privileges', async() => { - const ctx = {req: {accessToken: {userId: employeeId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let error; - try { - const options = {transaction: tx}; - - await models.VnUser.addAlias(ctx, employeeId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toContain(`You don't have grant privilege`); - }); - - it('should throw an error when user has privileges but not has the role from user', async() => { - const ctx = {req: {accessToken: {userId: sysadminId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let error; - try { - const options = {transaction: tx}; - - await models.VnUser.addAlias(ctx, employeeId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toContain(`You cannot assign an alias that you are not assigned to`); - }); - - it('should add an alias', async() => { - const ctx = {req: {accessToken: {userId: developerId}}}; - const tx = await models.VnUser.beginTransaction({}); - - let result; - try { - const options = {transaction: tx}; - - const user = await models.VnUser.findById(developerId, null, options); - await user.updateAttribute('hasGrant', true, options); - - result = await models.VnUser.addAlias(ctx, customerId, mailAlias, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - } - - expect(result.mailAlias).toBe(mailAlias); - expect(result.account).toBe(customerId); - }); -}); diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 0b47102ac..0fc8488ca 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -270,7 +270,7 @@ class Controller extends Section { }); } - return this.$http.post(`Tickets/invoiceTickets`, params) + return this.$http.post(`Tickets/invoiceTickets`, {ticketsIds: [this.id]}) .then(() => this.reload()) .then(() => this.vnApp.showSuccess(this.$t('Ticket invoiced'))); } From 660612cb849e9615e09c5fb98abd424b9d37493a Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 13 Jul 2023 10:22:41 +0200 Subject: [PATCH 050/130] refs #5999 url --- modules/client/front/defaulter/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 95c7622f9..a2efdcb5c 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -32,6 +32,7 @@ export default class Controller extends Section { }, { field: 'country', autocomplete: { + url: 'Countries', showField: 'country', valueField: 'country' } From 2627cafc229aa0910e07198e7f19f99d44883c07 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 13 Jul 2023 10:54:22 +0200 Subject: [PATCH 051/130] refs #5999 defaulter country autocomplete --- modules/client/back/methods/defaulter/filter.js | 3 ++- modules/client/back/models/defaulter.json | 4 ++-- modules/client/front/defaulter/index.html | 4 ++-- modules/client/front/defaulter/index.js | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index 736c29f9c..ec6088ff0 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -69,11 +69,12 @@ module.exports = Self => { c.creditInsurance, d.defaulterSinced, cn.country, + c.countryFk, pm.name payMethod FROM vn.defaulter d JOIN vn.client c ON c.id = d.clientFk JOIN vn.country cn ON cn.id = c.countryFk - JOIN vn.payMethod pm ON pm.id = c.payMethodFk + JOIN vn.payMethod pm ON pm.id = c.payMethodFk LEFT JOIN vn.clientObservation co ON co.clientFk = c.id LEFT JOIN account.user u ON u.id = c.salesPersonFk LEFT JOIN account.user uw ON uw.id = co.workerFk diff --git a/modules/client/back/models/defaulter.json b/modules/client/back/models/defaulter.json index 03d68ea71..ef22c2429 100644 --- a/modules/client/back/models/defaulter.json +++ b/modules/client/back/models/defaulter.json @@ -33,7 +33,7 @@ "country": { "type": "belongsTo", "model": "Country", - "foreignKey": "country" + "foreignKey": "countryFk" }, "payMethod": { "type": "belongsTo", @@ -41,4 +41,4 @@ "foreignKey": "payMethod" } } -} \ No newline at end of file +} diff --git a/modules/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html index 4f662b62b..3c66e6459 100644 --- a/modules/client/front/defaulter/index.html +++ b/modules/client/front/defaulter/index.html @@ -57,7 +57,7 @@ Comercial - + Country {{::defaulter.payMethod}} - + {{::defaulter.amount | currency: 'EUR': 2}} Date: Thu, 13 Jul 2023 13:45:07 +0200 Subject: [PATCH 052/130] refs #5964 fix supply --- modules/supplier/back/models/supplier.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index 9c78e8590..488b03b0f 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -68,9 +68,9 @@ module.exports = Self => { }; const country = await Self.app.models.Country.findOne(filter); const code = country ? country.code.toLowerCase() : null; - const countryCode = this.nif.toLowerCase().substring(0, 2); + const countryCode = this.nif?.toLowerCase().substring(0, 2); - if (!this.nif || !validateTin(this.nif, code) || (this.isVies && countryCode == code)) + if (!validateTin(this.nif, code) || (this.isVies && countryCode == code)) err(); done(); } @@ -122,7 +122,7 @@ module.exports = Self => { }); async function hasSupplierSameName(err, done) { - if (!this.name || !this.countryFk) done(); + if (!this.name || !this.countryFk) return done(); const supplier = await Self.app.models.Supplier.findOne( { where: { From 765a84e2eb9ec325fc892994d18361796f6dfd7e Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 14 Jul 2023 07:27:04 +0200 Subject: [PATCH 053/130] refs #5819 Added param to call zone_getLeaves --- modules/zone/back/methods/zone/getLeaves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/zone/back/methods/zone/getLeaves.js b/modules/zone/back/methods/zone/getLeaves.js index a6db3b711..aeed9f3a2 100644 --- a/modules/zone/back/methods/zone/getLeaves.js +++ b/modules/zone/back/methods/zone/getLeaves.js @@ -38,7 +38,7 @@ module.exports = Self => { Object.assign(myOptions, options); const [res] = await Self.rawSql( - `CALL zone_getLeaves(?, ?, ?)`, + `CALL zone_getLeaves(?, ?, ?, FALSE)`, [id, parentId, search], myOptions ); From 6d8b3e346dc99043d23af1c771d3483b80aef386 Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 14 Jul 2023 09:40:16 +0200 Subject: [PATCH 054/130] refs #5837 fix filter existingClient France --- modules/client/back/models/client.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index ca279ef71..dc48f9d3d 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -50,9 +50,14 @@ module.exports = Self => { ] } }; - const client = await Self.app.models.Client.findOne(filter); - if (client) - err(); + + const existingClient = await Self.app.models.Client.findOne(filter); + + if (existingClient) { + if (this.countryFk !== 19 && this.socialName === existingClient.socialName) + err(); + } + done(); } From 765c22df969a5ebd8c73907cd30f503a7934ca5e Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 14 Jul 2023 11:30:13 +0200 Subject: [PATCH 055/130] refs #5837 new table --- back/models/country.json | 5 ++++- db/changes/233001/00-noUniqueSocialName.sql | 2 ++ modules/client/back/models/client.js | 3 ++- modules/client/back/models/client.json | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 db/changes/233001/00-noUniqueSocialName.sql diff --git a/back/models/country.json b/back/models/country.json index 8fa25b88e..fd540d819 100644 --- a/back/models/country.json +++ b/back/models/country.json @@ -22,6 +22,9 @@ }, "isUeeMember": { "type": "boolean" + }, + "isSocialNameUnique": { + "type": "boolean" } }, "relations": { @@ -39,4 +42,4 @@ "permission": "ALLOW" } ] -} \ No newline at end of file +} diff --git a/db/changes/233001/00-noUniqueSocialName.sql b/db/changes/233001/00-noUniqueSocialName.sql new file mode 100644 index 000000000..0dc4c832f --- /dev/null +++ b/db/changes/233001/00-noUniqueSocialName.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`country` +ADD COLUMN `isSocialNameUnique` tinyint(1) NOT NULL DEFAULT 1; diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index dc48f9d3d..089500149 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -54,7 +54,8 @@ module.exports = Self => { const existingClient = await Self.app.models.Client.findOne(filter); if (existingClient) { - if (this.countryFk !== 19 && this.socialName === existingClient.socialName) + console.log(this.isSocialNameUnique); + if (!this.isSocialNameUnique && this.socialName === existingClient.socialName) err(); } diff --git a/modules/client/back/models/client.json b/modules/client/back/models/client.json index 5f56a1ed2..66a67ec2e 100644 --- a/modules/client/back/models/client.json +++ b/modules/client/back/models/client.json @@ -181,6 +181,11 @@ "model": "Country", "foreignKey": "countryFk" }, + "isSocialNameUnique": { + "type": "belongsTo", + "model": "Country", + "foreignKey": "countryFk" + }, "contactChannel": { "type": "belongsTo", "model": "ContactChannel", From 4a7cfe912204156944dc354db1eb256ef101bfb6 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 14 Jul 2023 11:51:15 +0200 Subject: [PATCH 056/130] fix: workCenter --- modules/worker/front/calendar/index.html | 142 ++++++------ modules/worker/front/calendar/index.js | 7 +- modules/worker/front/card/index.js | 15 +- modules/worker/front/time-control/index.html | 222 ++++++++++--------- modules/worker/front/time-control/index.js | 6 +- 5 files changed, 201 insertions(+), 191 deletions(-) diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index 877add57b..d264e0ebc 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -1,9 +1,9 @@ - - -
+
+ +
-
-
- Autonomous worker -
- -
-
-
{{'Contract' | translate}} #{{$ctrl.businessId}}
-
- {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} + +
+
+
{{'Contract' | translate}} #{{$ctrl.businessId}}
+
+ {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} +
+
+ {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} +
+
+ {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}} +
-
- {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} -
-
- {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}} -
-
-
-
{{'Year' | translate}} {{$ctrl.year}}
-
- {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} +
+
{{'Year' | translate}} {{$ctrl.year}}
+
+ {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} +
+
+ {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} +
-
- {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} -
-
-
- + - - + +
- - - - {{absenceType.name}} - -
-
- - - - Festive - - - - - Current day - -
+ ng-click="$ctrl.pick(absenceType)"> + + + + {{absenceType.name}} +
- - - +
+ + + + Festive + + + + + Current day + +
+
+
+ + +
+
+ Autonomous worker +
diff --git a/modules/worker/front/calendar/index.js b/modules/worker/front/calendar/index.js index 87e806cc3..5606ad0ce 100644 --- a/modules/worker/front/calendar/index.js +++ b/modules/worker/front/calendar/index.js @@ -31,6 +31,8 @@ class Controller extends Section { } set businessId(value) { + if (!this.card.hasWorkCenter) return; + this._businessId = value; if (value) { this.refresh() @@ -64,7 +66,7 @@ class Controller extends Section { set worker(value) { this._worker = value; - if (value && value.hasWorkCenter) { + if (value) { this.getIsSubordinate(); this.getActiveContract(); } @@ -293,5 +295,8 @@ ngModule.vnComponent('vnWorkerCalendar', { controller: Controller, bindings: { worker: '<' + }, + require: { + card: '^vnWorkerCard' } }); diff --git a/modules/worker/front/card/index.js b/modules/worker/front/card/index.js index 35f331764..0bf9ae5c4 100644 --- a/modules/worker/front/card/index.js +++ b/modules/worker/front/card/index.js @@ -3,7 +3,7 @@ import ModuleCard from 'salix/components/module-card'; class Controller extends ModuleCard { reload() { - let filter = { + const filter = { include: [ { relation: 'user', @@ -32,13 +32,12 @@ class Controller extends ModuleCard { ] }; - this.$http.get(`Workers/${this.$params.id}`, {filter}) - .then(res => this.worker = res.data) - .then(() => - this.$http.get(`Workers/${this.$params.id}/activeContract`) - .then(res => { - if (res.data) this.worker.hasWorkCenter = res.data.workCenterFk; - })); + return Promise.all([ + this.$http.get(`Workers/${this.$params.id}`, {filter}) + .then(res => this.worker = res.data), + this.$http.get(`Workers/${this.$params.id}/activeContract`) + .then(res => this.hasWorkCenter = res.data.workCenterFk) + ]); } } diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 5f0855ee6..5d8d2c503 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -4,7 +4,7 @@ filter="::$ctrl.filter" data="$ctrl.hours"> -
+
@@ -105,118 +105,120 @@ ng-show="::$ctrl.isHr"> + + + +
+
+
Hours
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + +
+ + + + Are you sure you want to send it? + + + + + +
Autonomous worker
- - -
-
-
Hours
- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- - - - -
- - - - Are you sure you want to send it? - - - - - - diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index 90ec33293..38e6721d6 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -141,6 +141,8 @@ class Controller extends Section { ]} }; this.$.model.applyFilter(filter, params).then(() => { + if (!this.card.hasWorkCenter) return; + this.getWorkedHours(this.started, this.ended); this.getAbsences(); }); @@ -151,7 +153,6 @@ class Controller extends Section { } getAbsences() { - if (!this.worker.hasWorkerCenter) return; const fullYear = this.started.getFullYear(); let params = { workerFk: this.$params.id, @@ -486,5 +487,8 @@ ngModule.vnComponent('vnWorkerTimeControl', { controller: Controller, bindings: { worker: '<' + }, + require: { + card: '^vnWorkerCard' } }); From 4f183d1c6a6d52d2cf4f55b7b15baff616e3c830 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 14 Jul 2023 12:18:41 +0200 Subject: [PATCH 057/130] fix: worker.basic-data el boton guardar estava activo al hacer F5 --- db/changes/232802/01-aclAddAlias.sql | 4 +++ modules/worker/front/descriptor/index.html | 37 +++++++++------------- modules/worker/front/descriptor/index.js | 25 +++++---------- 3 files changed, 27 insertions(+), 39 deletions(-) create mode 100644 db/changes/232802/01-aclAddAlias.sql diff --git a/db/changes/232802/01-aclAddAlias.sql b/db/changes/232802/01-aclAddAlias.sql new file mode 100644 index 000000000..149dd6f15 --- /dev/null +++ b/db/changes/232802/01-aclAddAlias.sql @@ -0,0 +1,4 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('WorkerDisableExcluded', '*', 'READ', 'ALLOW', 'ROLE', 'itManagement'), + ('WorkerDisableExcluded', '*', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/modules/worker/front/descriptor/index.html b/modules/worker/front/descriptor/index.html index 58ac3d9e6..ea005e1a2 100644 --- a/modules/worker/front/descriptor/index.html +++ b/modules/worker/front/descriptor/index.html @@ -5,8 +5,8 @@
- - Click to exclude the user from getting disabled - - - Click to allow the user to be disabled - + + {{$ctrl.workerExcluded + ? 'Click to allow the user to be disabled' + : 'Click to exclude the user from getting disabled'}} +
@@ -84,7 +77,7 @@ - - \ No newline at end of file + diff --git a/modules/worker/front/descriptor/index.js b/modules/worker/front/descriptor/index.js index ef2f64e85..a53528ef2 100644 --- a/modules/worker/front/descriptor/index.js +++ b/modules/worker/front/descriptor/index.js @@ -18,28 +18,19 @@ class Controller extends Descriptor { this.getIsExcluded(); } - get excluded() { - return this.entity.excluded; - } - - set excluded(value) { - this.entity.excluded = value; - } - getIsExcluded() { - this.$http.get(`workerDisableExcludeds/${this.entity.id}/exists`).then(data => { - this.excluded = data.data.exists; + this.$http.get(`WorkerDisableExcludeds/${this.entity.id}/exists`).then(data => { + this.workerExcluded = data.data.exists; }); } handleExcluded() { - if (this.excluded) { - this.$http.delete(`workerDisableExcludeds/${this.entity.id}`); - this.excluded = false; - } else { - this.$http.post(`workerDisableExcludeds`, {workerFk: this.entity.id, dated: new Date}); - this.excluded = true; - } + if (this.workerExcluded) + this.$http.delete(`WorkerDisableExcludeds/${this.entity.id}`); + else + this.$http.post(`WorkerDisableExcludeds`, {workerFk: this.entity.id, dated: new Date}); + + this.workerExcluded = !this.workerExcluded; } loadData() { From 5716acaa3c94b9396553acac874bd9cb58d5c39c Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 14 Jul 2023 13:01:31 +0200 Subject: [PATCH 058/130] fix: test --- modules/worker/front/calendar/index.html | 174 +++++++------- modules/worker/front/calendar/index.spec.js | 5 +- modules/worker/front/time-control/index.html | 219 +++++++++--------- .../worker/front/time-control/index.spec.js | 5 +- 4 files changed, 202 insertions(+), 201 deletions(-) diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index d264e0ebc..1b0560185 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -1,9 +1,9 @@ + +
- -
- -
-
-
{{'Contract' | translate}} #{{$ctrl.businessId}}
-
- {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} -
-
- {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} -
-
- {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}} -
-
- -
-
{{'Year' | translate}} {{$ctrl.year}}
-
- {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} -
-
- {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} - {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} -
-
- -
- - - - -
#{{businessFk}}
-
- {{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}} -
-
-
-
-
- - - - - {{absenceType.name}} - -
-
- - - - Festive - - - - - Current day - -
-
-
- -
Autonomous worker
+ +
+
+
{{'Contract' | translate}} #{{$ctrl.businessId}}
+
+ {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} +
+
+ {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} +
+
+ {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}} +
+
+
+
{{'Year' | translate}} {{$ctrl.year}}
+
+ {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} +
+
+ {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} +
+
+ +
+ + + + +
#{{businessFk}}
+
+ {{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}} +
+
+
+
+
+ + + + + {{absenceType.name}} + +
+
+ + + + Festive + + + + + Current day + +
+
+
+ + + diff --git a/modules/worker/front/calendar/index.spec.js b/modules/worker/front/calendar/index.spec.js index 4b78d883b..5d7ae0795 100644 --- a/modules/worker/front/calendar/index.spec.js +++ b/modules/worker/front/calendar/index.spec.js @@ -20,6 +20,9 @@ describe('Worker', () => { controller.absenceType = {id: 1, name: 'Holiday', code: 'holiday', rgb: 'red'}; controller.$params.id = 1106; controller._worker = {id: 1106}; + controller.card = { + hasWorkCenter: true + }; })); describe('year() getter', () => { @@ -74,7 +77,7 @@ describe('Worker', () => { let yesterday = new Date(today.getTime()); yesterday.setDate(yesterday.getDate() - 1); - controller.worker = {id: 1107, hasWorkCenter: true}; + controller.worker = {id: 1107}; expect(controller.getIsSubordinate).toHaveBeenCalledWith(); expect(controller.getActiveContract).toHaveBeenCalledWith(); diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 5d8d2c503..760b0dafc 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -105,116 +105,6 @@ ng-show="::$ctrl.isHr"> - - - -
-
-
Hours
- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- - - - -
- - - - Are you sure you want to send it? - - - - - -
Autonomous worker
+ + +
+
+
Hours
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + +
+ + + + Are you sure you want to send it? + + + + + + diff --git a/modules/worker/front/time-control/index.spec.js b/modules/worker/front/time-control/index.spec.js index 0132f50fe..6d8510ba8 100644 --- a/modules/worker/front/time-control/index.spec.js +++ b/modules/worker/front/time-control/index.spec.js @@ -16,9 +16,8 @@ describe('Component vnWorkerTimeControl', () => { $scope = $rootScope.$new(); $element = angular.element(''); controller = $componentController('vnWorkerTimeControl', {$element, $scope}); - controller.worker = { - hasWorkerCenter: true - + controller.card = { + hasWorkCenter: true }; })); From 93387cae62aed6a12f860fe3207bf656b84d73ac Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 14 Jul 2023 13:07:40 +0200 Subject: [PATCH 059/130] refs #5837 if isSocialNameUnique --- modules/client/back/models/client.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 089500149..163d51fc5 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -42,6 +42,14 @@ module.exports = Self => { async function socialNameIsUnique(err, done) { const filter = { + include: { + relation: 'country', + scope: { + fields: { + isSocialNameUnique: true, + }, + }, + }, where: { and: [ {socialName: this.socialName}, @@ -54,8 +62,8 @@ module.exports = Self => { const existingClient = await Self.app.models.Client.findOne(filter); if (existingClient) { - console.log(this.isSocialNameUnique); - if (!this.isSocialNameUnique && this.socialName === existingClient.socialName) + // eslint-disable-next-line max-len + if (existingClient.country().isSocialNameUnique && this.socialName === existingClient.socialName) err(); } From 6980392ba1a44925b198806c4ec80ee31803a5f1 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 14 Jul 2023 13:11:09 +0200 Subject: [PATCH 060/130] fix: tabulacion --- ...clAddAlias.sql => 01-aclWorkerDisable.sql} | 0 modules/worker/front/calendar/index.html | 24 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) rename db/changes/232802/{01-aclAddAlias.sql => 01-aclWorkerDisable.sql} (100%) diff --git a/db/changes/232802/01-aclAddAlias.sql b/db/changes/232802/01-aclWorkerDisable.sql similarity index 100% rename from db/changes/232802/01-aclAddAlias.sql rename to db/changes/232802/01-aclWorkerDisable.sql diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index 1b0560185..08f63ddf9 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -59,20 +59,20 @@
+ url="Workers/{{$ctrl.$params.id}}/contracts" + fields="['started', 'ended']" + ng-model="$ctrl.businessId" + search-function="{businessFk: $search}" + value-field="businessFk" + order="businessFk DESC" + limit="5">
#{{businessFk}}
@@ -82,10 +82,8 @@
- - + + {{absenceType.name}} From 87f125453d976fbaf9382f0f3a6aaaf484660b35 Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 14 Jul 2023 13:35:13 +0200 Subject: [PATCH 061/130] refs #5640 fix mayus quit function --- loopback/locale/es.json | 6 ++++-- modules/client/back/models/client.js | 14 ++++++++++++++ modules/client/front/fiscal-data/index.html | 4 ++-- modules/client/front/fiscal-data/index.js | 6 ------ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 784ff5e6e..55a7e2f82 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -305,5 +305,7 @@ "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Valid priorities": "Prioridades válidas: %d", "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", - "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado" -} + "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", + "Social name should be uppercase": "Social name should be uppercase", + "Street should be uppercase": "Street should be uppercase" +} \ No newline at end of file diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index ca279ef71..9302d81c7 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -36,6 +36,20 @@ module.exports = Self => { min: 3, max: 10 }); + Self.validatesFormatOf('street', { + message: 'Street should be uppercase', + allowNull: false, + allowBlank: false, + with: /^[^a-z]*$/ + }); + + Self.validatesFormatOf('socialName', { + message: 'Social name should be uppercase', + allowNull: false, + allowBlank: false, + with: /^[^a-z]*$/ + }); + Self.validateAsync('socialName', socialNameIsUnique, { message: 'The company name must be unique' }); diff --git a/modules/client/front/fiscal-data/index.html b/modules/client/front/fiscal-data/index.html index 4d001e226..d1de87309 100644 --- a/modules/client/front/fiscal-data/index.html +++ b/modules/client/front/fiscal-data/index.html @@ -33,7 +33,7 @@ ng-model="$ctrl.client.socialName" info="Only letters, numbers and spaces can be used" required="true" - ng-keyup="$ctrl.mayus($event)" + ng-keyup="$ctrl.client.socialName = $ctrl.client.socialName.toUpperCase()" rule> diff --git a/modules/client/front/fiscal-data/index.js b/modules/client/front/fiscal-data/index.js index 1599c917b..acad38185 100644 --- a/modules/client/front/fiscal-data/index.js +++ b/modules/client/front/fiscal-data/index.js @@ -177,12 +177,6 @@ export default class Controller extends Section { this.client.provinceFk = response.provinceFk; this.client.countryFk = response.countryFk; } - - mayus(event) { - let input = event.target; - let inputValue = input.value; - input.value = inputValue.toUpperCase(); - } } ngModule.vnComponent('vnClientFiscalData', { From b113052b5c631d1582160deb71f0e6d8388bc81e Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 14 Jul 2023 13:48:36 +0200 Subject: [PATCH 062/130] refs #5640 fixtures and test fix --- db/dump/fixtures.sql | 4 ++-- e2e/paths/03-worker/06_create.spec.js | 2 +- .../client/back/methods/client/specs/createWithUser.spec.js | 4 ++-- modules/worker/back/methods/worker/specs/new.spec.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index fe11d5b64..2e3122c89 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -360,8 +360,8 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`) INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`, `businessTypeFk`) VALUES - (1101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@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, NULL, 0, 0, 18, 0, 1, 'florist'), - (1102, 'Petter Parker', '87945234L', 'Spider man', 'Aunt May', '20 Ingram Street, Queens, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), + (1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@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, NULL, 0, 0, 18, 0, 1, 'florist'), + (1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (1103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street, Apartament 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (1104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (1105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist'), diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js index 11d36b3cf..07eb57fe4 100644 --- a/e2e/paths/03-worker/06_create.spec.js +++ b/e2e/paths/03-worker/06_create.spec.js @@ -23,7 +23,7 @@ describe('Worker create path', () => { await page.write(selectors.workerCreate.fi, '78457139E'); await page.write(selectors.workerCreate.phone, '12356789'); await page.write(selectors.workerCreate.postcode, '46680'); - await page.write(selectors.workerCreate.street, 'S/ Doomstadt'); + await page.write(selectors.workerCreate.street, 'S/ DOOMSTADT'); await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com'); await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332'); diff --git a/modules/client/back/methods/client/specs/createWithUser.spec.js b/modules/client/back/methods/client/specs/createWithUser.spec.js index 69440c1d1..03106acc1 100644 --- a/modules/client/back/methods/client/specs/createWithUser.spec.js +++ b/modules/client/back/methods/client/specs/createWithUser.spec.js @@ -7,8 +7,8 @@ describe('Client Create', () => { email: 'Deadpool@marvel.com', fi: '16195279J', name: 'Wade', - socialName: 'Deadpool Marvel', - street: 'Wall Street', + socialName: 'DEADPOOL MARVEL', + street: 'WALL STREET', city: 'New York', businessTypeFk: 'florist', provinceFk: 1 diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js index b2804c203..1c41d666b 100644 --- a/modules/worker/back/methods/worker/specs/new.spec.js +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -24,7 +24,7 @@ describe('Worker new', () => { firstName: 'default', lastNames: 'worker', email: 'defaultWorker@mydomain.com', - street: 'S/ defaultWorkerStreet', + street: 'S/ DEFAULTWORKERSTREET', city: 'defaultWorkerCity', provinceFk: 1, companyFk: 442, From 6f3cdd3508566050b73c691f29edd92e951b62a7 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 12:30:48 +0200 Subject: [PATCH 063/130] refs #5640 fix e2e back --- db/dump/fixtures.sql | 4 ++-- e2e/paths/02-client/01_create_client.spec.js | 4 ++-- e2e/paths/02-client/12_lock_of_verified_data.spec.js | 2 +- e2e/paths/02-client/19_summary.spec.js | 2 +- loopback/locale/en.json | 6 ++++-- modules/worker/back/methods/worker/specs/new.spec.js | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2e3122c89..b1e7888a8 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -365,8 +365,8 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city (1103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street, Apartament 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (1104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'), (1105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist'), - (1106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'City of New York, New York, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist'), - (1107, 'Hank Pym', '09854837G', 'Ant man', 'Hawk', 'Anthill, San Francisco, California', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@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, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist'), + (1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist'), + (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@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, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist'), (1108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@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, 1, NULL, 0, 0, 19, 0, 1, 'florist'), (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, 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, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'), diff --git a/e2e/paths/02-client/01_create_client.spec.js b/e2e/paths/02-client/01_create_client.spec.js index ff2aac6b9..3274ae8f1 100644 --- a/e2e/paths/02-client/01_create_client.spec.js +++ b/e2e/paths/02-client/01_create_client.spec.js @@ -73,8 +73,8 @@ describe('Client create path', () => { it(`should attempt to create a new user with all it's data but wrong email`, async() => { await page.write(selectors.createClientView.name, 'Carol Danvers'); - await page.write(selectors.createClientView.socialName, 'AVG tax'); - await page.write(selectors.createClientView.street, 'Many places'); + await page.write(selectors.createClientView.socialName, 'AVG TAX'); + await page.write(selectors.createClientView.street, 'MANY PLACES'); await page.clearInput(selectors.createClientView.email); await page.write(selectors.createClientView.email, 'incorrect email format'); await page.waitToClick(selectors.createClientView.createButton); diff --git a/e2e/paths/02-client/12_lock_of_verified_data.spec.js b/e2e/paths/02-client/12_lock_of_verified_data.spec.js index 7abe15460..2d7ab7541 100644 --- a/e2e/paths/02-client/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client/12_lock_of_verified_data.spec.js @@ -28,7 +28,7 @@ describe('Client lock verified data path', () => { it('should edit the social name', async() => { await page.waitForSelector(selectors.clientFiscalData.socialName); await page.clearInput(selectors.clientFiscalData.socialName); - await page.write(selectors.clientFiscalData.socialName, 'Captain America Civil War'); + await page.write(selectors.clientFiscalData.socialName, 'CAPTAIN AMERICA CIVIL WAR'); await page.waitToClick(selectors.clientFiscalData.saveButton); const message = await page.waitForSnackbar(); diff --git a/e2e/paths/02-client/19_summary.spec.js b/e2e/paths/02-client/19_summary.spec.js index ab39154cf..b3bf43c5c 100644 --- a/e2e/paths/02-client/19_summary.spec.js +++ b/e2e/paths/02-client/19_summary.spec.js @@ -36,7 +36,7 @@ describe('Client summary path', () => { it('should display fiscal address details', async() => { const result = await page.waitToGetProperty(selectors.clientSummary.street, 'innerText'); - expect(result).toContain('20 Ingram Street'); + expect(result).toContain('20 INGRAM STREET'); }); it('should display some fiscal data', async() => { diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 030afbe9e..6f1f72ffb 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -178,5 +178,7 @@ "The renew period has not been exceeded": "The renew period has not been exceeded", "You can not use the same password": "You can not use the same password", "Valid priorities": "Valid priorities: %d", - "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}" -} + "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}", + "Social name should be uppercase": "Social name should be uppercase", + "Street should be uppercase": "Street should be uppercase" +} \ No newline at end of file diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js index 1c41d666b..4dc6c5540 100644 --- a/modules/worker/back/methods/worker/specs/new.spec.js +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -20,7 +20,7 @@ describe('Worker new', () => { const employeeId = 1; const defaultWorker = { fi: '78457139E', - name: 'defaultWorker', + name: 'DEFAULTERWORKER', firstName: 'default', lastNames: 'worker', email: 'defaultWorker@mydomain.com', From f24aa2c80130ce509ffc9e7b4e03a5c9b42a211d Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 13:27:27 +0200 Subject: [PATCH 064/130] pop vehicle error --- back/models/invoice-in.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 back/models/invoice-in.js diff --git a/back/models/invoice-in.js b/back/models/invoice-in.js new file mode 100644 index 000000000..6fa1fa0e1 --- /dev/null +++ b/back/models/invoice-in.js @@ -0,0 +1,9 @@ +let UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_ROW_IS_REFERENCED') + return new UserError(`This invoice has a linked vehicle.`); + return err; + }); +}; From 10e726c48656803a2c076adc066e43bff49a0595 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 13:51:16 +0200 Subject: [PATCH 065/130] move vehicleInvoice --- .../invoiceIn/back/models/invoiceInVehicle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename back/models/invoice-in.js => modules/invoiceIn/back/models/invoiceInVehicle.js (81%) diff --git a/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoiceInVehicle.js similarity index 81% rename from back/models/invoice-in.js rename to modules/invoiceIn/back/models/invoiceInVehicle.js index 6fa1fa0e1..cf45bf741 100644 --- a/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoiceInVehicle.js @@ -2,7 +2,7 @@ let UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.rewriteDbError(function(err) { - if (err.code === 'ER_ROW_IS_REFERENCED') + if (err.code === 'ER_ROW_IS_REFERENCED_2') return new UserError(`This invoice has a linked vehicle.`); return err; }); From a5d1c68511060e930ec2a802542ec591913c728c Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 14:07:45 +0200 Subject: [PATCH 066/130] change err and traduction --- loopback/locale/es.json | 3 ++- modules/invoiceIn/back/models/invoice-in.js | 8 ++++++++ modules/invoiceIn/back/models/invoiceInVehicle.js | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 4086cfa4a..08f5bf765 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -305,5 +305,6 @@ "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Valid priorities": "Prioridades válidas: %d", "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", - "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado" + "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", + "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado" } diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 51905ccb8..0efa6c309 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { require('../methods/invoice-in/filter')(Self); require('../methods/invoice-in/summary')(Self); @@ -7,4 +9,10 @@ module.exports = Self => { require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); require('../methods/invoice-in/getSerial')(Self); + Self.rewriteDbError(function(err) { + console.log(err); + if (err.code === 'ER_ROW_IS_REFERENCED_2') + return new UserError(`This invoice has a linked vehicle.`); + return err; + }); }; diff --git a/modules/invoiceIn/back/models/invoiceInVehicle.js b/modules/invoiceIn/back/models/invoiceInVehicle.js index cf45bf741..7fa780142 100644 --- a/modules/invoiceIn/back/models/invoiceInVehicle.js +++ b/modules/invoiceIn/back/models/invoiceInVehicle.js @@ -2,6 +2,7 @@ let UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.rewriteDbError(function(err) { + console.log(err); if (err.code === 'ER_ROW_IS_REFERENCED_2') return new UserError(`This invoice has a linked vehicle.`); return err; From 52f58a92c85f78d978bec7304816bef5b55c2d2f Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 14:11:05 +0200 Subject: [PATCH 067/130] refs err.sqlMessage --- modules/invoiceIn/back/models/invoice-in.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 0efa6c309..82e0bf078 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -10,8 +10,7 @@ module.exports = Self => { require('../methods/invoice-in/invoiceInEmail')(Self); require('../methods/invoice-in/getSerial')(Self); Self.rewriteDbError(function(err) { - console.log(err); - if (err.code === 'ER_ROW_IS_REFERENCED_2') + if (err.code === 'ER_ROW_IS_REFERENCED_2' && err.sqlMessage.includes('vehicleInvoiceIn')) return new UserError(`This invoice has a linked vehicle.`); return err; }); From 47e8fab8d9401ce78c6baa04a6c1667f59e786c6 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 17 Jul 2023 19:51:46 +0200 Subject: [PATCH 068/130] refs remove --- modules/invoiceIn/back/models/invoiceInVehicle.js | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 modules/invoiceIn/back/models/invoiceInVehicle.js diff --git a/modules/invoiceIn/back/models/invoiceInVehicle.js b/modules/invoiceIn/back/models/invoiceInVehicle.js deleted file mode 100644 index 7fa780142..000000000 --- a/modules/invoiceIn/back/models/invoiceInVehicle.js +++ /dev/null @@ -1,10 +0,0 @@ -let UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.rewriteDbError(function(err) { - console.log(err); - if (err.code === 'ER_ROW_IS_REFERENCED_2') - return new UserError(`This invoice has a linked vehicle.`); - return err; - }); -}; From 3c013110d35a96aadb7f78b226f3de590bf4957a Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 18 Jul 2023 07:32:45 +0200 Subject: [PATCH 069/130] refs #5819 Changed structure sql --- db/dump/structure.sql | 121 ++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 47 deletions(-) diff --git a/db/dump/structure.sql b/db/dump/structure.sql index ee5fb40a1..4e7127310 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -77831,7 +77831,7 @@ BEGIN LEAVE cur1Loop; END IF; - CALL zone_getLeaves2(vZoneFk, NULL, NULL); + CALL zone_getLeaves(vZoneFk, NULL, NULL, TRUE); myLoop: LOOP SET vGeoFk = NULL; @@ -77844,7 +77844,7 @@ BEGIN LEAVE myLoop; END IF; - CALL zone_getLeaves2(vZoneFk, vGeoFk, NULL); + CALL zone_getLeaves(vZoneFk, vGeoFk, NULL, TRUE); UPDATE tmp.zoneNodes SET isChecked = TRUE WHERE geoFk = vGeoFk; @@ -78130,55 +78130,58 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; -CREATE DEFINER=`root`@`localhost` PROCEDURE `zone_getLeaves`(vSelf INT, vParentFk INT, vSearch VARCHAR(255)) -BEGIN +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`zone_getLeaves`( + vSelf INT, + vParentFk INT, + vSearch VARCHAR(255), + vHasInsert BOOL +) +BEGIN /** * Devuelve las ubicaciones incluidas en la ruta y que sean hijos de parentFk. * @param vSelf Id de la zona * @param vParentFk Id del geo a calcular - * @param vSearch cadena a buscar + * @param vSearch Cadena a buscar + * @param vHasInsert Indica si inserta en tmp.zoneNodes + * Optional @table tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) */ DECLARE vIsNumber BOOL; - DECLARE vIsSearch BOOL DEFAULT vSearch IS NOT NULL AND vSearch != ''; + DECLARE vIsSearch BOOL DEFAULT vSearch IS NOT NULL AND vSearch <> ''; - DROP TEMPORARY TABLE IF EXISTS tNodes; - CREATE TEMPORARY TABLE tNodes + CREATE OR REPLACE TEMPORARY TABLE tNodes (UNIQUE (id)) ENGINE = MEMORY - SELECT id - FROM zoneGeo + SELECT id + FROM zoneGeo LIMIT 0; IF vIsSearch THEN SET vIsNumber = vSearch REGEXP '^[0-9]+$'; - + INSERT INTO tNodes - SELECT id + SELECT id FROM zoneGeo WHERE (vIsNumber AND `name` = vSearch) OR (!vIsNumber AND `name` LIKE CONCAT('%', vSearch, '%')) LIMIT 1000; - + ELSEIF vParentFk IS NULL THEN INSERT INTO tNodes - SELECT geoFk + SELECT geoFk FROM zoneIncluded WHERE zoneFk = vSelf; END IF; IF vParentFk IS NULL THEN - DROP TEMPORARY TABLE IF EXISTS tChilds; - CREATE TEMPORARY TABLE tChilds + CREATE OR REPLACE TEMPORARY TABLE tChilds + (INDEX(id)) ENGINE = MEMORY - SELECT id - FROM tNodes; + SELECT id FROM tNodes; - DROP TEMPORARY TABLE IF EXISTS tParents; - CREATE TEMPORARY TABLE tParents + CREATE OR REPLACE TEMPORARY TABLE tParents + (INDEX(id)) ENGINE = MEMORY - SELECT id - FROM zoneGeo - LIMIT 0; + SELECT id FROM zoneGeo LIMIT 0; myLoop: LOOP DELETE FROM tParents; @@ -78186,43 +78189,67 @@ BEGIN SELECT parentFk id FROM zoneGeo g JOIN tChilds c ON c.id = g.id - WHERE g.parentFk IS NOT NULL; - + WHERE g.parentFk IS NOT NULL; + INSERT IGNORE INTO tNodes - SELECT id - FROM tParents; - - IF ROW_COUNT() = 0 THEN + SELECT id FROM tParents; + + IF NOT ROW_COUNT() THEN LEAVE myLoop; END IF; - + DELETE FROM tChilds; INSERT INTO tChilds - SELECT id - FROM tParents; + SELECT id FROM tParents; END LOOP; - + DROP TEMPORARY TABLE tChilds, tParents; END IF; - IF !vIsSearch THEN + IF NOT vIsSearch THEN INSERT IGNORE INTO tNodes - SELECT id + SELECT id FROM zoneGeo WHERE parentFk <=> vParentFk; END IF; - SELECT g.id, - g.name, - g.parentFk, - g.sons, - isIncluded selected - FROM zoneGeo g - JOIN tNodes n ON n.id = g.id - LEFT JOIN zoneIncluded i ON i.geoFk = g.id AND i.zoneFk = vSelf - ORDER BY `depth`, selected DESC, name; + CREATE OR REPLACE TEMPORARY TABLE tZones + SELECT g.id, + g.name, + g.parentFk, + g.sons, + NOT g.sons OR `type` = 'country' isChecked, + i.isIncluded selected, + g.`depth`, + vSelf + FROM zoneGeo g + JOIN tNodes n ON n.id = g.id + LEFT JOIN zoneIncluded i ON i.geoFk = g.id + AND i.zoneFk = vSelf + ORDER BY g.`depth`, selected DESC, g.name; - DROP TEMPORARY TABLE tNodes; + IF vHasInsert THEN + INSERT IGNORE INTO tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) + SELECT id, + name, + parentFk, + sons, + isChecked, + vSelf + FROM tZones + WHERE selected + OR (selected IS NULL AND vParentFk IS NOT NULL); + ELSE + SELECT id, + name, + parentFk, + sons, + selected + FROM tZones + ORDER BY `depth`, selected DESC, name; + END IF; + + DROP TEMPORARY TABLE tNodes, tZones; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -78540,7 +78567,7 @@ BEGIN INDEX(geoFk)) ENGINE = MEMORY; - CALL zone_getLeaves2(vSelf, NULL , NULL); + CALL zone_getLeaves(vSelf, NULL , NULL, TRUE); UPDATE tmp.zoneNodes zn SET isChecked = 0 @@ -78553,7 +78580,7 @@ BEGIN WHERE NOT isChecked LIMIT 1; - CALL zone_getLeaves2(vSelf, vGeoFk, NULL); + CALL zone_getLeaves(vSelf, vGeoFk, NULL, TRUE); UPDATE tmp.zoneNodes SET isChecked = TRUE WHERE geoFk = vGeoFk; From 834e4b3723d3d3c9ed569f1397a4d75d475a59e0 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 07:56:44 +0200 Subject: [PATCH 070/130] refs #4734 refactor: variables definindas --- back/methods/viaexpress-config/renderer.js | 40 +++++--------------- back/methods/viaexpress-config/template.ejs | 42 ++++++++++----------- back/models/viaexpress-config.json | 6 +-- db/changes/232601/00-viaexpress.sql | 6 +-- 4 files changed, 37 insertions(+), 57 deletions(-) diff --git a/back/methods/viaexpress-config/renderer.js b/back/methods/viaexpress-config/renderer.js index 4014dd42d..e9abce5ca 100644 --- a/back/methods/viaexpress-config/renderer.js +++ b/back/methods/viaexpress-config/renderer.js @@ -24,7 +24,7 @@ module.exports = Self => { const models = Self.app.models; const viaexpressConfig = await models.ViaexpressConfig.findOne({ - fields: ['clientViaexpress', 'userViaexpress', 'passwordViaexpress', 'defaultWeight', 'deliveryType'] + fields: ['client', 'user', 'password', 'defaultWeight', 'deliveryType'] }); const expedition = await models.Expedition.findOne({ @@ -107,36 +107,16 @@ module.exports = Self => { ] }); - const shipped = expedition.ticket().shipped; - + const ticket = expedition.ticket(); + const sender = ticket.company().client(); + const shipped = ticket.shipped.toISOString(); const data = { - defaultWeight: viaexpressConfig.defaultWeight, - date: shipped.toISOString(), // const date = new Date().toISOString(); - deliveryType: viaexpressConfig.deliveryType, - senderName: expedition.ticket().company().client().socialName, - senderStreet: expedition.ticket().company().client().defaultAddress().street, - senderPostalCode: expedition.ticket().company().client().defaultAddress().postalCode, - senderCity: expedition.ticket().company().client().defaultAddress().city, - senderProvince: expedition.ticket().company().client().defaultAddress().province().name, - senderPhone: expedition.ticket().company().client().defaultAddress().mobile - || expedition.ticket().company().client().defaultAddress().phone - || expedition.ticket().company().client().mobile - || expedition.ticket().company().client().phone, - senderEmail: expedition.ticket().company().client().email, - receiverName: expedition.ticket().address().nickname, - receiverStreet: expedition.ticket().address().street, - receiverPostalCode: expedition.ticket().address().postalCode, - receiverCity: expedition.ticket().address().city, - receiverProvince: expedition.ticket().address().province().name, - receiverPhone: expedition.ticket().address().mobile - || expedition.ticket().address().phone - || expedition.ticket().client().mobile - || expedition.ticket().client().phone, - receiverEmail: expedition.ticket().client().email, - receiverCountry: expedition.ticket().address().province().country().code, - clientViaexpress: viaexpressConfig.clientViaexpress, - userViaexpress: viaexpressConfig.userViaexpress, - passwordViaexpress: viaexpressConfig.passwordViaexpress + viaexpressConfig, + sender, + senderAddress: sender.defaultAddress(), + client: ticket.client(), + address: ticket.address(), + shipped }; const template = fs.readFileSync(__dirname + '/template.ejs', 'utf-8'); diff --git a/back/methods/viaexpress-config/template.ejs b/back/methods/viaexpress-config/template.ejs index e8b1f1977..0b6eb468c 100644 --- a/back/methods/viaexpress-config/template.ejs +++ b/back/methods/viaexpress-config/template.ejs @@ -3,12 +3,12 @@ - <%= defaultWeight %> + <%= viaexpressConfig.defaultWeight %> 1 0 - <%= date %> + <%= shipped %> 0 - <%= deliveryType %> + <%= viaexpressConfig.deliveryType %> 0 0 0 @@ -20,31 +20,31 @@ - <%= senderName %> - <%= senderStreet %> - <%= senderPostalCode %> - <%= senderCity %> - <%= senderProvince %> + <%= sender.socialName %> + <%= senderAddress.street %> + <%= senderAddress.postalCode %> + <%= senderAddress.city %> + <%= senderAddress.province().name %> - <%= senderPhone %> - <%= senderEmail %> + <%= senderAddress.mobile || senderAddress.phone || sender.mobile || sender.phone %> + <%= sender.email %> - <%= receiverName %> - <%= receiverStreet %> - <%= receiverPostalCode %> - <%= receiverCity %> + <%= address.nickname %> + <%= address.street %> + <%= address.postalCode %> + <%= address.city %> - <%= receiverProvince %> + <%= address.province().name %> - <%= receiverPhone %> - <%= receiverEmail %> - <%= receiverCountry %> + <%= address.mobile || address.phone || client.mobile || client.phone %> + <%= client.email %> + <%= address.province().country().code %> - <%= clientViaexpress %> - <%= userViaexpress %> - <%= passwordViaexpress %> + <%= viaexpressConfig.client %> + <%= viaexpressConfig.user %> + <%= viaexpressConfig.password %> diff --git a/back/models/viaexpress-config.json b/back/models/viaexpress-config.json index 26d6c8e37..8df24201b 100644 --- a/back/models/viaexpress-config.json +++ b/back/models/viaexpress-config.json @@ -15,13 +15,13 @@ "type": "string", "required": true }, - "clientViaexpress": { + "client": { "type": "string" }, - "userViaexpress": { + "user": { "type": "string" }, - "passwordViaexpress": { + "password": { "type": "string" }, "defaultWeight": { diff --git a/db/changes/232601/00-viaexpress.sql b/db/changes/232601/00-viaexpress.sql index 9e3baa9fd..42cf3b647 100644 --- a/db/changes/232601/00-viaexpress.sql +++ b/db/changes/232601/00-viaexpress.sql @@ -1,9 +1,9 @@ CREATE TABLE `vn`.`viaexpressConfig` ( id int auto_increment NOT NULL, url varchar(100) NOT NULL, - clientViaexpress varchar(100) NOT NULL, - userViaexpress varchar(100) NOT NULL, - passwordViaexpress varchar(100) NOT NULL, + client varchar(100) NOT NULL, + user varchar(100) NOT NULL, + password varchar(100) NOT NULL, defaultWeight decimal(10,2) NOT NULL, deliveryType varchar(5) NOT NULL, CONSTRAINT viaexpressConfig_PK PRIMARY KEY (id) From 93da12923959e0b829871d30e08b1e157f3b6e7c Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 18 Jul 2023 08:54:45 +0200 Subject: [PATCH 071/130] refs #5983 feat(itemShelving): add getInventory --- .../233001/00-itemShelving_inventory.sql | 52 +++++++++++++++++++ .../methods/item-shelving/getInventory.js | 37 +++++++++++++ .../item-shelving/specs/getInventory.spec.js | 19 +++++++ modules/item/back/models/item-shelving.js | 1 + 4 files changed, 109 insertions(+) create mode 100644 db/changes/233001/00-itemShelving_inventory.sql create mode 100644 modules/item/back/methods/item-shelving/getInventory.js create mode 100644 modules/item/back/methods/item-shelving/specs/getInventory.spec.js diff --git a/db/changes/233001/00-itemShelving_inventory.sql b/db/changes/233001/00-itemShelving_inventory.sql new file mode 100644 index 000000000..b2a2ff321 --- /dev/null +++ b/db/changes/233001/00-itemShelving_inventory.sql @@ -0,0 +1,52 @@ + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_inventory`(vParkingFromFk INT, vParkingToFk INT) +/** + * Devuelve un listado de ubicaciones a revisar + * + * @param vParkingFromFk Parking de partida, identificador de vn.parking + * @param vParkingToFk Parking de llegada, identificador de vn.parking +*/ + + DECLARE vSectorFk INT; + DECLARE vPickingOrderFrom INT; + DECLARE vPickingOrderTo INT; + + SELECT ish.id, + p.pickingOrder, + p.code parking, + ish.shelvingFk, + ish.itemFk, + i.longName, + ish.visible, + p.sectorFk, + it.workerFk buyer, + CONCAT('http:',ic.url, '/catalog/1600x900/',i.image) urlImage, + ish.isChecked, + CASE + WHEN s.notPrepared > sm.parked THEN 0 + WHEN sm.visible > sm.parked THEN 1 + ELSE 2 + END + FROM vn.itemShelving ish + JOIN vn.item i ON i.id = ish.itemFk + JOIN vn.itemType it ON it.id = i.typeFk + JOIN tmp.stockMisfit sm ON sm.itemFk = ish.itemFk + JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.parking p ON p.id = sh.parkingFk + JOIN (SELECT s.itemFk, sum(s.quantity) notPrepared + FROM vn.sale s + JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.warehouse w ON w.id = t.warehouseFk + WHERE t.shipped BETWEEN CURDATE() + AND CURDATE() + INTERVAL 23 HOUR + AND s.isPicked = FALSE + AND w.name = 'Algemesi' + GROUP BY s.itemFk) s ON s.itemFk = i.id + JOIN hedera.imageConfig ic + WHERE p.pickingOrder BETWEEN vParkingFrom AND vPickingOrderTo + AND p.sectorFk = vSectorFk + ORDER BY p.pickingOrder; + +END ;; +DELIMITER ; diff --git a/modules/item/back/methods/item-shelving/getInventory.js b/modules/item/back/methods/item-shelving/getInventory.js new file mode 100644 index 000000000..144bd83e7 --- /dev/null +++ b/modules/item/back/methods/item-shelving/getInventory.js @@ -0,0 +1,37 @@ +module.exports = Self => { + Self.remoteMethod('getInventory', { + description: 'Get list of itemShelving to review between two parking code', + accessType: 'WRITE', + accepts: [{ + arg: 'parkingFrom', + type: 'string', + required: true, + description: 'Parking code from' + }, + { + arg: 'parkingTo', + type: 'string', + required: true, + description: 'Parking code to' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/getInventory`, + verb: 'POST' + } + }); + + Self.getInventory = async(parkingFrom, parkingTo, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const [result] = await Self.rawSql(`CALL vn.itemShelving_inventory(?, ?)`, [parkingFrom, parkingTo], myOptions); + + return result; + }; +}; diff --git a/modules/item/back/methods/item-shelving/specs/getInventory.spec.js b/modules/item/back/methods/item-shelving/specs/getInventory.spec.js new file mode 100644 index 000000000..76cc39073 --- /dev/null +++ b/modules/item/back/methods/item-shelving/specs/getInventory.spec.js @@ -0,0 +1,19 @@ +const models = require('vn-loopback/server/server').models; + +describe('itemShelving getInventory()', () => { + it('should return a list of itemShelvings', async() => { + const tx = await models.ItemShelving.beginTransaction({}); + + let response; + try { + const options = {transaction: tx}; + response = await models.ItemShelving.getInventory(1, 2, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(response.length).toEqual(2); + }); +}); diff --git a/modules/item/back/models/item-shelving.js b/modules/item/back/models/item-shelving.js index 5f372a3be..98ff18931 100644 --- a/modules/item/back/models/item-shelving.js +++ b/modules/item/back/models/item-shelving.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/item-shelving/deleteItemShelvings')(Self); + require('../methods/item-shelving/getInventory')(Self); }; From b3a7a170f0522ff693be1684d3201b8914a8ca7e Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 11:54:43 +0200 Subject: [PATCH 072/130] =?UTF-8?q?refs=20#5934=20feat:=20a=C3=B1adido=20c?= =?UTF-8?q?lientSms=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/changes/233001/00-clientSms.sql | 15 +++++++ modules/client/back/methods/client/sendSms.js | 8 +++- modules/client/back/model-config.json | 3 ++ modules/client/back/models/client-sms.json | 29 +++++++++++++ modules/client/back/models/sms.json | 2 +- modules/client/front/index.js | 1 + modules/client/front/routes.json | 7 ++++ modules/client/front/sms/index.html | 42 +++++++++++++++++++ modules/client/front/sms/index.js | 39 +++++++++++++++++ modules/client/front/sms/locale/es.yml | 2 + 10 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 db/changes/233001/00-clientSms.sql create mode 100644 modules/client/back/models/client-sms.json create mode 100644 modules/client/front/sms/index.html create mode 100644 modules/client/front/sms/index.js create mode 100644 modules/client/front/sms/locale/es.yml diff --git a/db/changes/233001/00-clientSms.sql b/db/changes/233001/00-clientSms.sql new file mode 100644 index 000000000..353041ad9 --- /dev/null +++ b/db/changes/233001/00-clientSms.sql @@ -0,0 +1,15 @@ +CREATE TABLE `vn`.`clientSms` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `clientFk` int(11) NOT NULL, + `smsFk` mediumint(8) unsigned NOT NULL, + PRIMARY KEY (`id`), + KEY `clientSms_FK` (`clientFk`), + KEY `clientSms_FK_1` (`smsFk`), + CONSTRAINT `clientSms_FK` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE, + CONSTRAINT `clientSms_FK_1` FOREIGN KEY (`smsFk`) REFERENCES `sms` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('ClientSms', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('ClientSms', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/modules/client/back/methods/client/sendSms.js b/modules/client/back/methods/client/sendSms.js index 83b7c8d6e..270d7e5b5 100644 --- a/modules/client/back/methods/client/sendSms.js +++ b/modules/client/back/methods/client/sendSms.js @@ -7,7 +7,7 @@ module.exports = Self => { arg: 'id', type: 'number', required: true, - description: 'The ticket id', + description: 'The client id', http: {source: 'path'} }, { @@ -33,6 +33,12 @@ module.exports = Self => { Self.sendSms = async(ctx, id, destination, message) => { const models = Self.app.models; const sms = await models.Sms.send(ctx, destination, message); + + await models.ClientSms.create({ + clientFk: id, + smsFk: sms.id + }); + return sms; }; }; diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index 1e06ea1c0..bc48ec360 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -95,6 +95,9 @@ "ClientSample": { "dataSource": "vn" }, + "ClientSms": { + "dataSource": "vn" + }, "Sms": { "dataSource": "vn" }, diff --git a/modules/client/back/models/client-sms.json b/modules/client/back/models/client-sms.json new file mode 100644 index 000000000..18d7ad051 --- /dev/null +++ b/modules/client/back/models/client-sms.json @@ -0,0 +1,29 @@ +{ + "name": "ClientSms", + "base": "VnModel", + "options": { + "mysql": { + "table": "clientSms" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "clientFk": { + "type": "number" + }, + "smsFk": { + "type": "number" + } + }, + "relations": { + "sms": { + "type": "belongsTo", + "model": "Sms", + "foreignKey": "smsFk" + } + } +} diff --git a/modules/client/back/models/sms.json b/modules/client/back/models/sms.json index 4639131ef..8f349b073 100644 --- a/modules/client/back/models/sms.json +++ b/modules/client/back/models/sms.json @@ -36,7 +36,7 @@ } }, "relations": { - "sender": { + "user": { "type": "belongsTo", "model": "VnUser", "foreignKey": "senderFk" diff --git a/modules/client/front/index.js b/modules/client/front/index.js index c7e39ea5d..62076459b 100644 --- a/modules/client/front/index.js +++ b/modules/client/front/index.js @@ -48,4 +48,5 @@ import './notification'; import './unpaid'; import './extended-list'; import './credit-management'; +import './sms'; diff --git a/modules/client/front/routes.json b/modules/client/front/routes.json index 01d1b53bf..773b7b22a 100644 --- a/modules/client/front/routes.json +++ b/modules/client/front/routes.json @@ -23,6 +23,7 @@ {"state": "client.card.recovery.index", "icon": "icon-recovery"}, {"state": "client.card.webAccess", "icon": "cloud"}, {"state": "client.card.log", "icon": "history"}, + {"state": "client.card.sms", "icon": "contact_support"}, { "description": "Credit management", "icon": "monetization_on", @@ -373,6 +374,12 @@ "component": "vn-client-log", "description": "Log" }, + { + "url" : "/sms", + "state": "client.card.sms", + "component": "vn-client-sms", + "description": "Sms" + }, { "url": "/dms", "state": "client.card.dms", diff --git a/modules/client/front/sms/index.html b/modules/client/front/sms/index.html new file mode 100644 index 000000000..db944e3b0 --- /dev/null +++ b/modules/client/front/sms/index.html @@ -0,0 +1,42 @@ + + + + + + + + Sender + Number sender + Destination + Message + Status + Created + + + + + + + {{::clientSms.sms.user.name}} + + + {{::clientSms.sms.sender}} + {{::clientSms.sms.destination}} + {{::clientSms.sms.message}} + {{::clientSms.sms.status}} + {{::clientSms.sms.created | date:'dd/MM/yyyy HH:mm'}} + + + + + + + diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js new file mode 100644 index 000000000..1478b78e9 --- /dev/null +++ b/modules/client/front/sms/index.js @@ -0,0 +1,39 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.filter = { + fields: ['id', 'smsFk'], + include: { + relation: 'sms', + scope: { + fields: [ + 'senderFk', + 'sender', + 'destination', + 'message', + 'statusCode', + 'status', + 'created'], + include: { + relation: 'user', + scope: { + fields: ['name'] + } + } + } + } + }; + } +} + +ngModule.vnComponent('vnClientSms', { + template: require('./index.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/modules/client/front/sms/locale/es.yml b/modules/client/front/sms/locale/es.yml new file mode 100644 index 000000000..6d1e9e147 --- /dev/null +++ b/modules/client/front/sms/locale/es.yml @@ -0,0 +1,2 @@ +Sender: Remitente +Number sender: Número remitente From 3e8775149a4dc286ebedeeb4cd9b95a4157d2596 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 13:02:42 +0200 Subject: [PATCH 073/130] refs #5934 feat: change icon --- modules/client/back/models/sms.json | 2 +- modules/client/front/routes.json | 2 +- modules/client/front/sms/index.html | 4 +--- modules/client/front/sms/index.js | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/client/back/models/sms.json b/modules/client/back/models/sms.json index 8f349b073..4639131ef 100644 --- a/modules/client/back/models/sms.json +++ b/modules/client/back/models/sms.json @@ -36,7 +36,7 @@ } }, "relations": { - "user": { + "sender": { "type": "belongsTo", "model": "VnUser", "foreignKey": "senderFk" diff --git a/modules/client/front/routes.json b/modules/client/front/routes.json index 773b7b22a..63d6709e5 100644 --- a/modules/client/front/routes.json +++ b/modules/client/front/routes.json @@ -23,7 +23,7 @@ {"state": "client.card.recovery.index", "icon": "icon-recovery"}, {"state": "client.card.webAccess", "icon": "cloud"}, {"state": "client.card.log", "icon": "history"}, - {"state": "client.card.sms", "icon": "contact_support"}, + {"state": "client.card.sms", "icon": "sms"}, { "description": "Credit management", "icon": "monetization_on", diff --git a/modules/client/front/sms/index.html b/modules/client/front/sms/index.html index db944e3b0..3331f217b 100644 --- a/modules/client/front/sms/index.html +++ b/modules/client/front/sms/index.html @@ -13,7 +13,6 @@ Sender - Number sender Destination Message Status @@ -24,10 +23,9 @@ - {{::clientSms.sms.user.name}} + {{::clientSms.sms.sender.name}} - {{::clientSms.sms.sender}} {{::clientSms.sms.destination}} {{::clientSms.sms.message}} {{::clientSms.sms.status}} diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js index 1478b78e9..6ad64282e 100644 --- a/modules/client/front/sms/index.js +++ b/modules/client/front/sms/index.js @@ -19,7 +19,7 @@ export default class Controller extends Section { 'status', 'created'], include: { - relation: 'user', + relation: 'sender', scope: { fields: ['name'] } From 9076553070b5ff5e7399eeb5df7d28904a86ba79 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 18 Jul 2023 14:11:50 +0200 Subject: [PATCH 074/130] refs #5983 test(itemShelving): add getInventory --- .../233001/00-itemShelving_inventory.sql | 94 +++++++++++-------- db/dump/fixtures.sql | 12 ++- .../item-shelving/specs/getInventory.spec.js | 7 +- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/db/changes/233001/00-itemShelving_inventory.sql b/db/changes/233001/00-itemShelving_inventory.sql index b2a2ff321..c66ad69e9 100644 --- a/db/changes/233001/00-itemShelving_inventory.sql +++ b/db/changes/233001/00-itemShelving_inventory.sql @@ -1,52 +1,64 @@ DELIMITER $$ -CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_inventory`(vParkingFromFk INT, vParkingToFk INT) +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_inventory`(vParkingFromFk VARCHAR(8), vParkingToFk VARCHAR(8)) +BEGIN /** * Devuelve un listado de ubicaciones a revisar * - * @param vParkingFromFk Parking de partida, identificador de vn.parking - * @param vParkingToFk Parking de llegada, identificador de vn.parking + * @param vParkingFromFk Parking de partida, identificador de parking + * @param vParkingToFk Parking de llegada, identificador de parking */ DECLARE vSectorFk INT; DECLARE vPickingOrderFrom INT; - DECLARE vPickingOrderTo INT; - - SELECT ish.id, - p.pickingOrder, - p.code parking, - ish.shelvingFk, - ish.itemFk, - i.longName, - ish.visible, - p.sectorFk, - it.workerFk buyer, - CONCAT('http:',ic.url, '/catalog/1600x900/',i.image) urlImage, - ish.isChecked, - CASE - WHEN s.notPrepared > sm.parked THEN 0 - WHEN sm.visible > sm.parked THEN 1 - ELSE 2 - END - FROM vn.itemShelving ish - JOIN vn.item i ON i.id = ish.itemFk - JOIN vn.itemType it ON it.id = i.typeFk - JOIN tmp.stockMisfit sm ON sm.itemFk = ish.itemFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk - JOIN vn.parking p ON p.id = sh.parkingFk - JOIN (SELECT s.itemFk, sum(s.quantity) notPrepared - FROM vn.sale s - JOIN vn.ticket t ON t.id = s.ticketFk - JOIN vn.warehouse w ON w.id = t.warehouseFk - WHERE t.shipped BETWEEN CURDATE() - AND CURDATE() + INTERVAL 23 HOUR - AND s.isPicked = FALSE - AND w.name = 'Algemesi' - GROUP BY s.itemFk) s ON s.itemFk = i.id - JOIN hedera.imageConfig ic - WHERE p.pickingOrder BETWEEN vParkingFrom AND vPickingOrderTo - AND p.sectorFk = vSectorFk - ORDER BY p.pickingOrder; + DECLARE vPickingOrderTo INT; -END ;; + SELECT p.sectorFk, p.pickingOrder INTO vSectorFk, vPickingOrderFrom + FROM vn.parking p + WHERE p.code = vParkingFromFk COLLATE 'utf8mb3_general_ci'; + + SELECT p.pickingOrder INTO vPickingOrderTo + FROM vn.parking p + WHERE p.code = vParkingToFk COLLATE 'utf8mb3_general_ci'; + + CALL vn.visible_getMisfit(vSectorFk); + + SELECT ish.id, + p.pickingOrder, + p.code parking, + ish.shelvingFk, + ish.itemFk, + i.longName, + ish.visible, + p.sectorFk, + it.workerFk buyer, + CONCAT('http:',ic.url, '/catalog/1600x900/',i.image) urlImage, + ish.isChecked, + CASE + WHEN s.notPrepared > sm.parked THEN 0 + WHEN sm.visible > sm.parked THEN 1 + ELSE 2 + END priority + FROM vn.itemShelving ish + JOIN vn.item i ON i.id = ish.itemFk + JOIN vn.itemType it ON it.id = i.typeFk + JOIN tmp.stockMisfit sm ON sm.itemFk = ish.itemFk + JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.parking p ON p.id = sh.parkingFk + JOIN (SELECT s.itemFk, sum(s.quantity) notPrepared + FROM vn.sale s + JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.warehouse w ON w.id = t.warehouseFk + JOIN vn.config c ON c.mainWarehouseFk = w.id + WHERE t.shipped BETWEEN util.VN_CURDATE() + AND util.VN_CURDATE() + INTERVAL 23 HOUR + AND s.isPicked = FALSE + GROUP BY s.itemFk) s ON s.itemFk = i.id + JOIN hedera.imageConfig ic + WHERE p.pickingOrder BETWEEN vPickingOrderFrom AND vPickingOrderTo + AND p.sectorFk = vSectorFk + ORDER BY p.pickingOrder; + +END$$ DELIMITER ; + diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index fe11d5b64..670a45778 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -37,7 +37,7 @@ ALTER TABLE `vn`.`ticket` AUTO_INCREMENT = 1; INSERT INTO `salix`.`AccessToken` (`id`, `ttl`, `created`, `userId`) VALUES - ('DEFAULT_TOKEN', '1209600', util.VN_CURDATE(), 66); + ('DEFAULT_TOKEN', '1209600', CURDATE(), 66); INSERT INTO `salix`.`printConfig` (`id`, `itRecipient`, `incidencesEmail`) VALUES @@ -2953,3 +2953,13 @@ INSERT INTO `vn`.`invoiceInSerial` (`code`, `description`, `cplusTerIdNifFk`, `t ('E', 'Midgard', 1, 'CEE'), ('R', 'Jotunheim', 1, 'NATIONAL'), ('W', 'Vanaheim', 1, 'WORLD'); + + +INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`) + VALUES + (1, 0, 0, 'marvel.com'); + +/* DELETE ME */ +UPDATE vn.config + SET mainWarehouseFk=1 + WHERE id=1; \ No newline at end of file diff --git a/modules/item/back/methods/item-shelving/specs/getInventory.spec.js b/modules/item/back/methods/item-shelving/specs/getInventory.spec.js index 76cc39073..6a8c9804c 100644 --- a/modules/item/back/methods/item-shelving/specs/getInventory.spec.js +++ b/modules/item/back/methods/item-shelving/specs/getInventory.spec.js @@ -7,7 +7,12 @@ describe('itemShelving getInventory()', () => { let response; try { const options = {transaction: tx}; - response = await models.ItemShelving.getInventory(1, 2, options); + await models.ItemShelving.rawSql(` + UPDATE vn.config + SET mainWarehouseFk=1 + WHERE id=1 + `, null, options); + response = await models.ItemShelving.getInventory('100-01', 'LR-02-3', options); await tx.rollback(); } catch (e) { await tx.rollback(); From 7bd378e9dde911c7176e92fc1d4a5883f44e071d Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 14:15:56 +0200 Subject: [PATCH 075/130] refs # --- back/models/company.json | 3 + db/changes/233001/00-company.sql | 1 + loopback/locale/en.json | 1 + loopback/locale/es.json | 4 +- .../back/methods/client/canBeInvoiced.js | 25 ++++++- .../ticket/back/methods/ticket/makeInvoice.js | 4 +- print/templates/reports/invoice/sql/sales.sql | 66 ++++++------------- 7 files changed, 53 insertions(+), 51 deletions(-) create mode 100644 db/changes/233001/00-company.sql diff --git a/back/models/company.json b/back/models/company.json index f16c5762f..f8b5641ac 100644 --- a/back/models/company.json +++ b/back/models/company.json @@ -18,6 +18,9 @@ }, "expired": { "type": "date" + }, + "supplierAccountFk": { + "type": "number" } }, "scope": { diff --git a/db/changes/233001/00-company.sql b/db/changes/233001/00-company.sql new file mode 100644 index 000000000..a3b61b9cc --- /dev/null +++ b/db/changes/233001/00-company.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`company` MODIFY COLUMN sage200Company int(2) DEFAULT 10 NOT NULL; diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 030afbe9e..5c7c10967 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -177,6 +177,7 @@ "Mail not sent": "There has been an error sending the invoice to the client [{{clientId}}]({{{clientUrl}}}), please check the email address", "The renew period has not been exceeded": "The renew period has not been exceeded", "You can not use the same password": "You can not use the same password", + "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", "Valid priorities": "Valid priorities: %d", "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 784ff5e6e..69f157a47 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -305,5 +305,7 @@ "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Valid priorities": "Prioridades válidas: %d", "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", - "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado" + "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", + "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias" + " } diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js index 567d491f1..843e9549f 100644 --- a/modules/client/back/methods/client/canBeInvoiced.js +++ b/modules/client/back/methods/client/canBeInvoiced.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = function(Self) { Self.remoteMethodCtx('canBeInvoiced', { description: 'Change property isEqualizated in all client addresses', @@ -9,6 +11,12 @@ module.exports = function(Self) { required: true, description: 'Client id', http: {source: 'path'} + }, + { + arg: 'companyFk', + description: 'The company id', + type: 'number', + required: true } ], returns: { @@ -22,18 +30,29 @@ module.exports = function(Self) { } }); - Self.canBeInvoiced = async(id, options) => { + Self.canBeInvoiced = async(id, companyFk, options) => { const models = Self.app.models; - const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const client = await models.Client.findById(id, { - fields: ['id', 'isTaxDataChecked', 'hasToInvoice'] + fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk'], + include: + { + relation: 'payMethod', + scope: { + fields: ['code'] + } + } }, myOptions); + const company = await models.Company.findById(companyFk, {fields: ['supplierAccountFk']}, myOptions); + + if (client.payMethod().code === 'wireTransfer' && !company.supplierAccountFk) + throw new UserError('The company has not informed the supplier account for bank transfers'); + if (client.isTaxDataChecked && client.hasToInvoice) return true; diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index 22fe7b3f5..e18e58e0b 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -14,7 +14,7 @@ module.exports = function(Self) { { arg: 'companyFk', description: 'The company id', - type: 'string', + type: 'number', required: true }, { @@ -67,7 +67,7 @@ module.exports = function(Self) { const [firstTicket] = tickets; const clientId = firstTicket.clientFk; - const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, myOptions); + const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, myOptions); if (!clientCanBeInvoiced) throw new UserError(`This client can't be invoiced`); diff --git a/print/templates/reports/invoice/sql/sales.sql b/print/templates/reports/invoice/sql/sales.sql index f5721a594..3833a3700 100644 --- a/print/templates/reports/invoice/sql/sales.sql +++ b/print/templates/reports/invoice/sql/sales.sql @@ -1,31 +1,19 @@ -SELECT +SELECT io.ref, - c.socialName, - sa.iban, - pm.name AS payMethod, - t.clientFk, - t.shipped, - t.nickname, s.ticketFk, - s.itemFk, - s.concept, - s.quantity, - s.price, + ib.ediBotanic botanical, + s.quantity, + s.price, s.discount, - i.tag5, - i.value5, - i.tag6, - i.value6, - i.tag7, - i.value7, - tc.code AS vatType, - ib.ediBotanic botanical + s.itemFk, + s.concept, + tc.code vatType FROM vn.invoiceOut io JOIN vn.ticket t ON t.refFk = io.ref JOIN vn.supplier su ON su.id = io.companyFk - JOIN vn.client c ON c.id = t.clientFk + JOIN vn.client c ON c.id = t.clientFk JOIN vn.payMethod pm ON pm.id = c.payMethodFk - JOIN vn.company co ON co.id = io.companyFk + JOIN vn.company co ON co.id = io.companyFk JOIN vn.supplierAccount sa ON sa.id = co.supplierAccountFk JOIN vn.sale s ON s.ticketFk = t.id JOIN item i ON i.id = s.itemFk @@ -38,35 +26,23 @@ SELECT AND itc.itemFk = s.itemFk JOIN vn.taxClass tc ON tc.id = itc.taxClassFk WHERE t.refFk = ? - UNION ALL -SELECT + UNION ALL +SELECT io.ref, - c.socialName, - sa.iban, - pm.name AS payMethod, - t.clientFk, - t.shipped, - t.nickname, - t.id AS ticketFk, + t.id ticketFk, + NULL botanical, + ts.quantity, + ts.price, + 0 discount, '', - ts.description concept, - ts.quantity, - ts.price, - 0 discount, - NULL AS tag5, - NULL AS value5, - NULL AS tag6, - NULL AS value6, - NULL AS tag7, - NULL AS value7, - tc.code AS vatType, - NULL AS botanical + ts.description concept, + tc.code vatType FROM vn.invoiceOut io JOIN vn.ticket t ON t.refFk = io.ref JOIN vn.ticketService ts ON ts.ticketFk = t.id - JOIN vn.client c ON c.id = t.clientFk + JOIN vn.client c ON c.id = t.clientFk JOIN vn.payMethod pm ON pm.id = c.payMethodFk - JOIN vn.company co ON co.id = io.companyFk + JOIN vn.company co ON co.id = io.companyFk JOIN vn.supplierAccount sa ON sa.id = co.supplierAccountFk JOIN vn.taxClass tc ON tc.id = ts.taxClassFk - WHERE t.refFk = ? \ No newline at end of file + WHERE t.refFk = ? From 4c7f42acb5a05bd868dbc095feff9504d80f2d91 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 14:17:07 +0200 Subject: [PATCH 076/130] a --- loopback/locale/es.json | 1 - 1 file changed, 1 deletion(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 69f157a47..9412a9571 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -307,5 +307,4 @@ "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias" - " } From d3165fcdc75c74bb05a15060dcfec1c55bc80394 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 18 Jul 2023 14:25:53 +0200 Subject: [PATCH 077/130] refs #5849 fix: tback --- .../client/back/methods/client/specs/canBeInvoiced.spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js index 2f11d8013..397be3c92 100644 --- a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js +++ b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js @@ -4,6 +4,7 @@ const LoopBackContext = require('loopback-context'); describe('client canBeInvoiced()', () => { const userId = 19; const clientId = 1101; + const companyId = 442; const activeCtx = { accessToken: {userId: userId} }; @@ -23,7 +24,7 @@ describe('client canBeInvoiced()', () => { const client = await models.Client.findById(clientId, null, options); await client.updateAttribute('isTaxDataChecked', false, options); - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, options); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); expect(canBeInvoiced).toEqual(false); @@ -43,7 +44,7 @@ describe('client canBeInvoiced()', () => { const client = await models.Client.findById(clientId, null, options); await client.updateAttribute('hasToInvoice', false, options); - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, options); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); expect(canBeInvoiced).toEqual(false); @@ -60,7 +61,7 @@ describe('client canBeInvoiced()', () => { try { const options = {transaction: tx}; - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, options); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); expect(canBeInvoiced).toEqual(true); From bd723bb7ba540771f786ecd3bc9972781d92e0ca Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 18 Jul 2023 15:01:58 +0200 Subject: [PATCH 078/130] refs #5824 mod ng --- modules/item/front/fixed-price/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index d9a955fe1..f1f6e1419 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -85,7 +85,7 @@ show-field="id" value-field="id" search-function="$ctrl.itemSearchFunc($search)" - on-change="$ctrl.upsertPrice(price, true)" + ng-change="$ctrl.upsertPrice(price, true)" order="id DESC" tabindex="1"> From 49c656928ed8049f00f333c4e7cb482d836cefd1 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 18 Jul 2023 15:43:11 +0200 Subject: [PATCH 079/130] refs #5983 feat(itemShelving): add visible --- modules/item/back/models/item-shelving.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index 49bebcb6b..be379adca 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -23,6 +23,9 @@ }, "isChecked": { "type": "boolean" + }, + "visible": { + "type": "number" } }, "relations": { From 85c017431ce9c199bfa0f7f5a1e394cd43b8931f Mon Sep 17 00:00:00 2001 From: sergiodt Date: Wed, 19 Jul 2023 07:01:43 +0200 Subject: [PATCH 080/130] refs #5983 fix(itemShelving): fixtures --- db/dump/fixtures.sql | 5 ----- 1 file changed, 5 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 670a45778..eaa00a3de 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2958,8 +2958,3 @@ INSERT INTO `vn`.`invoiceInSerial` (`code`, `description`, `cplusTerIdNifFk`, `t INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`) VALUES (1, 0, 0, 'marvel.com'); - -/* DELETE ME */ -UPDATE vn.config - SET mainWarehouseFk=1 - WHERE id=1; \ No newline at end of file From b17de86fb1f7f94e6f892f0662ec09d8d5d467f8 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 19 Jul 2023 12:15:52 +0200 Subject: [PATCH 081/130] refs #6043 add ACL --- db/changes/233001/00-fixACLVehicle.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 db/changes/233001/00-fixACLVehicle.sql diff --git a/db/changes/233001/00-fixACLVehicle.sql b/db/changes/233001/00-fixACLVehicle.sql new file mode 100644 index 000000000..6625f0d5c --- /dev/null +++ b/db/changes/233001/00-fixACLVehicle.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) + VALUES + ('Vehicle','sorted','WRITE','ALLOW','employee'); \ No newline at end of file From 36c31af455bff82604fd29fee0a397051172de47 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 19 Jul 2023 12:38:13 +0200 Subject: [PATCH 082/130] refs #5690 rounding translate --- modules/ticket/front/future/index.html | 1 + modules/ticket/front/index/index.html | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 742143b27..5119d103b 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -125,6 +125,7 @@ diff --git a/modules/ticket/front/index/index.html b/modules/ticket/front/index/index.html index 3b490a3a9..26e5553ed 100644 --- a/modules/ticket/front/index/index.html +++ b/modules/ticket/front/index/index.html @@ -77,6 +77,7 @@ From 7cff0149887a1eb09d586a51212798caa97d570a Mon Sep 17 00:00:00 2001 From: sergiodt Date: Wed, 19 Jul 2023 13:27:31 +0200 Subject: [PATCH 083/130] refs #5983 fix(itemShelving): vn --- .../233001/00-itemShelving_inventory.sql | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/db/changes/233001/00-itemShelving_inventory.sql b/db/changes/233001/00-itemShelving_inventory.sql index c66ad69e9..b0b080ef3 100644 --- a/db/changes/233001/00-itemShelving_inventory.sql +++ b/db/changes/233001/00-itemShelving_inventory.sql @@ -14,14 +14,14 @@ BEGIN DECLARE vPickingOrderTo INT; SELECT p.sectorFk, p.pickingOrder INTO vSectorFk, vPickingOrderFrom - FROM vn.parking p + FROM parking p WHERE p.code = vParkingFromFk COLLATE 'utf8mb3_general_ci'; SELECT p.pickingOrder INTO vPickingOrderTo - FROM vn.parking p + FROM parking p WHERE p.code = vParkingToFk COLLATE 'utf8mb3_general_ci'; - CALL vn.visible_getMisfit(vSectorFk); + CALL visible_getMisfit(vSectorFk); SELECT ish.id, p.pickingOrder, @@ -39,19 +39,19 @@ BEGIN WHEN sm.visible > sm.parked THEN 1 ELSE 2 END priority - FROM vn.itemShelving ish - JOIN vn.item i ON i.id = ish.itemFk - JOIN vn.itemType it ON it.id = i.typeFk + FROM itemShelving ish + JOIN item i ON i.id = ish.itemFk + JOIN itemType it ON it.id = i.typeFk JOIN tmp.stockMisfit sm ON sm.itemFk = ish.itemFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk - JOIN vn.parking p ON p.id = sh.parkingFk + JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN parking p ON p.id = sh.parkingFk JOIN (SELECT s.itemFk, sum(s.quantity) notPrepared - FROM vn.sale s - JOIN vn.ticket t ON t.id = s.ticketFk - JOIN vn.warehouse w ON w.id = t.warehouseFk - JOIN vn.config c ON c.mainWarehouseFk = w.id + FROM sale s + JOIN ticket t ON t.id = s.ticketFk + JOIN warehouse w ON w.id = t.warehouseFk + JOIN config c ON c.mainWarehouseFk = w.id WHERE t.shipped BETWEEN util.VN_CURDATE() - AND util.VN_CURDATE() + INTERVAL 23 HOUR + AND util.dayEnd(util.VN_CURDATE()) AND s.isPicked = FALSE GROUP BY s.itemFk) s ON s.itemFk = i.id JOIN hedera.imageConfig ic From ab95ef74a945c4c232f2cb6a9a73c9c51f767147 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 20 Jul 2023 07:17:35 +0200 Subject: [PATCH 084/130] refs #5934 refactor: nombres variables --- db/changes/233001/00-clientSms.sql | 6 +++--- modules/client/back/models/client-sms.json | 3 --- modules/client/front/sms/index.html | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/db/changes/233001/00-clientSms.sql b/db/changes/233001/00-clientSms.sql index 353041ad9..e1e34f6b2 100644 --- a/db/changes/233001/00-clientSms.sql +++ b/db/changes/233001/00-clientSms.sql @@ -7,9 +7,9 @@ CREATE TABLE `vn`.`clientSms` ( KEY `clientSms_FK_1` (`smsFk`), CONSTRAINT `clientSms_FK` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE, CONSTRAINT `clientSms_FK_1` FOREIGN KEY (`smsFk`) REFERENCES `sms` (`id`) ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('ClientSms', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), - ('ClientSms', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'); + ('ClientSms', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('ClientSms', 'create', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/modules/client/back/models/client-sms.json b/modules/client/back/models/client-sms.json index 18d7ad051..b2244ebbb 100644 --- a/modules/client/back/models/client-sms.json +++ b/modules/client/back/models/client-sms.json @@ -14,9 +14,6 @@ }, "clientFk": { "type": "number" - }, - "smsFk": { - "type": "number" } }, "relations": { diff --git a/modules/client/front/sms/index.html b/modules/client/front/sms/index.html index 3331f217b..9abadd312 100644 --- a/modules/client/front/sms/index.html +++ b/modules/client/front/sms/index.html @@ -3,7 +3,7 @@ url="ClientSms" link="{clientFk: $ctrl.$params.id}" filter="::$ctrl.filter" - data="clientSmss" + data="clientSmsList" limit="20" auto-load="true"> @@ -20,7 +20,7 @@ - + {{::clientSms.sms.sender.name}} From b13618529aebd455f42d1285dbe59e2c6313549a Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 20 Jul 2023 07:21:38 +0200 Subject: [PATCH 085/130] =?UTF-8?q?refs=20#5849=20delete:=20traducci=C3=B3?= =?UTF-8?q?n=20erronea?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- loopback/locale/en.json | 1 - 1 file changed, 1 deletion(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 5c7c10967..030afbe9e 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -177,7 +177,6 @@ "Mail not sent": "There has been an error sending the invoice to the client [{{clientId}}]({{{clientUrl}}}), please check the email address", "The renew period has not been exceeded": "The renew period has not been exceeded", "You can not use the same password": "You can not use the same password", - "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", "Valid priorities": "Valid priorities: %d", "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}" } From 60e75d7825cfdc9c5222700ac0f36cf3d92101e0 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 20 Jul 2023 08:23:43 +0200 Subject: [PATCH 086/130] refs #5837 fix client condition --- modules/client/back/models/client.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 163d51fc5..8369fa906 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -41,6 +41,9 @@ module.exports = Self => { }); async function socialNameIsUnique(err, done) { + if (!this.countryFk) + return done(); + const filter = { include: { relation: 'country', @@ -59,13 +62,11 @@ module.exports = Self => { } }; - const existingClient = await Self.app.models.Client.findOne(filter); + const client = await Self.app.models.Country.findById(this.countryFk, {fields: ['isSocialNameUnique']}); + const existingClient = await Self.findOne(filter); - if (existingClient) { - // eslint-disable-next-line max-len - if (existingClient.country().isSocialNameUnique && this.socialName === existingClient.socialName) - err(); - } + if (existingClient && (existingClient.country().isSocialNameUnique || client.isSocialNameUnique)) + err(); done(); } From 0585080303f72750987698c299e4d716ca13890f Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 20 Jul 2023 09:26:40 +0200 Subject: [PATCH 087/130] refs #6011 deploy 2330 version --- CHANGELOG.md | 5 +++++ db/changes/232401/00-ACLgetVehiclesSorted.sql | 3 --- db/changes/{232801 => 233001}/00-roadmap.sql | 2 -- db/changes/{232801 => 233001}/00-roadmapACL.sql | 0 4 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 db/changes/232401/00-ACLgetVehiclesSorted.sql rename db/changes/{232801 => 233001}/00-roadmap.sql (69%) rename db/changes/{232801 => 233001}/00-roadmapACL.sql (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76527ac83..847275825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2330.01] - 2023-07-27 ### Added +- (Artículos -> Vista Previa) Añadido campo "Plástico reciclado" +- (Rutas -> Troncales) Nueva sección +- (Tickets -> Opciones) Opción establecer peso ### Changed +- (General -> Iconos) Añadidos nuevos iconos + ### Fixed diff --git a/db/changes/232401/00-ACLgetVehiclesSorted.sql b/db/changes/232401/00-ACLgetVehiclesSorted.sql deleted file mode 100644 index 6625f0d5c..000000000 --- a/db/changes/232401/00-ACLgetVehiclesSorted.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) - VALUES - ('Vehicle','sorted','WRITE','ALLOW','employee'); \ No newline at end of file diff --git a/db/changes/232801/00-roadmap.sql b/db/changes/233001/00-roadmap.sql similarity index 69% rename from db/changes/232801/00-roadmap.sql rename to db/changes/233001/00-roadmap.sql index a2835160f..9b5db54eb 100644 --- a/db/changes/232801/00-roadmap.sql +++ b/db/changes/233001/00-roadmap.sql @@ -6,5 +6,3 @@ ALTER TABLE `vn`.`roadmap` CHANGE name name varchar(45) CHARACTER SET utf8mb3 CO ALTER TABLE `vn`.`roadmap` MODIFY COLUMN etd datetime NOT NULL; ALTER TABLE `vn`.`expeditionTruck` COMMENT='Distintas paradas que hacen los trocales'; -ALTER TABLE `vn`.`expeditionTruck` DROP FOREIGN KEY expeditionTruck_FK_2; -ALTER TABLE `vn`.`expeditionTruck` ADD CONSTRAINT expeditionTruck_FK_2 FOREIGN KEY (roadmapFk) REFERENCES vn.roadmap(id) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/db/changes/232801/00-roadmapACL.sql b/db/changes/233001/00-roadmapACL.sql similarity index 100% rename from db/changes/232801/00-roadmapACL.sql rename to db/changes/233001/00-roadmapACL.sql From 071a891d30079e13792765a7578b5aae03da6ee2 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 20 Jul 2023 09:30:18 +0200 Subject: [PATCH 088/130] refs #6011 add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 847275825..d5928e9c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - (Artículos -> Vista Previa) Añadido campo "Plástico reciclado" - (Rutas -> Troncales) Nueva sección - (Tickets -> Opciones) Opción establecer peso +- (Clientes -> SMS) Nueva sección ### Changed - (General -> Iconos) Añadidos nuevos iconos +- (Clientes -> Razón social) Nuevas restricciones por pais ### Fixed From 75ea5942729af3e528157f6b946ef0d3679596e7 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 20 Jul 2023 09:32:52 +0200 Subject: [PATCH 089/130] refs #6011 deploy(2332): init version --- CHANGELOG.md | 9 +++++++++ db/changes/233201/.gitkeep | 0 package-lock.json | 2 +- package.json | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 db/changes/233201/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index d5928e9c4..d4a1e147f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2330.01] - 2023-07-27 + +### Added + +### Changed + +### Fixed + + ## [2330.01] - 2023-07-27 ### Added diff --git a/db/changes/233201/.gitkeep b/db/changes/233201/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package-lock.json b/package-lock.json index ee6d4e0fa..5506075b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.30.01", + "version": "23.32.01", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 66e341ad5..37e39d5a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.30.01", + "version": "23.32.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", From 9db8ae237fcbb9fce120af1f237d7b6496338fd7 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 20 Jul 2023 10:19:03 +0200 Subject: [PATCH 090/130] refs #5866 addBackTransferClient --- db/changes/233001/00-transferClient.sql | 2 + .../back/methods/ticket/transferClient.js | 69 +++++++++++++++++++ modules/ticket/back/models/ticket-methods.js | 1 + modules/ticket/front/descriptor-menu/index.js | 8 +++ 4 files changed, 80 insertions(+) create mode 100644 db/changes/233001/00-transferClient.sql create mode 100644 modules/ticket/back/methods/ticket/transferClient.js diff --git a/db/changes/233001/00-transferClient.sql b/db/changes/233001/00-transferClient.sql new file mode 100644 index 000000000..8a7ce0543 --- /dev/null +++ b/db/changes/233001/00-transferClient.sql @@ -0,0 +1,2 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) + VALUES ('Ticket','transferClient','WRITE','ALLOW','ROLE','administrative'); \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js new file mode 100644 index 000000000..226f5dedf --- /dev/null +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -0,0 +1,69 @@ +const UserError = require('vn-loopback/util/user-error'); +module.exports = Self => { + Self.remoteMethodCtx('transferClient', { + description: 'Transfering ticket to another client', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'the ticket id', + http: {source: 'path'} + }, + { + arg: 'data', + type: 'object', + required: true, + description: 'the client id', + http: {source: 'body'} + }, + ], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/:id/transferClient`, + verb: 'PATCH' + } + }); + + Self.transferClient = async(ctx, ticketId, params) => { + const models = Self.app.models; + const args = ctx.args; + const myOptions = {}; + try { + const clientId = params.clientId; + const isEditable = await Self.isEditable(ctx, args.id, myOptions); + console.log('es editable?',isEditable) // Revisar + /* if (!isEditable){ + console.log('no es editable!') + throw new UserError(`The sales of this ticket can't be modified`); + } */ + + const ticket = await models.Ticket.findById(ticketId, myOptions); + console.log('ticket',ticket); + if(!ticket) return false; + const nparams = { + clientFk: clientId, + addressFk: ticket.addressFk, + } + + const promise = await ticket.updateAttributes(nparams); + console.log('promise', promise); + if(promise) return true; + } catch (error) { + console.log(error); + } + + /* if (typeof options == 'object') + Object.assign(myOptions, options); + + const ticket = await Self.findById(id, { + fields: ['isDeleted', 'refFk'] + }, myOptions); */ + + return false; + }; +}; \ No newline at end of file diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js index f0c85ecc4..b432c9f6b 100644 --- a/modules/ticket/back/models/ticket-methods.js +++ b/modules/ticket/back/models/ticket-methods.js @@ -19,6 +19,7 @@ module.exports = function(Self) { require('../methods/ticket/uploadFile')(Self); require('../methods/ticket/addSale')(Self); require('../methods/ticket/transferSales')(Self); + require('../methods/ticket/transferClient')(Self); require('../methods/ticket/recalculateComponents')(Self); require('../methods/ticket/sendSms')(Self); require('../methods/ticket/isLocked')(Self); diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 0fc8488ca..019ae4fa6 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -96,6 +96,14 @@ class Controller extends Section { } transferClient() { + const ticket = this.ticket; + const clientId = ticket.client.id; + console.log('ticketId',ticket.id) + console.log('clientId',clientId); + this.$http.patch(`Tickets/${ticket.id}/transferClient`, {clientId}).then(() =>{ + this.vnApp.showSuccess(this.$t('Data saved!')); + this.reload(); + }) this.$http.get(`Clients/${this.ticket.client.id}`).then(client => { const ticket = this.ticket; From 618989052a481df85338fa54ec297c0ae57d876c Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 20 Jul 2023 15:15:33 +0200 Subject: [PATCH 091/130] refs #5866 fix transferClient and test added --- .../{233001 => 233201}/00-transferClient.sql | 0 .../ticket/specs/transferClient.spec.js | 49 +++++++++++++++ .../back/methods/ticket/transferClient.js | 60 +++++++------------ modules/ticket/front/descriptor-menu/index.js | 18 +----- .../front/descriptor-menu/index.spec.js | 13 ---- 5 files changed, 71 insertions(+), 69 deletions(-) rename db/changes/{233001 => 233201}/00-transferClient.sql (100%) create mode 100644 modules/ticket/back/methods/ticket/specs/transferClient.spec.js diff --git a/db/changes/233001/00-transferClient.sql b/db/changes/233201/00-transferClient.sql similarity index 100% rename from db/changes/233001/00-transferClient.sql rename to db/changes/233201/00-transferClient.sql diff --git a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js new file mode 100644 index 000000000..ed10e5159 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js @@ -0,0 +1,49 @@ +const models = require('vn-loopback/server/server').models; + +describe('Ticket transferClient()', () => { + const userId = 9; + const activeCtx = { + accessToken: {userId: userId}, + }; + const ctx = {req: activeCtx}; + + it('should throw an error as the ticket is not editable', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + + try { + const options = {transaction: tx}; + const ticketId = 4; + const clientId = 1; + await models.Ticket.transferClient(ctx, ticketId, clientId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toEqual(`The current ticket can't be modified`); + }); + + it('should be assigned a different clientFk', async() => { + const tx = await models.Ticket.beginTransaction({}); + let updatedTicket; + const ticketId = 10; + const clientId = 1; + + try { + const options = {transaction: tx}; + + await models.Ticket.transferClient(ctx, ticketId, clientId, options); + updatedTicket = await models.Ticket.findById(ticketId, {fields: ['clientFk']}, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(updatedTicket.clientFk).toEqual(clientId); + }); +}); diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js index 226f5dedf..05ea27fa0 100644 --- a/modules/ticket/back/methods/ticket/transferClient.js +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -12,58 +12,38 @@ module.exports = Self => { http: {source: 'path'} }, { - arg: 'data', - type: 'object', + arg: 'clientId', + type: 'number', required: true, - description: 'the client id', - http: {source: 'body'} }, ], - returns: { - type: 'boolean', - root: true - }, http: { path: `/:id/transferClient`, verb: 'PATCH' } }); - Self.transferClient = async(ctx, ticketId, params) => { + Self.transferClient = async(ctx, ticketId, clientId, options) => { const models = Self.app.models; - const args = ctx.args; const myOptions = {}; - try { - const clientId = params.clientId; - const isEditable = await Self.isEditable(ctx, args.id, myOptions); - console.log('es editable?',isEditable) // Revisar - /* if (!isEditable){ - console.log('no es editable!') - throw new UserError(`The sales of this ticket can't be modified`); - } */ - - const ticket = await models.Ticket.findById(ticketId, myOptions); - console.log('ticket',ticket); - if(!ticket) return false; - const nparams = { - clientFk: clientId, - addressFk: ticket.addressFk, - } - - const promise = await ticket.updateAttributes(nparams); - console.log('promise', promise); - if(promise) return true; - } catch (error) { - console.log(error); - } - - /* if (typeof options == 'object') + if (typeof options == 'object') Object.assign(myOptions, options); - const ticket = await Self.findById(id, { - fields: ['isDeleted', 'refFk'] - }, myOptions); */ + const isEditable = await Self.isEditable(ctx, ticketId, myOptions); - return false; + if (!isEditable) + throw new UserError(`The current ticket can't be modified`); + + const ticket = await models.Ticket.findById( + ticketId, + {fields: ['id', 'shipped', 'clientFk', 'addressFk']}, + myOptions + ); + const client = await models.Client.findById(clientId, {fields: ['id', 'defaultAddressFk']}, myOptions); + + await ticket.updateAttributes({ + clientFk: clientId, + addressFk: client.defaultAddressFk, + }); }; -}; \ No newline at end of file +}; diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 019ae4fa6..62a233891 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -98,26 +98,12 @@ class Controller extends Section { transferClient() { const ticket = this.ticket; const clientId = ticket.client.id; - console.log('ticketId',ticket.id) - console.log('clientId',clientId); - this.$http.patch(`Tickets/${ticket.id}/transferClient`, {clientId}).then(() =>{ - this.vnApp.showSuccess(this.$t('Data saved!')); - this.reload(); - }) - this.$http.get(`Clients/${this.ticket.client.id}`).then(client => { - const ticket = this.ticket; - const params = - { - clientFk: client.data.id, - addressFk: client.data.defaultAddressFk, - }; - - this.$http.patch(`Tickets/${ticket.id}`, params).then(() => { + this.$http.patch(`Tickets/${ticket.id}/transferClient`, {clientId}) + .then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.reload(); }); - }); } isTicketEditable() { diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 914fe486c..1bb270165 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -326,17 +326,4 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { expect(controller.vnApp.showSuccess).toHaveBeenCalled(); }); }); - - describe('transferClient()', () => { - it(`should perform two queries, a get to obtain the clientData and a patch to update the ticket`, () => { - const client = - { - clientFk: 1101, - addressFk: 1, - }; - $httpBackend.expect('GET', `Clients/${ticket.client.id}`).respond(client); - $httpBackend.expect('PATCH', `Tickets/${ticket.id}`).respond(); - controller.transferClient(); - }); - }); }); From eb963ff993f8f142298a6edefc631f2451fbf90b Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 21 Jul 2023 08:28:19 +0200 Subject: [PATCH 092/130] refs #5866 fix(transferClient): correct variable name --- modules/ticket/back/methods/ticket/transferClient.js | 12 ++++++------ modules/ticket/front/descriptor-menu/index.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js index 05ea27fa0..04c153bd2 100644 --- a/modules/ticket/back/methods/ticket/transferClient.js +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -12,7 +12,7 @@ module.exports = Self => { http: {source: 'path'} }, { - arg: 'clientId', + arg: 'clientFk', type: 'number', required: true, }, @@ -23,26 +23,26 @@ module.exports = Self => { } }); - Self.transferClient = async(ctx, ticketId, clientId, options) => { + Self.transferClient = async(ctx, id, clientFk, options) => { const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const isEditable = await Self.isEditable(ctx, ticketId, myOptions); + const isEditable = await Self.isEditable(ctx, id, myOptions); if (!isEditable) throw new UserError(`The current ticket can't be modified`); const ticket = await models.Ticket.findById( - ticketId, + id, {fields: ['id', 'shipped', 'clientFk', 'addressFk']}, myOptions ); - const client = await models.Client.findById(clientId, {fields: ['id', 'defaultAddressFk']}, myOptions); + const client = await models.Client.findById(clientFk, {fields: ['id', 'defaultAddressFk']}, myOptions); await ticket.updateAttributes({ - clientFk: clientId, + clientFk, addressFk: client.defaultAddressFk, }); }; diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 62a233891..7bdefcd97 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -97,9 +97,9 @@ class Controller extends Section { transferClient() { const ticket = this.ticket; - const clientId = ticket.client.id; + const clientFk = ticket.client.id; - this.$http.patch(`Tickets/${ticket.id}/transferClient`, {clientId}) + this.$http.patch(`Tickets/${ticket.id}/transferClient`, {clientFk}) .then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.reload(); From 985e258529a0debad2e27172049fc0e91bc9ee13 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 21 Jul 2023 12:33:14 +0200 Subject: [PATCH 093/130] refs #5769 fix(web-access): email rule --- back/methods/vn-user/privileges.js | 2 +- back/models/vn-user.js | 2 +- modules/client/front/web-access/index.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/methods/vn-user/privileges.js b/back/methods/vn-user/privileges.js index 690ce74a3..08cfaaae8 100644 --- a/back/methods/vn-user/privileges.js +++ b/back/methods/vn-user/privileges.js @@ -47,7 +47,7 @@ module.exports = Self => { const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions); const userToUpdate = await Self.findById(id, { - fields: ['id', 'name', 'hasGrant', 'roleFk', 'password'], + fields: ['id', 'name', 'hasGrant', 'roleFk', 'password', 'email'], include: { relation: 'role', scope: { diff --git a/back/models/vn-user.js b/back/models/vn-user.js index a7ce12073..985f017a5 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -20,7 +20,7 @@ module.exports = function(Self) { Self.validatesFormatOf('email', { message: 'Invalid email', allowNull: true, - allowBlank: true, + allowBlank: false, with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/ }); diff --git a/modules/client/front/web-access/index.html b/modules/client/front/web-access/index.html index 74407ba5c..bf3d34c79 100644 --- a/modules/client/front/web-access/index.html +++ b/modules/client/front/web-access/index.html @@ -39,7 +39,7 @@ label="Recovery email" ng-model="$ctrl.account.email" info="This email is used for user to regain access their account." - rule="VnUser.name"> + rule="VnUser.email"> From 203f6a5659f6fdead03c013a43f2b59ec881e5f8 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 21 Jul 2023 12:41:16 +0200 Subject: [PATCH 094/130] refs #5712 correct sql folder --- db/changes/{232801 => 233201}/00-workerDocuware.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{232801 => 233201}/00-workerDocuware.sql (100%) diff --git a/db/changes/232801/00-workerDocuware.sql b/db/changes/233201/00-workerDocuware.sql similarity index 100% rename from db/changes/232801/00-workerDocuware.sql rename to db/changes/233201/00-workerDocuware.sql From ade7303a6fd6878bac8d3de5bd88af0c61991254 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 21 Jul 2023 13:05:55 +0200 Subject: [PATCH 095/130] refs #6047 added editable-td component --- e2e/helpers/selectors.js | 2 +- e2e/paths/08-route/04_tickets.spec.js | 3 +-- modules/route/front/tickets/index.html | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 977c8a837..93288efa7 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -875,7 +875,7 @@ export default { }, routeTickets: { - firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]', + firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-td-editable', firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check', buscamanButton: 'vn-route-tickets vn-button[icon="icon-buscaman"]', firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]', diff --git a/e2e/paths/08-route/04_tickets.spec.js b/e2e/paths/08-route/04_tickets.spec.js index ccd5562c2..c890162a1 100644 --- a/e2e/paths/08-route/04_tickets.spec.js +++ b/e2e/paths/08-route/04_tickets.spec.js @@ -18,8 +18,7 @@ describe('Route tickets path', () => { }); it('should modify the first ticket priority', async() => { - await page.clearInput(selectors.routeTickets.firstTicketPriority); - await page.type(selectors.routeTickets.firstTicketPriority, '9'); + await page.writeOnEditableTD(selectors.routeTickets.firstTicketPriority, '9'); await page.keyboard.press('Enter'); const message = await page.waitForSnackbar(); diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index 32a4a2d7c..453eb0517 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -84,14 +84,27 @@ tabindex="-1"> - - + + {{ticket.priority}} + + + + + + + {{::ticket.street}} Date: Fri, 21 Jul 2023 13:13:44 +0200 Subject: [PATCH 096/130] removed unnecesary comments --- modules/route/front/tickets/index.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index 453eb0517..ea6755cca 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -98,12 +98,6 @@ vn-focus> - {{::ticket.street}} Date: Mon, 24 Jul 2023 10:34:44 +0200 Subject: [PATCH 097/130] refs #5929 added ACL and accurate errors --- db/changes/233201/00-updatePrice.sql | 2 ++ loopback/locale/es.json | 6 +++-- .../ticket/back/methods/ticket/isEditable.js | 23 +++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 db/changes/233201/00-updatePrice.sql diff --git a/db/changes/233201/00-updatePrice.sql b/db/changes/233201/00-updatePrice.sql new file mode 100644 index 000000000..93888df6e --- /dev/null +++ b/db/changes/233201/00-updatePrice.sql @@ -0,0 +1,2 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) + VALUES ('Ticket','*','*','ALLOW','ROLE','buyer'); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index d95e8d8a4..1a200709f 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -307,5 +307,7 @@ "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", - "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado" -} + "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", + "You don't have enough privileges.": "You don't have enough privileges.", + "This ticket is locked.": "This ticket is locked." +} \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/isEditable.js b/modules/ticket/back/methods/ticket/isEditable.js index 13bd4d57f..9f7e14dcc 100644 --- a/modules/ticket/back/methods/ticket/isEditable.js +++ b/modules/ticket/back/methods/ticket/isEditable.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { Self.remoteMethodCtx('isEditable', { description: 'Check if a ticket is editable', @@ -31,7 +33,7 @@ module.exports = Self => { }, myOptions); const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*'); - + const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'buyer', 'WRITE'); const alertLevel = state ? state.alertLevel : null; const ticket = await models.Ticket.findById(id, { fields: ['clientFk'], @@ -48,13 +50,26 @@ module.exports = Self => { const isLocked = await models.Ticket.isLocked(id, myOptions); const isWeekly = await models.TicketWeekly.findOne({where: {ticketFk: id}}, myOptions); + console.log('isRoleAdvanced', isRoleAdvanced); + console.log('canEditWeeklyTicket', canEditWeeklyTicket); + console.log('ticket', ticket); + console.log('isLocked', isLocked); + console.log('isWeekly', isWeekly); const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0); const isNormalClient = ticket && ticket.client().type().code == 'normal'; const isEditable = !(alertLevelGreaterThanZero && isNormalClient); + if (!ticket) + throw new UserError(`The ticket doesn't exist.`); - if (ticket && (isEditable || isRoleAdvanced) && !isLocked && !isWeekly) - return true; + if (!isEditable && !isRoleAdvanced) + throw new UserError(`This ticket is not editable.`); - return false; + if (isLocked) + throw new UserError(`This ticket is locked.`); + + if (isWeekly && !canEditWeeklyTicket) + throw new UserError(`You don't have enough privileges.`); + + return true; }; }; From 44ceeac9c4195ed2808fa9a8be20bd53bd9ed5f1 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 25 Jul 2023 10:21:54 +0200 Subject: [PATCH 098/130] refs #5983 feat(itemShelving): add userFk field --- modules/item/back/models/item-shelving.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index be379adca..8628bfeee 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -25,6 +25,9 @@ "type": "boolean" }, "visible": { + "type": "number" + }, + "userFk": { "type": "number" } }, From 9978db9d523f4b82670a5ea6b431c8b37630c121 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 25 Jul 2023 11:33:01 +0200 Subject: [PATCH 099/130] refs #5929 WIP test created --- db/changes/233201/00-updatePrice.sql | 2 +- loopback/locale/es.json | 3 +- .../ticket/back/methods/ticket/isEditable.js | 8 +- .../methods/ticket/specs/isEditable.spec.js | 130 +++++------------- 4 files changed, 42 insertions(+), 101 deletions(-) diff --git a/db/changes/233201/00-updatePrice.sql b/db/changes/233201/00-updatePrice.sql index 93888df6e..959943d6f 100644 --- a/db/changes/233201/00-updatePrice.sql +++ b/db/changes/233201/00-updatePrice.sql @@ -1,2 +1,2 @@ INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) - VALUES ('Ticket','*','*','ALLOW','ROLE','buyer'); + VALUES ('Ticket','canEditWeekly','WRITE','ALLOW','ROLE','buyer'); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 1a200709f..942cc74c7 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -309,5 +309,6 @@ "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", "You don't have enough privileges.": "You don't have enough privileges.", - "This ticket is locked.": "This ticket is locked." + "This ticket is locked.": "This ticket is locked.", + "This ticket is not editable.": "This ticket is not editable." } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/isEditable.js b/modules/ticket/back/methods/ticket/isEditable.js index 9f7e14dcc..967988214 100644 --- a/modules/ticket/back/methods/ticket/isEditable.js +++ b/modules/ticket/back/methods/ticket/isEditable.js @@ -33,7 +33,7 @@ module.exports = Self => { }, myOptions); const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*'); - const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'buyer', 'WRITE'); + const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'canEditWeekly', 'WRITE'); const alertLevel = state ? state.alertLevel : null; const ticket = await models.Ticket.findById(id, { fields: ['clientFk'], @@ -50,14 +50,10 @@ module.exports = Self => { const isLocked = await models.Ticket.isLocked(id, myOptions); const isWeekly = await models.TicketWeekly.findOne({where: {ticketFk: id}}, myOptions); - console.log('isRoleAdvanced', isRoleAdvanced); - console.log('canEditWeeklyTicket', canEditWeeklyTicket); - console.log('ticket', ticket); - console.log('isLocked', isLocked); - console.log('isWeekly', isWeekly); const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0); const isNormalClient = ticket && ticket.client().type().code == 'normal'; const isEditable = !(alertLevelGreaterThanZero && isNormalClient); + if (!ticket) throw new UserError(`The ticket doesn't exist.`); diff --git a/modules/ticket/back/methods/ticket/specs/isEditable.spec.js b/modules/ticket/back/methods/ticket/specs/isEditable.spec.js index 7337017d6..043445c28 100644 --- a/modules/ticket/back/methods/ticket/specs/isEditable.spec.js +++ b/modules/ticket/back/methods/ticket/specs/isEditable.spec.js @@ -1,143 +1,68 @@ const models = require('vn-loopback/server/server').models; describe('ticket isEditable()', () => { - it('should return false if the given ticket does not exist', async() => { + it('should throw an error as the ticket does not exist', async() => { const tx = await models.Ticket.beginTransaction({}); - let result; - + let error; try { const options = {transaction: tx}; const ctx = { req: {accessToken: {userId: 9}} }; - result = await models.Ticket.isEditable(ctx, 9999, options); - + await models.Ticket.isEditable(ctx, 9999, options); await tx.rollback(); } catch (e) { await tx.rollback(); - throw e; + error = e; } - expect(result).toEqual(false); + expect(error.message).toEqual(`The ticket doesn't exist.`); }); - it(`should return false if the given ticket isn't invoiced but isDeleted`, async() => { + it('should throw an error as this ticket is not editable', async() => { const tx = await models.Ticket.beginTransaction({}); - let result; - - try { - const options = {transaction: tx}; - const deletedTicket = await models.Ticket.findOne({ - where: { - invoiceOut: null, - isDeleted: true - }, - fields: ['id'] - }); - - const ctx = { - req: {accessToken: {userId: 9}} - }; - - result = await models.Ticket.isEditable(ctx, deletedTicket.id, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - - expect(result).toEqual(false); - }); - - it('should return true if the given ticket is editable', async() => { - const tx = await models.Ticket.beginTransaction({}); - let result; + let error; try { const options = {transaction: tx}; const ctx = { - req: {accessToken: {userId: 9}} + req: {accessToken: {userId: 1}} }; - result = await models.Ticket.isEditable(ctx, 16, options); - + await models.Ticket.isEditable(ctx, 8, options); await tx.rollback(); } catch (e) { + error = e; await tx.rollback(); - throw e; } - expect(result).toEqual(true); + expect(error.message).toEqual(`This ticket is not editable.`); }); - it('should not be able to edit a deleted or invoiced ticket even for salesAssistant', async() => { + it('should throw an error as this ticket is locked.', async() => { const tx = await models.Ticket.beginTransaction({}); - let result; - - try { - const options = {transaction: tx}; - const ctx = { - req: {accessToken: {userId: 21}} - }; - - result = await models.Ticket.isEditable(ctx, 19, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - - expect(result).toEqual(false); - }); - - it('should not be able to edit a deleted or invoiced ticket even for productionBoss', async() => { - const tx = await models.Ticket.beginTransaction({}); - let result; - - try { - const options = {transaction: tx}; - const ctx = { - req: {accessToken: {userId: 50}} - }; - - result = await models.Ticket.isEditable(ctx, 19, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - - expect(result).toEqual(false); - }); - - it('should not be able to edit a deleted or invoiced ticket even for salesPerson', async() => { - const tx = await models.Ticket.beginTransaction({}); - let result; - + let error; try { const options = {transaction: tx}; const ctx = { req: {accessToken: {userId: 18}} }; - result = await models.Ticket.isEditable(ctx, 19, options); + await models.Ticket.isEditable(ctx, 19, options); await tx.rollback(); } catch (e) { + error = e; await tx.rollback(); - throw e; } - expect(result).toEqual(false); + expect(error.message).toEqual(`This ticket is locked.`); }); - it('should not be able to edit if is a ticket weekly', async() => { + it('should throw an error as you do not have enough privileges.', async() => { const tx = await models.Ticket.beginTransaction({}); - + let error; try { const options = {transaction: tx}; @@ -147,10 +72,29 @@ describe('ticket isEditable()', () => { expect(result).toEqual(false); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`You don't have enough privileges.`); + }); + + it('should be able to edit a ticket weekly', async() => { + const tx = await models.Ticket.beginTransaction({}); + let result; + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: 35}}}; + + result = await models.Ticket.isEditable(ctx, 15, options); await tx.rollback(); } catch (e) { await tx.rollback(); throw e; } + + expect(result).toEqual(true); }); }); From bf92c5d482ce4bf7a4055da56e279136f3651926 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 25 Jul 2023 15:00:08 +0200 Subject: [PATCH 100/130] refs #6059 validateLogin sync user --- back/models/vn-user.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 985f017a5..68a556d77 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -115,6 +115,14 @@ module.exports = function(Self) { Self.validateLogin = async function(user, password) { let loginInfo = Object.assign({password}, Self.userUses(user)); token = await Self.login(loginInfo, 'user'); + + const userToken = await token.user.get(); + try { + await Self.app.models.Account.sync(userToken.name, password); + } catch (err) { + console.warn(err); + } + return {token: token.id, ttl: token.ttl}; }; From 543fbf3c0a322e9b586ed3caf8194c1491753235 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 25 Jul 2023 15:35:08 +0200 Subject: [PATCH 101/130] refs #5929 isEditableOrThrow created, tests passed --- loopback/locale/en.json | 6 +- loopback/locale/es.json | 7 +- modules/ticket/back/methods/ticket/addSale.js | 5 +- .../back/methods/ticket/componentUpdate.js | 6 +- .../ticket/back/methods/ticket/isEditable.js | 52 +-------- .../back/methods/ticket/isEditableOrThrow.js | 49 ++++++++ .../back/methods/ticket/priceDifference.js | 7 +- .../methods/ticket/recalculateComponents.js | 6 +- .../ticket/back/methods/ticket/setDeleted.js | 5 +- .../back/methods/ticket/specs/addSale.spec.js | 2 +- .../methods/ticket/specs/isEditable.spec.js | 109 ++++-------------- .../ticket/specs/isEditableOrThrow.spec.js | 100 ++++++++++++++++ .../ticket/specs/priceDifference.spec.js | 3 +- .../specs/recalculateComponents.spec.js | 3 +- .../ticket/specs/transferClient.spec.js | 2 +- .../ticket/specs/transferSales.spec.js | 2 +- .../back/methods/ticket/transferClient.js | 6 +- .../back/methods/ticket/transferSales.js | 6 +- modules/ticket/back/models/ticket-methods.js | 1 + 19 files changed, 203 insertions(+), 174 deletions(-) create mode 100644 modules/ticket/back/methods/ticket/isEditableOrThrow.js create mode 100644 modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 030afbe9e..135bb2be9 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -178,5 +178,9 @@ "The renew period has not been exceeded": "The renew period has not been exceeded", "You can not use the same password": "You can not use the same password", "Valid priorities": "Valid priorities: %d", - "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}" + "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}", + "You don't have enough privileges.": "You don't have enough privileges.", + "This ticket is locked.": "This ticket is locked.", + "This ticket is not editable.": "This ticket is not editable.", + "The ticket doesn't exist.": "The ticket doesn't exist." } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 942cc74c7..ac62d62e1 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -308,7 +308,8 @@ "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", - "You don't have enough privileges.": "You don't have enough privileges.", - "This ticket is locked.": "This ticket is locked.", - "This ticket is not editable.": "This ticket is not editable." + "You don't have enough privileges.": "No tienes suficientes permisos.", + "This ticket is locked.": "Este ticket está bloqueado.", + "This ticket is not editable.": "Este ticket no es editable.", + "The ticket doesn't exist.": "No existe el ticket." } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/addSale.js b/modules/ticket/back/methods/ticket/addSale.js index 2cd02a8a4..9a3e32a7e 100644 --- a/modules/ticket/back/methods/ticket/addSale.js +++ b/modules/ticket/back/methods/ticket/addSale.js @@ -1,4 +1,3 @@ - const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { @@ -47,9 +46,7 @@ module.exports = Self => { } try { - const isEditable = await models.Ticket.isEditable(ctx, id, myOptions); - if (!isEditable) - throw new UserError(`The sales of this ticket can't be modified`); + const isEditable = await models.Ticket.isEditableOrThrow(ctx, id, myOptions); const item = await models.Item.findById(itemId, null, myOptions); const ticket = await models.Ticket.findById(id, { diff --git a/modules/ticket/back/methods/ticket/componentUpdate.js b/modules/ticket/back/methods/ticket/componentUpdate.js index 48aee36d4..eadbf65c2 100644 --- a/modules/ticket/back/methods/ticket/componentUpdate.js +++ b/modules/ticket/back/methods/ticket/componentUpdate.js @@ -1,4 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); const loggable = require('vn-loopback/util/log'); module.exports = Self => { @@ -116,10 +115,7 @@ module.exports = Self => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; const $t = ctx.req.__; // $translate - const isEditable = await models.Ticket.isEditable(ctx, args.id, myOptions); - - if (!isEditable) - throw new UserError(`The sales of this ticket can't be modified`); + const isEditable = await models.Ticket.isEditableOrThrow(ctx, args.id, myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE'); if (!editZone) { diff --git a/modules/ticket/back/methods/ticket/isEditable.js b/modules/ticket/back/methods/ticket/isEditable.js index 967988214..f657cd5e3 100644 --- a/modules/ticket/back/methods/ticket/isEditable.js +++ b/modules/ticket/back/methods/ticket/isEditable.js @@ -1,5 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); - module.exports = Self => { Self.remoteMethodCtx('isEditable', { description: 'Check if a ticket is editable', @@ -22,50 +20,12 @@ module.exports = Self => { }); Self.isEditable = async(ctx, id, options) => { - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const state = await models.TicketState.findOne({ - where: {ticketFk: id} - }, myOptions); - - const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*'); - const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'canEditWeekly', 'WRITE'); - const alertLevel = state ? state.alertLevel : null; - const ticket = await models.Ticket.findById(id, { - fields: ['clientFk'], - include: [{ - relation: 'client', - scope: { - include: { - relation: 'type' - } - } - }] - }, myOptions); - - const isLocked = await models.Ticket.isLocked(id, myOptions); - const isWeekly = await models.TicketWeekly.findOne({where: {ticketFk: id}}, myOptions); - - const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0); - const isNormalClient = ticket && ticket.client().type().code == 'normal'; - const isEditable = !(alertLevelGreaterThanZero && isNormalClient); - - if (!ticket) - throw new UserError(`The ticket doesn't exist.`); - - if (!isEditable && !isRoleAdvanced) - throw new UserError(`This ticket is not editable.`); - - if (isLocked) - throw new UserError(`This ticket is locked.`); - - if (isWeekly && !canEditWeeklyTicket) - throw new UserError(`You don't have enough privileges.`); - + try { + await Self.isEditableOrThrow(ctx, id, options); + } catch (e) { + if (e.name === 'ForbiddenError') return false; + throw e; + } return true; }; }; diff --git a/modules/ticket/back/methods/ticket/isEditableOrThrow.js b/modules/ticket/back/methods/ticket/isEditableOrThrow.js new file mode 100644 index 000000000..6a8bafa2c --- /dev/null +++ b/modules/ticket/back/methods/ticket/isEditableOrThrow.js @@ -0,0 +1,49 @@ +const ForbiddenError = require('vn-loopback/util/forbiddenError'); + +module.exports = Self => { + Self.isEditableOrThrow = async(ctx, id, options) => { + const models = Self.app.models; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const state = await models.TicketState.findOne({ + where: {ticketFk: id} + }, myOptions); + + const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*'); + const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'canEditWeekly', 'WRITE'); + const alertLevel = state ? state.alertLevel : null; + const ticket = await models.Ticket.findById(id, { + fields: ['clientFk'], + include: [{ + relation: 'client', + scope: { + include: { + relation: 'type' + } + } + }] + }, myOptions); + + const isLocked = await models.Ticket.isLocked(id, myOptions); + const isWeekly = await models.TicketWeekly.findOne({where: {ticketFk: id}}, myOptions); + + const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0); + const isNormalClient = ticket && ticket.client().type().code == 'normal'; + const isEditable = !(alertLevelGreaterThanZero && isNormalClient); + + if (!ticket) + throw new ForbiddenError(`The ticket doesn't exist.`); + + if (!isEditable && !isRoleAdvanced) + throw new ForbiddenError(`This ticket is not editable.`); + + if (isLocked) + throw new ForbiddenError(`This ticket is locked.`); + + if (isWeekly && !canEditWeeklyTicket) + throw new ForbiddenError(`You don't have enough privileges.`); + }; +}; diff --git a/modules/ticket/back/methods/ticket/priceDifference.js b/modules/ticket/back/methods/ticket/priceDifference.js index 42a71f1c8..754646b03 100644 --- a/modules/ticket/back/methods/ticket/priceDifference.js +++ b/modules/ticket/back/methods/ticket/priceDifference.js @@ -1,5 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); - module.exports = Self => { Self.remoteMethodCtx('priceDifference', { description: 'Returns sales with price difference if the ticket is editable', @@ -72,10 +70,7 @@ module.exports = Self => { } try { - const isEditable = await Self.isEditable(ctx, args.id, myOptions); - - if (!isEditable) - throw new UserError(`The sales of this ticket can't be modified`); + const isEditable = await Self.isEditableOrThrow(ctx, args.id, myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE'); if (!editZone) { diff --git a/modules/ticket/back/methods/ticket/recalculateComponents.js b/modules/ticket/back/methods/ticket/recalculateComponents.js index eb9c8a72e..78c44bab3 100644 --- a/modules/ticket/back/methods/ticket/recalculateComponents.js +++ b/modules/ticket/back/methods/ticket/recalculateComponents.js @@ -1,4 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('recalculateComponents', { description: 'Calculates the price of a sale and its components', @@ -33,10 +32,7 @@ module.exports = Self => { } try { - const isEditable = await Self.isEditable(ctx, id, myOptions); - - if (!isEditable) - throw new UserError(`The current ticket can't be modified`); + const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); const recalculation = await Self.rawSql('CALL vn.ticket_recalcComponents(?, NULL)', [id], myOptions); diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index 878cce056..6485f198e 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -39,10 +39,7 @@ module.exports = Self => { const ticketToDelete = await models.Ticket.findById(id, {fields: ['isDeleted']}, myOptions); if (ticketToDelete.isDeleted) return false; - const isEditable = await Self.isEditable(ctx, id, myOptions); - - if (!isEditable) - throw new UserError(`The sales of this ticket can't be modified`); + const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); // Check if ticket has refunds const ticketRefunds = await models.TicketRefund.find({ diff --git a/modules/ticket/back/methods/ticket/specs/addSale.spec.js b/modules/ticket/back/methods/ticket/specs/addSale.spec.js index 2e568716a..b1ecb133b 100644 --- a/modules/ticket/back/methods/ticket/specs/addSale.spec.js +++ b/modules/ticket/back/methods/ticket/specs/addSale.spec.js @@ -97,6 +97,6 @@ describe('ticket addSale()', () => { error = e; } - expect(error.message).toEqual(`The sales of this ticket can't be modified`); + expect(error.message).toEqual(`This ticket is locked.`); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/isEditable.spec.js b/modules/ticket/back/methods/ticket/specs/isEditable.spec.js index 043445c28..301745ed3 100644 --- a/modules/ticket/back/methods/ticket/specs/isEditable.spec.js +++ b/modules/ticket/back/methods/ticket/specs/isEditable.spec.js @@ -1,100 +1,37 @@ const models = require('vn-loopback/server/server').models; -describe('ticket isEditable()', () => { - it('should throw an error as the ticket does not exist', async() => { - const tx = await models.Ticket.beginTransaction({}); - let error; - try { - const options = {transaction: tx}; - const ctx = { - req: {accessToken: {userId: 9}} - }; - - await models.Ticket.isEditable(ctx, 9999, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toEqual(`The ticket doesn't exist.`); - }); - - it('should throw an error as this ticket is not editable', async() => { - const tx = await models.Ticket.beginTransaction({}); - let error; - - try { - const options = {transaction: tx}; - const ctx = { - req: {accessToken: {userId: 1}} - }; - - await models.Ticket.isEditable(ctx, 8, options); - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toEqual(`This ticket is not editable.`); - }); - - it('should throw an error as this ticket is locked.', async() => { - const tx = await models.Ticket.beginTransaction({}); - let error; - try { - const options = {transaction: tx}; - const ctx = { - req: {accessToken: {userId: 18}} - }; - - await models.Ticket.isEditable(ctx, 19, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toEqual(`This ticket is locked.`); - }); - - it('should throw an error as you do not have enough privileges.', async() => { - const tx = await models.Ticket.beginTransaction({}); - let error; - try { - const options = {transaction: tx}; - - const ctx = {req: {accessToken: {userId: 1}}}; - - const result = await models.Ticket.isEditable(ctx, 15, options); - - expect(result).toEqual(false); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error.message).toEqual(`You don't have enough privileges.`); - }); - - it('should be able to edit a ticket weekly', async() => { +describe('isEditable()', () => { + it('should return false if It is able to edit', async() => { const tx = await models.Ticket.beginTransaction({}); let result; + try { const options = {transaction: tx}; const ctx = {req: {accessToken: {userId: 35}}}; - - result = await models.Ticket.isEditable(ctx, 15, options); + result = await models.Ticket.isEditable(ctx, 5, options); await tx.rollback(); - } catch (e) { + } catch (error) { await tx.rollback(); throw e; } - expect(result).toEqual(true); + expect(result).toBeFalse(); + }); + + it('should return true if It is able to edit', async() => { + const tx = await models.Ticket.beginTransaction({}); + let result; + + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: 35}}}; + result = await models.Ticket.isEditable(ctx, 15, options); + await tx.rollback(); + } catch (error) { + await tx.rollback(); + throw e; + } + + expect(result).toBeTrue(); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js new file mode 100644 index 000000000..b65ed64a1 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js @@ -0,0 +1,100 @@ +const models = require('vn-loopback/server/server').models; + +describe('ticket isEditableOrThrow()', () => { + it('should throw an error as the ticket does not exist', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + const ctx = { + req: {accessToken: {userId: 9}} + }; + + await models.Ticket.isEditableOrThrow(ctx, 9999, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toEqual(`The ticket doesn't exist.`); + }); + + it('should throw an error as this ticket is not editable', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + + try { + const options = {transaction: tx}; + const ctx = { + req: {accessToken: {userId: 1}} + }; + + await models.Ticket.isEditableOrThrow(ctx, 8, options); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`This ticket is not editable.`); + }); + + it('should throw an error as this ticket is locked.', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + const ctx = { + req: {accessToken: {userId: 18}} + }; + + await models.Ticket.isEditableOrThrow(ctx, 19, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`This ticket is locked.`); + }); + + it('should throw an error as you do not have enough privileges.', async() => { + const tx = await models.Ticket.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + + const ctx = {req: {accessToken: {userId: 1}}}; + + const result = await models.Ticket.isEditableOrThrow(ctx, 15, options); + + expect(result).toEqual(false); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`You don't have enough privileges.`); + }); + + it('should return undefined if It can be edited', async() => { + const tx = await models.Ticket.beginTransaction({}); + let result; + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: 35}}}; + + result = await models.Ticket.isEditableOrThrow(ctx, 15, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(result).toBeUndefined(); + }); +}); diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js index cc54353ef..d01f0c1bb 100644 --- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js +++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js @@ -1,5 +1,6 @@ const models = require('vn-loopback/server/server').models; const UserError = require('vn-loopback/util/user-error'); +const ForbiddenError = require('vn-loopback/util/forbiddenError'); describe('sale priceDifference()', () => { it('should return ticket price differences', async() => { @@ -59,7 +60,7 @@ describe('sale priceDifference()', () => { await tx.rollback(); } - expect(error).toEqual(new UserError(`The sales of this ticket can't be modified`)); + expect(error).toEqual(new ForbiddenError(`This ticket is not editable.`)); }); it('should return ticket movable', async() => { diff --git a/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js b/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js index ed10d114f..383c2c6d5 100644 --- a/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js +++ b/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const ForbiddenError = require('vn-loopback/util/forbiddenError'); describe('ticket recalculateComponents()', () => { const ticketId = 11; @@ -38,6 +39,6 @@ describe('ticket recalculateComponents()', () => { error = e; } - expect(error).toEqual(new Error(`The current ticket can't be modified`)); + expect(error).toEqual(new ForbiddenError(`This ticket is locked.`)); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js index ed10e5159..c09c20083 100644 --- a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js +++ b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js @@ -23,7 +23,7 @@ describe('Ticket transferClient()', () => { error = e; } - expect(error.message).toEqual(`The current ticket can't be modified`); + expect(error.message).toEqual(`This ticket is locked.`); }); it('should be assigned a different clientFk', async() => { diff --git a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js index 562688917..ef92e88c0 100644 --- a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js +++ b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js @@ -33,7 +33,7 @@ describe('sale transferSales()', () => { error = e; } - expect(error.message).toEqual(`The sales of this ticket can't be modified`); + expect(error.message).toEqual(`This ticket is not editable.`); }); it('should throw an error if the receiving ticket is not editable', async() => { diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js index 04c153bd2..c87ad4881 100644 --- a/modules/ticket/back/methods/ticket/transferClient.js +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -1,4 +1,3 @@ -const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('transferClient', { description: 'Transfering ticket to another client', @@ -29,10 +28,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const isEditable = await Self.isEditable(ctx, id, myOptions); - - if (!isEditable) - throw new UserError(`The current ticket can't be modified`); + const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); const ticket = await models.Ticket.findById( id, diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js index 0eee50d5f..bd99920db 100644 --- a/modules/ticket/back/methods/ticket/transferSales.js +++ b/modules/ticket/back/methods/ticket/transferSales.js @@ -1,4 +1,4 @@ -let UserError = require('vn-loopback/util/user-error'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('transferSales', { @@ -48,9 +48,7 @@ module.exports = Self => { } try { - const isEditable = await models.Ticket.isEditable(ctx, id, myOptions); - if (!isEditable) - throw new UserError(`The sales of this ticket can't be modified`); + const isEditable = await models.Ticket.isEditableOrThrow(ctx, id, myOptions); if (ticketId) { const isReceiverEditable = await models.Ticket.isEditable(ctx, ticketId, myOptions); diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js index b432c9f6b..c37337253 100644 --- a/modules/ticket/back/models/ticket-methods.js +++ b/modules/ticket/back/models/ticket-methods.js @@ -6,6 +6,7 @@ module.exports = function(Self) { require('../methods/ticket/componentUpdate')(Self); require('../methods/ticket/new')(Self); require('../methods/ticket/isEditable')(Self); + require('../methods/ticket/isEditableOrThrow')(Self); require('../methods/ticket/setDeleted')(Self); require('../methods/ticket/restore')(Self); require('../methods/ticket/getSales')(Self); From a0fee6ad50add6065c60c701ab9abcbf1adfc611 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 26 Jul 2023 09:20:54 +0200 Subject: [PATCH 102/130] refs #5929 removed useless vars --- modules/ticket/back/methods/ticket/addSale.js | 2 +- modules/ticket/back/methods/ticket/componentUpdate.js | 2 +- modules/ticket/back/methods/ticket/priceDifference.js | 2 +- modules/ticket/back/methods/ticket/recalculateComponents.js | 2 +- modules/ticket/back/methods/ticket/setDeleted.js | 2 +- .../back/methods/ticket/specs/isEditableOrThrow.spec.js | 6 +----- modules/ticket/back/methods/ticket/transferClient.js | 2 +- modules/ticket/back/methods/ticket/transferSales.js | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/modules/ticket/back/methods/ticket/addSale.js b/modules/ticket/back/methods/ticket/addSale.js index 9a3e32a7e..cbf884273 100644 --- a/modules/ticket/back/methods/ticket/addSale.js +++ b/modules/ticket/back/methods/ticket/addSale.js @@ -46,7 +46,7 @@ module.exports = Self => { } try { - const isEditable = await models.Ticket.isEditableOrThrow(ctx, id, myOptions); + await models.Ticket.isEditableOrThrow(ctx, id, myOptions); const item = await models.Item.findById(itemId, null, myOptions); const ticket = await models.Ticket.findById(id, { diff --git a/modules/ticket/back/methods/ticket/componentUpdate.js b/modules/ticket/back/methods/ticket/componentUpdate.js index eadbf65c2..b5ff50d59 100644 --- a/modules/ticket/back/methods/ticket/componentUpdate.js +++ b/modules/ticket/back/methods/ticket/componentUpdate.js @@ -115,7 +115,7 @@ module.exports = Self => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; const $t = ctx.req.__; // $translate - const isEditable = await models.Ticket.isEditableOrThrow(ctx, args.id, myOptions); + await models.Ticket.isEditableOrThrow(ctx, args.id, myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE'); if (!editZone) { diff --git a/modules/ticket/back/methods/ticket/priceDifference.js b/modules/ticket/back/methods/ticket/priceDifference.js index 754646b03..495e9e1aa 100644 --- a/modules/ticket/back/methods/ticket/priceDifference.js +++ b/modules/ticket/back/methods/ticket/priceDifference.js @@ -70,7 +70,7 @@ module.exports = Self => { } try { - const isEditable = await Self.isEditableOrThrow(ctx, args.id, myOptions); + await Self.isEditableOrThrow(ctx, args.id, myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE'); if (!editZone) { diff --git a/modules/ticket/back/methods/ticket/recalculateComponents.js b/modules/ticket/back/methods/ticket/recalculateComponents.js index 78c44bab3..bdf74f8b6 100644 --- a/modules/ticket/back/methods/ticket/recalculateComponents.js +++ b/modules/ticket/back/methods/ticket/recalculateComponents.js @@ -32,7 +32,7 @@ module.exports = Self => { } try { - const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); + await Self.isEditableOrThrow(ctx, id, myOptions); const recalculation = await Self.rawSql('CALL vn.ticket_recalcComponents(?, NULL)', [id], myOptions); diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index 6485f198e..2f8c402da 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -39,7 +39,7 @@ module.exports = Self => { const ticketToDelete = await models.Ticket.findById(id, {fields: ['isDeleted']}, myOptions); if (ticketToDelete.isDeleted) return false; - const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); + await Self.isEditableOrThrow(ctx, id, myOptions); // Check if ticket has refunds const ticketRefunds = await models.TicketRefund.find({ diff --git a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js index b65ed64a1..6c89bac26 100644 --- a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js +++ b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js @@ -65,13 +65,9 @@ describe('ticket isEditableOrThrow()', () => { let error; try { const options = {transaction: tx}; - const ctx = {req: {accessToken: {userId: 1}}}; - const result = await models.Ticket.isEditableOrThrow(ctx, 15, options); - - expect(result).toEqual(false); - + await models.Ticket.isEditableOrThrow(ctx, 15, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js index c87ad4881..60e70d710 100644 --- a/modules/ticket/back/methods/ticket/transferClient.js +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -28,7 +28,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const isEditable = await Self.isEditableOrThrow(ctx, id, myOptions); + await Self.isEditableOrThrow(ctx, id, myOptions); const ticket = await models.Ticket.findById( id, diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js index bd99920db..a48c5683c 100644 --- a/modules/ticket/back/methods/ticket/transferSales.js +++ b/modules/ticket/back/methods/ticket/transferSales.js @@ -48,7 +48,7 @@ module.exports = Self => { } try { - const isEditable = await models.Ticket.isEditableOrThrow(ctx, id, myOptions); + await models.Ticket.isEditableOrThrow(ctx, id, myOptions); if (ticketId) { const isReceiverEditable = await models.Ticket.isEditable(ctx, ticketId, myOptions); From 2a0c363dc5443091d71df034da772032b56191e3 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 26 Jul 2023 13:28:40 +0200 Subject: [PATCH 103/130] hotfix change model --- .../assets/files/{model.ezp => model.ezpx} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename print/templates/email/printer-setup/assets/files/{model.ezp => model.ezpx} (95%) diff --git a/print/templates/email/printer-setup/assets/files/model.ezp b/print/templates/email/printer-setup/assets/files/model.ezpx similarity index 95% rename from print/templates/email/printer-setup/assets/files/model.ezp rename to print/templates/email/printer-setup/assets/files/model.ezpx index dba98e0ee..739593447 100644 --- a/print/templates/email/printer-setup/assets/files/model.ezp +++ b/print/templates/email/printer-setup/assets/files/model.ezpx @@ -539,9 +539,9 @@ 2 4 - + false - false + true 4294967295 5 W5 @@ -571,15 +571,15 @@ 2896 - 187 - 24 + 138 + 32 426 2896 - 187 - 24 + 138 + 32 426 2896 @@ -621,14 +621,14 @@ New label -Lang:(es-ES) OS:Microsoft Windows NT 10.0.22000.0(Win32NT) +Lang:(es-ES) OS:Microsoft Windows NT 10.0.19045.0(Win32NT) Mm 203 EZPL - GODEX G300#132207AB - None + 00000000 + COM1 USB 2886794855 9100 From 1277af1399ff877069a7f33840e1174f374ba11c Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 26 Jul 2023 13:53:15 +0200 Subject: [PATCH 104/130] hotfix mod path --- print/templates/email/printer-setup/attachments.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/print/templates/email/printer-setup/attachments.json b/print/templates/email/printer-setup/attachments.json index 1e1f710c3..969fdd23a 100644 --- a/print/templates/email/printer-setup/attachments.json +++ b/print/templates/email/printer-setup/attachments.json @@ -1,9 +1,9 @@ [ { - "filename": "model.ezp", + "filename": "model.ezpx", "component": "printer-setup", - "path": "/assets/files/model.ezp", - "cid": "model.ezp" + "path": "/assets/files/model.ezpx", + "cid": "model.ezpx" }, { "filename": "port.png", @@ -11,4 +11,4 @@ "path": "/assets/files/port.png", "cid": "port.png" } -] \ No newline at end of file +] From 29baa2f0c7d7998864863761adca7eb30b6608bc Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 27 Jul 2023 08:27:09 +0200 Subject: [PATCH 105/130] refs #6015 modify changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5928e9c4..8440e0f2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - (General -> Iconos) Añadidos nuevos iconos -- (Clientes -> Razón social) Nuevas restricciones por pais +- (Clientes -> Razón social) Permite crear clientes con la misma razón social según el país ### Fixed From 65b9cadd9e6ed72d263c8a23e1efb0878069b4ca Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 27 Jul 2023 12:51:14 +0200 Subject: [PATCH 106/130] refs #5804 refactor: sustituido activeBuyers por getItemTypeWorker --- .../item/back/methods/item/activeBuyers.js | 44 ------------------- .../methods/item/specs/activeBuyers.spec.js | 24 ---------- modules/item/back/models/item.js | 1 - .../front/request-search-panel/index.html | 14 +++--- modules/item/front/search-panel/index.html | 12 ++--- .../ticket-request/getItemTypeWorker.js | 33 ++++++++------ .../specs/getItemTypeWorkers.spec.js | 6 +-- 7 files changed, 34 insertions(+), 100 deletions(-) delete mode 100644 modules/item/back/methods/item/activeBuyers.js delete mode 100644 modules/item/back/methods/item/specs/activeBuyers.spec.js diff --git a/modules/item/back/methods/item/activeBuyers.js b/modules/item/back/methods/item/activeBuyers.js deleted file mode 100644 index e16ff877b..000000000 --- a/modules/item/back/methods/item/activeBuyers.js +++ /dev/null @@ -1,44 +0,0 @@ -const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; -const mergeFilters = require('vn-loopback/util/filter').mergeFilters; - -module.exports = Self => { - Self.remoteMethod('activeBuyers', { - description: 'Returns a list of buyers for the given item type', - accepts: [{ - 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: `/activeBuyers`, - verb: 'GET' - } - }); - - Self.activeBuyers = async(filter, options) => { - const conn = Self.dataSource.connector; - const where = {isActive: true}; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - filter = mergeFilters(filter, {where}); - - let stmt = new ParameterizedSQL( - `SELECT DISTINCT w.id workerFk, w.firstName, w.lastName, u.name, u.nickname - FROM worker w - JOIN itemType it ON it.workerFk = w.id - JOIN account.user u ON u.id = w.id - JOIN item i ON i.typeFk = it.id`, - null, myOptions); - - stmt.merge(conn.makeSuffix(filter)); - - return conn.executeStmt(stmt); - }; -}; diff --git a/modules/item/back/methods/item/specs/activeBuyers.spec.js b/modules/item/back/methods/item/specs/activeBuyers.spec.js deleted file mode 100644 index 5bf36756f..000000000 --- a/modules/item/back/methods/item/specs/activeBuyers.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('Worker activeBuyers', () => { - it('should return the buyers in itemType as result', async() => { - const tx = await models.Item.beginTransaction({}); - - try { - const options = {transaction: tx}; - const filter = {}; - const result = await models.Item.activeBuyers(filter, options); - const firstWorker = result[0]; - const secondWorker = result[1]; - - expect(result.length).toEqual(2); - expect(firstWorker.nickname).toEqual('logisticBossNick'); - expect(secondWorker.nickname).toEqual('buyerNick'); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index b8baa97ea..61c5c2588 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -14,7 +14,6 @@ module.exports = Self => { require('../methods/item/getWasteByWorker')(Self); require('../methods/item/getWasteByItem')(Self); require('../methods/item/createIntrastat')(Self); - require('../methods/item/activeBuyers')(Self); require('../methods/item/buyerWasteEmail')(Self); require('../methods/item/labelPdf')(Self); diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index a76684776..9d35fbca4 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -1,7 +1,7 @@
@@ -26,7 +26,7 @@ search-function="{firstName: $search}" value-field="id" where="{role: {inq: ['logistic', 'buyer']}}" - label="Atender"> + label="Buyer"> {{nickname}} @@ -57,7 +57,7 @@ {{firstName}} {{lastName}} - +
- - - - { - Self.remoteMethodCtx('getItemTypeWorker', { + Self.remoteMethod('getItemTypeWorker', { description: 'Returns the workers that appear in itemType', accessType: 'READ', accepts: [{ @@ -20,10 +22,9 @@ module.exports = Self => { } }); - Self.getItemTypeWorker = async(ctx, filter, options) => { + Self.getItemTypeWorker = async(filter, options) => { const myOptions = {}; const conn = Self.dataSource.connector; - let tx; if (typeof options == 'object') Object.assign(myOptions, options); @@ -33,25 +34,29 @@ module.exports = Self => { FROM itemType it JOIN worker w ON w.id = it.workerFk JOIN account.user u ON u.id = w.id`; + const stmt = new ParameterizedSQL(query); - let stmt = new ParameterizedSQL(query); - - if (filter.where) { - const value = filter.where.firstName; - const myFilter = { - where: {or: [ + filter.where = buildFilter(filter.where, (param, value) => { + switch (param) { + case 'firstName': + return {or: [ {'w.firstName': {like: `%${value}%`}}, {'w.lastName': {like: `%${value}%`}}, {'u.name': {like: `%${value}%`}}, {'u.nickname': {like: `%${value}%`}} - ]} - }; + ]}; + case 'id': + return {'w.id': value}; + } + }); - stmt.merge(conn.makeSuffix(myFilter)); - } + let myFilter = { + where: {'u.active': true} + }; - if (tx) await tx.commit(); + myFilter = mergeFilters(myFilter, filter); + stmt.merge(conn.makeSuffix(myFilter)); return conn.executeStmt(stmt); }; }; diff --git a/modules/ticket/back/methods/ticket-request/specs/getItemTypeWorkers.spec.js b/modules/ticket/back/methods/ticket-request/specs/getItemTypeWorkers.spec.js index ae5c508b6..c57451c26 100644 --- a/modules/ticket/back/methods/ticket-request/specs/getItemTypeWorkers.spec.js +++ b/modules/ticket/back/methods/ticket-request/specs/getItemTypeWorkers.spec.js @@ -1,12 +1,10 @@ const models = require('vn-loopback/server/server').models; describe('ticket-request getItemTypeWorker()', () => { - const ctx = {req: {accessToken: {userId: 18}}}; - it('should return the buyer as result', async() => { const filter = {where: {firstName: 'buyer'}}; - const result = await models.TicketRequest.getItemTypeWorker(ctx, filter); + const result = await models.TicketRequest.getItemTypeWorker(filter); expect(result.length).toEqual(1); }); @@ -14,7 +12,7 @@ describe('ticket-request getItemTypeWorker()', () => { it('should return the workers at itemType as result', async() => { const filter = {}; - const result = await models.TicketRequest.getItemTypeWorker(ctx, filter); + const result = await models.TicketRequest.getItemTypeWorker(filter); expect(result.length).toBeGreaterThan(1); }); From 3bc3ffe1153644fc568d24176e6ca3590d36f491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 27 Jul 2023 13:40:39 +0200 Subject: [PATCH 107/130] refs #6077 Log-InvoiceInDueday-incorrecto --- .../invoiceIn/back/locale/invoiceIn/en.yml | 20 +++++++++++++++++++ .../invoiceIn/back/locale/invoiceIn/es.yml | 20 +++++++++++++++++++ .../back/locale/invoiceInDueDay/en.yml | 9 +++++++++ .../back/locale/invoiceInDueDay/es.yml | 9 +++++++++ .../invoiceIn/back/locale/invoiceInTax/en.yml | 12 +++++++++++ .../invoiceIn/back/locale/invoiceInTax/es.yml | 12 +++++++++++ 6 files changed, 82 insertions(+) create mode 100644 modules/invoiceIn/back/locale/invoiceIn/en.yml create mode 100644 modules/invoiceIn/back/locale/invoiceIn/es.yml create mode 100644 modules/invoiceIn/back/locale/invoiceInDueDay/en.yml create mode 100644 modules/invoiceIn/back/locale/invoiceInDueDay/es.yml create mode 100644 modules/invoiceIn/back/locale/invoiceInTax/en.yml create mode 100644 modules/invoiceIn/back/locale/invoiceInTax/es.yml diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml new file mode 100644 index 000000000..4110dcdbc --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml @@ -0,0 +1,20 @@ +name: invoice in +columns: + id: id + serialNumber: serial number + serial: serial + supplierFk: supplier + issued: issued + supplierRef: supplierRef + isBooked: is booked + currencyFk: currency + created: created + companyFk: company + docFk: document + booked: booked + operated: operated + bookEntried: book entried + isVatDeductible: is VAT deductible + withholdingSageFk: withholding + expenceFkDeductible: expence deductible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml new file mode 100644 index 000000000..432b27cb3 --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml @@ -0,0 +1,20 @@ +name: factura recibida +columns: + id: id + serialNumber: número de serie + serial: serie + supplierFk: proveedor + issued: fecha emisión + supplierRef: referéncia proveedor + isBooked: facturado + currencyFk: moneda + created: creado + companyFk: empresa + docFk: documento + booked: fecha contabilización + operated: fecha entrega + bookEntried: fecha asiento + isVatDeductible: impuesto deducible + withholdingSageFk: código de retención + expenceFkDeductible: gasto deducible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml new file mode 100644 index 000000000..5e42dfc66 --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml @@ -0,0 +1,9 @@ +name: invoice in due day +columns: + id: id + invoiceInFk: invoice in + dueDated: due date + bankFk: bank + amount: amount + foreignValue : foreign amount + created: created diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml new file mode 100644 index 000000000..168db9803 --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml @@ -0,0 +1,9 @@ +name: vencimientos factura recibida +columns: + id: id + invoiceInFk: factura + dueDated: fecha vto. + bankFk: banco + amount: importe + foreignValue : importe divisa + created: creado diff --git a/modules/invoiceIn/back/locale/invoiceInTax/en.yml b/modules/invoiceIn/back/locale/invoiceInTax/en.yml new file mode 100644 index 000000000..86a9e42c3 --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceInTax/en.yml @@ -0,0 +1,12 @@ +name: invoice in tax +colmns: + id: id + invoiceInFk: invoice in + taxCodeFk: tax + taxableBase: taxable base + expenceFk: expence + foreignValue: foreign amount + taxTypeSageFk: tax type + transactionTypeSageFk: transaction type + created: created + editorFk: editor diff --git a/modules/invoiceIn/back/locale/invoiceInTax/es.yml b/modules/invoiceIn/back/locale/invoiceInTax/es.yml new file mode 100644 index 000000000..233c591e9 --- /dev/null +++ b/modules/invoiceIn/back/locale/invoiceInTax/es.yml @@ -0,0 +1,12 @@ +name: factura recibida impuesto +colmns: + id: id + invoiceInFk: factura recibida + taxCodeFk: código IVA + taxableBase: base imponible + expenceFk: código gasto + foreignValue: importe divisa + taxTypeSageFk: código impuesto + transactionTypeSageFk: código transacción + created: creado + editorFk: editor \ No newline at end of file From 1d4ce2c70342e01371143b317f80d5c17214c474 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 28 Jul 2023 12:24:24 +0200 Subject: [PATCH 108/130] refs #5804 fix: delete transaction --- .../ticket/back/methods/ticket-request/getItemTypeWorker.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js index f160cfaac..9ea859f7c 100644 --- a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js +++ b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js @@ -22,13 +22,9 @@ module.exports = Self => { } }); - Self.getItemTypeWorker = async(filter, options) => { - const myOptions = {}; + Self.getItemTypeWorker = async filter => { const conn = Self.dataSource.connector; - if (typeof options == 'object') - Object.assign(myOptions, options); - const query = `SELECT DISTINCT u.id, u.nickname FROM itemType it From 4061f3e5ce87668745a74e04986aaee49c35e926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Fri, 28 Jul 2023 12:28:41 +0200 Subject: [PATCH 109/130] #refs 6077 espacios por tabulaciones --- .../invoiceIn/back/locale/invoiceIn/en.yml | 36 +++++++++---------- .../invoiceIn/back/locale/invoiceIn/es.yml | 36 +++++++++---------- .../back/locale/invoiceInDueDay/en.yml | 14 ++++---- .../back/locale/invoiceInDueDay/es.yml | 14 ++++---- .../invoiceIn/back/locale/invoiceInTax/en.yml | 20 +++++------ .../invoiceIn/back/locale/invoiceInTax/es.yml | 20 +++++------ 6 files changed, 70 insertions(+), 70 deletions(-) diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml index 4110dcdbc..5aa81b9ff 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/en.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml @@ -1,20 +1,20 @@ name: invoice in columns: - id: id - serialNumber: serial number - serial: serial - supplierFk: supplier - issued: issued - supplierRef: supplierRef - isBooked: is booked - currencyFk: currency - created: created - companyFk: company - docFk: document - booked: booked - operated: operated - bookEntried: book entried - isVatDeductible: is VAT deductible - withholdingSageFk: withholding - expenceFkDeductible: expence deductible - editorFk: editor \ No newline at end of file + id: id + serialNumber: serial number + serial: serial + supplierFk: supplier + issued: issued + supplierRef: supplierRef + isBooked: is booked + currencyFk: currency + created: created + companyFk: company + docFk: document + booked: booked + operated: operated + bookEntried: book entried + isVatDeductible: is VAT deductible + withholdingSageFk: withholding + expenceFkDeductible: expence deductible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml index 432b27cb3..61f62f022 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/es.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml @@ -1,20 +1,20 @@ name: factura recibida columns: - id: id - serialNumber: número de serie - serial: serie - supplierFk: proveedor - issued: fecha emisión - supplierRef: referéncia proveedor - isBooked: facturado - currencyFk: moneda - created: creado - companyFk: empresa - docFk: documento - booked: fecha contabilización - operated: fecha entrega - bookEntried: fecha asiento - isVatDeductible: impuesto deducible - withholdingSageFk: código de retención - expenceFkDeductible: gasto deducible - editorFk: editor \ No newline at end of file + id: id + serialNumber: número de serie + serial: serie + supplierFk: proveedor + issued: fecha emisión + supplierRef: referéncia proveedor + isBooked: facturado + currencyFk: moneda + created: creado + companyFk: empresa + docFk: documento + booked: fecha contabilización + operated: fecha entrega + bookEntried: fecha asiento + isVatDeductible: impuesto deducible + withholdingSageFk: código de retención + expenceFkDeductible: gasto deducible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml index 5e42dfc66..f01a0de46 100644 --- a/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml @@ -1,9 +1,9 @@ name: invoice in due day columns: - id: id - invoiceInFk: invoice in - dueDated: due date - bankFk: bank - amount: amount - foreignValue : foreign amount - created: created + id: id + invoiceInFk: invoice in + dueDated: due date + bankFk: bank + amount: amount + foreignValue : foreign amount + created: created diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml index 168db9803..34b20b37d 100644 --- a/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml @@ -1,9 +1,9 @@ name: vencimientos factura recibida columns: - id: id - invoiceInFk: factura - dueDated: fecha vto. - bankFk: banco - amount: importe - foreignValue : importe divisa - created: creado + id: id + invoiceInFk: factura + dueDated: fecha vto. + bankFk: banco + amount: importe + foreignValue : importe divisa + created: creado diff --git a/modules/invoiceIn/back/locale/invoiceInTax/en.yml b/modules/invoiceIn/back/locale/invoiceInTax/en.yml index 86a9e42c3..374f62e7d 100644 --- a/modules/invoiceIn/back/locale/invoiceInTax/en.yml +++ b/modules/invoiceIn/back/locale/invoiceInTax/en.yml @@ -1,12 +1,12 @@ name: invoice in tax colmns: - id: id - invoiceInFk: invoice in - taxCodeFk: tax - taxableBase: taxable base - expenceFk: expence - foreignValue: foreign amount - taxTypeSageFk: tax type - transactionTypeSageFk: transaction type - created: created - editorFk: editor + id: id + invoiceInFk: invoice in + taxCodeFk: tax + taxableBase: taxable base + expenceFk: expence + foreignValue: foreign amount + taxTypeSageFk: tax type + transactionTypeSageFk: transaction type + created: created + editorFk: editor diff --git a/modules/invoiceIn/back/locale/invoiceInTax/es.yml b/modules/invoiceIn/back/locale/invoiceInTax/es.yml index 233c591e9..b20663dd4 100644 --- a/modules/invoiceIn/back/locale/invoiceInTax/es.yml +++ b/modules/invoiceIn/back/locale/invoiceInTax/es.yml @@ -1,12 +1,12 @@ name: factura recibida impuesto colmns: - id: id - invoiceInFk: factura recibida - taxCodeFk: código IVA - taxableBase: base imponible - expenceFk: código gasto - foreignValue: importe divisa - taxTypeSageFk: código impuesto - transactionTypeSageFk: código transacción - created: creado - editorFk: editor \ No newline at end of file + id: id + invoiceInFk: factura recibida + taxCodeFk: código IVA + taxableBase: base imponible + expenceFk: código gasto + foreignValue: importe divisa + taxTypeSageFk: código impuesto + transactionTypeSageFk: código transacción + created: creado + editorFk: editor \ No newline at end of file From 136b401ede36eed3d0e3cc9025a429bf74d48ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Fri, 28 Jul 2023 14:17:50 +0200 Subject: [PATCH 110/130] refs #6077 espacios correctos --- .../invoiceIn/back/locale/invoiceIn/en.yml | 36 +++++++++---------- .../invoiceIn/back/locale/invoiceIn/es.yml | 36 +++++++++---------- .../back/locale/invoiceInDueDay/en.yml | 14 ++++---- .../back/locale/invoiceInDueDay/es.yml | 14 ++++---- .../invoiceIn/back/locale/invoiceInTax/en.yml | 22 ++++++------ .../invoiceIn/back/locale/invoiceInTax/es.yml | 22 ++++++------ 6 files changed, 72 insertions(+), 72 deletions(-) diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml index 5aa81b9ff..ec9a824b6 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/en.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml @@ -1,20 +1,20 @@ name: invoice in columns: - id: id - serialNumber: serial number - serial: serial - supplierFk: supplier - issued: issued - supplierRef: supplierRef - isBooked: is booked - currencyFk: currency - created: created - companyFk: company - docFk: document - booked: booked - operated: operated - bookEntried: book entried - isVatDeductible: is VAT deductible - withholdingSageFk: withholding - expenceFkDeductible: expence deductible - editorFk: editor \ No newline at end of file + id: id + serialNumber: serial number + serial: serial + supplierFk: supplier + issued: issued + supplierRef: supplierRef + isBooked: is booked + currencyFk: currency + created: created + companyFk: company + docFk: document + booked: booked + operated: operated + bookEntried: book entried + isVatDeductible: is VAT deductible + withholdingSageFk: withholding + expenceFkDeductible: expence deductible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml index 61f62f022..64e96b379 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/es.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml @@ -1,20 +1,20 @@ name: factura recibida columns: - id: id - serialNumber: número de serie - serial: serie - supplierFk: proveedor - issued: fecha emisión - supplierRef: referéncia proveedor - isBooked: facturado - currencyFk: moneda - created: creado - companyFk: empresa - docFk: documento - booked: fecha contabilización - operated: fecha entrega - bookEntried: fecha asiento - isVatDeductible: impuesto deducible - withholdingSageFk: código de retención - expenceFkDeductible: gasto deducible - editorFk: editor \ No newline at end of file + id: id + serialNumber: número de serie + serial: serie + supplierFk: proveedor + issued: fecha emisión + supplierRef: referéncia proveedor + isBooked: facturado + currencyFk: moneda + created: creado + companyFk: empresa + docFk: documento + booked: fecha contabilización + operated: fecha entrega + bookEntried: fecha asiento + isVatDeductible: impuesto deducible + withholdingSageFk: código de retención + expenceFkDeductible: gasto deducible + editorFk: editor \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml index f01a0de46..7a6c0dfaf 100644 --- a/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/en.yml @@ -1,9 +1,9 @@ name: invoice in due day columns: - id: id - invoiceInFk: invoice in - dueDated: due date - bankFk: bank - amount: amount - foreignValue : foreign amount - created: created + id: id + invoiceInFk: invoice in + dueDated: due date + bankFk: bank + amount: amount + foreignValue : foreign amount + created: created diff --git a/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml index 34b20b37d..993437b05 100644 --- a/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml +++ b/modules/invoiceIn/back/locale/invoiceInDueDay/es.yml @@ -1,9 +1,9 @@ name: vencimientos factura recibida columns: - id: id - invoiceInFk: factura - dueDated: fecha vto. - bankFk: banco - amount: importe - foreignValue : importe divisa - created: creado + id: id + invoiceInFk: factura + dueDated: fecha vto. + bankFk: banco + amount: importe + foreignValue : importe divisa + created: creado diff --git a/modules/invoiceIn/back/locale/invoiceInTax/en.yml b/modules/invoiceIn/back/locale/invoiceInTax/en.yml index 374f62e7d..c0d12c37d 100644 --- a/modules/invoiceIn/back/locale/invoiceInTax/en.yml +++ b/modules/invoiceIn/back/locale/invoiceInTax/en.yml @@ -1,12 +1,12 @@ name: invoice in tax -colmns: - id: id - invoiceInFk: invoice in - taxCodeFk: tax - taxableBase: taxable base - expenceFk: expence - foreignValue: foreign amount - taxTypeSageFk: tax type - transactionTypeSageFk: transaction type - created: created - editorFk: editor +columns: + id: id + invoiceInFk: invoice in + taxCodeFk: tax + taxableBase: taxable base + expenceFk: expence + foreignValue: foreign amount + taxTypeSageFk: tax type + transactionTypeSageFk: transaction type + created: created + editorFk: editor diff --git a/modules/invoiceIn/back/locale/invoiceInTax/es.yml b/modules/invoiceIn/back/locale/invoiceInTax/es.yml index b20663dd4..7cb847ed8 100644 --- a/modules/invoiceIn/back/locale/invoiceInTax/es.yml +++ b/modules/invoiceIn/back/locale/invoiceInTax/es.yml @@ -1,12 +1,12 @@ name: factura recibida impuesto -colmns: - id: id - invoiceInFk: factura recibida - taxCodeFk: código IVA - taxableBase: base imponible - expenceFk: código gasto - foreignValue: importe divisa - taxTypeSageFk: código impuesto - transactionTypeSageFk: código transacción - created: creado - editorFk: editor \ No newline at end of file +columns: + id: id + invoiceInFk: factura recibida + taxCodeFk: código IVA + taxableBase: base imponible + expenceFk: código gasto + foreignValue: importe divisa + taxTypeSageFk: código impuesto + transactionTypeSageFk: código transacción + created: creado + editorFk: editor \ No newline at end of file From e253dd79822b068849a43dc78f5167bfb15388a8 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 28 Jul 2023 14:39:01 +0200 Subject: [PATCH 111/130] refs #5351 fix(worker_model): remove required userFk --- modules/worker/back/models/worker.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 6d23c1b66..6e1371055 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -25,8 +25,7 @@ "type" : "string" }, "userFk": { - "type" : "number", - "required": true + "type" : "number" }, "bossFk": { "type" : "number" From 81dc163819fb45e288d004378f7f916cb7e7b5d1 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 28 Jul 2023 14:40:03 +0200 Subject: [PATCH 112/130] ya no muestra error en el front --- modules/worker/front/card/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/front/card/index.js b/modules/worker/front/card/index.js index 0bf9ae5c4..b8b533c5d 100644 --- a/modules/worker/front/card/index.js +++ b/modules/worker/front/card/index.js @@ -36,7 +36,7 @@ class Controller extends ModuleCard { this.$http.get(`Workers/${this.$params.id}`, {filter}) .then(res => this.worker = res.data), this.$http.get(`Workers/${this.$params.id}/activeContract`) - .then(res => this.hasWorkCenter = res.data.workCenterFk) + .then(res => this.hasWorkCenter = res.data?.workCenterFk) ]); } } From 40607a42cfc37606bf4496dc1d759d1e6d4757a3 Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 1 Aug 2023 10:25:44 +0200 Subject: [PATCH 113/130] hotfix-loadData --- .../front/department/descriptor/index.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/modules/worker/front/department/descriptor/index.js b/modules/worker/front/department/descriptor/index.js index 5ab1059d9..388a7f776 100644 --- a/modules/worker/front/department/descriptor/index.js +++ b/modules/worker/front/department/descriptor/index.js @@ -32,6 +32,28 @@ class Controller extends Descriptor { this.vnApp.showSuccess(this.$t('Department deleted.')); }); } + + loadData() { + const filter = { + fields: ['id', 'name', 'code', 'workerFk', 'isProduction', 'chatName', + 'isTeleworking', 'notificationEmail', 'hasToRefill', 'hasToSendMail', 'hasToMistake', 'clientFk'], + include: [ + {relation: 'client', + scope: { + fields: ['id', 'name'] + }}, + { + relation: 'worker', + scope: { + fields: ['id', 'firstName', 'lastName'] + } + } + ] + }; + + return this.getData(`Departments/${this.id}`, {filter}) + .then(res => this.entity = res.data); + } } Controller.$inject = ['$element', '$scope', '$rootScope']; From 30c5e8d8ccd638e57e85f35f55de8f16fe7c1103 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 1 Aug 2023 11:11:29 +0200 Subject: [PATCH 114/130] hotFix(canBeInvoiced): no de vuelve error si hay mas de un ticket y uno esta a 0 --- modules/ticket/back/methods/ticket/canBeInvoiced.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/canBeInvoiced.js b/modules/ticket/back/methods/ticket/canBeInvoiced.js index 0f6cb476b..348f02348 100644 --- a/modules/ticket/back/methods/ticket/canBeInvoiced.js +++ b/modules/ticket/back/methods/ticket/canBeInvoiced.js @@ -67,7 +67,7 @@ module.exports = function(Self) { throw new UserError(`This ticket is already invoiced`); const priceZero = ticket.totalWithVat == 0; - if (priceZero) + if (ticketsIds.length == 1 && priceZero) throw new UserError(`A ticket with an amount of zero can't be invoiced`); }); From 16353dfddc1fab62c3b3e16a7b1aa040af632486 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 2 Aug 2023 07:35:40 +0200 Subject: [PATCH 115/130] refs #5995 First commit --- modules/route/back/methods/route/cmr.js | 36 ++ modules/route/back/models/route.js | 1 + modules/ticket/back/methods/ticket/closure.js | 319 ++++++++++-------- .../reports/cmr/assets/css/import.js | 12 + .../reports/cmr/assets/css/style.css | 101 ++++++ .../reports/cmr/assets/images/signature.png | Bin 0 -> 27129 bytes print/templates/reports/cmr/cmr.html | 212 ++++++++++++ print/templates/reports/cmr/cmr.js | 38 +++ print/templates/reports/cmr/locale/es.yml | 1 + print/templates/reports/cmr/options.json | 3 + print/templates/reports/cmr/sql/data.sql | 49 +++ .../templates/reports/cmr/sql/merchandise.sql | 11 + .../templates/reports/cmr/sql/signatures.sql | 7 + 13 files changed, 646 insertions(+), 144 deletions(-) create mode 100644 modules/route/back/methods/route/cmr.js create mode 100644 print/templates/reports/cmr/assets/css/import.js create mode 100644 print/templates/reports/cmr/assets/css/style.css create mode 100644 print/templates/reports/cmr/assets/images/signature.png create mode 100644 print/templates/reports/cmr/cmr.html create mode 100644 print/templates/reports/cmr/cmr.js create mode 100644 print/templates/reports/cmr/locale/es.yml create mode 100644 print/templates/reports/cmr/options.json create mode 100644 print/templates/reports/cmr/sql/data.sql create mode 100644 print/templates/reports/cmr/sql/merchandise.sql create mode 100644 print/templates/reports/cmr/sql/signatures.sql diff --git a/modules/route/back/methods/route/cmr.js b/modules/route/back/methods/route/cmr.js new file mode 100644 index 000000000..cd7ef57ce --- /dev/null +++ b/modules/route/back/methods/route/cmr.js @@ -0,0 +1,36 @@ +module.exports = Self => { + Self.remoteMethodCtx('cmr', { + description: 'Returns the cmr', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The cmr id', + http: {source: 'path'} + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'String', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'String', + http: {target: 'header'} + } + ], + http: { + path: '/:id/cmr', + verb: 'GET' + } + }); + + Self.cmr = (ctx, id) => Self.printReport(ctx, id, 'cmr'); +}; diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 883f4597e..96e7ed04f 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -14,6 +14,7 @@ module.exports = Self => { require('../methods/route/driverRouteEmail')(Self); require('../methods/route/sendSms')(Self); require('../methods/route/downloadZip')(Self); + require('../methods/route/cmr')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js index eee5e28e2..493a2c3a0 100644 --- a/modules/ticket/back/methods/ticket/closure.js +++ b/modules/ticket/back/methods/ticket/closure.js @@ -5,177 +5,208 @@ const config = require('vn-print/core/config'); const storage = require('vn-print/core/storage'); module.exports = async function(ctx, Self, tickets, reqArgs = {}) { - const userId = ctx.req.accessToken.userId; - if (tickets.length == 0) return; + const userId = ctx.req.accessToken.userId; + if (tickets.length == 0) return; - const failedtickets = []; - for (const ticket of tickets) { - try { - await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId}); + const failedtickets = []; + for (const ticket of tickets) { + try { + await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId}); - const [invoiceOut] = await Self.rawSql(` - SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued - FROM ticket t - JOIN invoiceOut io ON io.ref = t.refFk - JOIN company cny ON cny.id = io.companyFk - WHERE t.id = ? - `, [ticket.id]); + const [invoiceOut] = await Self.rawSql(` + SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued + FROM ticket t + JOIN invoiceOut io ON io.ref = t.refFk + JOIN company cny ON cny.id = io.companyFk + WHERE t.id = ? + `, [ticket.id]); - const mailOptions = { - overrideAttachments: true, - attachments: [] - }; + const mailOptions = { + overrideAttachments: true, + attachments: [] + }; - const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; + const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; - if (invoiceOut) { - const args = { - reference: invoiceOut.ref, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + if (invoiceOut) { + const args = { + reference: invoiceOut.ref, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; - const invoiceReport = new Report('invoice', args); - const stream = await invoiceReport.toPdfStream(); + const invoiceReport = new Report('invoice', args); + const stream = await invoiceReport.toPdfStream(); - const issued = invoiceOut.issued; - const year = issued.getFullYear().toString(); - const month = (issued.getMonth() + 1).toString(); - const day = issued.getDate().toString(); + const issued = invoiceOut.issued; + const year = issued.getFullYear().toString(); + const month = (issued.getMonth() + 1).toString(); + const day = issued.getDate().toString(); - const fileName = `${year}${invoiceOut.ref}.pdf`; + const fileName = `${year}${invoiceOut.ref}.pdf`; - // Store invoice - await storage.write(stream, { - type: 'invoice', - path: `${year}/${month}/${day}`, - fileName: fileName - }); + // Store invoice + await storage.write(stream, { + type: 'invoice', + path: `${year}/${month}/${day}`, + fileName: fileName + }); - await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId}); + await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId}); - if (isToBeMailed) { - const invoiceAttachment = { - filename: fileName, - content: stream - }; + if (isToBeMailed) { + const invoiceAttachment = { + filename: fileName, + content: stream + }; - if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { - const exportation = new Report('exportation', args); - const stream = await exportation.toPdfStream(); - const fileName = `CITES-${invoiceOut.ref}.pdf`; + if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { + const exportation = new Report('exportation', args); + const stream = await exportation.toPdfStream(); + const fileName = `CITES-${invoiceOut.ref}.pdf`; - mailOptions.attachments.push({ - filename: fileName, - content: stream - }); - } + mailOptions.attachments.push({ + filename: fileName, + content: stream + }); + } - mailOptions.attachments.push(invoiceAttachment); + mailOptions.attachments.push(invoiceAttachment); - const email = new Email('invoice', args); - await email.send(mailOptions); - } - } else if (isToBeMailed) { - const args = { - id: ticket.id, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + const email = new Email('invoice', args); + await email.send(mailOptions); + } + } else if (isToBeMailed) { + const args = { + id: ticket.id, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; - const email = new Email('delivery-note-link', args); - await email.send(); - } + const email = new Email('delivery-note-link', args); + await email.send(); + } - // Incoterms authorization - const [{firstOrder}] = await Self.rawSql(` - SELECT COUNT(*) as firstOrder - FROM ticket t - JOIN client c ON c.id = t.clientFk - WHERE t.clientFk = ? - AND NOT t.isDeleted - AND c.isVies - `, [ticket.clientFk]); + // Incoterms authorization + const [{firstOrder}] = await Self.rawSql(` + SELECT COUNT(*) as firstOrder + FROM ticket t + JOIN client c ON c.id = t.clientFk + WHERE t.clientFk = ? + AND NOT t.isDeleted + AND c.isVies + `, [ticket.clientFk]); - if (firstOrder == 1) { - const args = { - id: ticket.clientFk, - companyId: ticket.companyFk, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + if (firstOrder == 1) { + const args = { + id: ticket.clientFk, + companyId: ticket.companyFk, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; - const email = new Email('incoterms-authorization', args); - await email.send(); + const email = new Email('incoterms-authorization', args); + await email.send(); - const [sample] = await Self.rawSql( - `SELECT id - FROM sample - WHERE code = 'incoterms-authorization' - `); + const [sample] = await Self.rawSql( + `SELECT id + FROM sample + WHERE code = 'incoterms-authorization' + `); - await Self.rawSql(` - INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) - `, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); - } - } catch (error) { - // Domain not found - if (error.responseCode == 450) - return invalidEmail(ticket); + await Self.rawSql(` + INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) + `, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); + } - // Save tickets on a list of failed ids - failedtickets.push({ - id: ticket.id, - stacktrace: error - }); - } - } + await Self.rawSql(` + INSERT INTO cmr (ticketFk, companyFk, addressToFk, addressFromFk, supplierFk, ead) + SELECT t.id, + com.id, + a.id, + c2.defaultAddressFk, + su.id, + t.landed + FROM ticket t + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state s ON s.id = ts.stateFk + JOIN alertLevel al ON al.id = s.alertLevel + JOIN client c ON c.id = t.clientFk + JOIN address a ON a.id = t.addressFk + JOIN province p ON p.id = a.provinceFk + JOIN country co ON co.id = p.countryFk + JOIN agencyMode am ON am.id = t.agencyModeFk + JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk + JOIN warehouse w ON w.id = t.warehouseFk + JOIN company com ON com.id = t.companyFk + JOIN client c2 ON c2.id = com.clientFk + JOIN supplierAccount sa ON sa.id = com.supplierAccountFk + JOIN supplier su ON su.id = sa.supplierFk + WHERE shipped BETWEEN util.yesterday() AND util.dayEnd(util.yesterday()) + AND al.code IN ('PACKED', 'DELIVERED') + AND co.code <> 'ES' + AND am.name <> 'ABONO' + AND w.code = 'ALG' + AND dm.code = 'DELIVERY' + `); + } catch (error) { + // Domain not found + if (error.responseCode == 450) + return invalidEmail(ticket); - // Send email with failed tickets - if (failedtickets.length > 0) { - let body = 'This following tickets have failed:

'; + // Save tickets on a list of failed ids + failedtickets.push({ + id: ticket.id, + stacktrace: error + }); + } + } - for (const ticket of failedtickets) { - body += `Ticket: ${ticket.id} -
${ticket.stacktrace}

`; - } + // Send email with failed tickets + if (failedtickets.length > 0) { + let body = 'This following tickets have failed:

'; - smtp.send({ - to: config.app.reportEmail, - subject: '[API] Nightly ticket closure report', - html: body - }); - } + for (const ticket of failedtickets) { + body += `Ticket: ${ticket.id} +
${ticket.stacktrace}

`; + } - async function invalidEmail(ticket) { - await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ - ticket.clientFk - ], {userId}); + smtp.send({ + to: config.app.reportEmail, + subject: '[API] Nightly ticket closure report', + html: body + }); + } - const oldInstance = `{"email": "${ticket.recipient}"}`; - const newInstance = `{"email": ""}`; - await Self.rawSql(` - INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) - VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ - ticket.clientFk, - oldInstance, - newInstance - ], {userId}); + async function invalidEmail(ticket) { + await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ + ticket.clientFk + ], {userId}); - const body = `No se ha podido enviar el albarán ${ticket.id} - al cliente ${ticket.clientFk} - ${ticket.clientName} - porque la dirección de email "${ticket.recipient}" no es correcta - o no está disponible.

- Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. - Actualiza la dirección de email con una correcta.`; + const oldInstance = `{"email": "${ticket.recipient}"}`; + const newInstance = `{"email": ""}`; + await Self.rawSql(` + INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) + VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ + ticket.clientFk, + oldInstance, + newInstance + ], {userId}); - smtp.send({ - to: ticket.salesPersonEmail, - subject: 'No se ha podido enviar el albarán', - html: body - }); - } + const body = `No se ha podido enviar el albarán ${ticket.id} + al cliente ${ticket.clientFk} - ${ticket.clientName} + porque la dirección de email "${ticket.recipient}" no es correcta + o no está disponible.

+ Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. + Actualiza la dirección de email con una correcta.`; + + smtp.send({ + to: ticket.salesPersonEmail, + subject: 'No se ha podido enviar el albarán', + html: body + }); + } }; diff --git a/print/templates/reports/cmr/assets/css/import.js b/print/templates/reports/cmr/assets/css/import.js new file mode 100644 index 000000000..37a98dfdd --- /dev/null +++ b/print/templates/reports/cmr/assets/css/import.js @@ -0,0 +1,12 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/report.css`, + `${__dirname}/style.css`]) + .mergeStyles(); diff --git a/print/templates/reports/cmr/assets/css/style.css b/print/templates/reports/cmr/assets/css/style.css new file mode 100644 index 000000000..201afc3b6 --- /dev/null +++ b/print/templates/reports/cmr/assets/css/style.css @@ -0,0 +1,101 @@ +html { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + margin: 10px; + font-size: 22px; +} +.mainTable, .specialTable, .categoryTable { + width: 100%; + border-collapse: collapse; + font-size: inherit; +} +.mainTable td { + width: 50%; + border: 1px solid black; + vertical-align: top; + padding: 15px; + font-size: inherit; +} +.signTable { + height: 12%; +} +.signTable td { + width: calc(100% / 3); + border: 1px solid black; + vertical-align: top; + font-size: inherit; + padding: 15px; + border-top: none; +} +#title { + font-weight: bold; + font-size: 85px; +} +hr { + border: 1px solid #cccccc; + height: 0px; + border-radius: 25px; +} +#cellHeader { + border: 0px; + text-align: center; + vertical-align: middle; +} +#label, #merchandiseLabels { + font-size: 13px; +} +#merchandiseLabels { + border: none; +} +.imgSection { + text-align: center; + height: 200px; + overflow: hidden; +} +img { + object-fit: contain; + width: 100%; + height: 100%; +} +#lineBreak { + white-space: pre-line; +} +.specialTable td { + border: 1px solid black; + vertical-align: top; + padding: 15px; + font-size: inherit; + border-top: none; + border-bottom: none; +} +.specialTable #itemCategoryList { + width: 70%; + padding-top: 10px; +} +.categoryTable { + padding-bottom: none; +} +.categoryTable td { + vertical-align: top; + font-size: inherit; + border: none; + padding: 5px; + overflow: hidden; +} +.categoryTable #merchandiseLabels { + border-bottom: 4px solid #cccccc; + padding: none; +} +#merchandiseDetail { + font-weight: bold; + padding-top: 10px; +} +#merchandiseData { + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +#merchandiseLabels td { + padding-bottom: 11px; + max-width: 300px; +} \ No newline at end of file diff --git a/print/templates/reports/cmr/assets/images/signature.png b/print/templates/reports/cmr/assets/images/signature.png new file mode 100644 index 0000000000000000000000000000000000000000..0961df764f5e038b0c61620b60ba0c601d41ae93 GIT binary patch literal 27129 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 + + + + + + + + + + + + + + + + + + + + + + + +
+ 1. Remitente / Expediteur / Sender +
+ {{data.senderName}}
+ {{data.senderStreet}}
+ {{data.senderPostCode}} {{data.senderCity}} {{(data.senderCountry) ? `(${data.senderCountry})` : null}} +
+ CMR
+ {{data.cmrFk}} +
+ 2. Consignatario / Destinataire / Consignee +
+ {{data.deliveryAddressFk}}
+ {{data.deliveryName}}
+ {{data.deliveryPhone || data.clientPhone}} + {{((data.deliveryPhone || data.clientPhone) && data.deliveryMobile) ? '/' : null}} + {{data.deliveryMobile}}
+
+ 16. Transportista / Transporteur / Carrier +
+ {{data.carrierName}}
+ {{data.carrierStreet}}
+ {{data.carrierPostalCode}} {{data.carrierCity}} {{(data.carrierCountry) ? `(${data.carrierCountry})` : null}} +
+ + 3. Lugar y fecha de entrega / + Lieu et date de livraison / + Place and date of delivery + +
+ {{data.deliveryStreet}}
+ {{data.deliveryPostalCode}} {{data.deliveryCity}} {{(data.deliveryCountry) ? `(${data.deliveryCountry})` : null}}
+ {{(data.ead) ? formatDate(data.ead, '%d/%m/%Y') : null}}
+ +
+ 17. Porteadores sucesivos / Transporteurs succesifs / Succesive Carriers +
+
+ + 4. Lugar y fecha de carga / + Lieu et date del prise en charge de la merchandise / + Place and date of taking over the goods + +
+ {{data.loadStreet}}
+ {{data.loadPostalCode}} {{data.loadCity}} {{(data.loadCountry) ? `(${data.loadCountry})` : null}}
+ {{formatDate(data.created, '%d/%m/%Y')}}
+
+ + 18. Obervaciones del transportista / + Reserves et observations du transporteur / + Carrier's reservations and observations + +
+ {{data.truckPlate}}
+ {{data.observations}} +
+ 5. Documentos anexos / Documents annexes / Documents attached +
+
+ + + + + +
+ + 7 & 8. Número de bultos y clase de embalage / + Number of packages and packaging class / + Nombre de colis et classe d'emballage + +
+
+ {{data.packagesList}} +
+
+ + + + + + + + + + + + + + + +
6. Marcas y números / Brands and numbers / Marques et numéros9. Naturaleza de la merc. / Nature of goods / Nature des marchandises10. nº Estadístico / Statistical no. / n° statistique11. Peso bruto / Gross weight / Poids brut (kg)12. Volumen / Volume (m3)
{{merchandise.ticketFk}}{{merchandise.name}}N/A{{merchandise.weight}}{{merchandise.volume}}
+
+ {{data.merchandiseDetail}} +
+
+ + + + + + + + + + + + + +
+ + 13. Instrucciones del remitente / + Instrunstions de l'expèditeur / Sender + instruccions + +
+ {{data.senderInstruccions}} +
+ + 19. Estipulaciones particulares / + Conventions particulieres / + Special agreements + +
+ {{data.specialAgreements}} +
+ + 14. Forma de pago / + Prescriptions d'affranchissement / + Instruction as to payment for carriage + +
+ {{data.paymentInstruccions}} +
+ 20. A pagar por / Être payé pour / To be paid by +
+
+ 21. Formalizado en / Etabile a / Estabilshed in +
+ {{data.loadStreet}}
+ {{data.loadPostalCode}} {{data.loadCity}} {{(data.loadCountry) ? `(${data.loadCountry})` : null}}
+
+ 15. Reembolso / Remboursement / Cash on delivery +
+
+ + + + + + + + + +
+ + 22. Firma y sello del remitente / + Signature et timbre de l'expèditeur / + Signature and stamp of the sender + +
+
+ +
+
+ + 23. Firma y sello del transportista / + Signature et timbre du transporteur / + Signature and stamp of the carrier + +
+
+ +
+
+ + 24. Firma y sello del consignatario / + Signature et timbre du destinataire / + Signature and stamp of the consignee + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/print/templates/reports/cmr/cmr.js b/print/templates/reports/cmr/cmr.js new file mode 100644 index 000000000..cfb3dd360 --- /dev/null +++ b/print/templates/reports/cmr/cmr.js @@ -0,0 +1,38 @@ +const config = require(`vn-print/core/config`); +const vnReport = require('../../../core/mixins/vn-report.js'); +const md5 = require('md5'); +const fs = require('fs-extra'); + +module.exports = { + name: 'cmr', + mixins: [vnReport], + async serverPrefetch() { + this.data = await this.findOneFromDef('data', [this.id]); + if (this.data.ticketFk) { + this.merchandises = await this.rawSqlFromDef('merchandise', [this.data.ticketFk]); + this.signatures = await this.findOneFromDef('signatures', [this.data.ticketFk]); + } + }, + props: { + id: { + type: Number, + required: true, + description: 'The cmr id' + }, + }, + methods: { + dmsPath(isClient) { + if (!this.signatures) return; + + const signatureName = (isClient) + ? this.signatures.clientSignature + : this.signatures.deliverySignature; + const hash = md5(signatureName.toString()).substring(0, 3); + const file = `${config.storage.root}/${hash}/${signatureName}.png`; + + if (!fs.existsSync(file)) return null; + + return `data:image/png;base64, ${Buffer.from(fs.readFileSync(file), 'utf8').toString('base64')}`; + } + } +}; \ No newline at end of file diff --git a/print/templates/reports/cmr/locale/es.yml b/print/templates/reports/cmr/locale/es.yml new file mode 100644 index 000000000..79f481b35 --- /dev/null +++ b/print/templates/reports/cmr/locale/es.yml @@ -0,0 +1 @@ +reportName: cmr \ No newline at end of file diff --git a/print/templates/reports/cmr/options.json b/print/templates/reports/cmr/options.json new file mode 100644 index 000000000..9151ca63b --- /dev/null +++ b/print/templates/reports/cmr/options.json @@ -0,0 +1,3 @@ +{ + "format": "A4" +} \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/data.sql b/print/templates/reports/cmr/sql/data.sql new file mode 100644 index 000000000..e66ab7154 --- /dev/null +++ b/print/templates/reports/cmr/sql/data.sql @@ -0,0 +1,49 @@ +SELECT c.id cmrFk, + c.ticketFk, + c.truckPlate, + c.observations, + c.senderInstruccions, + c.paymentInstruccions, + c.specialAgreements, + c.created, + c.packagesList, + c.merchandiseDetail, + c.ead, + s.name carrierName, + s.street carrierStreet, + s.postCode carrierPostCode, + s.city carrierCity, + cou.country carrierCountry, + s2.name senderName, + s2.street senderStreet, + s2.postCode senderPostCode, + s2.city senderCity, + cou2.country senderCountry, + a.street deliveryStreet, + a.id deliveryAddressFk, + a.postalCode deliveryPostalCode, + a.city deliveryCity, + a.nickname deliveryName, + a.phone deliveryPhone, + a.mobile deliveryMobile, + cou3.country deliveryCountry, + cl.phone clientPhone, + a2.street loadStreet, + a2.postalCode loadPostalCode, + a2.city loadCity, + cou4.country loadCountry + FROM cmr c + LEFT JOIN supplier s ON s.id = c.supplierFk + LEFT JOIN country cou ON cou.id = s.countryFk + LEFT JOIN company co ON co.id = c.companyFk + LEFT JOIN supplierAccount sa ON sa.id = co.supplierAccountFk + LEFT JOIN supplier s2 ON s2.id = sa.supplierFk + LEFT JOIN country cou2 ON cou2.id = s2.countryFk + LEFT JOIN `address` a ON a.id = c.addressToFk + LEFT JOIN province p ON p.id = a.provinceFk + LEFT JOIN country cou3 ON cou3.id = p.countryFk + LEFT JOIN client cl ON cl.id = a.clientFk + LEFT JOIN `address` a2 ON a2.id = c.addressFromFk + LEFT JOIN province p2 ON p2.id = a2.provinceFk + LEFT JOIN country cou4 ON cou4.id = p2.countryFk + WHERE c.id = ? \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/merchandise.sql b/print/templates/reports/cmr/sql/merchandise.sql new file mode 100644 index 000000000..cab597caa --- /dev/null +++ b/print/templates/reports/cmr/sql/merchandise.sql @@ -0,0 +1,11 @@ +SELECT s.ticketFk, + ic.name, + CAST(SUM(sv.weight) AS DECIMAL(10,2)) `weight`, + CAST(SUM(sv.volume) AS DECIMAL(10,3)) volume + FROM sale s + JOIN saleVolume sv ON sv.saleFk = s.id + JOIN item i ON i.id = s.itemFk + JOIN itemType it ON it.id = i.typeFk + JOIN itemCategory ic ON ic.id = it.categoryFk + WHERE sv.ticketFk = ? + GROUP BY ic.id \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/signatures.sql b/print/templates/reports/cmr/sql/signatures.sql new file mode 100644 index 000000000..c90d4c91c --- /dev/null +++ b/print/templates/reports/cmr/sql/signatures.sql @@ -0,0 +1,7 @@ +SELECT dc.id clientSignature, dd.id deliverySignature + FROM ticket t + JOIN ticketDms dt ON dt.ticketFk = t.id + LEFT JOIN dms dc ON dc.id = dt.dmsFk + JOIN `route` r ON r.id = t.routeFk + LEFT JOIN dms dd ON dd.id = r.deliverySignFk + WHERE t.id = ? \ No newline at end of file From 84624935d6d2c08155ba6baa324b74d8787e2a9f Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 2 Aug 2023 09:09:50 +0200 Subject: [PATCH 116/130] refs #5995 Load blob --- .../reports/cmr/assets/images/signature.png | Bin 27129 -> 0 bytes print/templates/reports/cmr/cmr.html | 6 ++--- print/templates/reports/cmr/cmr.js | 22 ++++++++++-------- print/templates/reports/cmr/sql/data.sql | 3 ++- print/templates/reports/cmr/sql/signature.sql | 5 ++++ .../templates/reports/cmr/sql/signatures.sql | 7 ------ 6 files changed, 22 insertions(+), 21 deletions(-) delete mode 100644 print/templates/reports/cmr/assets/images/signature.png create mode 100644 print/templates/reports/cmr/sql/signature.sql delete mode 100644 print/templates/reports/cmr/sql/signatures.sql diff --git a/print/templates/reports/cmr/assets/images/signature.png b/print/templates/reports/cmr/assets/images/signature.png deleted file mode 100644 index 0961df764f5e038b0c61620b60ba0c601d41ae93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27129 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
- +
@@ -191,7 +191,7 @@
- + Aquí va la el stamp
@@ -202,7 +202,7 @@
- +
diff --git a/print/templates/reports/cmr/cmr.js b/print/templates/reports/cmr/cmr.js index cfb3dd360..ea9dc2a70 100644 --- a/print/templates/reports/cmr/cmr.js +++ b/print/templates/reports/cmr/cmr.js @@ -10,8 +10,9 @@ module.exports = { this.data = await this.findOneFromDef('data', [this.id]); if (this.data.ticketFk) { this.merchandises = await this.rawSqlFromDef('merchandise', [this.data.ticketFk]); - this.signatures = await this.findOneFromDef('signatures', [this.data.ticketFk]); - } + this.signature = await this.findOneFromDef('signature', [this.data.ticketFk]); + } else + this.merchandises = null; }, props: { id: { @@ -20,19 +21,20 @@ module.exports = { description: 'The cmr id' }, }, - methods: { - dmsPath(isClient) { - if (!this.signatures) return; + computed: { + signPath() { + if (!this.signature) return; - const signatureName = (isClient) - ? this.signatures.clientSignature - : this.signatures.deliverySignature; + const signatureName = this.signature.signature const hash = md5(signatureName.toString()).substring(0, 3); const file = `${config.storage.root}/${hash}/${signatureName}.png`; - if (!fs.existsSync(file)) return null; return `data:image/png;base64, ${Buffer.from(fs.readFileSync(file), 'utf8').toString('base64')}`; + }, + async getStamp() { + const data = this.data.stamp.toString('base64'); + return `data:image/png;base64, ${data}`; } - } + }, }; \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/data.sql b/print/templates/reports/cmr/sql/data.sql index e66ab7154..41ebee4bb 100644 --- a/print/templates/reports/cmr/sql/data.sql +++ b/print/templates/reports/cmr/sql/data.sql @@ -31,7 +31,8 @@ SELECT c.id cmrFk, a2.street loadStreet, a2.postalCode loadPostalCode, a2.city loadCity, - cou4.country loadCountry + cou4.country loadCountry, + co.stamp FROM cmr c LEFT JOIN supplier s ON s.id = c.supplierFk LEFT JOIN country cou ON cou.id = s.countryFk diff --git a/print/templates/reports/cmr/sql/signature.sql b/print/templates/reports/cmr/sql/signature.sql new file mode 100644 index 000000000..7ec7380a5 --- /dev/null +++ b/print/templates/reports/cmr/sql/signature.sql @@ -0,0 +1,5 @@ +SELECT dc.id `signature` + FROM ticket t + JOIN ticketDms dt ON dt.ticketFk = t.id + LEFT JOIN dms dc ON dc.id = dt.dmsFk + WHERE t.id = ? \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/signatures.sql b/print/templates/reports/cmr/sql/signatures.sql deleted file mode 100644 index c90d4c91c..000000000 --- a/print/templates/reports/cmr/sql/signatures.sql +++ /dev/null @@ -1,7 +0,0 @@ -SELECT dc.id clientSignature, dd.id deliverySignature - FROM ticket t - JOIN ticketDms dt ON dt.ticketFk = t.id - LEFT JOIN dms dc ON dc.id = dt.dmsFk - JOIN `route` r ON r.id = t.routeFk - LEFT JOIN dms dd ON dd.id = r.deliverySignFk - WHERE t.id = ? \ No newline at end of file From 56cd94feaa8d0261054d4600761f0243d4b46025 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 2 Aug 2023 13:26:42 +0200 Subject: [PATCH 117/130] refs #5843 fix(timeControl_filter): not use userFk --- modules/worker/back/methods/worker-time-control/filter.js | 4 ++-- modules/worker/front/time-control/index.html | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/filter.js b/modules/worker/back/methods/worker-time-control/filter.js index 041c6cbfb..6d0880253 100644 --- a/modules/worker/back/methods/worker-time-control/filter.js +++ b/modules/worker/back/methods/worker-time-control/filter.js @@ -36,9 +36,9 @@ module.exports = Self => { if (isSubordinate === false) throw new UserError(`You don't have enough privileges`); - const subordinate = await Worker.findById(ctx.args.workerFk); + const subordinate = await Worker.findById(ctx.args.workerFk, {fields: ['id']}); filter = mergeFilters(filter, {where: { - userFk: subordinate.userFk + userFk: subordinate.id }}); return Self.find(filter); diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 760b0dafc..b77acbddc 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -4,7 +4,7 @@ filter="::$ctrl.filter" data="$ctrl.hours"> -
+
@@ -106,12 +106,6 @@
-
- Autonomous worker -
From 4a0b8f37cd02b23637cc9eebb255e949196633ab Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 2 Aug 2023 13:41:44 +0200 Subject: [PATCH 118/130] refs #5995 Load blob --- modules/route/back/models/route.js | 2 +- print/templates/reports/cmr/cmr.html | 4 ++-- print/templates/reports/cmr/cmr.js | 17 +++++++++++------ print/templates/reports/cmr/sql/data.sql | 3 ++- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 96e7ed04f..a8d44cd05 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -29,5 +29,5 @@ module.exports = Self => { const routeMaxKm = 1000; if (routeTotalKm > routeMaxKm || this.kmStart > this.kmEnd) err(); - } + }; }; diff --git a/print/templates/reports/cmr/cmr.html b/print/templates/reports/cmr/cmr.html index b403cc6d8..ba0f8bfab 100644 --- a/print/templates/reports/cmr/cmr.html +++ b/print/templates/reports/cmr/cmr.html @@ -180,7 +180,7 @@
- +
@@ -191,7 +191,7 @@
- Aquí va la el stamp +
diff --git a/print/templates/reports/cmr/cmr.js b/print/templates/reports/cmr/cmr.js index ea9dc2a70..c939e5152 100644 --- a/print/templates/reports/cmr/cmr.js +++ b/print/templates/reports/cmr/cmr.js @@ -3,6 +3,8 @@ const vnReport = require('../../../core/mixins/vn-report.js'); const md5 = require('md5'); const fs = require('fs-extra'); +const prefixBase64 = 'data:image/png;base64,'; + module.exports = { name: 'cmr', mixins: [vnReport], @@ -13,6 +15,13 @@ module.exports = { this.signature = await this.findOneFromDef('signature', [this.data.ticketFk]); } else this.merchandises = null; + + this.senderStamp = (this.data.senderStamp) + ? `${prefixBase64} ${this.data.senderStamp.toString('base64')}` + : null; + this.deliveryStamp = (this.data.deliveryStamp) + ? `${prefixBase64} ${this.data.deliveryStamp.toString('base64')}` + : null; }, props: { id: { @@ -30,11 +39,7 @@ module.exports = { const file = `${config.storage.root}/${hash}/${signatureName}.png`; if (!fs.existsSync(file)) return null; - return `data:image/png;base64, ${Buffer.from(fs.readFileSync(file), 'utf8').toString('base64')}`; + return `${prefixBase64} ${Buffer.from(fs.readFileSync(file), 'utf8').toString('base64')}`; }, - async getStamp() { - const data = this.data.stamp.toString('base64'); - return `data:image/png;base64, ${data}`; - } - }, + } }; \ No newline at end of file diff --git a/print/templates/reports/cmr/sql/data.sql b/print/templates/reports/cmr/sql/data.sql index 41ebee4bb..d7c585f22 100644 --- a/print/templates/reports/cmr/sql/data.sql +++ b/print/templates/reports/cmr/sql/data.sql @@ -32,7 +32,8 @@ SELECT c.id cmrFk, a2.postalCode loadPostalCode, a2.city loadCity, cou4.country loadCountry, - co.stamp + co.stamp senderStamp, + s.stamp deliveryStamp FROM cmr c LEFT JOIN supplier s ON s.id = c.supplierFk LEFT JOIN country cou ON cou.id = s.countryFk From 29fe1c0c84f59ce37b81759d4e123a5ee860ff1c Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 2 Aug 2023 13:55:01 +0200 Subject: [PATCH 119/130] refs #5325 displaySearch return if not has search row --- front/core/components/smart-table/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index c3b927c62..63a9f6488 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -339,8 +339,9 @@ export default class SmartTable extends Component { if (!header) return; const tbody = this.element.querySelector('tbody'); - const columns = header.querySelectorAll('th'); + if (!tbody) return; + const columns = header.querySelectorAll('th'); const hasSearchRow = tbody.querySelector('tr#searchRow'); if (hasSearchRow) { if (this.$inputsScope) From 3d200ed64b8bdbf12a6da6f1d977bacfc3e9e5ab Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 2 Aug 2023 13:59:56 +0200 Subject: [PATCH 120/130] changeLog correct version --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de66fe928..2f935f786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2330.01] - 2023-07-27 +## [2332.01] - 2023-08-09 ### Added From aab0771e6ed5fe2e8393bf1b91ad0c4fcf8e4eb0 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 2 Aug 2023 14:37:38 +0200 Subject: [PATCH 121/130] refs #5995 Removed my code in closure.js --- modules/ticket/back/methods/ticket/closure.js | 33 +------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js index 493a2c3a0..9f9aec9bd 100644 --- a/modules/ticket/back/methods/ticket/closure.js +++ b/modules/ticket/back/methods/ticket/closure.js @@ -120,38 +120,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) { await Self.rawSql(` INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) `, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); - } - - await Self.rawSql(` - INSERT INTO cmr (ticketFk, companyFk, addressToFk, addressFromFk, supplierFk, ead) - SELECT t.id, - com.id, - a.id, - c2.defaultAddressFk, - su.id, - t.landed - FROM ticket t - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN state s ON s.id = ts.stateFk - JOIN alertLevel al ON al.id = s.alertLevel - JOIN client c ON c.id = t.clientFk - JOIN address a ON a.id = t.addressFk - JOIN province p ON p.id = a.provinceFk - JOIN country co ON co.id = p.countryFk - JOIN agencyMode am ON am.id = t.agencyModeFk - JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk - JOIN warehouse w ON w.id = t.warehouseFk - JOIN company com ON com.id = t.companyFk - JOIN client c2 ON c2.id = com.clientFk - JOIN supplierAccount sa ON sa.id = com.supplierAccountFk - JOIN supplier su ON su.id = sa.supplierFk - WHERE shipped BETWEEN util.yesterday() AND util.dayEnd(util.yesterday()) - AND al.code IN ('PACKED', 'DELIVERED') - AND co.code <> 'ES' - AND am.name <> 'ABONO' - AND w.code = 'ALG' - AND dm.code = 'DELIVERY' - `); + }; } catch (error) { // Domain not found if (error.responseCode == 450) From 688a72ddb300f0fb2c8be3d9b944da29173674f9 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 3 Aug 2023 08:39:37 +0200 Subject: [PATCH 122/130] refs #5995 Modify sql --- print/templates/reports/cmr/cmr.html | 2 +- print/templates/reports/cmr/sql/data.sql | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/print/templates/reports/cmr/cmr.html b/print/templates/reports/cmr/cmr.html index ba0f8bfab..c6a9e79d6 100644 --- a/print/templates/reports/cmr/cmr.html +++ b/print/templates/reports/cmr/cmr.html @@ -202,7 +202,7 @@
- +
diff --git a/print/templates/reports/cmr/sql/data.sql b/print/templates/reports/cmr/sql/data.sql index d7c585f22..9708c4483 100644 --- a/print/templates/reports/cmr/sql/data.sql +++ b/print/templates/reports/cmr/sql/data.sql @@ -1,5 +1,5 @@ SELECT c.id cmrFk, - c.ticketFk, + t.id ticketFk, c.truckPlate, c.observations, c.senderInstruccions, @@ -48,4 +48,5 @@ SELECT c.id cmrFk, LEFT JOIN `address` a2 ON a2.id = c.addressFromFk LEFT JOIN province p2 ON p2.id = a2.provinceFk LEFT JOIN country cou4 ON cou4.id = p2.countryFk + LEFT JOIN ticket t ON t.cmrFk = c.id WHERE c.id = ? \ No newline at end of file From ca34065e899257be75c14ede0b25b7c260529c92 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 3 Aug 2023 09:17:32 +0200 Subject: [PATCH 123/130] refs #6093 deploy(2332): dev to test --- CHANGELOG.md | 4 ++++ db/changes/{232601 => 233201}/00-acl_viaexpressConfig.sql | 0 db/changes/{232601 => 233201}/00-viaexpress.sql | 0 3 files changed, 4 insertions(+) rename db/changes/{232601 => 233201}/00-acl_viaexpressConfig.sql (100%) rename db/changes/{232601 => 233201}/00-viaexpress.sql (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f935f786..73520a6db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2332.01] - 2023-08-09 ### Added +- (Trabajadores -> Gestión documental) Soporte para Docuware +- (General -> Agencia) Soporte para Viaexpress ### Changed +- (General -> Tickets) Devuelve el motivo por el cual no es editable +- (Desplegables -> Trabajadores) Mejorados ### Fixed diff --git a/db/changes/232601/00-acl_viaexpressConfig.sql b/db/changes/233201/00-acl_viaexpressConfig.sql similarity index 100% rename from db/changes/232601/00-acl_viaexpressConfig.sql rename to db/changes/233201/00-acl_viaexpressConfig.sql diff --git a/db/changes/232601/00-viaexpress.sql b/db/changes/233201/00-viaexpress.sql similarity index 100% rename from db/changes/232601/00-viaexpress.sql rename to db/changes/233201/00-viaexpress.sql From 4628450240c99ddbafa958b232e14c6791ca80ec Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 3 Aug 2023 09:20:03 +0200 Subject: [PATCH 124/130] refs #6093 deploy: 2334 init version --- CHANGELOG.md | 9 +++++++++ db/changes/233401/.gitkeep | 0 package-lock.json | 2 +- package.json | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 db/changes/233401/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 73520a6db..80d8517de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2334.01] - 2023-08-24 + +### Added + +### Changed + +### Fixed + + ## [2332.01] - 2023-08-09 ### Added diff --git a/db/changes/233401/.gitkeep b/db/changes/233401/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package-lock.json b/package-lock.json index 5506075b9..f87e3f64b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.32.01", + "version": "23.34.01", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 37e39d5a5..2aa37379e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.32.01", + "version": "23.34.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", From 9b114796756bc2509e17337105dbb7931a2d1c82 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 3 Aug 2023 10:10:53 +0200 Subject: [PATCH 125/130] refs #5640 traducciones --- loopback/locale/es.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 784ff5e6e..7be7e3c34 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -305,5 +305,14 @@ "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Valid priorities": "Prioridades válidas: %d", "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", - "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado" + "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", + "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", + "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", + "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", + "You don't have enough privileges.": "No tienes suficientes permisos.", + "This ticket is locked.": "Este ticket está bloqueado.", + "This ticket is not editable.": "Este ticket no es editable.", + "The ticket doesn't exist.": "No existe el ticket.", + "Social name should be uppercase": "La razón social debe ir en mayuscula", + "Street should be uppercase": "La dirección fiscal debe ir en mayúscula" } From b85023b46d0f5fae9cf09eb41f371c0784092ce8 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 3 Aug 2023 10:11:17 +0200 Subject: [PATCH 126/130] accent --- loopback/locale/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 7be7e3c34..b69eb1574 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -313,6 +313,6 @@ "This ticket is locked.": "Este ticket está bloqueado.", "This ticket is not editable.": "Este ticket no es editable.", "The ticket doesn't exist.": "No existe el ticket.", - "Social name should be uppercase": "La razón social debe ir en mayuscula", + "Social name should be uppercase": "La razón social debe ir en mayúscula", "Street should be uppercase": "La dirección fiscal debe ir en mayúscula" } From 3388fd7c59249a08635bac6268352e17417a9557 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 3 Aug 2023 10:26:29 +0200 Subject: [PATCH 127/130] fix test back --- modules/worker/back/methods/worker/specs/new.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js index 4dc6c5540..d0830b00f 100644 --- a/modules/worker/back/methods/worker/specs/new.spec.js +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -21,8 +21,8 @@ describe('Worker new', () => { const defaultWorker = { fi: '78457139E', name: 'DEFAULTERWORKER', - firstName: 'default', - lastNames: 'worker', + firstName: 'DEFAULT', + lastNames: 'WORKER', email: 'defaultWorker@mydomain.com', street: 'S/ DEFAULTWORKERSTREET', city: 'defaultWorkerCity', From 83d0a394e359a976d286b0ab6c72bdbbd1cc7033 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 3 Aug 2023 15:59:09 +0200 Subject: [PATCH 128/130] refs #5973 refactor(item_fetched-tags): restyle empty tags --- modules/item/front/fetched-tags/index.html | 28 +++++++++++----------- modules/item/front/fetched-tags/style.scss | 14 +++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/item/front/fetched-tags/index.html b/modules/item/front/fetched-tags/index.html index 472fa676b..df5936871 100644 --- a/modules/item/front/fetched-tags/index.html +++ b/modules/item/front/fetched-tags/index.html @@ -1,40 +1,40 @@ - -
+
{{::$ctrl.item.value5}}
-
{{::$ctrl.item.value6}}
-
{{::$ctrl.item.value7}}
-
{{::$ctrl.item.value8}}
-
{{::$ctrl.item.value9}}
-
{{::$ctrl.item.value10}}
- \ No newline at end of file + diff --git a/modules/item/front/fetched-tags/style.scss b/modules/item/front/fetched-tags/style.scss index 2cd7afbb2..250ca07ab 100644 --- a/modules/item/front/fetched-tags/style.scss +++ b/modules/item/front/fetched-tags/style.scss @@ -28,7 +28,7 @@ vn-fetched-tags { & > vn-horizontal { align-items: center; - + max-width: 210px; & > vn-auto { flex-wrap: wrap; @@ -43,19 +43,19 @@ vn-fetched-tags { & > .inline-tag { color: $color-font-secondary; text-align: center; - font-size: .75rem; - height: 12px; + font-size: .8rem; + height: 13px; padding: 1px; width: 64px; min-width: 64px; max-width: 64px; flex: 1; - border: 1px solid $color-spacer; - + border: 1px solid $color-font-secondary; + &.empty { - border: 1px solid $color-spacer-light; + border: 1px solid darken($color-font-secondary, 30%); } } } } -} \ No newline at end of file +} From 4191d2529d10ca3b40771801f06349b6d6cf698c Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 7 Aug 2023 07:57:38 +0200 Subject: [PATCH 129/130] refs #5712 warnFix: getById condition --- modules/worker/back/methods/worker-dms/filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 5f55f1bd7..9d8554484 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -71,8 +71,9 @@ module.exports = Self => { 'Stored on': 'created', 'Document ID': 'id' }; + workerDocuware = - await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse) ?? []; + await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? []; for (document of workerDocuware) { const defaultData = { file: 'dw' + document.id + '.png', From 26d6bbff4cb792592dc18973ca856433715acbf3 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 7 Aug 2023 10:04:46 +0200 Subject: [PATCH 130/130] refs #5929 hotFix: add UserError --- modules/ticket/back/methods/ticket/componentUpdate.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/ticket/back/methods/ticket/componentUpdate.js b/modules/ticket/back/methods/ticket/componentUpdate.js index b5ff50d59..8aad8959b 100644 --- a/modules/ticket/back/methods/ticket/componentUpdate.js +++ b/modules/ticket/back/methods/ticket/componentUpdate.js @@ -1,4 +1,5 @@ const loggable = require('vn-loopback/util/log'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('componentUpdate', { @@ -112,7 +113,6 @@ module.exports = Self => { } try { - const userId = ctx.req.accessToken.userId; const models = Self.app.models; const $t = ctx.req.__; // $translate await models.Ticket.isEditableOrThrow(ctx, args.id, myOptions); @@ -127,11 +127,8 @@ module.exports = Self => { args.warehouseFk, myOptions); - if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk) { - const error = `You don't have privileges to change the zone`; - - throw new UserError(error); - } + if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk) + throw new UserError(`You don't have privileges to change the zone`); } if (args.isWithoutNegatives) {