fixes #4839 - docuware_send #1254
|
@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- [General](Inicio) Permite recuperar la contraseña
|
- [General](Inicio) Permite recuperar la contraseña
|
||||||
|
- [Ticket](Opciones) Subir albarán a Docuware
|
||||||
|
- [Ticket](Opciones) Enviar correo con PDF de Docuware
|
||||||
- [Artículo](Datos Básicos) Añadido campo Unidades/Caja
|
- [Artículo](Datos Básicos) Añadido campo Unidades/Caja
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const got = require('got');
|
const axios = require('axios');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('checkFile', {
|
Self.remoteMethodCtx('checkFile', {
|
||||||
|
@ -8,7 +8,7 @@ module.exports = Self => {
|
||||||
{
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The id',
|
description: 'The id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18,14 +18,14 @@ module.exports = Self => {
|
||||||
description: 'The fileCabinet name'
|
description: 'The fileCabinet name'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'dialog',
|
arg: 'signed',
|
||||||
type: 'string',
|
type: 'boolean',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The dialog name'
|
description: 'If pdf is necessary to be signed'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'boolean',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -34,58 +34,51 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.checkFile = async function(ctx, id, fileCabinet, dialog) {
|
Self.checkFile = async function(ctx, id, fileCabinet, signed) {
|
||||||
const myUserId = ctx.req.accessToken.userId;
|
|
||||||
if (!myUserId)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const docuwareConfig = await models.DocuwareConfig.findOne();
|
const action = 'find';
|
||||||
|
|
||||||
const docuwareInfo = await models.Docuware.findOne({
|
const docuwareInfo = await models.Docuware.findOne({
|
||||||
where: {
|
where: {
|
||||||
code: fileCabinet,
|
code: fileCabinet,
|
||||||
dialogName: dialog
|
action: action
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const docuwareUrl = docuwareConfig.url;
|
|
||||||
const cookie = docuwareConfig.token;
|
|
||||||
const fileCabinetName = docuwareInfo.fileCabinetName;
|
|
||||||
const find = docuwareInfo.find;
|
|
||||||
const options = {
|
|
||||||
'headers': {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Cookie': cookie
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const searchFilter = {
|
const searchFilter = {
|
||||||
condition: [
|
condition: [
|
||||||
{
|
{
|
||||||
DBName: find,
|
DBName: docuwareInfo.findById,
|
||||||
|
|
||||||
Value: [id]
|
Value: [id]
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
sortOrder: [
|
||||||
|
{
|
||||||
|
Field: 'FILENAME',
|
||||||
|
Direction: 'Desc'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// get fileCabinetId
|
const options = await Self.getOptions();
|
||||||
const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options);
|
|
||||||
const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet;
|
|
||||||
const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id;
|
|
||||||
|
|
||||||
// get dialog
|
const fileCabinetId = await Self.getFileCabinet(fileCabinet);
|
||||||
const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options);
|
const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId);
|
||||||
const dialogJson = JSON.parse(dialogResponse.body).Dialog;
|
|
||||||
const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
|
|
||||||
|
|
||||||
// get docuwareID
|
const response = await axios.post(
|
||||||
Object.assign(options, {'body': JSON.stringify(searchFilter)});
|
`${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
|
||||||
const response = await got.post(
|
searchFilter,
|
||||||
`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
|
options.headers
|
||||||
JSON.parse(response.body).Items[0].Id;
|
);
|
||||||
|
const [documents] = response.data.Items;
|
||||||
|
if (!documents) return false;
|
||||||
|
|
||||||
return true;
|
const state = documents.Fields.find(field => field.FieldName == 'ESTADO');
|
||||||
|
if (signed && state.Item != 'Firmado') return false;
|
||||||
|
|
||||||
|
return {id: documents.Id};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,72 @@
|
||||||
|
const {Email} = require('vn-print');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('deliveryNoteEmail', {
|
||||||
|
description: 'Sends the delivery note email with an docuware attached PDF',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The ticket id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'recipient',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The recipient email',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'recipientId',
|
||||||
|
type: 'number',
|
||||||
|
description: 'The client id',
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
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/delivery-note-email',
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.deliveryNoteEmail = async(ctx, id) => {
|
||||||
|
const args = Object.assign({}, ctx.args);
|
||||||
|
const params = {
|
||||||
|
recipient: args.recipient,
|
||||||
|
lang: ctx.req.getLocale()
|
||||||
|
};
|
||||||
|
|
||||||
|
delete args.ctx;
|
||||||
|
for (const param in args)
|
||||||
|
params[param] = args[param];
|
||||||
|
|
||||||
|
const email = new Email('delivery-note', params);
|
||||||
|
|
||||||
|
const docuwareFile = await Self.app.models.Docuware.download(ctx, id, 'deliveryNote');
|
||||||
|
|
||||||
|
return email.send({
|
||||||
|
overrideAttachments: true,
|
||||||
|
attachments: [{
|
||||||
|
filename: `${id}.pdf`,
|
||||||
|
content: docuwareFile[0]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint max-len: ["error", { "code": 180 }]*/
|
/* eslint max-len: ["error", { "code": 180 }]*/
|
||||||
const got = require('got');
|
const axios = require('axios');
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
|
@ -10,19 +10,13 @@ module.exports = Self => {
|
||||||
{
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The id',
|
description: 'The ticket id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'fileCabinet',
|
arg: 'fileCabinet',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'The id',
|
description: 'The file cabinet',
|
||||||
http: {source: 'path'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'dialog',
|
|
||||||
type: 'string',
|
|
||||||
description: 'The id',
|
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -42,79 +36,26 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
http: {
|
http: {
|
||||||
path: `/:id/download/:fileCabinet/:dialog`,
|
path: `/:id/download/:fileCabinet`,
|
||||||
verb: 'GET'
|
verb: 'GET'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.download = async function(ctx, id, fileCabinet, dialog) {
|
Self.download = async function(ctx, id, fileCabinet) {
|
||||||
const myUserId = ctx.req.accessToken.userId;
|
|
||||||
if (!myUserId)
|
|
||||||
throw new UserError(`You don't have enough privileges`);
|
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const docuwareConfig = await models.DocuwareConfig.findOne();
|
const docuwareFile = await models.Docuware.checkFile(ctx, id, fileCabinet, true);
|
||||||
const docuwareInfo = await models.Docuware.findOne({
|
if (!docuwareFile) throw new UserError('The DOCUWARE PDF document does not exists');
|
||||||
where: {
|
|
||||||
code: fileCabinet,
|
|
||||||
dialogName: dialog
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const docuwareUrl = docuwareConfig.url;
|
const fileCabinetId = await Self.getFileCabinet(fileCabinet);
|
||||||
const cookie = docuwareConfig.token;
|
const options = await Self.getOptions();
|
||||||
const fileCabinetName = docuwareInfo.fileCabinetName;
|
options.headers.responseType = 'stream';
|
||||||
const find = docuwareInfo.find;
|
|
||||||
const options = {
|
|
||||||
'headers': {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Cookie': cookie
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const searchFilter = {
|
|
||||||
condition: [
|
|
||||||
{
|
|
||||||
DBName: find,
|
|
||||||
Value: [id]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
const fileName = `filename="${id}.pdf"`;
|
||||||
// get fileCabinetId
|
const contentType = 'application/pdf';
|
||||||
const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options);
|
const downloadUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
|
||||||
const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet;
|
|
||||||
const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id;
|
|
||||||
|
|
||||||
// get dialog
|
const stream = await axios.get(downloadUri, options.headers);
|
||||||
const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options);
|
|
||||||
const dialogJson = JSON.parse(dialogResponse.body).Dialog;
|
|
||||||
const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
|
|
||||||
|
|
||||||
// get docuwareID
|
return [stream.data, contentType, fileName];
|
||||||
Object.assign(options, {'body': JSON.stringify(searchFilter)});
|
|
||||||
const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
|
|
||||||
const docuwareId = JSON.parse(response.body).Items[0].Id;
|
|
||||||
|
|
||||||
// download & save file
|
|
||||||
const fileName = `filename="${id}.pdf"`;
|
|
||||||
const contentType = 'application/pdf';
|
|
||||||
const downloadUri = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
|
|
||||||
const downloadOptions = {
|
|
||||||
'headers': {
|
|
||||||
'Cookie': cookie
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const stream = got.stream(downloadUri, downloadOptions);
|
|
||||||
|
|
||||||
return [stream, contentType, fileName];
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === 'ENOENT')
|
|
||||||
throw new UserError('The DOCUWARE PDF document does not exists');
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
const got = require('got');
|
const axios = require('axios');
|
||||||
|
|
||||||
describe('docuware download()', () => {
|
describe('docuware download()', () => {
|
||||||
const ticketId = 1;
|
const ticketId = 1;
|
||||||
|
@ -12,53 +12,71 @@ describe('docuware download()', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fileCabinetName = 'deliveryClient';
|
const docuwareModel = models.Docuware;
|
||||||
const dialogDisplayName = 'find';
|
const fileCabinetName = 'deliveryNote';
|
||||||
const dialogName = 'findTicket';
|
|
||||||
|
|
||||||
const gotGetResponse = {
|
beforeAll(() => {
|
||||||
body: JSON.stringify(
|
spyOn(docuwareModel, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
||||||
{
|
spyOn(docuwareModel, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
||||||
FileCabinet: [
|
|
||||||
{Id: 12, Name: fileCabinetName}
|
|
||||||
],
|
|
||||||
Dialog: [
|
|
||||||
{Id: 34, DisplayName: dialogDisplayName}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should return exist file in docuware', async() => {
|
|
||||||
const gotPostResponse = {
|
|
||||||
body: JSON.stringify(
|
|
||||||
{
|
|
||||||
Items: [
|
|
||||||
{Id: 56}
|
|
||||||
],
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
|
|
||||||
spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
|
|
||||||
|
|
||||||
const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName);
|
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return not exist file in docuware', async() => {
|
it('should return false if there are no documents', async() => {
|
||||||
const gotPostResponse = {
|
const response = {
|
||||||
body: JSON.stringify(
|
data: {
|
||||||
{
|
Items: []
|
||||||
Items: [],
|
}
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(response)));
|
||||||
|
|
||||||
spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
|
const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, true);
|
||||||
spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
|
|
||||||
|
|
||||||
const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName);
|
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
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);
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the document data', async() => {
|
||||||
|
const docuwareId = 1;
|
||||||
|
const response = {
|
||||||
|
data: {
|
||||||
|
Items: [
|
||||||
|
{
|
||||||
|
Id: docuwareId,
|
||||||
|
Fields: [
|
||||||
|
{
|
||||||
|
FieldName: 'ESTADO',
|
||||||
|
Item: 'Firmado'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(response)));
|
||||||
|
|
||||||
|
const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, true);
|
||||||
|
|
||||||
|
expect(result.id).toEqual(docuwareId);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
const got = require('got');
|
const axios = require('axios');
|
||||||
const stream = require('stream');
|
const stream = require('stream');
|
||||||
|
|
||||||
describe('docuware download()', () => {
|
describe('docuware download()', () => {
|
||||||
|
@ -13,36 +13,33 @@ describe('docuware download()', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should return the downloaded file name', async() => {
|
const docuwareModel = models.Docuware;
|
||||||
const fileCabinetName = 'deliveryClient';
|
const fileCabinetName = 'deliveryNote';
|
||||||
const dialogDisplayName = 'find';
|
|
||||||
const dialogName = 'findTicket';
|
|
||||||
const gotGetResponse = {
|
|
||||||
body: JSON.stringify(
|
|
||||||
{
|
|
||||||
FileCabinet: [
|
|
||||||
{Id: 12, Name: fileCabinetName}
|
|
||||||
],
|
|
||||||
Dialog: [
|
|
||||||
{Id: 34, DisplayName: dialogDisplayName}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const gotPostResponse = {
|
beforeAll(() => {
|
||||||
body: JSON.stringify(
|
spyOn(docuwareModel, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
||||||
{
|
spyOn(docuwareModel, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
||||||
Items: [
|
});
|
||||||
{Id: 56}
|
|
||||||
],
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
|
it('should return error if file not exist', async() => {
|
||||||
spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
|
spyOn(docuwareModel, 'checkFile').and.returnValue(false);
|
||||||
spyOn(got, 'stream').and.returnValue(new stream.PassThrough({objectMode: true}));
|
spyOn(axios, 'get').and.returnValue(new stream.PassThrough({objectMode: true}));
|
||||||
|
|
||||||
const result = await models.Docuware.download(ctx, ticketId, fileCabinetName, dialogName);
|
let error;
|
||||||
|
try {
|
||||||
|
await models.Docuware.download(ctx, ticketId, fileCabinetName);
|
||||||
|
} catch (e) {
|
||||||
|
error = e.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toEqual('The DOCUWARE PDF document does not exists');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the downloaded file if exist file ', async() => {
|
||||||
|
spyOn(docuwareModel, 'checkFile').and.returnValue({});
|
||||||
|
spyOn(axios, 'get').and.returnValue(new stream.PassThrough({objectMode: true}));
|
||||||
|
|
||||||
|
const result = await models.Docuware.download(ctx, ticketId, fileCabinetName);
|
||||||
|
|
||||||
expect(result[1]).toEqual('application/pdf');
|
expect(result[1]).toEqual('application/pdf');
|
||||||
expect(result[2]).toEqual(`filename="${ticketId}.pdf"`);
|
expect(result[2]).toEqual(`filename="${ticketId}.pdf"`);
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('docuware upload()', () => {
|
||||||
|
const userId = 9;
|
||||||
|
const ticketId = 10;
|
||||||
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
getLocale: () => {
|
||||||
|
return 'en';
|
||||||
|
},
|
||||||
|
accessToken: {userId: userId},
|
||||||
|
headers: {origin: 'http://localhost:5000'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const docuwareModel = models.Docuware;
|
||||||
|
const ticketModel = models.Ticket;
|
||||||
|
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 try upload file', async() => {
|
||||||
|
spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({})));
|
||||||
|
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await models.Docuware.upload(ctx, ticketId, fileCabinetName);
|
||||||
|
} catch (e) {
|
||||||
|
error = e.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toEqual('Action not allowed on the test environment');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,141 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
const axios = require('axios');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('upload', {
|
||||||
|
description: 'Upload an docuware PDF',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
description: 'The ticket id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'fileCabinet',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The file cabinet'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dialog',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The dialog'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: [],
|
||||||
|
http: {
|
||||||
|
path: `/:id/upload`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.upload = async function(ctx, id, fileCabinet) {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const action = 'store';
|
||||||
|
|
||||||
|
const options = await Self.getOptions();
|
||||||
|
const fileCabinetId = await Self.getFileCabinet(fileCabinet);
|
||||||
|
const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId);
|
||||||
|
|
||||||
|
// get delivery note
|
||||||
|
const deliveryNote = await models.Ticket.deliveryNotePdf(ctx, {
|
||||||
|
id,
|
||||||
|
type: 'deliveryNote'
|
||||||
|
});
|
||||||
|
|
||||||
|
// get ticket data
|
||||||
|
const ticket = await models.Ticket.findById(id, {
|
||||||
|
include: [{
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'socialName', 'fi']
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// upload file
|
||||||
|
const templateJson = {
|
||||||
|
'Fields': [
|
||||||
|
{
|
||||||
|
'FieldName': 'N__ALBAR_N',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'CIF_PROVEEDOR',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': ticket.client().fi,
|
||||||
|
},
|
||||||
alexm marked this conversation as resolved
|
|||||||
|
{
|
||||||
|
'FieldName': 'CODIGO_PROVEEDOR',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': ticket.client().id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'NOMBRE_PROVEEDOR',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': ticket.client().socialName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'FECHA_FACTURA',
|
||||||
|
'ItemElementName': 'date',
|
||||||
|
'Item': ticket.shipped,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'TOTAL_FACTURA',
|
||||||
|
'ItemElementName': 'Decimal',
|
||||||
|
'Item': ticket.totalWithVat,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'ESTADO',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': 'Pendiente procesar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'FIRMA_',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': 'Si',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'FieldName': 'FILTRO_TABLET',
|
||||||
|
'ItemElementName': 'string',
|
||||||
|
'Item': 'Tablet1',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV != 'production')
|
||||||
|
throw new UserError('Action not allowed on the test environment');
|
||||||
|
|
||||||
|
// delete old
|
||||||
|
const docuwareFile = await models.Docuware.checkFile(ctx, id, fileCabinet, false);
|
||||||
|
if (docuwareFile) {
|
||||||
|
const deleteJson = {
|
||||||
|
'Field': [{'FieldName': 'ESTADO', 'Item': 'Pendiente eliminar', 'ItemElementName': 'String'}]
|
||||||
|
};
|
||||||
|
const deleteUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`;
|
||||||
|
await axios.put(deleteUri, deleteJson, options.headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents?StoreDialogId=${dialogId}`;
|
||||||
|
const FormData = require('form-data');
|
||||||
|
const data = new FormData();
|
||||||
|
|
||||||
|
data.append('document', JSON.stringify(templateJson), 'schema.json');
|
||||||
|
data.append('file[]', deliveryNote[0], 'file.pdf');
|
||||||
|
const uploadOptions = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
'X-File-ModifiedDate': new Date(),
|
||||||
|
'Cookie': options.headers.headers.Cookie,
|
||||||
|
...data.getHeaders()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return await axios.post(uploadUri, data, uploadOptions)
|
||||||
|
.catch(() => {
|
||||||
|
throw new UserError('Failed to upload file');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
|
@ -16,7 +16,7 @@
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"token": {
|
"cookie": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/docuware/download')(Self);
|
require('../methods/docuware/download')(Self);
|
||||||
|
require('../methods/docuware/upload')(Self);
|
||||||
require('../methods/docuware/checkFile')(Self);
|
require('../methods/docuware/checkFile')(Self);
|
||||||
|
require('../methods/docuware/deliveryNoteEmail')(Self);
|
||||||
|
require('../methods/docuware/core')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,20 +19,14 @@
|
||||||
"fileCabinetName": {
|
"fileCabinetName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"dialogName": {
|
"dialogName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"find": {
|
"findById": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"property": "*",
|
|
||||||
"accessType": "*",
|
|
||||||
"principalType": "ROLE",
|
|
||||||
"principalId": "$everyone",
|
|
||||||
"permission": "ALLOW"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
CREATE OR REPLACE TABLE `vn`.`docuware` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`code` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`fileCabinetName` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`action` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`dialogName` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,
|
||||||
|
`findById` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `action`, `dialogName`, `findById`)
|
||||||
|
VALUES
|
||||||
|
('deliveryNote', 'Albaranes cliente', 'find', 'find', 'N__ALBAR_N'),
|
||||||
|
('deliveryNote', 'Albaranes cliente', 'store', 'Archivar', 'N__ALBAR_N');
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
|
||||||
|
VALUES
|
||||||
|
('Docuware','checkFile','READ','ALLOW','employee'),
|
||||||
|
('Docuware','download','READ','ALLOW','salesPerson'),
|
||||||
|
('Docuware','upload','WRITE','ALLOW','productionAssi'),
|
||||||
|
('Docuware','deliveryNoteEmail','WRITE','ALLOW','salesPerson');
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`docuwareConfig` CHANGE token cookie varchar(1000) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL;
|
|
@ -2580,13 +2580,9 @@ INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`)
|
||||||
(4, 33.8, util.VN_CURDATE(), 1, 1101),
|
(4, 33.8, util.VN_CURDATE(), 1, 1101),
|
||||||
(30, 34.4, util.VN_CURDATE(), 1, 1108);
|
(30, 34.4, util.VN_CURDATE(), 1, 1108);
|
||||||
|
|
||||||
INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
|
|
||||||
VALUES
|
|
||||||
('deliveryClient', 'deliveryClient', 'findTicket', 'word');
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`docuwareConfig` (`url`)
|
INSERT INTO `vn`.`docuwareConfig` (`url`)
|
||||||
VALUES
|
VALUES
|
||||||
('https://verdnatura.docuware.cloud/docuware/platform');
|
('http://docuware.url/');
|
||||||
|
|
||||||
INSERT INTO `vn`.`calendarHolidaysName` (`id`, `name`)
|
INSERT INTO `vn`.`calendarHolidaysName` (`id`, `name`)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -59,6 +59,7 @@ TABLES=(
|
||||||
componentType
|
componentType
|
||||||
continent
|
continent
|
||||||
department
|
department
|
||||||
|
docuware
|
||||||
itemPackingType
|
itemPackingType
|
||||||
pgc
|
pgc
|
||||||
sample
|
sample
|
||||||
|
|
|
@ -135,7 +135,7 @@
|
||||||
"Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
|
"Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
|
||||||
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
|
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
|
||||||
"Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
|
"Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
|
||||||
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*",
|
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*",
|
||||||
"Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*",
|
"Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*",
|
||||||
"Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*",
|
"Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*",
|
||||||
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
||||||
|
@ -252,5 +252,6 @@
|
||||||
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
||||||
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
||||||
"Client's email was not found": "No se encontró el email del cliente",
|
"Client's email was not found": "No se encontró el email del cliente",
|
||||||
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9"
|
"Failed to upload file": "Error al subir archivo",
|
||||||
|
"The DOCUWARE PDF document does not exists": "The DOCUWARE PDF document does not exists"
|
||||||
}
|
}
|
|
@ -11,6 +11,7 @@ describe('InvoiceOut createPdf()', () => {
|
||||||
const ctx = {req: activeCtx};
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
it('should create a new PDF file and set true the hasPdf property', async() => {
|
it('should create a new PDF file and set true the hasPdf property', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5035');
|
||||||
const invoiceId = 1;
|
const invoiceId = 1;
|
||||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
active: activeCtx
|
active: activeCtx
|
||||||
|
|
|
@ -21,30 +21,28 @@
|
||||||
Add turn
|
Add turn
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item class="dropdown"
|
<vn-item class="dropdown"
|
||||||
vn-click-stop="showDeliveryNoteMenu.show($event, 'left')"
|
vn-click-stop="showDeliveryNoteMenu.show($event, 'left'); $ctrl.hasDocuware()"
|
||||||
translate>
|
translate>
|
||||||
Show Delivery Note...
|
Show Delivery Note...
|
||||||
<vn-menu vn-id="showDeliveryNoteMenu">
|
<vn-menu vn-id="showDeliveryNoteMenu">
|
||||||
<vn-list>
|
<vn-list>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-if="!$ctrl.hasDocuwareFile"
|
|
||||||
ng-click="$ctrl.showPdfDeliveryNote('deliveryNote')"
|
ng-click="$ctrl.showPdfDeliveryNote('deliveryNote')"
|
||||||
translate>
|
translate>
|
||||||
as PDF
|
as PDF
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<a class="vn-item"
|
|
||||||
ng-if="$ctrl.hasDocuwareFile"
|
|
||||||
href='api/Docuwares/{{$ctrl.ticket.id}}/download/deliveryClient/findTicket?access_token={{$ctrl.vnToken.token}}'
|
|
||||||
target="_blank"
|
|
||||||
translate>
|
|
||||||
as PDF
|
|
||||||
</a>
|
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-if="!$ctrl.hasDocuwareFile"
|
|
||||||
ng-click="$ctrl.showPdfDeliveryNote('withoutPrices')"
|
ng-click="$ctrl.showPdfDeliveryNote('withoutPrices')"
|
||||||
translate>
|
translate>
|
||||||
as PDF without prices
|
as PDF without prices
|
||||||
</vn-item>
|
</vn-item>
|
||||||
|
<a class="vn-item"
|
||||||
|
ng-if="$ctrl.hasDocuwareFile"
|
||||||
|
href='api/Docuwares/{{$ctrl.ticket.id}}/download/deliveryNote?access_token={{$ctrl.vnToken.token}}'
|
||||||
|
target="_blank"
|
||||||
|
translate>
|
||||||
|
as PDF signed
|
||||||
|
</a>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="$ctrl.showCsvDeliveryNote()"
|
ng-click="$ctrl.showCsvDeliveryNote()"
|
||||||
translate>
|
translate>
|
||||||
|
@ -54,7 +52,7 @@
|
||||||
</vn-menu>
|
</vn-menu>
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item class="dropdown"
|
<vn-item class="dropdown"
|
||||||
vn-click-stop="sendDeliveryNoteMenu.show($event, 'left')"
|
vn-click-stop="sendDeliveryNoteMenu.show($event, 'left'); $ctrl.hasDocuware()"
|
||||||
translate>
|
translate>
|
||||||
Send Delivery Note...
|
Send Delivery Note...
|
||||||
<vn-menu vn-id="sendDeliveryNoteMenu">
|
<vn-menu vn-id="sendDeliveryNoteMenu">
|
||||||
|
@ -64,6 +62,11 @@
|
||||||
translate>
|
translate>
|
||||||
Send PDF
|
Send PDF
|
||||||
</vn-item>
|
</vn-item>
|
||||||
|
<vn-item
|
||||||
|
ng-click="$ctrl.uploadDocuware(!$ctrl.hasDocuwareFile)"
|
||||||
|
translate>
|
||||||
|
Send PDF to tablet
|
||||||
|
</vn-item>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="sendCsvConfirmation.show({email: $ctrl.ticket.client.email})"
|
ng-click="sendCsvConfirmation.show({email: $ctrl.ticket.client.email})"
|
||||||
translate>
|
translate>
|
||||||
|
@ -323,3 +326,18 @@
|
||||||
question="Are you sure you want to refund all?"
|
question="Are you sure you want to refund all?"
|
||||||
message="Refund all">
|
message="Refund all">
|
||||||
</vn-confirm>
|
</vn-confirm>
|
||||||
|
|
||||||
|
<!-- Client balance popup-->
|
||||||
|
<vn-client-balance-create
|
||||||
|
vn-id="balance-create"
|
||||||
|
company-fk="$ctrl.vnConfig.companyFk"
|
||||||
|
client-fk="$ctrl.ticket.client.id">
|
||||||
|
</vn-client-balance-create>
|
||||||
|
|
||||||
|
<!-- Send pdf to tablet -->
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="pdfToTablet"
|
||||||
|
on-accept="$ctrl.uploadDocuware(true)"
|
||||||
|
question="Are you sure you want to replace this delivery note?"
|
||||||
|
message="Already exist signed delivery note">
|
||||||
|
</vn-confirm>
|
||||||
|
|
|
@ -85,7 +85,6 @@ class Controller extends Section {
|
||||||
.then(res => this.ticket = res.data)
|
.then(res => this.ticket = res.data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isTicketEditable();
|
this.isTicketEditable();
|
||||||
this.hasDocuware();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,15 +133,6 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasDocuware() {
|
|
||||||
const params = {
|
|
||||||
fileCabinet: 'deliveryClient',
|
|
||||||
dialog: 'findTicket'
|
|
||||||
};
|
|
||||||
this.$http.post(`Docuwares/${this.id}/checkFile`, params)
|
|
||||||
.then(res => this.hasDocuwareFile = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
showPdfDeliveryNote(type) {
|
showPdfDeliveryNote(type) {
|
||||||
this.vnReport.show(`tickets/${this.id}/delivery-note-pdf`, {
|
this.vnReport.show(`tickets/${this.id}/delivery-note-pdf`, {
|
||||||
recipientId: this.ticket.client.id,
|
recipientId: this.ticket.client.id,
|
||||||
|
@ -151,7 +141,10 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPdfDeliveryNote($data) {
|
sendPdfDeliveryNote($data) {
|
||||||
return this.vnEmail.send(`tickets/${this.id}/delivery-note-email`, {
|
let query = `tickets/${this.id}/delivery-note-email`;
|
||||||
|
if (this.hasDocuwareFile) query = `docuwares/${this.id}/delivery-note-email`;
|
||||||
|
|
||||||
|
return this.vnEmail.send(query, {
|
||||||
recipientId: this.ticket.client.id,
|
recipientId: this.ticket.client.id,
|
||||||
recipient: $data.email
|
recipient: $data.email
|
||||||
});
|
});
|
||||||
|
@ -319,6 +312,24 @@ class Controller extends Section {
|
||||||
return this.$http.post(`Tickets/${this.id}/sendSms`, sms)
|
return this.$http.post(`Tickets/${this.id}/sendSms`, sms)
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
|
.then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasDocuware() {
|
||||||
|
this.$http.post(`Docuwares/${this.id}/checkFile`, {fileCabinet: 'deliveryNote', signed: true})
|
||||||
|
.then(res => {
|
||||||
|
this.hasDocuwareFile = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadDocuware(force) {
|
||||||
|
if (!force)
|
||||||
|
return this.$.pdfToTablet.show();
|
||||||
|
|
||||||
|
return this.$http.post(`Docuwares/${this.id}/upload`, {fileCabinet: 'deliveryNote'})
|
||||||
|
.then(() => {
|
||||||
|
this.vnApp.showSuccess(this.$t('PDF sent!'));
|
||||||
|
this.$.balanceCreate.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail'];
|
Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail'];
|
||||||
|
|
|
@ -286,9 +286,34 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
|
||||||
|
|
||||||
describe('hasDocuware()', () => {
|
describe('hasDocuware()', () => {
|
||||||
it('should call hasDocuware method', () => {
|
it('should call hasDocuware method', () => {
|
||||||
$httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond();
|
$httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond(true);
|
||||||
controller.hasDocuware();
|
controller.hasDocuware();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.hasDocuwareFile).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('uploadDocuware()', () => {
|
||||||
|
it('should open dialog if not force', () => {
|
||||||
|
controller.$.pdfToTablet = {show: () => {}};
|
||||||
|
jest.spyOn(controller.$.pdfToTablet, 'show');
|
||||||
|
controller.uploadDocuware(false);
|
||||||
|
|
||||||
|
expect(controller.$.pdfToTablet.show).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make a query and show balance create', () => {
|
||||||
|
controller.$.balanceCreate = {show: () => {}};
|
||||||
|
jest.spyOn(controller.$.balanceCreate, 'show');
|
||||||
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
|
||||||
|
$httpBackend.whenPOST(`Docuwares/${ticket.id}/upload`).respond(true);
|
||||||
|
controller.uploadDocuware(true);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||||
|
expect(controller.$.balanceCreate.show).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
Show Delivery Note...: Ver albarán...
|
Show Delivery Note...: Ver albarán...
|
||||||
Send Delivery Note...: Enviar albarán...
|
Send Delivery Note...: Enviar albarán...
|
||||||
as PDF: como PDF
|
as PDF: como PDF
|
||||||
|
as PDF signed: como PDF firmado
|
||||||
as CSV: como CSV
|
as CSV: como CSV
|
||||||
as PDF without prices: como PDF sin precios
|
as PDF without prices: como PDF sin precios
|
||||||
Send PDF: Enviar PDF
|
Send PDF: Enviar PDF
|
||||||
|
Send PDF to tablet: Enviar PDF a tablet
|
||||||
Send CSV: Enviar CSV
|
Send CSV: Enviar CSV
|
||||||
Send CSV Delivery Note: Enviar albarán en CSV
|
Send CSV Delivery Note: Enviar albarán en CSV
|
||||||
Send PDF Delivery Note: Enviar albarán en PDF
|
Send PDF Delivery Note: Enviar albarán en PDF
|
||||||
|
@ -13,3 +15,6 @@ Invoice sent: Factura enviada
|
||||||
The following refund ticket have been created: "Se ha creado siguiente ticket de abono: {{ticketId}}"
|
The following refund ticket have been created: "Se ha creado siguiente ticket de abono: {{ticketId}}"
|
||||||
Transfer client: Transferir cliente
|
Transfer client: Transferir cliente
|
||||||
SMS Notify changes: SMS Notificar cambios
|
SMS Notify changes: SMS Notificar cambios
|
||||||
|
PDF sent!: ¡PDF enviado!
|
||||||
|
Already exist signed delivery note: Ya existe albarán de entrega firmado
|
||||||
|
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán de entrega?
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.25.0",
|
"axios": "^1.2.2",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bmp-js": "^0.1.0",
|
"bmp-js": "^0.1.0",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
|
@ -3893,10 +3893,13 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "0.25.0",
|
"version": "1.2.2",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.14.7"
|
"follow-redirects": "^1.15.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-jest": {
|
"node_modules/babel-jest": {
|
||||||
|
@ -8401,14 +8404,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.14.9",
|
"version": "1.15.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
},
|
},
|
||||||
|
@ -28842,9 +28846,13 @@
|
||||||
"version": "1.11.0"
|
"version": "1.11.0"
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.25.0",
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.14.7"
|
"follow-redirects": "^1.15.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"babel-jest": {
|
"babel-jest": {
|
||||||
|
@ -31964,7 +31972,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.14.9"
|
"version": "1.15.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||||
},
|
},
|
||||||
"for-in": {
|
"for-in": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.25.0",
|
"axios": "^1.2.2",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bmp-js": "^0.1.0",
|
"bmp-js": "^0.1.0",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
|
|
Loading…
Reference in New Issue
Com aci hi ha molts numeros confirmar en Juan si ho deixem ací o es trau a una taula config