diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76527ac83..d4a1e147f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+## [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
+- (Clientes -> SMS) Nueva sección
+
+### Changed
+- (General -> Iconos) Añadidos nuevos iconos
+- (Clientes -> Razón social) Nuevas restricciones por pais
+
+
+### Fixed
+
+
## [2328.01] - 2023-07-13
### Added
diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js
index c0a4e8ef3..19224057c 100644
--- a/back/methods/docuware/checkFile.js
+++ b/back/methods/docuware/checkFile.js
@@ -1,7 +1,5 @@
-const axios = require('axios');
-
module.exports = Self => {
- Self.remoteMethodCtx('checkFile', {
+ Self.remoteMethod('checkFile', {
description: 'Check if exist docuware file',
accessType: 'READ',
accepts: [
@@ -17,12 +15,16 @@ module.exports = Self => {
required: true,
description: 'The fileCabinet name'
},
+ {
+ arg: 'filter',
+ type: 'object',
+ description: 'The filter'
+ },
{
arg: 'signed',
type: 'boolean',
- required: true,
description: 'If pdf is necessary to be signed'
- }
+ },
],
returns: {
type: 'object',
@@ -34,7 +36,7 @@ module.exports = Self => {
}
});
- Self.checkFile = async function(ctx, id, fileCabinet, signed) {
+ Self.checkFile = async function(id, fileCabinet, filter, signed) {
const models = Self.app.models;
const action = 'find';
@@ -45,39 +47,34 @@ module.exports = Self => {
}
});
- const searchFilter = {
- condition: [
- {
- DBName: docuwareInfo.findById,
-
- Value: [id]
- }
- ],
- sortOrder: [
- {
- Field: 'FILENAME',
- Direction: 'Desc'
- }
- ]
- };
+ if (!filter) {
+ filter = {
+ condition: [
+ {
+ DBName: docuwareInfo.findById,
+ Value: [id]
+ }
+ ],
+ sortOrder: [
+ {
+ Field: 'FILENAME',
+ Direction: 'Desc'
+ }
+ ]
+ };
+ }
+ 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);
-
- const response = await axios.post(
- `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
- searchFilter,
- options.headers
- );
- const [documents] = response.data.Items;
+ const response = await Self.get(fileCabinet, filter);
+ const [documents] = response.Items;
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 2053ddf85..74d922236 100644
--- a/back/methods/docuware/core.js
+++ b/back/methods/docuware/core.js
@@ -1,59 +1,6 @@
const axios = require('axios');
module.exports = Self => {
- /**
- * Returns the dialog id
- *
- * @param {string} code - The fileCabinet name
- * @param {string} action - The fileCabinet name
- * @param {string} fileCabinetId - Optional The fileCabinet name
- * @return {number} - The fileCabinet id
- */
- Self.getDialog = async(code, action, fileCabinetId) => {
- const docuwareInfo = await Self.app.models.Docuware.findOne({
- where: {
- code: code,
- action: action
- }
- });
- if (!fileCabinetId) fileCabinetId = await Self.getFileCabinet(code);
-
- 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;
-
- return dialogId;
- };
-
- /**
- * Returns the fileCabinetId
- *
- * @param {string} code - The fileCabinet code
- * @return {number} - The fileCabinet id
- */
- Self.getFileCabinet = async code => {
- const options = await Self.getOptions();
- const docuwareInfo = await Self.app.models.Docuware.findOne({
- where: {
- code: code
- }
- });
-
- 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;
-
- return fileCabinetId;
- };
-
/**
* Returns basic headers
*
@@ -75,4 +22,139 @@ module.exports = Self => {
headers
};
};
+
+ /**
+ * Returns the dialog id
+ *
+ * @param {string} code - The fileCabinet name
+ * @param {string} action - The fileCabinet name
+ * @param {string} fileCabinetId - Optional The fileCabinet name
+ * @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,
+ action
+ }
+ });
+ if (!fileCabinetId) fileCabinetId = await Self.getFileCabinet(code);
+
+ const options = await Self.getOptions();
+
+ 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;
+
+ return dialogId;
+ };
+
+ /**
+ * Returns the fileCabinetId
+ *
+ * @param {string} code - The fileCabinet code
+ * @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
+ }
+ });
+
+ 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;
+
+ return fileCabinetId;
+ };
+
+ /**
+ * Returns docuware data
+ *
+ * @param {string} code - The fileCabinet code
+ * @param {object} filter - The filter for docuware
+ * @param {object} parse - The fields parsed
+ * @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);
+
+ const data = await axios.post(
+ `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
+ filter,
+ options.headers
+ );
+ return parser(data.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) => {
+ if (!process.env.NODE_ENV) return;
+
+ const docuwareInfo = await Self.app.models.Docuware.findOne({
+ fields: ['findById'],
+ where: {
+ code,
+ action: 'find'
+ }
+ });
+ const filter = {
+ condition: [
+ {
+ DBName: docuwareInfo.findById,
+ Value: [id]
+ }
+ ]
+ };
+
+ 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..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,14 +40,15 @@ module.exports = Self => {
}
],
http: {
- path: `/:id/download/:fileCabinet`,
+ path: `/:id/download`,
verb: 'GET'
}
});
- Self.download = async function(ctx, id, fileCabinet) {
+ Self.download = async function(id, fileCabinet, filter) {
const models = Self.app.models;
- 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/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/back/methods/viaexpress-config/internationalExpedition.js b/back/methods/viaexpress-config/internationalExpedition.js
new file mode 100644
index 000000000..698bb1dac
--- /dev/null
+++ b/back/methods/viaexpress-config/internationalExpedition.js
@@ -0,0 +1,45 @@
+const axios = require('axios');
+const {DOMParser} = require('xmldom');
+
+module.exports = Self => {
+ Self.remoteMethod('internationalExpedition', {
+ description: 'Create an expedition and return a label',
+ accessType: 'WRITE',
+ accepts: [{
+ arg: 'expeditionFk',
+ type: 'number',
+ required: true
+ }],
+ returns: {
+ type: ['object'],
+ root: true
+ },
+ http: {
+ path: `/internationalExpedition`,
+ verb: 'POST'
+ }
+ });
+
+ Self.internationalExpedition = async expeditionFk => {
+ const models = Self.app.models;
+
+ const viaexpressConfig = await models.ViaexpressConfig.findOne({
+ fields: ['url']
+ });
+
+ const renderedXml = await models.ViaexpressConfig.renderer(expeditionFk);
+ const response = await axios.post(`${viaexpressConfig.url}ServicioVxClientes.asmx`, renderedXml, {
+ headers: {
+ 'Content-Type': 'application/soap+xml; charset=utf-8'
+ }
+ });
+
+ 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
new file mode 100644
index 000000000..e9abce5ca
--- /dev/null
+++ b/back/methods/viaexpress-config/renderer.js
@@ -0,0 +1,126 @@
+const fs = require('fs');
+const ejs = require('ejs');
+
+module.exports = Self => {
+ Self.remoteMethod('renderer', {
+ description: 'Renders the data from an XML',
+ 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: ['client', 'user', 'password', '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 ticket = expedition.ticket();
+ const sender = ticket.company().client();
+ const shipped = ticket.shipped.toISOString();
+ const data = {
+ viaexpressConfig,
+ sender,
+ senderAddress: sender.defaultAddress(),
+ client: ticket.client(),
+ address: ticket.address(),
+ shipped
+ };
+
+ 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..0b6eb468c
--- /dev/null
+++ b/back/methods/viaexpress-config/template.ejs
@@ -0,0 +1,52 @@
+
+