diff --git a/CHANGELOG.md b/CHANGELOG.md index 2292d3309..58ecee889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,18 +5,29 @@ 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). -## [2302.01] - 2023-01-12 +## [2304.01] - 2023-02-09 ### Added -- [General](Inicio) Permite recuperar la contraseña -- [Artículo](Datos Básicos) Añadido campo Unidades/Caja +- ### Changed -- [Tickets](Líneas preparadas) Actualizada sección para que sea más visual +- + +## [2302.01] - 2023-01-26 + +### Added +- (General -> Inicio) Permite recuperar la contraseña +- (Tickets -> Opciones) Subir albarán a Docuware +- (Tickets -> Opciones) Enviar correo con PDF de Docuware +- (Artículos -> Datos Básicos) Añadido campo Unidades/Caja + +### Changed +- (Reclamaciones -> Descriptor) Cambiado el campo Agencia por Zona +- (Tickets -> Líneas preparadas) Actualizada sección para que sea más visual ### Fixed -- [General] Al utilizar el traductor de Google se descuadraban los iconos -- [Artículos](Etiquetas) Permite intercambiar la relevancia entre dos etiquetas. +- (General) Al utilizar el traductor de Google se descuadraban los iconos +- (Artículos -> Etiquetas) Permite intercambiar la relevancia entre dos etiquetas. ### Removed -- [Tickets](Control clientes) Eliminada sección +- (Tickets -> Control clientes) Eliminada sección diff --git a/back/methods/collection/previousLabel.js b/back/methods/collection/previousLabel.js new file mode 100644 index 000000000..fb2df8133 --- /dev/null +++ b/back/methods/collection/previousLabel.js @@ -0,0 +1,49 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('previousLabel', { + description: 'Returns the previa label pdf', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The item 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/previousLabel', + verb: 'GET' + } + }); + + Self.previousLabel = async(ctx, id) => { + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + const report = new Report('previa-label', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="previa-${id}.pdf"`]; + }; +}; diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js index c6712bb65..c0a4e8ef3 100644 --- a/back/methods/docuware/checkFile.js +++ b/back/methods/docuware/checkFile.js @@ -1,4 +1,4 @@ -const got = require('got'); +const axios = require('axios'); module.exports = Self => { Self.remoteMethodCtx('checkFile', { @@ -8,7 +8,7 @@ module.exports = Self => { { arg: 'id', type: 'number', - description: 'The id', + description: 'The id', http: {source: 'path'} }, { @@ -18,14 +18,14 @@ module.exports = Self => { description: 'The fileCabinet name' }, { - arg: 'dialog', - type: 'string', + arg: 'signed', + type: 'boolean', required: true, - description: 'The dialog name' + description: 'If pdf is necessary to be signed' } ], returns: { - type: 'boolean', + type: 'object', root: true }, http: { @@ -34,58 +34,51 @@ module.exports = Self => { } }); - Self.checkFile = async function(ctx, id, fileCabinet, dialog) { - const myUserId = ctx.req.accessToken.userId; - if (!myUserId) - return false; - + Self.checkFile = async function(ctx, id, fileCabinet, signed) { const models = Self.app.models; - const docuwareConfig = await models.DocuwareConfig.findOne(); + const action = 'find'; + const docuwareInfo = await models.Docuware.findOne({ where: { 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 = { condition: [ { - DBName: find, + DBName: docuwareInfo.findById, + Value: [id] } + ], + sortOrder: [ + { + Field: 'FILENAME', + Direction: 'Desc' + } ] }; try { - // get fileCabinetId - const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options); - const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet; - const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id; + const options = await Self.getOptions(); - // get dialog - 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; + const fileCabinetId = await Self.getFileCabinet(fileCabinet); + const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); - // get docuwareID - Object.assign(options, {'body': JSON.stringify(searchFilter)}); - const response = await got.post( - `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options); - JSON.parse(response.body).Items[0].Id; + const response = await axios.post( + `${options.url}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, + searchFilter, + options.headers + ); + 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) { return false; } diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js new file mode 100644 index 000000000..2053ddf85 --- /dev/null +++ b/back/methods/docuware/core.js @@ -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 + }; + }; +}; diff --git a/back/methods/docuware/deliveryNoteEmail.js b/back/methods/docuware/deliveryNoteEmail.js new file mode 100644 index 000000000..1f9d7556f --- /dev/null +++ b/back/methods/docuware/deliveryNoteEmail.js @@ -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] + }] + }); + }; +}; diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js index 489a07e34..56d006ee7 100644 --- a/back/methods/docuware/download.js +++ b/back/methods/docuware/download.js @@ -1,5 +1,5 @@ /* eslint max-len: ["error", { "code": 180 }]*/ -const got = require('got'); +const axios = require('axios'); const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { @@ -10,19 +10,13 @@ module.exports = Self => { { arg: 'id', type: 'number', - description: 'The id', + description: 'The ticket id', http: {source: 'path'} }, { arg: 'fileCabinet', type: 'string', - description: 'The id', - http: {source: 'path'} - }, - { - arg: 'dialog', - type: 'string', - description: 'The id', + description: 'The file cabinet', http: {source: 'path'} } ], @@ -42,79 +36,26 @@ module.exports = Self => { } ], http: { - path: `/:id/download/:fileCabinet/:dialog`, + path: `/:id/download/:fileCabinet`, verb: 'GET' } }); - Self.download = async function(ctx, id, fileCabinet, dialog) { - const myUserId = ctx.req.accessToken.userId; - if (!myUserId) - throw new UserError(`You don't have enough privileges`); - + Self.download = async function(ctx, id, fileCabinet) { const models = Self.app.models; - const docuwareConfig = await models.DocuwareConfig.findOne(); - const docuwareInfo = await models.Docuware.findOne({ - where: { - code: fileCabinet, - dialogName: dialog - } - }); + const docuwareFile = await models.Docuware.checkFile(ctx, id, fileCabinet, true); + if (!docuwareFile) throw new UserError('The DOCUWARE PDF document does not exists'); - 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 = { - condition: [ - { - DBName: find, - Value: [id] - } - ] - }; + const fileCabinetId = await Self.getFileCabinet(fileCabinet); + const options = await Self.getOptions(); + options.headers.responseType = 'stream'; - try { - // get fileCabinetId - const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options); - const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet; - const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id; + const fileName = `filename="${id}.pdf"`; + const contentType = 'application/pdf'; + const downloadUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/FileDownload?targetFileType=Auto&keepAnnotations=false`; - // get dialog - 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; + const stream = await axios.get(downloadUri, options.headers); - // get docuwareID - 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; - } + return [stream.data, contentType, fileName]; }; }; diff --git a/back/methods/docuware/specs/checkFile.spec.js b/back/methods/docuware/specs/checkFile.spec.js index 0d0e4d71a..dd11951cc 100644 --- a/back/methods/docuware/specs/checkFile.spec.js +++ b/back/methods/docuware/specs/checkFile.spec.js @@ -1,5 +1,5 @@ const models = require('vn-loopback/server/server').models; -const got = require('got'); +const axios = require('axios'); describe('docuware download()', () => { const ticketId = 1; @@ -12,53 +12,71 @@ describe('docuware download()', () => { } }; - const fileCabinetName = 'deliveryClient'; - const dialogDisplayName = 'find'; - const dialogName = 'findTicket'; + const docuwareModel = models.Docuware; + const fileCabinetName = 'deliveryNote'; - const gotGetResponse = { - body: JSON.stringify( - { - 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); + 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 not exist file in docuware', async() => { - const gotPostResponse = { - body: JSON.stringify( - { - Items: [], - }) + 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(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); + 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); + + 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); + }); }); diff --git a/back/methods/docuware/specs/download.spec.js b/back/methods/docuware/specs/download.spec.js index dc80c67d8..fcc1671a6 100644 --- a/back/methods/docuware/specs/download.spec.js +++ b/back/methods/docuware/specs/download.spec.js @@ -1,5 +1,5 @@ const models = require('vn-loopback/server/server').models; -const got = require('got'); +const axios = require('axios'); const stream = require('stream'); describe('docuware download()', () => { @@ -13,36 +13,33 @@ describe('docuware download()', () => { } }; - it('should return the downloaded file name', async() => { - const fileCabinetName = 'deliveryClient'; - const dialogDisplayName = 'find'; - const dialogName = 'findTicket'; - const gotGetResponse = { - body: JSON.stringify( - { - FileCabinet: [ - {Id: 12, Name: fileCabinetName} - ], - Dialog: [ - {Id: 34, DisplayName: dialogDisplayName} - ] - }) - }; + const docuwareModel = models.Docuware; + const fileCabinetName = 'deliveryNote'; - const gotPostResponse = { - body: JSON.stringify( - { - Items: [ - {Id: 56} - ], - }) - }; + beforeAll(() => { + spyOn(docuwareModel, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); + spyOn(docuwareModel, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); + }); - spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse))); - spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse))); - spyOn(got, 'stream').and.returnValue(new stream.PassThrough({objectMode: true})); + it('should return error if file not exist', async() => { + spyOn(docuwareModel, 'checkFile').and.returnValue(false); + 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[2]).toEqual(`filename="${ticketId}.pdf"`); diff --git a/back/methods/docuware/specs/upload.spec.js b/back/methods/docuware/specs/upload.spec.js new file mode 100644 index 000000000..7ac873e95 --- /dev/null +++ b/back/methods/docuware/specs/upload.spec.js @@ -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'); + }); +}); diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js new file mode 100644 index 000000000..b5ee3d18f --- /dev/null +++ b/back/methods/docuware/upload.js @@ -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, + }, + { + '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'); + }); + }; +}; diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 33fe5958b..32b369c8d 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -25,36 +25,43 @@ module.exports = Self => { return false; const con = mysql.createConnection({ - host: `${config.hostDb}`, - user: `${config.userDb}`, - password: `${config.passwordDb}`, - port: `${config.portDb}` + host: config.hostDb, + user: config.userDb, + password: config.passwordDb, + port: config.portDb }); const sql = `SELECT ot.ticket_id, ot.number FROM osticket.ost_ticket ot - JOIN osticket.ost_ticket_status ots ON ots.id = ot.status_id + JOIN osticket.ost_ticket_status ots ON ots.id = ot.status_id JOIN osticket.ost_thread ot2 ON ot2.object_id = ot.ticket_id AND ot2.object_type = 'T' JOIN ( - SELECT ote.thread_id, MAX(ote.created) created, MAX(ote.updated) updated - FROM osticket.ost_thread_entry ote - WHERE ote.staff_id != 0 AND ote.type = 'R' - GROUP BY ote.thread_id - ) sub ON sub.thread_id = ot2.id - WHERE ot.isanswered = 1 - AND ots.state = '${config.oldStatus}' - AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ${config.day} DAY)`; + SELECT sub2.thread_id, sub2.type, sub2.updated, sub2.created + FROM ( + SELECT ote.thread_id, ote.created, ote.updated, ote.type + FROM osticket.ost_thread_entry ote + WHERE ote.staff_id + ORDER BY ote.id DESC + LIMIT 10000000000000000000) sub2 + GROUP BY sub2.thread_id + ) sub ON sub.thread_id = ot2.id + WHERE ot.isanswered + AND ots.id IN (?) + AND sub.type = 'R' + AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY);`; + + const ticketsId = []; + const statusIdToClose = config.oldStatus.split(','); - let ticketsId = []; con.connect(err => { if (err) throw err; - con.query(sql, (err, results) => { - if (err) throw err; - for (const result of results) - ticketsId.push(result.ticket_id); - }); + con.query(sql, [statusIdToClose, config.day], + (err, results) => { + if (err) throw err; + for (const result of results) + ticketsId.push(result.ticket_id); + }); }); - await getRequestToken(); async function getRequestToken() { @@ -94,6 +101,44 @@ module.exports = Self => { await close(token, secondCookie); } + async function close(token, secondCookie) { + for (const ticketId of ticketsId) { + try { + const lock = await getLockCode(token, secondCookie, ticketId); + if (!lock.code) { + let error = `Can't get lock code`; + if (lock.msg) error += `: ${lock.msg}`; + throw new Error(error); + } + let form = new FormData(); + form.append('__CSRFToken__', token); + form.append('id', ticketId); + form.append('a', config.responseType); + form.append('lockCode', lock.code); + form.append('from_email_id', config.fromEmailId); + form.append('reply-to', config.replyTo); + form.append('cannedResp', 0); + form.append('response', config.comment); + form.append('signature', 'none'); + form.append('reply_status_id', config.newStatusId); + + const ostUri = `${config.host}/tickets.php?id=${ticketId}`; + const params = { + method: 'POST', + body: form, + headers: { + 'Cookie': secondCookie + } + }; + await fetch(ostUri, params); + } catch (e) { + const err = new Error(`${ticketId} Ticket close failed: ${e.message}`); + err.stack += e.stack; + console.error(err); + } + } + } + async function getLockCode(token, secondCookie, ticketId) { const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`; const params = { @@ -107,34 +152,7 @@ module.exports = Self => { const body = await response.text(); const json = JSON.parse(body); - return json.code; - } - - async function close(token, secondCookie) { - for (const ticketId of ticketsId) { - const lockCode = await getLockCode(token, secondCookie, ticketId); - let form = new FormData(); - form.append('__CSRFToken__', token); - form.append('id', ticketId); - form.append('a', config.responseType); - form.append('lockCode', lockCode); - form.append('from_email_id', config.fromEmailId); - form.append('reply-to', config.replyTo); - form.append('cannedResp', 0); - form.append('response', config.comment); - form.append('signature', 'none'); - form.append('reply_status_id', config.newStatusId); - - const ostUri = `${config.host}/tickets.php?id=${ticketId}`; - const params = { - method: 'POST', - body: form, - headers: { - 'Cookie': secondCookie - } - }; - return fetch(ostUri, params); - } + return json; } }; }; diff --git a/back/models/collection.js b/back/models/collection.js index 436414f62..a41742ee7 100644 --- a/back/models/collection.js +++ b/back/models/collection.js @@ -3,4 +3,5 @@ module.exports = Self => { require('../methods/collection/newCollection')(Self); require('../methods/collection/getSectors')(Self); require('../methods/collection/setSaleQuantity')(Self); + require('../methods/collection/previousLabel')(Self); }; diff --git a/back/models/docuware-config.json b/back/models/docuware-config.json index 8ca76d8ba..9d06c4874 100644 --- a/back/models/docuware-config.json +++ b/back/models/docuware-config.json @@ -16,7 +16,7 @@ "url": { "type": "string" }, - "token": { + "cookie": { "type": "string" } }, @@ -29,4 +29,4 @@ "permission": "ALLOW" } ] -} \ No newline at end of file +} diff --git a/back/models/docuware.js b/back/models/docuware.js index 8fd8065ed..b983f7bb4 100644 --- a/back/models/docuware.js +++ b/back/models/docuware.js @@ -1,4 +1,7 @@ module.exports = Self => { require('../methods/docuware/download')(Self); + require('../methods/docuware/upload')(Self); require('../methods/docuware/checkFile')(Self); + require('../methods/docuware/deliveryNoteEmail')(Self); + require('../methods/docuware/core')(Self); }; diff --git a/back/models/docuware.json b/back/models/docuware.json index fb2ed919e..dec20eede 100644 --- a/back/models/docuware.json +++ b/back/models/docuware.json @@ -19,20 +19,14 @@ "fileCabinetName": { "type": "string" }, + "action": { + "type": "string" + }, "dialogName": { "type": "string" }, - "find": { + "findById": { "type": "string" } - }, - "acls": [ - { - "property": "*", - "accessType": "*", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - } - ] -} \ No newline at end of file + } +} diff --git a/db/changes/224903/00-insert_notification_invoiceE.sql b/db/changes/224903/00-insert_notification_invoiceE.sql deleted file mode 100644 index 1d416c196..000000000 --- a/db/changes/224903/00-insert_notification_invoiceE.sql +++ /dev/null @@ -1 +0,0 @@ -insert into `util`.`notification` (`id`, `name`,`description`) values (2, 'invoiceElectronic', 'A electronic invoice has been generated'); \ No newline at end of file diff --git a/db/changes/225001/00-updateCollection.sql b/db/changes/225001/00-updateCollection.sql new file mode 100644 index 000000000..6d4ec4307 --- /dev/null +++ b/db/changes/225001/00-updateCollection.sql @@ -0,0 +1,3 @@ +UPDATE `vn`.`collection` + SET sectorFk=1 + WHERE id=1; diff --git a/db/changes/225201/00-invoiceOut_new.sql b/db/changes/225201/00-invoiceOut_new.sql new file mode 100644 index 000000000..10a42d40d --- /dev/null +++ b/db/changes/225201/00-invoiceOut_new.sql @@ -0,0 +1,225 @@ +DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`; +DELIMITER $$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`( + vSerial VARCHAR(255), + vInvoiceDate DATETIME, + vTaxArea VARCHAR(25), + OUT vNewInvoiceId INT) +BEGIN +/** + * Creación de facturas emitidas. + * requiere previamente tabla ticketToInvoice(id). + * + * @param vSerial serie a la cual se hace la factura + * @param vInvoiceDate fecha de la factura + * @param vTaxArea tipo de iva en relacion a la empresa y al cliente + * @param vNewInvoiceId id de la factura que se acaba de generar + * @return vNewInvoiceId + */ + DECLARE vSpainCountryCode INT DEFAULT 1; + DECLARE vIsAnySaleToInvoice BOOL; + DECLARE vIsAnyServiceToInvoice BOOL; + DECLARE vNewRef VARCHAR(255); + DECLARE vWorker INT DEFAULT account.myUser_getId(); + DECLARE vCompany INT; + DECLARE vSupplier INT; + DECLARE vClient INT; + DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1; + DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6; + DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2; + DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R'; + DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S'; + DECLARE vNewInvoiceInId INT; + DECLARE vIsInterCompany BOOL; + + SET vInvoiceDate = IFNULL(vInvoiceDate,CURDATE()); + + SELECT t.clientFk, t.companyFk + INTO vClient, vCompany + FROM ticketToInvoice tt + JOIN ticket t ON t.id = tt.id + LIMIT 1; + + -- Eliminem de ticketToInvoice els tickets que no han de ser facturats + DELETE ti.* + FROM ticketToInvoice ti + JOIN ticket t ON t.id = ti.id + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN supplier su ON su.id = t.companyFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk + WHERE YEAR(t.shipped) < 2001 + OR c.isTaxDataChecked = FALSE + OR t.isDeleted + OR c.hasToInvoice = FALSE + OR itc.id IS NULL; + + SELECT SUM(s.quantity * s.price * (100 - s.discount)/100), ts.id + INTO vIsAnySaleToInvoice, vIsAnyServiceToInvoice + FROM ticketToInvoice t + LEFT JOIN sale s ON s.ticketFk = t.id + LEFT JOIN ticketService ts ON ts.ticketFk = t.id; + + IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice) + AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase()) + THEN + + -- el trigger añade el siguiente Id_Factura correspondiente a la vSerial + INSERT INTO invoiceOut + ( + ref, + serial, + issued, + clientFk, + dued, + companyFk, + cplusInvoiceType477Fk + ) + SELECT + 1, + vSerial, + vInvoiceDate, + vClient, + getDueDate(vInvoiceDate, dueDay), + vCompany, + IF(vSerial = vCorrectingSerial, + vCplusCorrectingInvoiceTypeFk, + IF(vSerial = vSimplifiedSerial, + vCplusSimplifiedInvoiceTypeFk, + vCplusStandardInvoiceTypeFk)) + FROM client + WHERE id = vClient; + + + SET vNewInvoiceId = LAST_INSERT_ID(); + + SELECT `ref` + INTO vNewRef + FROM invoiceOut + WHERE id = vNewInvoiceId; + + UPDATE ticket t + JOIN ticketToInvoice ti ON ti.id = t.id + SET t.refFk = vNewRef; + + DROP TEMPORARY TABLE IF EXISTS tmp.updateInter; + CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY + SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador + FROM ticketToInvoice ti + LEFT JOIN ticketState ts ON ti.id = ts.ticket + JOIN state s + WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id); + + INSERT INTO vncontrol.inter(state_id,Id_Ticket,Id_Trabajador) + SELECT * FROM tmp.updateInter; + + INSERT INTO ticketLog (action, userFk, originFk, description) + SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef) + FROM ticketToInvoice ti; + + CALL invoiceExpenceMake(vNewInvoiceId); + CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); + + UPDATE invoiceOut io + JOIN ( + SELECT SUM(amount) AS total + FROM invoiceOutExpence + WHERE invoiceOutFk = vNewInvoiceId + ) base + JOIN ( + SELECT SUM(vat) AS total + FROM invoiceOutTax + WHERE invoiceOutFk = vNewInvoiceId + ) vat + SET io.amount = base.total + vat.total + WHERE io.id = vNewInvoiceId; + + DROP TEMPORARY TABLE tmp.updateInter; + + SELECT ios.isCEE INTO vIsInterCompany + FROM vn.ticket t + JOIN vn.invoiceOut io ON io.`ref` = t.refFk + JOIN vn.invoiceOutSerial ios ON ios.code = io.serial + WHERE t.refFk = vNewRef + LIMIT 1; + + IF (vIsInterCompany) THEN + + SELECT vCompany INTO vSupplier; + SELECT id INTO vCompany FROM company WHERE clientFk = vClient; + + INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk) + SELECT vSupplier, vNewRef, vInvoiceDate, vCompany; + + SET vNewInvoiceInId = LAST_INSERT_ID(); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket; + CREATE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM ticketToInvoice; + + CALL `ticket_getTax`('NATIONAL'); + + SET @vTaxableBaseServices := 0.00; + SET @vTaxCodeGeneral := NULL; + + INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInId, @vTaxableBaseServices, sub.expenceFk, sub.taxTypeSageFk , sub.transactionTypeSageFk + FROM ( + SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk, @vTaxCodeGeneral := i.taxClassCodeFk + FROM tmp.ticketServiceTax tst + JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code + WHERE i.isService + HAVING taxableBase + ) sub; + + INSERT INTO vn.invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInId, SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, @vTaxableBaseServices, 0) taxableBase, i.expenceFk, i.taxTypeSageFk , i.transactionTypeSageFk + FROM tmp.ticketTax tt + JOIN vn.invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code + WHERE !i.isService + GROUP BY tt.pgcFk + HAVING taxableBase + ORDER BY tt.priority; + + CALL invoiceInDueDay_calculate(vNewInvoiceInId); + + INSERT INTO invoiceInIntrastat ( + invoiceInFk, + intrastatFk, + amount, + stems, + countryFk, + net) + SELECT + vNewInvoiceInId invoiceInFk, + i.intrastatFk, + CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) subtotal, + CAST(SUM(IFNULL(i.stems, 1) * s.quantity) AS DECIMAL(10,2)) stems, + su.countryFk, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, i.weightByPiece) / 1000) AS DECIMAL(10,2)) netKg + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + JOIN vn.itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + JOIN intrastat ir ON ir.id = i.intrastatFk + WHERE t.refFk = vNewRef; + + DROP TEMPORARY TABLE tmp.ticket; + DROP TEMPORARY TABLE tmp.ticketAmount; + DROP TEMPORARY TABLE tmp.ticketTax; + DROP TEMPORARY TABLE tmp.ticketServiceTax; + + END IF; + + END IF; + + DROP TEMPORARY TABLE `ticketToInvoice`; +END$$ +DELIMITER ; diff --git a/db/changes/225201/01-modules.sql b/db/changes/225201/01-modules.sql index 82861a5e2..243d2d016 100644 --- a/db/changes/225201/01-modules.sql +++ b/db/changes/225201/01-modules.sql @@ -43,7 +43,7 @@ SET t.code = 'claim' WHERE t.code LIKE 'Claims' ESCAPE '#'; UPDATE salix.module t -SET t.code = 'user' +SET t.code = 'account' WHERE t.code LIKE 'Users' ESCAPE '#'; UPDATE salix.module t diff --git a/db/changes/225202/00-mdbApp.sql b/db/changes/225202/00-mdbApp.sql new file mode 100644 index 000000000..50c595d71 --- /dev/null +++ b/db/changes/225202/00-mdbApp.sql @@ -0,0 +1,28 @@ +ALTER TABLE `vn`.`mdbApp` DROP PRIMARY KEY; +ALTER TABLE `vn`.`mdbApp` ADD CONSTRAINT mdbApp_PK PRIMARY KEY (app,baselineBranchFk); + +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('com','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('enc','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('ent','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('eti','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('lab','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('tpv','master'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('com','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('enc','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('ent','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('eti','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('lab','dev'); +INSERT INTO `vn`.`mdbApp` (app,baselineBranchFk) + VALUES ('tpv','dev'); + diff --git a/db/changes/225203/00-mdbApp.sql b/db/changes/225203/00-mdbApp.sql new file mode 100644 index 000000000..32a21eb6b --- /dev/null +++ b/db/changes/225203/00-mdbApp.sql @@ -0,0 +1,5 @@ +UPDATE `vn`.`osTicketConfig` +SET oldStatus='1,6' +WHERE id=0; + + diff --git a/db/changes/230201/00-borradoLogicoIPT.sql b/db/changes/230201/00-borradoLogicoIPT.sql new file mode 100644 index 000000000..ae7ecf0ca --- /dev/null +++ b/db/changes/230201/00-borradoLogicoIPT.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`itemPackingType` ADD isActive BOOLEAN NOT NULL; +UPDATE `vn`.`itemPackingType` SET isActive = 0 WHERE code IN ('P', 'F'); +UPDATE `vn`.`itemPackingType` SET isActive = 1 WHERE code IN ('V', 'H'); diff --git a/db/changes/230201/00-docuwareStore.sql b/db/changes/230201/00-docuwareStore.sql new file mode 100644 index 000000000..b20c2554f --- /dev/null +++ b/db/changes/230201/00-docuwareStore.sql @@ -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; diff --git a/db/changes/230201/00-priceFixed_getRate2.sql b/db/changes/230201/00-priceFixed_getRate2.sql new file mode 100644 index 000000000..cf36efb57 --- /dev/null +++ b/db/changes/230201/00-priceFixed_getRate2.sql @@ -0,0 +1,23 @@ +DROP FUNCTION IF EXISTS `vn`.`priceFixed_getRate2`; + +DELIMITER $$ +$$ +CREATE FUNCTION `vn`.`priceFixed_getRate2`(vFixedPriceFk INT, vRate3 DOUBLE) +RETURNS DOUBLE +BEGIN + + DECLARE vWarehouse INT; + DECLARE vRate2 DOUBLE; + + SELECT round(vRate3 * (1 + ((r.rate2 - r.rate3)/100)), 2) INTO vRate2 + FROM vn.rate r + JOIN vn.priceFixed p ON p.id = vFixedPriceFk + WHERE r.dated <= p.started + AND r.warehouseFk = p.warehouseFk + ORDER BY r.dated DESC + LIMIT 1; + + RETURN vRate2; + +END$$ +DELIMITER ; diff --git a/db/changes/230201/00-triggersXDiario.sql b/db/changes/230201/00-triggersXDiario.sql new file mode 100644 index 000000000..5cf0b6253 --- /dev/null +++ b/db/changes/230201/00-triggersXDiario.sql @@ -0,0 +1,73 @@ +DROP TRIGGER IF EXISTS vn.XDiario_beforeUpdate; +USE vn; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`XDiario_beforeUpdate` + BEFORE UPDATE ON `XDiario` + FOR EACH ROW +BEGIN + IF NOT NEW.SUBCTA <=> OLD.SUBCTA THEN + IF NEW.SUBCTA <=> '' THEN + SET NEW.SUBCTA = NULL; + END IF; + IF NEW.SUBCTA IS NOT NULL AND NOT LENGTH(NEW.SUBCTA) <=> 10 THEN + CALL util.throw('INVALID_STRING_LENGTH'); + END IF; + END IF; + IF NOT NEW.CONTRA <=> OLD.CONTRA THEN + IF NEW.CONTRA <=> '' THEN + SET NEW.CONTRA = NULL; + END IF; + IF NEW.CONTRA IS NOT NULL AND NOT LENGTH(NEW.CONTRA) <=> 10 THEN + CALL util.throw('INVALID_STRING_LENGTH'); + END IF; + END IF; + IF NOT NEW.FECHA <=> OLD.FECHA THEN + CALL XDiario_checkDate(NEW.FECHA); + END IF; + IF NOT NEW.FECHA_EX <=> OLD.FECHA_EX THEN + CALL XDiario_checkDate(NEW.FECHA_EX); + END IF; + IF NOT NEW.FECHA_OP <=> OLD.FECHA_OP THEN + CALL XDiario_checkDate(NEW.FECHA_OP); + END IF; + IF NOT NEW.FECHA_RT <=> OLD.FECHA_RT THEN + CALL XDiario_checkDate(NEW.FECHA_RT); + END IF; + IF NOT NEW.FECREGCON <=> OLD.FECREGCON THEN + CALL XDiario_checkDate(NEW.FECREGCON); + END IF; +END$$ +DELIMITER ; + + +DROP TRIGGER IF EXISTS vn.XDiario_beforeInsert; +USE vn; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`XDiario_beforeInsert` + BEFORE INSERT ON `XDiario` + FOR EACH ROW +BEGIN + IF NEW.SUBCTA <=> '' THEN + SET NEW.SUBCTA = NULL; + END IF; + IF NEW.SUBCTA IS NOT NULL AND NOT LENGTH(NEW.SUBCTA) <=> 10 THEN + CALL util.throw('INVALID_STRING_LENGTH'); + END IF; + IF NEW.CONTRA <=> '' THEN + SET NEW.CONTRA = NULL; + END IF; + IF NEW.CONTRA IS NOT NULL AND NOT LENGTH(NEW.CONTRA) <=> 10 THEN + CALL util.throw('INVALID_STRING_LENGTH'); + END IF; + CALL XDiario_checkDate(NEW.FECHA); + CALL XDiario_checkDate(NEW.FECHA_EX); + CALL XDiario_checkDate(NEW.FECHA_OP); + CALL XDiario_checkDate(NEW.FECHA_RT); + CALL XDiario_checkDate(NEW.FECREGCON); +END$$ +DELIMITER ; + diff --git a/db/changes/230201/00-workerTimeControlConfig.sql b/db/changes/230201/00-workerTimeControlConfig.sql new file mode 100644 index 000000000..c04acd936 --- /dev/null +++ b/db/changes/230201/00-workerTimeControlConfig.sql @@ -0,0 +1,6 @@ +ALTER TABLE `vn`.`workerTimeControlConfig` ADD teleworkingStart INT NULL COMMENT 'Hora comienzo jornada de los teletrabajdores expresada en segundos'; +ALTER TABLE `vn`.`workerTimeControlConfig` ADD teleworkingStartBreakTime INT NULL COMMENT 'Hora comienzo descanso de los teletrabjadores expresada en segundos'; + +UPDATE `vn`.`workerTimeControlConfig` + SET `teleworkingStart`=28800, `teleworkingStartBreakTime`=32400 +WHERE `id`=1; diff --git a/db/changes/225001/.gitkeep b/db/changes/230401/.gitkeep similarity index 100% rename from db/changes/225001/.gitkeep rename to db/changes/230401/.gitkeep diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index f1c9df51f..ece33f813 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1215,7 +1215,7 @@ INSERT INTO `vn`.`tag`(`id`, `code`, `name`, `isFree`, `isQuantitatif`, `sourceT (7, NULL, 'Ancho de la base', 1, 1, NULL, 'mm',NULL, NULL), (23, 'stems', 'Tallos', 1, 1, NULL, NULL, NULL, 'stems'), (27, NULL, 'Longitud(cm)', 1, 1, NULL, 'cm', NULL, NULL), - (36, NULL, 'Proveedor', 1, 0, NULL, NULL, NULL, NULL), + (36, 'producer', 'Proveedor', 1, 0, NULL, NULL, NULL, 'producer'), (56, NULL, 'Genero', 1, 0, NULL, NULL, NULL, NULL), (58, NULL, 'Variedad', 1, 0, NULL, NULL, NULL, NULL), (67, 'category', 'Categoria', 1, 0, NULL, NULL, NULL, NULL), @@ -2580,13 +2580,9 @@ INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`) (4, 33.8, util.VN_CURDATE(), 1, 1101), (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`) VALUES - ('https://verdnatura.docuware.cloud/docuware/platform'); + ('http://docuware.url/'); INSERT INTO `vn`.`calendarHolidaysName` (`id`, `name`) VALUES @@ -2671,9 +2667,9 @@ INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk VALUES (1, 1); -INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`) +INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`) VALUES - (1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13); + (1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13, 28800, 32400); INSERT INTO `vn`.`host` (`id`, `code`, `description`, `warehouseFk`, `bankFk`) VALUES @@ -2692,6 +2688,7 @@ INSERT INTO `util`.`notificationConfig` INSERT INTO `util`.`notification` (`id`, `name`, `description`) VALUES (1, 'print-email', 'notification fixture one'), + (2, 'invoice-electronic', 'A electronic invoice has been generated'), (4, 'supplier-pay-method-update', 'A supplier pay method has been updated'); INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) @@ -2744,7 +2741,7 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES - (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); + (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`) VALUES diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 47fdd6d74..772d6055d 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -80202,3 +80202,5 @@ USE `vncontrol`; -- Dump completed on 2022-11-21 7:57:28 + + diff --git a/db/export-data.sh b/db/export-data.sh index 8bff538a7..bdf8049e0 100755 --- a/db/export-data.sh +++ b/db/export-data.sh @@ -59,6 +59,7 @@ TABLES=( componentType continent department + docuware itemPackingType pgc sample diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 052d8a480..c0f10a506 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -417,8 +417,8 @@ export default { fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)', fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]', fourthWarehouse: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.warehouseFk"]', - fourthPPU: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)', - fourthPPP: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)', + fourthGroupingPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)', + fourthPackingPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)', fourthHasMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-check[ng-model="price.hasMinPrice"]', fourthMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-input-number[ng-model="price.minPrice"]', fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]', @@ -679,7 +679,10 @@ export default { moveToTicketButton: '.vn-popover.shown vn-icon[icon="arrow_forward_ios"]', moveToNewTicketButton: '.vn-popover.shown vn-button[label="New ticket"]', stateMenuButton: 'vn-ticket-sale vn-tool-bar > vn-button-menu[label="State"]', - moreMenuState: 'body > div > div > div.content > div.filter.ng-scope > vn-textfield' + moreMenuState: 'body > div > div > div.content > div.filter.ng-scope > vn-textfield', + firstSaleHistoryButton: 'vn-ticket-sale vn-tr:nth-child(1) vn-icon-button[icon="history"]', + firstSaleHistory: 'form vn-table div > vn-tbody > vn-tr', + closeHistory: 'div.window vn-button[icon="clear"]' }, ticketTracking: { createStateButton: 'vn-float-button' diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js index 4fc280209..ad558ace2 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -15,7 +15,7 @@ describe('SmartTable SearchBar integration', () => { await browser.close(); }); - describe('as filters', () => { + describe('as filters in smart-table section', () => { it('should search by type in searchBar', async() => { await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); @@ -47,6 +47,34 @@ describe('SmartTable SearchBar integration', () => { }); }); + describe('as filters in section without smart-table', () => { + it('go to zone section', async() => { + await page.loginAndModule('salesPerson', 'zone'); + await page.waitToClick(selectors.globalItems.searchButton); + }); + + it('should search in searchBar first time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + + it('should search in searchBar second time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + + it('should search in searchBar third time', async() => { + await page.doSearch('A'); + const count = await page.countElement(selectors.zoneIndex.searchResult); + + expect(count).toEqual(7); + }); + }); + describe('as orders', () => { it('should order by first id', async() => { await page.loginAndModule('developer', 'item'); diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index fc7aac3d0..40ccc009e 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -24,8 +24,8 @@ describe('Item fixed prices path', () => { it('should fill the fixed price data', async() => { const now = new Date(); await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one'); - await page.write(selectors.itemFixedPrice.fourthPPU, '1'); - await page.write(selectors.itemFixedPrice.fourthPPP, '1'); + await page.writeOnEditableTD(selectors.itemFixedPrice.fourthGroupingPrice, '1'); + await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPackingPrice, '1'); await page.write(selectors.itemFixedPrice.fourthMinPrice, '1'); await page.pickDate(selectors.itemFixedPrice.fourthStarted, now); await page.pickDate(selectors.itemFixedPrice.fourthEnded, now); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index 67dfd83bf..9d6fddbe6 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -196,6 +196,15 @@ describe('Ticket Edit sale path', () => { expect(result).toContain('22.50'); }); + it('should check in the history that logs has been added', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton); + await page.waitForSelector(selectors.ticketSales.firstSaleHistory); + const result = await page.countElement(selectors.ticketSales.firstSaleHistory); + + expect(result).toBeGreaterThan(0); + await page.waitToClick(selectors.ticketSales.closeHistory); + }); + it('should recalculate price of sales', async() => { await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); await page.waitToClick(selectors.ticketSales.secondSaleCheckbox); diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 45c39de86..34ae3d688 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -55,7 +55,7 @@ describe('Ticket Future path', () => { await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); it('should search with the destination IPT', async() => { @@ -68,7 +68,7 @@ describe('Ticket Future path', () => { await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal'); await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 0); + await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); it('should search with the origin grouped state', async() => { @@ -152,50 +152,6 @@ describe('Ticket Future path', () => { await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); }); - it('should search in smart-table with especified Lines', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableLines, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableLines, '1'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - }); - - it('should search in smart-table with especified Liters', async() => { - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableLiters, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 1); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.write(selectors.ticketFuture.tableLiters, '28'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 5); - - await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketFuture.submit); - await page.waitForNumberOfElements(selectors.ticketFuture.table, 4); - }); - it('should check the three last tickets and move to the future', async() => { await page.waitToClick(selectors.ticketFuture.multiCheck); await page.waitToClick(selectors.ticketFuture.firstCheck); diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index f2855d711..aefa89b5b 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -308,7 +308,7 @@ export default class Searchbar extends Component { this.tableQ = null; - const hasParams = this.$params.q && Object.keys(JSON.parse(this.$params.q)).length; + const hasParams = this.$params.q && JSON.parse(this.$params.q).tableQ; if (hasParams) { const stateFilter = JSON.parse(this.$params.q); for (let param in stateFilter) { @@ -325,8 +325,8 @@ export default class Searchbar extends Component { for (let param in stateFilter.tableQ) params[param] = stateFilter.tableQ[param]; - Object.assign(stateFilter, params); - return this.model.applyParams(params) + const newParams = Object.assign(stateFilter, params); + return this.model.applyParams(newParams) .then(() => this.model.data); } diff --git a/front/core/components/searchbar/searchbar.spec.js b/front/core/components/searchbar/searchbar.spec.js index ed8fd9d07..9998e7a7c 100644 --- a/front/core/components/searchbar/searchbar.spec.js +++ b/front/core/components/searchbar/searchbar.spec.js @@ -174,14 +174,12 @@ describe('Component vnSearchbar', () => { jest.spyOn(controller, 'doSearch'); controller.model = { refresh: jest.fn(), + applyFilter: jest.fn().mockReturnValue(Promise.resolve()), userParams: { id: 1 } }; - controller.model.applyParams = jest.fn().mockReturnValue(Promise.resolve()); - jest.spyOn(controller.model, 'applyParams'); - controller.filter = filter; controller.removeParam(0); diff --git a/front/salix/components/index.js b/front/salix/components/index.js index f6727fadf..8f5724862 100644 --- a/front/salix/components/index.js +++ b/front/salix/components/index.js @@ -19,4 +19,5 @@ import './user-popover'; import './upload-photo'; import './bank-entity'; import './log'; +import './instance-log'; import './sendSms'; diff --git a/front/salix/components/instance-log/index.html b/front/salix/components/instance-log/index.html new file mode 100644 index 000000000..354e81080 --- /dev/null +++ b/front/salix/components/instance-log/index.html @@ -0,0 +1,12 @@ + + + + + + + diff --git a/front/salix/components/instance-log/index.js b/front/salix/components/instance-log/index.js new file mode 100644 index 000000000..6d8497c2d --- /dev/null +++ b/front/salix/components/instance-log/index.js @@ -0,0 +1,21 @@ +import ngModule from '../../module'; +import Section from '../section'; +import './style.scss'; + +export default class Controller extends Section { + open() { + this.$.instanceLog.show(); + } +} + +ngModule.vnComponent('vnInstanceLog', { + controller: Controller, + template: require('./index.html'), + bindings: { + model: '<', + originId: '<', + changedModelId: '<', + changedModel: '@', + url: '@' + } +}); diff --git a/front/salix/components/instance-log/style.scss b/front/salix/components/instance-log/style.scss new file mode 100644 index 000000000..70cbc52dd --- /dev/null +++ b/front/salix/components/instance-log/style.scss @@ -0,0 +1,13 @@ +.vn-dialog { + & > .window:not(:has(.empty-rows)) { + width:60%; + vn-log { + vn-card { + visibility: hidden; + & > * { + visibility: visible; + } + } + } + } +} diff --git a/front/salix/components/sendSms/locale/es.yml b/front/salix/components/sendSms/locale/es.yml index 64c3fcca6..94ab8e588 100644 --- a/front/salix/components/sendSms/locale/es.yml +++ b/front/salix/components/sendSms/locale/es.yml @@ -1,7 +1,7 @@ Send SMS: Enviar SMS Destination: Destinatario Message: Mensaje -SMS sent!: ¡SMS enviado! +SMS sent: ¡SMS enviado! Characters remaining: Carácteres restantes The destination can't be empty: El destinatario no puede estar vacio The message can't be empty: El mensaje no puede estar vacio diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ea83b36c4..f6f305dc3 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -135,7 +135,7 @@ "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}}})", "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 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}}", @@ -252,5 +252,9 @@ "Receipt's bank was not found": "No se encontró el banco del recibo", "This receipt was not compensated": "Este recibo no ha sido compensado", "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" + "App name does not exist": "El nombre de aplicación no es válido", + "Try again": "Vuelve a intentarlo", + "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" } \ No newline at end of file diff --git a/modules/claim/front/card/index.js b/modules/claim/front/card/index.js index 747eea9e7..8fb35db75 100644 --- a/modules/claim/front/card/index.js +++ b/modules/claim/front/card/index.js @@ -19,9 +19,9 @@ class Controller extends ModuleCard { }, { relation: 'ticket', scope: { - fields: ['agencyModeFk'], + fields: ['zoneFk'], include: { - relation: 'agencyMode' + relation: 'zone' } } }, { diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html index 0bbacf94b..90246824b 100644 --- a/modules/claim/front/descriptor/index.html +++ b/modules/claim/front/descriptor/index.html @@ -27,16 +27,16 @@
- {{$ctrl.claim.client.salesPersonUser.name}} @@ -44,19 +44,23 @@ - {{$ctrl.claim.worker.user.name}} + label="Zone"> + + {{$ctrl.claim.ticket.zoneFk}} + - {{$ctrl.claim.ticketFk}} @@ -94,12 +98,15 @@ question="Delete claim" message="Are you sure you want to delete this claim?"> - - - \ No newline at end of file + + + diff --git a/modules/invoiceIn/front/descriptor/index.html b/modules/invoiceIn/front/descriptor/index.html index 40f7dec18..223914c9c 100644 --- a/modules/invoiceIn/front/descriptor/index.html +++ b/modules/invoiceIn/front/descriptor/index.html @@ -36,13 +36,13 @@ ng-if="$ctrl.isAgricultural()" ng-click="$ctrl.showPdfInvoice()" translate> - Show agricultural invoice as PDF + Show agricultural receipt as PDF - Send agricultural invoice as PDF + Send agricultural receipt as PDF diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index d8400dd67..35b43f9f6 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -19,6 +19,6 @@ To book: Contabilizar Total amount: Total importe Total net: Total neto Total stems: Total tallos -Show agricultural invoice as PDF: Ver factura agrícola como PDF -Send agricultural invoice as PDF: Enviar factura agrícola como PDF -New InvoiceIn: Nueva Factura \ No newline at end of file +Show agricultural receipt as PDF: Ver recibo agrícola como PDF +Send agricultural receipt as PDF: Enviar recibo agrícola como PDF +New InvoiceIn: Nueva Factura diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js index 803338ef3..26eae45ac 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js @@ -11,6 +11,7 @@ describe('InvoiceOut createPdf()', () => { const ctx = {req: activeCtx}; it('should create a new PDF file and set true the hasPdf property', async() => { + pending('https://redmine.verdnatura.es/issues/5035'); const invoiceId = 1; spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx diff --git a/modules/item/back/methods/fixed-price/getRate2.js b/modules/item/back/methods/fixed-price/getRate2.js new file mode 100644 index 000000000..c90a380e3 --- /dev/null +++ b/modules/item/back/methods/fixed-price/getRate2.js @@ -0,0 +1,39 @@ +module.exports = Self => { + Self.remoteMethod('getRate2', { + description: 'Return the rate2', + accessType: 'READ', + accepts: [ + { + arg: 'fixedPriceId', + type: 'integer', + description: 'The fixedPrice Id', + required: true + }, + { + arg: 'rate3', + type: 'number', + description: `The price rate 3`, + required: true + } + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/getRate2`, + verb: 'GET' + } + }); + + Self.getRate2 = async(fixedPriceId, rate3, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const [result] = await Self.rawSql(`SELECT vn.priceFixed_getRate2(?, ?) as rate2`, + [fixedPriceId, rate3], myOptions); + return result; + }; +}; diff --git a/modules/item/back/methods/fixed-price/specs/getRate2.spec.js b/modules/item/back/methods/fixed-price/specs/getRate2.spec.js new file mode 100644 index 000000000..2f5dd93cd --- /dev/null +++ b/modules/item/back/methods/fixed-price/specs/getRate2.spec.js @@ -0,0 +1,39 @@ +const models = require('vn-loopback/server/server').models; + +describe('getRate2()', () => { + it(`should return new rate2 if exists rate`, async() => { + const tx = await models.FixedPrice.beginTransaction({}); + + try { + const options = {transaction: tx}; + const fixedPriceId = 1; + const rate3 = 2; + const result = await models.FixedPrice.getRate2(fixedPriceId, rate3, options); + + expect(result.rate2).toEqual(1.9); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it(`should return null if not exists rate`, async() => { + const tx = await models.FixedPrice.beginTransaction({}); + + try { + const options = {transaction: tx}; + const fixedPriceId = 13; + const rate3 = 2; + const result = await models.FixedPrice.getRate2(fixedPriceId, rate3, options); + + expect(result.rate2).toEqual(null); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/item/back/models/fixed-price.js b/modules/item/back/models/fixed-price.js index 9c78c586f..91010805f 100644 --- a/modules/item/back/models/fixed-price.js +++ b/modules/item/back/models/fixed-price.js @@ -1,4 +1,5 @@ module.exports = Self => { require('../methods/fixed-price/filter')(Self); require('../methods/fixed-price/upsertFixedPrice')(Self); + require('../methods/fixed-price/getRate2')(Self); }; diff --git a/modules/item/back/models/item-packing-type.json b/modules/item/back/models/item-packing-type.json index d77c37dd8..da435db24 100644 --- a/modules/item/back/models/item-packing-type.json +++ b/modules/item/back/models/item-packing-type.json @@ -13,6 +13,9 @@ }, "description": { "type": "string" + }, + "isActive":{ + "type": "boolean" } }, "acls": [ @@ -23,4 +26,4 @@ "permission": "ALLOW" } ] -} \ No newline at end of file +} diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 9498bf96f..f9d177562 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -41,14 +41,12 @@ Warehouse - P.P.U. + field="rate2"> + Grouping price - P.P.P. + field="rate3"> + Packing price Min price @@ -72,7 +70,7 @@ show-field="name" value-field="id" search-function="$ctrl.itemSearchFunc($search)" - on-change="$ctrl.upsertPrice(price)" + on-change="$ctrl.upsertPrice(price, true)" order="id DESC" tabindex="1"> @@ -112,18 +110,32 @@ - - + + {{price.rate2 | currency: 'EUR':2}} + + + + + - - + + {{price.rate3 | currency: 'EUR':2}} + + + + + { + const rate2 = res.data.rate2; + if (rate2) { + price.rate2 = rate2; + this.upsertPrice(price); + } + }); + } } ngModule.vnComponent('vnFixedPrice', { diff --git a/modules/item/front/fixed-price/index.spec.js b/modules/item/front/fixed-price/index.spec.js index 94621e352..db9579444 100644 --- a/modules/item/front/fixed-price/index.spec.js +++ b/modules/item/front/fixed-price/index.spec.js @@ -85,5 +85,25 @@ describe('fixed price', () => { expect(controller.$.model.remove).toHaveBeenCalled(); }); }); + + describe('recalculateRate2()', () => { + it(`should rate2 recalculate`, () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + const price = { + id: 1, + itemFk: 1, + rate2: 2, + rate3: 2 + }; + const response = {rate2: 1}; + controller.recalculateRate2(price); + + const query = `FixedPrices/getRate2?fixedPriceId=${price.id}&rate3=${price.rate3}`; + $httpBackend.expectGET(query).respond(response); + $httpBackend.flush(); + + expect(price.rate2).toEqual(response.rate2); + }); + }); }); }); diff --git a/modules/item/front/fixed-price/locale/es.yml b/modules/item/front/fixed-price/locale/es.yml index 3f400336d..6bdfcb678 100644 --- a/modules/item/front/fixed-price/locale/es.yml +++ b/modules/item/front/fixed-price/locale/es.yml @@ -3,5 +3,3 @@ Search prices by item ID or code: Buscar por ID de artículo o código Search fixed prices: Buscar precios fijados Add fixed price: Añadir precio fijado This row will be removed: Esta linea se eliminará -Price By Unit: Precio Por Unidad -Price By Package: Precio Por Paquete \ No newline at end of file diff --git a/modules/mdb/back/methods/mdbVersion/last.js b/modules/mdb/back/methods/mdbVersion/last.js new file mode 100644 index 000000000..5f89f10fb --- /dev/null +++ b/modules/mdb/back/methods/mdbVersion/last.js @@ -0,0 +1,46 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('last', { + description: 'Gets the latest version of a access file', + accepts: [ + { + arg: 'appName', + type: 'string', + required: true, + description: 'The app name' + } + ], + returns: { + type: 'number', + root: true + }, + http: { + path: `/:appName/last`, + verb: 'GET' + } + }); + + Self.last = async(ctx, appName) => { + const models = Self.app.models; + const versions = await models.MdbVersion.find({ + where: {app: appName}, + fields: ['version'] + }); + + if (!versions.length) + throw new UserError('App name does not exist'); + + let maxNumber = 0; + for (let mdb of versions) { + if (mdb.version > maxNumber) + maxNumber = mdb.version; + } + + let response = { + version: maxNumber + }; + + return response; + }; +}; diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js index 5dfe5d3ef..1df4365a9 100644 --- a/modules/mdb/back/methods/mdbVersion/upload.js +++ b/modules/mdb/back/methods/mdbVersion/upload.js @@ -11,20 +11,22 @@ module.exports = Self => { type: 'string', required: true, description: 'The app name' - }, - { - arg: 'newVersion', + }, { + arg: 'toVersion', type: 'number', required: true, description: `The new version number` - }, - { + }, { arg: 'branch', type: 'string', required: true, description: `The branch name` - }, - { + }, { + arg: 'fromVersion', + type: 'string', + required: true, + description: `The old version number` + }, { arg: 'unlock', type: 'boolean', required: false, @@ -41,16 +43,13 @@ module.exports = Self => { } }); - Self.upload = async(ctx, appName, newVersion, branch, unlock, options) => { + Self.upload = async(ctx, appName, toVersion, branch, fromVersion, unlock, options) => { const models = Self.app.models; - const userId = ctx.req.accessToken.userId; const myOptions = {}; const $t = ctx.req.__; // $translate - const TempContainer = models.TempContainer; const AccessContainer = models.AccessContainer; const fileOptions = {}; - let tx; if (typeof options == 'object') @@ -63,14 +62,28 @@ module.exports = Self => { let srcFile; try { + const userId = ctx.req.accessToken.userId; const mdbApp = await models.MdbApp.findById(appName, null, myOptions); - if (mdbApp.locked && mdbApp.userFk != userId) { + if (mdbApp && mdbApp.locked && mdbApp.userFk != userId) { throw new UserError($t('App locked', { userId: mdbApp.userFk })); } + const existBranch = await models.MdbBranch.findOne({ + where: {name: branch} + }, myOptions); + + if (!existBranch) + throw new UserError('Not exist this branch'); + + let lastMethod = await Self.last(ctx, appName, myOptions); + lastMethod.version++; + + if (lastMethod.version != toVersion) + throw new UserError('Try again'); + const tempContainer = await TempContainer.container('access'); const uploaded = await TempContainer.upload(tempContainer.name, ctx.req, ctx.result, fileOptions); const files = Object.values(uploaded.files).map(file => { @@ -83,7 +96,7 @@ module.exports = Self => { const accessContainer = await AccessContainer.container('.archive'); const destinationFile = path.join( - accessContainer.client.root, accessContainer.name, appName, `${newVersion}.7z`); + accessContainer.client.root, accessContainer.name, appName, `${toVersion}.7z`); if (process.env.NODE_ENV == 'test') await fs.unlink(srcFile); @@ -104,7 +117,7 @@ module.exports = Self => { await fs.mkdir(branchPath, {recursive: true}); const destinationBranch = path.join(branchPath, `${appName}.7z`); - const destinationRelative = `../../.archive/${appName}/${newVersion}.7z`; + const destinationRelative = `../../.archive/${appName}/${toVersion}.7z`; try { await fs.unlink(destinationBranch); } catch (e) {} @@ -112,7 +125,7 @@ module.exports = Self => { if (branch == 'master') { const destinationRoot = path.join(accessContainer.client.root, `${appName}.7z`); - const rootRelative = `./.archive/${appName}/${newVersion}.7z`; + const rootRelative = `./.archive/${appName}/${toVersion}.7z`; try { await fs.unlink(destinationRoot); } catch (e) {} @@ -120,10 +133,18 @@ module.exports = Self => { } } + await models.MdbVersionTree.create({ + app: appName, + version: toVersion, + branchFk: branch, + fromVersion, + userFk: userId + }, myOptions); + await models.MdbVersion.upsert({ app: appName, branchFk: branch, - version: newVersion + version: toVersion }, myOptions); if (unlock) await models.MdbApp.unlock(ctx, appName, myOptions); @@ -133,7 +154,7 @@ module.exports = Self => { if (tx) await tx.rollback(); if (fs.existsSync(srcFile)) - await fs.unlink(srcFile); + fs.unlink(srcFile); throw e; } diff --git a/modules/mdb/back/model-config.json b/modules/mdb/back/model-config.json index 6107f8790..8010afca2 100644 --- a/modules/mdb/back/model-config.json +++ b/modules/mdb/back/model-config.json @@ -8,6 +8,9 @@ "MdbVersion": { "dataSource": "vn" }, + "MdbVersionTree": { + "dataSource": "vn" + }, "AccessContainer": { "dataSource": "accessStorage" } diff --git a/modules/mdb/back/models/mdbVersion.js b/modules/mdb/back/models/mdbVersion.js index b36ee2a60..3a7a0c6f3 100644 --- a/modules/mdb/back/models/mdbVersion.js +++ b/modules/mdb/back/models/mdbVersion.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/mdbVersion/upload')(Self); + require('../methods/mdbVersion/last')(Self); }; diff --git a/modules/mdb/back/models/mdbVersionTree.json b/modules/mdb/back/models/mdbVersionTree.json new file mode 100644 index 000000000..8c0260e54 --- /dev/null +++ b/modules/mdb/back/models/mdbVersionTree.json @@ -0,0 +1,35 @@ +{ + "name": "MdbVersionTree", + "base": "VnModel", + "options": { + "mysql": { + "table": "mdbVersionTree" + } + }, + "properties": { + "app": { + "type": "string", + "description": "The app name", + "id": true + }, + "version": { + "type": "number" + }, + "branchFk": { + "type": "string" + }, + "fromVersion": { + "type": "number" + }, + "userFk": { + "type": "number" + } + }, + "relations": { + "branch": { + "type": "belongsTo", + "model": "MdbBranch", + "foreignKey": "branchFk" + } + } +} \ No newline at end of file diff --git a/modules/monitor/front/index/tickets/index.html b/modules/monitor/front/index/tickets/index.html index 2f7c34e2d..b8559154e 100644 --- a/modules/monitor/front/index/tickets/index.html +++ b/modules/monitor/front/index/tickets/index.html @@ -79,51 +79,51 @@ @@ -133,64 +133,64 @@ - {{::ticket.id}} + {{ticket.id}} - {{::ticket.nickname}} + {{ticket.nickname}} - {{::ticket.userName | dashIfEmpty}} + {{ticket.userName | dashIfEmpty}} - - {{::ticket.shippedDate | date: 'dd/MM/yyyy'}} + + {{ticket.shippedDate | date: 'dd/MM/yyyy'}} - {{::ticket.zoneLanding | date: 'HH:mm'}} - {{::ticket.practicalHour | date: 'HH:mm'}} - {{::ticket.shipped | date: 'HH:mm'}} - {{::ticket.province}} + {{ticket.zoneLanding | date: 'HH:mm'}} + {{ticket.practicalHour | date: 'HH:mm'}} + {{ticket.shipped | date: 'HH:mm'}} + {{ticket.province}} - {{::ticket.refFk}} + {{ticket.refFk}} - {{::ticket.state}} + ng-show="!ticket.refFk" + class="chip {{ticket.classColor}}"> + {{ticket.state}} - {{::ticket.zoneName | dashIfEmpty}} + {{ticket.zoneName | dashIfEmpty}} - - {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} + + {{(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} { - this.vnApp.showMessage(this.$t('SMS sent!')); + this.vnApp.showMessage(this.$t('SMS sent')); if (res.data) this.emit('send', {response: res.data}); }); diff --git a/modules/route/front/sms/index.spec.js b/modules/route/front/sms/index.spec.js index 42bf30931..8bf35e673 100644 --- a/modules/route/front/sms/index.spec.js +++ b/modules/route/front/sms/index.spec.js @@ -30,7 +30,7 @@ describe('Route', () => { controller.onResponse(); $httpBackend.flush(); - expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!'); + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent'); }); it('should call onResponse without the destination and show an error snackbar', () => { diff --git a/modules/ticket/back/methods/sale/usesMana.js b/modules/ticket/back/methods/sale/usesMana.js index 093057dca..3f55293bf 100644 --- a/modules/ticket/back/methods/sale/usesMana.js +++ b/modules/ticket/back/methods/sale/usesMana.js @@ -24,6 +24,8 @@ module.exports = Self => { const salesDepartment = await models.Department.findOne({where: {code: 'VT'}, fields: 'id'}, myOptions); const departments = await models.Department.getLeaves(salesDepartment.id, null, myOptions); const workerDepartment = await models.WorkerDepartment.findById(userId, null, myOptions); + if (!workerDepartment) return false; + const usesMana = departments.find(department => department.id == workerDepartment.departmentFk); return usesMana ? true : false; diff --git a/modules/ticket/back/methods/ticket/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js index 6798df513..901e546f7 100644 --- a/modules/ticket/back/methods/ticket/getTicketsFuture.js +++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js @@ -108,16 +108,26 @@ module.exports = Self => { switch (param) { case 'id': return {'f.id': value}; - case 'lines': + case 'linesMax': return {'f.lines': {lte: value}}; - case 'liters': + case 'litersMax': return {'f.liters': {lte: value}}; case 'futureId': return {'f.futureId': value}; case 'ipt': - return {'f.ipt': value}; + return {or: + [ + {'f.ipt': {like: `%${value}%`}}, + {'f.ipt': null} + ] + }; case 'futureIpt': - return {'f.futureIpt': value}; + return {or: + [ + {'f.futureIpt': {like: `%${value}%`}}, + {'f.futureIpt': null} + ] + }; case 'state': return {'f.stateCode': {like: `%${value}%`}}; case 'futureState': @@ -203,7 +213,6 @@ module.exports = Self => { tmp.ticket_problems`); const sql = ParameterizedSQL.join(stmts, ';'); - const result = await conn.executeStmt(sql, myOptions); return result[ticketsIndex]; diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js index c05ba764d..51639e304 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js @@ -19,7 +19,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { await tx.rollback(); @@ -43,7 +43,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -93,7 +93,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -118,7 +118,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(1); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -143,7 +143,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -168,7 +168,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -187,13 +187,13 @@ describe('ticket getTicketsFuture()', () => { originDated: today, futureDated: today, warehouseFk: 1, - ipt: 0 + ipt: 'H' }; const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(0); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -218,7 +218,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -237,13 +237,13 @@ describe('ticket getTicketsFuture()', () => { originDated: today, futureDated: today, warehouseFk: 1, - futureIpt: 0 + futureIpt: 'H' }; const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(0); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -268,7 +268,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(1); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { @@ -293,7 +293,7 @@ describe('ticket getTicketsFuture()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsFuture(ctx, options); - expect(result.length).toEqual(4); + expect(result.length).toBeGreaterThan(0); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json index 50cfbd08a..62e763c8f 100644 --- a/modules/ticket/back/model-config.json +++ b/modules/ticket/back/model-config.json @@ -26,6 +26,9 @@ "PackingSiteConfig": { "dataSource": "vn" }, + "ExpeditionMistake": { + "dataSource": "vn" + }, "PrintServerQueue": { "dataSource": "vn" }, diff --git a/modules/ticket/back/models/expeditionMistake.json b/modules/ticket/back/models/expeditionMistake.json new file mode 100644 index 000000000..43033194a --- /dev/null +++ b/modules/ticket/back/models/expeditionMistake.json @@ -0,0 +1,33 @@ +{ + "name": "ExpeditionMistake", + "base": "VnModel", + "options": { + "mysql": { + "table": "expeditionMistake" + } + }, + "properties": { + "created": { + "type": "date" + } + }, + "relations": { + "expedition": { + "type": "belongsTo", + "model": "Expedition", + "foreignKey": "expeditionFk" + }, + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + }, + "type": { + "type": "belongsTo", + "model": "MistakeType", + "foreignKey": "typeFk" + } + } + + } + \ No newline at end of file diff --git a/modules/ticket/front/advance-search-panel/index.js b/modules/ticket/front/advance-search-panel/index.js index 259a40931..0ee16bc3c 100644 --- a/modules/ticket/front/advance-search-panel/index.js +++ b/modules/ticket/front/advance-search-panel/index.js @@ -25,7 +25,10 @@ class Controller extends SearchPanel { getItemPackingTypes() { let itemPackingTypes = []; - this.$http.get('ItemPackingTypes').then(res => { + const filter = { + where: {isActive: true} + }; + this.$http.get('ItemPackingTypes', {filter}).then(res => { for (let ipt of res.data) { itemPackingTypes.push({ code: ipt.code, diff --git a/modules/ticket/front/advance/index.js b/modules/ticket/front/advance/index.js index 1404f9472..b770440f1 100644 --- a/modules/ticket/front/advance/index.js +++ b/modules/ticket/front/advance/index.js @@ -39,6 +39,7 @@ export default class Controller extends Section { field: 'ipt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } @@ -47,6 +48,7 @@ export default class Controller extends Section { field: 'futureIpt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index 805e0b391..c2ebc3e3a 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -21,30 +21,28 @@ Add turn Show Delivery Note... as PDF - - as PDF - as PDF without prices + + as PDF signed + @@ -54,7 +52,7 @@ Send Delivery Note... @@ -64,6 +62,11 @@ translate> Send PDF + + Send PDF to tablet + @@ -323,3 +326,18 @@ question="Are you sure you want to refund all?" message="Refund all"> + + + + + + + + diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 168002d07..f6001c6b8 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -85,7 +85,6 @@ class Controller extends Section { .then(res => this.ticket = res.data) .then(() => { 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) { this.vnReport.show(`tickets/${this.id}/delivery-note-pdf`, { recipientId: this.ticket.client.id, @@ -151,7 +141,10 @@ class Controller extends Section { } 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, recipient: $data.email }); @@ -267,8 +260,15 @@ class Controller extends Section { if (client.hasElectronicInvoice) { this.$http.post(`NotificationQueues`, { - notificationFk: 'invoiceElectronic', + notificationFk: 'invoice-electronic', authorFk: client.id, + params: JSON.stringify( + { + 'name': client.name, + 'email': client.email, + 'ticketId': this.id, + 'url': window.location.href + }) }).then(() => { this.vnApp.showSuccess(this.$t('Invoice sent')); }); @@ -312,6 +312,24 @@ class Controller extends Section { return this.$http.post(`Tickets/${this.id}/sendSms`, sms) .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']; diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 48b64f4a0..67dc0affa 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -286,9 +286,34 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { describe('hasDocuware()', () => { it('should call hasDocuware method', () => { - $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond(); + $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond(true); controller.hasDocuware(); $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(); }); }); diff --git a/modules/ticket/front/descriptor-menu/locale/es.yml b/modules/ticket/front/descriptor-menu/locale/es.yml index a2725f485..b51637524 100644 --- a/modules/ticket/front/descriptor-menu/locale/es.yml +++ b/modules/ticket/front/descriptor-menu/locale/es.yml @@ -1,9 +1,11 @@ Show Delivery Note...: Ver albarán... Send Delivery Note...: Enviar albarán... as PDF: como PDF +as PDF signed: como PDF firmado as CSV: como CSV as PDF without prices: como PDF sin precios Send PDF: Enviar PDF +Send PDF to tablet: Enviar PDF a tablet Send CSV: Enviar CSV Send CSV Delivery Note: Enviar albarán en CSV 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}}" Transfer client: Transferir cliente 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? diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js index d7e7b3a5e..8a75420df 100644 --- a/modules/ticket/front/future-search-panel/index.js +++ b/modules/ticket/front/future-search-panel/index.js @@ -25,7 +25,10 @@ class Controller extends SearchPanel { getItemPackingTypes() { let itemPackingTypes = []; - this.$http.get('ItemPackingTypes').then(res => { + const filter = { + where: {isActive: true} + }; + this.$http.get('ItemPackingTypes', {filter}).then(res => { for (let ipt of res.data) { itemPackingTypes.push({ description: this.$t(ipt.description), diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index 1af1fb9ba..c0e1decc2 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -129,12 +129,12 @@ class="link"> {{::ticket.id}} - + - {{::ticket.shipped | date: 'dd/MM/yyyy'}} + {{::ticket.shipped | date: 'dd/MM/yyyy HH:mm'}} - {{::ticket.ipt}} + {{::ticket.ipt | dashIfEmpty}} @@ -150,12 +150,12 @@ {{::ticket.futureId}} - + - {{::ticket.futureShipped | date: 'dd/MM/yyyy'}} + {{::ticket.futureShipped | date: 'dd/MM/yyyy HH:mm'}} - {{::ticket.futureIpt}} + {{::ticket.futureIpt | dashIfEmpty}} diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index 56ba1608e..5fb2c8f82 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -34,6 +34,7 @@ export default class Controller extends Section { field: 'ipt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } @@ -42,6 +43,7 @@ export default class Controller extends Section { field: 'futureIpt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index c624b1a95..97f6a2a81 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -30,7 +30,7 @@ ng-click="moreOptions.show($event)" ng-show="$ctrl.hasSelectedSales()"> - - @@ -68,6 +68,7 @@ Disc Amount Packaging + @@ -84,13 +85,13 @@ vn-tooltip="{{::$ctrl.$t('Claim')}}: {{::sale.claim.claimFk}}"> - - @@ -108,21 +109,21 @@ - - {{::sale.visible}} - {{::sale.available}} @@ -195,7 +196,7 @@ translate-attr="{title: !$ctrl.isLocked ? 'Edit discount' : ''}" ng-click="$ctrl.showEditDiscountPopover($event, sale)" ng-if="sale.id"> - {{(sale.discount / 100) | percentage}} + {{(sale.discount / 100) | percentage}} @@ -204,6 +205,22 @@ {{::sale.item.itemPackingTypeFk | dashIfEmpty}} + + + + + + + @@ -383,8 +400,8 @@ - {{::ticket.id}} @@ -392,22 +409,22 @@ {{::ticket.agencyName}} {{::ticket.address}} - {{::ticket.nickname}} - {{::ticket.name}} - {{::ticket.street}} - {{::ticket.postalCode}} + {{::ticket.nickname}} + {{::ticket.name}} + {{::ticket.street}} + {{::ticket.postalCode}} {{::ticket.city}} @@ -441,10 +458,11 @@ - - + sms="$ctrl.newSMS" + on-send="$ctrl.onSmsSend($sms)"> + Refund - \ No newline at end of file + diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index f64d0b61b..618d4727d 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -389,6 +389,11 @@ class Controller extends Section { this.$.sms.open(); } + onSmsSend(sms) { + return this.$http.post(`Tickets/${this.ticket.id}/sendSms`, sms) + .then(() => this.vnApp.showSuccess(this.$t('SMS sent'))); + } + /** * Inserts a new instance */ diff --git a/modules/ticket/front/sale/locale/es.yml b/modules/ticket/front/sale/locale/es.yml index 072e57534..2668b7811 100644 --- a/modules/ticket/front/sale/locale/es.yml +++ b/modules/ticket/front/sale/locale/es.yml @@ -13,9 +13,9 @@ New ticket: Nuevo ticket Edit price: Editar precio You are going to delete lines of the ticket: Vas a eliminar lineas del ticket This ticket will be removed from current route! Continue anyway?: ¡Se eliminará el ticket de la ruta actual! ¿Continuar de todas formas? -You have to allow pop-ups in your web browser to use this functionality: +You have to allow pop-ups in your web browser to use this functionality: Debes permitir los pop-pups en tu navegador para que esta herramienta funcione correctamente -Disc: Dto +Disc: Dto Available: Disponible What is the day of receipt of the ticket?: ¿Cual es el día de preparación del pedido? Add claim: Crear reclamación @@ -39,3 +39,4 @@ Packaging: Encajado Refund: Abono Promotion mana: Maná promoción Claim mana: Maná reclamación +History: Historial diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 5174f8da2..ee8dcdf98 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -27,7 +27,7 @@
diff --git a/modules/travel/front/extra-community/index.js b/modules/travel/front/extra-community/index.js index a4ac487e6..2389570b9 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -43,16 +43,6 @@ class Controller extends Section { this.smartTableOptions = {}; } - get hasDateRange() { - const userParams = this.$.model.userParams; - const hasLanded = userParams.landedTo; - const hasShipped = userParams.shippedFrom; - const hasContinent = userParams.continent; - const hasWarehouseOut = userParams.warehouseOutFk; - - return hasLanded || hasShipped || hasContinent || hasWarehouseOut; - } - onDragInterval() { if (this.dragClientY > 0 && this.dragClientY < 75) this.$window.scrollTo(0, this.$window.scrollY - 10); diff --git a/modules/travel/front/extra-community/index.spec.js b/modules/travel/front/extra-community/index.spec.js index ae48b9ca1..18ddee665 100644 --- a/modules/travel/front/extra-community/index.spec.js +++ b/modules/travel/front/extra-community/index.spec.js @@ -14,17 +14,6 @@ describe('Travel Component vnTravelExtraCommunity', () => { controller.$.model.refresh = jest.fn(); })); - describe('hasDateRange()', () => { - it('should return truthy when shippedFrom or landedTo are set as userParams', () => { - const now = new Date(); - controller.$.model.userParams = {shippedFrom: now, landedTo: now}; - - const result = controller.hasDateRange; - - expect(result).toBeTruthy(); - }); - }); - describe('findDraggable()', () => { it('should find the draggable element', () => { const draggable = document.createElement('tr'); diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index b38405c1d..78c212e9b 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -32,94 +32,87 @@ module.exports = Self => { const models = Self.app.models; const conn = Self.dataSource.connector; const args = ctx.args; - const $t = ctx.req.__; // $translate let tx; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - const stmts = []; let stmt; - try { - if (!args.week || !args.year) { - const from = new Date(); - const to = new Date(); + if (!args.week || !args.year) { + const from = new Date(); + const to = new Date(); - const time = await models.Time.findOne({ - where: { - dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} - }, - order: 'week ASC' - }, myOptions); + const time = await models.Time.findOne({ + where: { + dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} + }, + order: 'week ASC' + }, myOptions); - args.week = time.week; - args.year = time.year; - } + args.week = time.week; + args.year = time.year; + } - const started = getStartDateOfWeekNumber(args.week, args.year); - started.setHours(0, 0, 0, 0); + const started = getStartDateOfWeekNumber(args.week, args.year); + started.setHours(0, 0, 0, 0); - const ended = new Date(started); - ended.setDate(started.getDate() + 6); - ended.setHours(23, 59, 59, 999); + const ended = new Date(started); + ended.setDate(started.getDate() + 6); + ended.setHours(23, 59, 59, 999); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate'); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate'); - if (args.workerId) { - await models.WorkerTimeControl.destroyAll({ - userFk: args.workerId, - timed: {between: [started, ended]}, - isSendMail: true - }, myOptions); + if (args.workerId) { + await models.WorkerTimeControl.destroyAll({ + userFk: args.workerId, + timed: {between: [started, ended]}, + isSendMail: true + }, myOptions); - const where = { - workerFk: args.workerId, - year: args.year, - week: args.week - }; - await models.WorkerTimeControlMail.updateAll(where, { - updated: new Date(), state: 'SENDED' - }, myOptions); + const where = { + workerFk: args.workerId, + year: args.year, + week: args.week + }; + await models.WorkerTimeControlMail.updateAll(where, { + updated: new Date(), state: 'SENDED' + }, myOptions); - stmt = new ParameterizedSQL( - `CALL vn.timeControl_calculateByUser(?, ?, ?) + stmt = new ParameterizedSQL( + `CALL vn.timeControl_calculateByUser(?, ?, ?) `, [args.workerId, started, ended]); - stmts.push(stmt); + stmts.push(stmt); - stmt = new ParameterizedSQL( - `CALL vn.timeBusiness_calculateByUser(?, ?, ?) + stmt = new ParameterizedSQL( + `CALL vn.timeBusiness_calculateByUser(?, ?, ?) `, [args.workerId, started, ended]); - stmts.push(stmt); - } else { - await models.WorkerTimeControl.destroyAll({ - timed: {between: [started, ended]}, - isSendMail: true - }, myOptions); + stmts.push(stmt); + } else { + await models.WorkerTimeControl.destroyAll({ + timed: {between: [started, ended]}, + isSendMail: true + }, myOptions); - const where = { - year: args.year, - week: args.week - }; - await models.WorkerTimeControlMail.updateAll(where, { - updated: new Date(), state: 'SENDED' - }, myOptions); + const where = { + year: args.year, + week: args.week + }; + await models.WorkerTimeControlMail.updateAll(where, { + updated: new Date(), state: 'SENDED' + }, myOptions); - stmt = new ParameterizedSQL(`CALL vn.timeControl_calculateAll(?, ?)`, [started, ended]); - stmts.push(stmt); + stmt = new ParameterizedSQL(`CALL vn.timeControl_calculateAll(?, ?)`, [started, ended]); + stmts.push(stmt); - stmt = new ParameterizedSQL(`CALL vn.timeBusiness_calculateAll(?, ?)`, [started, ended]); - stmts.push(stmt); - } + stmt = new ParameterizedSQL(`CALL vn.timeBusiness_calculateAll(?, ?)`, [started, ended]); + stmts.push(stmt); + } - stmt = new ParameterizedSQL(` + stmt = new ParameterizedSQL(` SELECT CONCAT(u.name, '@verdnatura.es') receiver, u.id workerFk, tb.dated, @@ -154,25 +147,33 @@ module.exports = Self => { AND w.businessFk ORDER BY u.id, tb.dated `, [args.workerId]); - const index = stmts.push(stmt) - 1; + const index = stmts.push(stmt) - 1; - const sql = ParameterizedSQL.join(stmts, ';'); - const days = await conn.executeStmt(sql, myOptions); + stmts.push('DROP TEMPORARY TABLE tmp.timeControlCalculate'); + stmts.push('DROP TEMPORARY TABLE tmp.timeBusinessCalculate'); - let previousWorkerFk = days[index][0].workerFk; - let previousReceiver = days[index][0].receiver; + const sql = ParameterizedSQL.join(stmts, ';'); + const days = await conn.executeStmt(sql, myOptions); - const workerTimeControlConfig = await models.WorkerTimeControlConfig.findOne(null, myOptions); + let previousWorkerFk = days[index][0].workerFk; + let previousReceiver = days[index][0].receiver; - for (let day of days[index]) { + const workerTimeControlConfig = await models.WorkerTimeControlConfig.findOne(null, myOptions); + + for (let day of days[index]) { + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + try { workerFk = day.workerFk; if (day.timeWorkDecimal > 0 && day.timeWorkedDecimal == null - && (day.permissionRate ? day.permissionRate : true)) { + && (day.permissionRate == null ? true : day.permissionRate)) { if (day.timeTable == null) { const timed = new Date(day.dated); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(8), + timed: timed.setHours(workerTimeControlConfig.teleworkingStart / 3600), manual: true, direction: 'in', isSendMail: true @@ -181,7 +182,7 @@ module.exports = Self => { if (day.timeWorkDecimal >= workerTimeControlConfig.timeToBreakTime / 3600) { await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(9), + timed: timed.setHours(workerTimeControlConfig.teleworkingStartBreakTime / 3600), manual: true, direction: 'middle', isSendMail: true @@ -189,7 +190,10 @@ module.exports = Self => { await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(9, 20), + timed: timed.setHours( + workerTimeControlConfig.teleworkingStartBreakTime / 3600, + workerTimeControlConfig.breakTime / 60 + ), manual: true, direction: 'middle', isSendMail: true @@ -199,7 +203,11 @@ module.exports = Self => { const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(8 + hoursWork, minutesWork, secondsWork), + timed: timed.setHours( + workerTimeControlConfig.teleworkingStart / 3600 + hoursWork, + minutesWork, + secondsWork + ), manual: true, direction: 'out', isSendMail: true @@ -307,7 +315,7 @@ module.exports = Self => { }, myOptions); if (firstWorkerTimeControl) - firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); + await firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); const lastWorkerTimeControl = await models.WorkerTimeControl.findOne({ where: { @@ -318,7 +326,7 @@ module.exports = Self => { }, myOptions); if (lastWorkerTimeControl) - lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); + await lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); } } @@ -339,15 +347,18 @@ module.exports = Self => { previousWorkerFk = day.workerFk; previousReceiver = day.receiver; } + + if (tx) { + await tx.commit(); + delete myOptions.transaction; + } + } catch (e) { + if (tx) await tx.rollback(); + throw e; } - - if (tx) await tx.commit(); - - return true; - } catch (e) { - if (tx) await tx.rollback(); - throw e; } + + return true; }; function getStartDateOfWeekNumber(week, year) { diff --git a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js index 5b2436be9..24bfd6904 100644 --- a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js @@ -10,7 +10,6 @@ describe('workerTimeControl sendMail()', () => { const ctx = {req: activeCtx, args: {}}; it('should fill time control of a worker without records in Journey and with rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { @@ -35,7 +34,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker without records in Journey and without rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const workdayOf20Hours = 3; const tx = await models.WorkerTimeControl.beginTransaction({}); @@ -63,7 +61,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker with records in Journey and with rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { @@ -95,7 +92,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker with records in Journey and without rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index 0cf614e57..6feadb936 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -2,7 +2,7 @@ const {Email} = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('weeklyHourRecordEmail', { - description: 'Sends the buyer waste email', + description: 'Sends the weekly hour record', accessType: 'WRITE', accepts: [ { diff --git a/modules/worker/back/models/worker-time-control-config.json b/modules/worker/back/models/worker-time-control-config.json index 4c12ce5d7..b96e2ae3b 100644 --- a/modules/worker/back/models/worker-time-control-config.json +++ b/modules/worker/back/models/worker-time-control-config.json @@ -11,8 +11,17 @@ "id": true, "type": "number" }, + "breakTime": { + "type": "number" + }, "timeToBreakTime": { "type": "number" + }, + "teleworkingStart": { + "type": "number" + }, + "teleworkingStartBreakTime": { + "type": "number" } } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 550a1ec76..31820196f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "9.0.0", "license": "GPL-3.0", "dependencies": { - "axios": "^0.25.0", + "axios": "^1.2.2", "bcrypt": "^5.0.1", "bmp-js": "^0.1.0", "compression": "^1.7.3", @@ -3893,10 +3893,13 @@ "license": "MIT" }, "node_modules/axios": { - "version": "0.25.0", - "license": "MIT", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz", + "integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==", "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": { @@ -8401,14 +8404,15 @@ } }, "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": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], - "license": "MIT", "engines": { "node": ">=4.0" }, @@ -28842,9 +28846,13 @@ "version": "1.11.0" }, "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": { - "follow-redirects": "^1.14.7" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "babel-jest": { @@ -31964,7 +31972,9 @@ } }, "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": { "version": "1.0.2", diff --git a/package.json b/package.json index 8cc33526d..2e0fb9ae8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "9.0.0", + "version": "230401", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", @@ -12,7 +12,7 @@ "node": ">=14" }, "dependencies": { - "axios": "^0.25.0", + "axios": "^1.2.2", "bcrypt": "^5.0.1", "bmp-js": "^0.1.0", "compression": "^1.7.3", diff --git a/print/package-lock.json b/print/package-lock.json deleted file mode 100644 index 2a657269f..000000000 --- a/print/package-lock.json +++ /dev/null @@ -1,3588 +0,0 @@ -{ - "name": "vn-print", - "version": "2.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vn-print", - "version": "2.0.0", - "license": "GPL-3.0", - "dependencies": { - "fs-extra": "^7.0.1", - "intl": "^1.2.5", - "js-yaml": "^3.13.1", - "jsbarcode": "^3.11.5", - "jsonexport": "^3.2.0", - "juice": "^5.2.0", - "log4js": "^6.7.0", - "mysql2": "^1.7.0", - "nodemailer": "^4.7.0", - "puppeteer-cluster": "^0.23.0", - "qrcode": "^1.4.2", - "strftime": "^0.10.0", - "vue": "^2.6.10", - "vue-i18n": "^8.15.0", - "vue-server-renderer": "^2.6.10", - "xmldom": "^0.6.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.19.3", - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@types/node": { - "version": "18.8.2", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "2.7.10", - "dependencies": { - "@babel/parser": "^7.18.4", - "postcss": "^8.4.14", - "source-map": "^0.6.1" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT", - "peer": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "license": "MIT", - "peer": true, - "engines": { - "node": "*" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "license": "Apache-2.0" - }, - "node_modules/chalk": { - "version": "2.4.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cheerio": { - "version": "0.22.0", - "license": "MIT", - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "license": "ISC", - "peer": true - }, - "node_modules/cliui": { - "version": "6.0.0", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT", - "peer": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "license": "MIT", - "peer": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/css-select": { - "version": "1.2.0", - "license": "BSD-like", - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/css-what": { - "version": "2.1.3", - "license": "BSD-2-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/csstype": { - "version": "3.1.1", - "license": "MIT" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/datauri": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "image-size": "^0.7.3", - "mimer": "^1.0.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.5.1", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/devtools-protocol": { - "version": "0.0.1045489", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/dijkstrajs": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/dom-serializer": { - "version": "0.1.1", - "license": "MIT", - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "2.4.2", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "node_modules/encode-utf8": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "license": "MIT", - "peer": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "1.1.2", - "license": "BSD-2-Clause" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "license": "MIT", - "peer": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "license": "MIT", - "peer": true - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "license": "ISC", - "peer": true - }, - "node_modules/function-bind": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/generate-function": { - "version": "2.3.1", - "license": "MIT", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "license": "MIT", - "peer": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "license": "ISC" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "deprecated": "this library is no longer supported", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/he": { - "version": "1.2.0", - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "license": "MIT", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "license": "MIT", - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.5.2", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/image-size": { - "version": "0.7.5", - "license": "MIT", - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "license": "ISC", - "peer": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/intl": { - "version": "1.2.5", - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.10.0", - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/isstream": { - "version": "0.1.2", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbarcode": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.11.5.tgz", - "integrity": "sha512-zv3KsH51zD00I/LrFzFSM6dst7rDn0vIMzaiZFL7qusTjPZiPtxg3zxetp0RR7obmjTw4f6NyGgbdkBCgZUIrA==", - "bin": { - "auto.js": "bin/barcodes/CODE128/auto.js", - "Barcode.js": "bin/barcodes/Barcode.js", - "barcodes": "bin/barcodes", - "canvas.js": "bin/renderers/canvas.js", - "checksums.js": "bin/barcodes/MSI/checksums.js", - "codabar": "bin/barcodes/codabar", - "CODE128": "bin/barcodes/CODE128", - "CODE128_AUTO.js": "bin/barcodes/CODE128/CODE128_AUTO.js", - "CODE128.js": "bin/barcodes/CODE128/CODE128.js", - "CODE128A.js": "bin/barcodes/CODE128/CODE128A.js", - "CODE128B.js": "bin/barcodes/CODE128/CODE128B.js", - "CODE128C.js": "bin/barcodes/CODE128/CODE128C.js", - "CODE39": "bin/barcodes/CODE39", - "constants.js": "bin/barcodes/ITF/constants.js", - "defaults.js": "bin/options/defaults.js", - "EAN_UPC": "bin/barcodes/EAN_UPC", - "EAN.js": "bin/barcodes/EAN_UPC/EAN.js", - "EAN13.js": "bin/barcodes/EAN_UPC/EAN13.js", - "EAN2.js": "bin/barcodes/EAN_UPC/EAN2.js", - "EAN5.js": "bin/barcodes/EAN_UPC/EAN5.js", - "EAN8.js": "bin/barcodes/EAN_UPC/EAN8.js", - "encoder.js": "bin/barcodes/EAN_UPC/encoder.js", - "ErrorHandler.js": "bin/exceptions/ErrorHandler.js", - "exceptions": "bin/exceptions", - "exceptions.js": "bin/exceptions/exceptions.js", - "fixOptions.js": "bin/help/fixOptions.js", - "GenericBarcode": "bin/barcodes/GenericBarcode", - "getOptionsFromElement.js": "bin/help/getOptionsFromElement.js", - "getRenderProperties.js": "bin/help/getRenderProperties.js", - "help": "bin/help", - "index.js": "bin/renderers/index.js", - "index.tmp.js": "bin/barcodes/index.tmp.js", - "ITF": "bin/barcodes/ITF", - "ITF.js": "bin/barcodes/ITF/ITF.js", - "ITF14.js": "bin/barcodes/ITF/ITF14.js", - "JsBarcode.js": "bin/JsBarcode.js", - "linearizeEncodings.js": "bin/help/linearizeEncodings.js", - "merge.js": "bin/help/merge.js", - "MSI": "bin/barcodes/MSI", - "MSI.js": "bin/barcodes/MSI/MSI.js", - "MSI10.js": "bin/barcodes/MSI/MSI10.js", - "MSI1010.js": "bin/barcodes/MSI/MSI1010.js", - "MSI11.js": "bin/barcodes/MSI/MSI11.js", - "MSI1110.js": "bin/barcodes/MSI/MSI1110.js", - "object.js": "bin/renderers/object.js", - "options": "bin/options", - "optionsFromStrings.js": "bin/help/optionsFromStrings.js", - "pharmacode": "bin/barcodes/pharmacode", - "renderers": "bin/renderers", - "shared.js": "bin/renderers/shared.js", - "svg.js": "bin/renderers/svg.js", - "UPC.js": "bin/barcodes/EAN_UPC/UPC.js", - "UPCE.js": "bin/barcodes/EAN_UPC/UPCE.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "license": "ISC" - }, - "node_modules/jsonexport": { - "version": "3.2.0", - "license": "Apache-2.0", - "bin": { - "jsonexport": "bin/jsonexport.js" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/juice": { - "version": "5.2.0", - "license": "MIT", - "dependencies": { - "cheerio": "^0.22.0", - "commander": "^2.15.1", - "cross-spawn": "^6.0.5", - "deep-extend": "^0.6.0", - "mensch": "^0.3.3", - "slick": "^1.12.2", - "web-resource-inliner": "^4.3.1" - }, - "bin": { - "juice": "bin/juice" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "license": "MIT" - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "license": "MIT" - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "license": "MIT" - }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "license": "MIT" - }, - "node_modules/lodash.map": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "license": "MIT" - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "license": "MIT" - }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "license": "MIT" - }, - "node_modules/lodash.template": { - "version": "4.5.0", - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "node_modules/lodash.unescape": { - "version": "4.0.1", - "license": "MIT" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "license": "MIT" - }, - "node_modules/log4js": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", - "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.3" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/long": { - "version": "4.0.0", - "license": "Apache-2.0" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/mensch": { - "version": "0.3.4", - "license": "MIT" - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimer": { - "version": "1.1.1", - "license": "MIT", - "bin": { - "mimer": "bin/mimer" - }, - "engines": { - "node": ">= 6.0" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "license": "MIT", - "peer": true - }, - "node_modules/ms": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/mysql2": { - "version": "1.7.0", - "license": "MIT", - "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", - "long": "^4.0.0", - "lru-cache": "^5.1.1", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "lru-cache": "^4.1.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "4.1.5", - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/named-placeholders/node_modules/yallist": { - "version": "2.1.2", - "license": "ISC" - }, - "node_modules/nanoid": { - "version": "3.3.4", - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "license": "MIT" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "license": "MIT", - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/nodemailer": { - "version": "4.7.0", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "peer": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "license": "MIT" - }, - "node_modules/pend": { - "version": "1.2.0", - "license": "MIT", - "peer": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/pngjs": { - "version": "5.0.0", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/postcss": { - "version": "8.4.17", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT", - "peer": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "license": "ISC" - }, - "node_modules/psl": { - "version": "1.9.0", - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.0", - "license": "MIT", - "peer": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/puppeteer": { - "version": "18.2.0", - "hasInstallScript": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "https-proxy-agent": "5.0.1", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "puppeteer-core": "18.2.0" - }, - "engines": { - "node": ">=14.1.0" - } - }, - "node_modules/puppeteer-cluster": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/puppeteer-cluster/-/puppeteer-cluster-0.23.0.tgz", - "integrity": "sha512-108terIWDzPrQopmoYSPd5yDoy3FGJ2dNnoGMkGYPs6xtkdhgaECwpfZkzaRToMQPZibUOz0/dSSGgPEdXEhkQ==", - "dependencies": { - "debug": "^4.3.3" - }, - "peerDependencies": { - "puppeteer": ">=1.5.0" - } - }, - "node_modules/puppeteer-core": { - "version": "18.2.0", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.1045489", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.9.0" - }, - "engines": { - "node": ">=14.1.0" - } - }, - "node_modules/qrcode": { - "version": "1.5.1", - "license": "MIT", - "dependencies": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request": { - "version": "2.88.2", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/resolve": { - "version": "1.22.1", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/semver": { - "version": "5.7.1", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/seq-queue": { - "version": "0.0.5" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/slick": { - "version": "1.12.2", - "license": "MIT (http://mootools.net/license.txt)", - "engines": { - "node": "*" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "license": "BSD-3-Clause" - }, - "node_modules/sqlstring": { - "version": "2.3.3", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/sshpk": { - "version": "1.17.0", - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/streamroller": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", - "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/strftime": { - "version": "0.10.1", - "license": "MIT", - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "license": "MIT", - "peer": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "license": "MIT", - "peer": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/through": { - "version": "2.3.8", - "license": "MIT", - "peer": true - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "license": "MIT", - "peer": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "license": "Unlicense" - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/uuid": { - "version": "3.4.0", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/valid-data-url": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/vue": { - "version": "2.7.10", - "license": "MIT", - "dependencies": { - "@vue/compiler-sfc": "2.7.10", - "csstype": "^3.1.0" - } - }, - "node_modules/vue-i18n": { - "version": "8.27.2", - "license": "MIT" - }, - "node_modules/vue-server-renderer": { - "version": "2.7.10", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "hash-sum": "^2.0.0", - "he": "^1.2.0", - "lodash.template": "^4.5.0", - "lodash.uniq": "^4.5.0", - "resolve": "^1.22.0", - "serialize-javascript": "^6.0.0", - "source-map": "0.5.6" - } - }, - "node_modules/vue-server-renderer/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/vue-server-renderer/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/vue-server-renderer/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/vue-server-renderer/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/vue-server-renderer/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-server-renderer/node_modules/source-map": { - "version": "0.5.6", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vue-server-renderer/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web-resource-inliner": { - "version": "4.3.4", - "license": "MIT", - "dependencies": { - "async": "^3.1.0", - "chalk": "^2.4.2", - "datauri": "^2.0.0", - "htmlparser2": "^4.0.0", - "lodash.unescape": "^4.0.1", - "request": "^2.88.0", - "safer-buffer": "^2.1.2", - "valid-data-url": "^2.0.0", - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/web-resource-inliner/node_modules/dom-serializer": { - "version": "1.4.1", - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/dom-serializer/node_modules/domhandler": { - "version": "4.3.1", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domelementtype": { - "version": "2.3.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/web-resource-inliner/node_modules/domhandler": { - "version": "3.3.0", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.0.1" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domutils": { - "version": "2.8.0", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/domutils/node_modules/domhandler": { - "version": "4.3.1", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/entities": { - "version": "2.2.0", - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/web-resource-inliner/node_modules/htmlparser2": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", - "entities": "^2.0.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "license": "BSD-2-Clause", - "peer": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "license": "MIT", - "peer": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "license": "ISC", - "peer": true - }, - "node_modules/ws": { - "version": "8.9.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "license": "ISC" - }, - "node_modules/yallist": { - "version": "3.1.1", - "license": "ISC" - }, - "node_modules/yargs": { - "version": "15.4.1", - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - }, - "dependencies": { - "@babel/parser": { - "version": "7.19.3" - }, - "@types/node": { - "version": "18.8.2", - "optional": true, - "peer": true - }, - "@types/yauzl": { - "version": "2.10.0", - "optional": true, - "peer": true, - "requires": { - "@types/node": "*" - } - }, - "@vue/compiler-sfc": { - "version": "2.7.10", - "requires": { - "@babel/parser": "^7.18.4", - "postcss": "^8.4.14", - "source-map": "^0.6.1" - } - }, - "agent-base": { - "version": "6.0.2", - "peer": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1" - }, - "ansi-styles": { - "version": "3.2.1", - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "asn1": { - "version": "0.2.6", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0" - }, - "async": { - "version": "3.2.4" - }, - "asynckit": { - "version": "0.4.0" - }, - "aws-sign2": { - "version": "0.7.0" - }, - "aws4": { - "version": "1.11.0" - }, - "balanced-match": { - "version": "1.0.2", - "peer": true - }, - "base64-js": { - "version": "1.5.1", - "peer": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bl": { - "version": "4.1.0", - "peer": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "boolbase": { - "version": "1.0.0" - }, - "brace-expansion": { - "version": "1.1.11", - "peer": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer": { - "version": "5.7.1", - "peer": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "peer": true - }, - "camelcase": { - "version": "5.3.1" - }, - "caseless": { - "version": "0.12.0" - }, - "chalk": { - "version": "2.4.2", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cheerio": { - "version": "0.22.0", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - } - }, - "chownr": { - "version": "1.1.4", - "peer": true - }, - "cliui": { - "version": "6.0.0", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "1.9.3", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3" - }, - "combined-stream": { - "version": "1.0.8", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3" - }, - "concat-map": { - "version": "0.0.1", - "peer": true - }, - "core-util-is": { - "version": "1.0.2" - }, - "cross-fetch": { - "version": "3.1.5", - "peer": true, - "requires": { - "node-fetch": "2.6.7" - } - }, - "cross-spawn": { - "version": "6.0.5", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "css-select": { - "version": "1.2.0", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3" - }, - "csstype": { - "version": "3.1.1" - }, - "dashdash": { - "version": "1.14.1", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "datauri": { - "version": "2.0.0", - "requires": { - "image-size": "^0.7.3", - "mimer": "^1.0.0" - } - }, - "date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==" - }, - "debug": { - "version": "4.3.4", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0" - }, - "deep-extend": { - "version": "0.6.0" - }, - "delayed-stream": { - "version": "1.0.0" - }, - "denque": { - "version": "1.5.1" - }, - "devtools-protocol": { - "version": "0.0.1045489", - "peer": true - }, - "dijkstrajs": { - "version": "1.0.2" - }, - "dom-serializer": { - "version": "0.1.1", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1" - }, - "domhandler": { - "version": "2.4.2", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0" - }, - "encode-utf8": { - "version": "1.0.3" - }, - "end-of-stream": { - "version": "1.4.4", - "peer": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "1.1.2" - }, - "escape-string-regexp": { - "version": "1.0.5" - }, - "esprima": { - "version": "4.0.1" - }, - "extend": { - "version": "3.0.2" - }, - "extract-zip": { - "version": "2.0.1", - "peer": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "extsprintf": { - "version": "1.3.0" - }, - "fast-deep-equal": { - "version": "3.1.3" - }, - "fast-json-stable-stringify": { - "version": "2.1.0" - }, - "fd-slicer": { - "version": "1.1.0", - "peer": true, - "requires": { - "pend": "~1.2.0" - } - }, - "find-up": { - "version": "4.1.0", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "forever-agent": { - "version": "0.6.1" - }, - "form-data": { - "version": "2.3.3", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-constants": { - "version": "1.0.0", - "peer": true - }, - "fs-extra": { - "version": "7.0.1", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "peer": true - }, - "function-bind": { - "version": "1.1.1" - }, - "generate-function": { - "version": "2.3.1", - "requires": { - "is-property": "^1.0.2" - } - }, - "get-caller-file": { - "version": "2.0.5" - }, - "get-stream": { - "version": "5.2.0", - "peer": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.2.3", - "peer": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10" - }, - "har-schema": { - "version": "2.0.0" - }, - "har-validator": { - "version": "5.1.5", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0" - }, - "hash-sum": { - "version": "2.0.0" - }, - "he": { - "version": "1.2.0" - }, - "htmlparser2": { - "version": "3.10.1", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "http-signature": { - "version": "1.2.0", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "peer": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.5.2", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "peer": true - }, - "image-size": { - "version": "0.7.5" - }, - "inflight": { - "version": "1.0.6", - "peer": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4" - }, - "intl": { - "version": "1.2.5" - }, - "is-core-module": { - "version": "2.10.0", - "requires": { - "has": "^1.0.3" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0" - }, - "is-property": { - "version": "1.0.2" - }, - "is-typedarray": { - "version": "1.0.0" - }, - "isexe": { - "version": "2.0.0" - }, - "isstream": { - "version": "0.1.2" - }, - "js-yaml": { - "version": "3.14.1", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbarcode": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.11.5.tgz", - "integrity": "sha512-zv3KsH51zD00I/LrFzFSM6dst7rDn0vIMzaiZFL7qusTjPZiPtxg3zxetp0RR7obmjTw4f6NyGgbdkBCgZUIrA==" - }, - "jsbn": { - "version": "0.1.1" - }, - "json-schema": { - "version": "0.4.0" - }, - "json-schema-traverse": { - "version": "0.4.1" - }, - "json-stringify-safe": { - "version": "5.0.1" - }, - "jsonexport": { - "version": "3.2.0" - }, - "jsonfile": { - "version": "4.0.0", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsprim": { - "version": "1.4.2", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "juice": { - "version": "5.2.0", - "requires": { - "cheerio": "^0.22.0", - "commander": "^2.15.1", - "cross-spawn": "^6.0.5", - "deep-extend": "^0.6.0", - "mensch": "^0.3.3", - "slick": "^1.12.2", - "web-resource-inliner": "^4.3.1" - } - }, - "locate-path": { - "version": "5.0.0", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash._reinterpolate": { - "version": "3.0.0" - }, - "lodash.assignin": { - "version": "4.2.0" - }, - "lodash.bind": { - "version": "4.2.1" - }, - "lodash.defaults": { - "version": "4.2.0" - }, - "lodash.filter": { - "version": "4.6.0" - }, - "lodash.flatten": { - "version": "4.4.0" - }, - "lodash.foreach": { - "version": "4.5.0" - }, - "lodash.map": { - "version": "4.6.0" - }, - "lodash.merge": { - "version": "4.6.2" - }, - "lodash.pick": { - "version": "4.4.0" - }, - "lodash.reduce": { - "version": "4.6.0" - }, - "lodash.reject": { - "version": "4.6.0" - }, - "lodash.some": { - "version": "4.6.0" - }, - "lodash.template": { - "version": "4.5.0", - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "lodash.unescape": { - "version": "4.0.1" - }, - "lodash.uniq": { - "version": "4.5.0" - }, - "log4js": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", - "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.3" - } - }, - "long": { - "version": "4.0.0" - }, - "lru-cache": { - "version": "5.1.1", - "requires": { - "yallist": "^3.0.2" - } - }, - "mensch": { - "version": "0.3.4" - }, - "mime-db": { - "version": "1.52.0" - }, - "mime-types": { - "version": "2.1.35", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimer": { - "version": "1.1.1" - }, - "minimatch": { - "version": "3.1.2", - "peer": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "peer": true - }, - "ms": { - "version": "2.1.2" - }, - "mysql2": { - "version": "1.7.0", - "requires": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", - "long": "^4.0.0", - "lru-cache": "^5.1.1", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" - } - }, - "named-placeholders": { - "version": "1.1.2", - "requires": { - "lru-cache": "^4.1.3" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2" - } - } - }, - "nanoid": { - "version": "3.3.4" - }, - "nice-try": { - "version": "1.0.5" - }, - "node-fetch": { - "version": "2.6.7", - "peer": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "nodemailer": { - "version": "4.7.0" - }, - "nth-check": { - "version": "1.0.2", - "requires": { - "boolbase": "~1.0.0" - } - }, - "oauth-sign": { - "version": "0.9.0" - }, - "once": { - "version": "1.4.0", - "peer": true, - "requires": { - "wrappy": "1" - } - }, - "p-limit": { - "version": "2.3.0", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0" - }, - "path-exists": { - "version": "4.0.0" - }, - "path-is-absolute": { - "version": "1.0.1", - "peer": true - }, - "path-key": { - "version": "2.0.1" - }, - "path-parse": { - "version": "1.0.7" - }, - "pend": { - "version": "1.2.0", - "peer": true - }, - "performance-now": { - "version": "2.1.0" - }, - "picocolors": { - "version": "1.0.0" - }, - "pngjs": { - "version": "5.0.0" - }, - "postcss": { - "version": "8.4.17", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "progress": { - "version": "2.0.3", - "peer": true - }, - "proxy-from-env": { - "version": "1.1.0", - "peer": true - }, - "pseudomap": { - "version": "1.0.2" - }, - "psl": { - "version": "1.9.0" - }, - "pump": { - "version": "3.0.0", - "peer": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1" - }, - "puppeteer": { - "version": "18.2.0", - "peer": true, - "requires": { - "https-proxy-agent": "5.0.1", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "puppeteer-core": "18.2.0" - } - }, - "puppeteer-cluster": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/puppeteer-cluster/-/puppeteer-cluster-0.23.0.tgz", - "integrity": "sha512-108terIWDzPrQopmoYSPd5yDoy3FGJ2dNnoGMkGYPs6xtkdhgaECwpfZkzaRToMQPZibUOz0/dSSGgPEdXEhkQ==", - "requires": { - "debug": "^4.3.3" - } - }, - "puppeteer-core": { - "version": "18.2.0", - "peer": true, - "requires": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.1045489", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.1", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.9.0" - } - }, - "qrcode": { - "version": "1.5.1", - "requires": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - } - }, - "qs": { - "version": "6.5.3" - }, - "randombytes": { - "version": "2.1.0", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "request": { - "version": "2.88.2", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1" - }, - "require-main-filename": { - "version": "2.0.0" - }, - "resolve": { - "version": "1.22.1", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "rimraf": { - "version": "3.0.2", - "peer": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.2.1" - }, - "safer-buffer": { - "version": "2.1.2" - }, - "semver": { - "version": "5.7.1" - }, - "seq-queue": { - "version": "0.0.5" - }, - "serialize-javascript": { - "version": "6.0.0", - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0" - }, - "shebang-command": { - "version": "1.2.0", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0" - }, - "slick": { - "version": "1.12.2" - }, - "source-map": { - "version": "0.6.1" - }, - "source-map-js": { - "version": "1.0.2" - }, - "sprintf-js": { - "version": "1.0.3" - }, - "sqlstring": { - "version": "2.3.3" - }, - "sshpk": { - "version": "1.17.0", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "streamroller": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", - "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } - } - }, - "strftime": { - "version": "0.10.1" - }, - "string_decoder": { - "version": "1.3.0", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0" - }, - "tar-fs": { - "version": "2.1.1", - "peer": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "peer": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - }, - "through": { - "version": "2.3.8", - "peer": true - }, - "tough-cookie": { - "version": "2.5.0", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "0.0.3", - "peer": true - }, - "tunnel-agent": { - "version": "0.6.0", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5" - }, - "unbzip2-stream": { - "version": "1.4.3", - "peer": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "universalify": { - "version": "0.1.2" - }, - "uri-js": { - "version": "4.4.1", - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2" - }, - "uuid": { - "version": "3.4.0" - }, - "valid-data-url": { - "version": "2.0.0" - }, - "verror": { - "version": "1.10.0", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vue": { - "version": "2.7.10", - "requires": { - "@vue/compiler-sfc": "2.7.10", - "csstype": "^3.1.0" - } - }, - "vue-i18n": { - "version": "8.27.2" - }, - "vue-server-renderer": { - "version": "2.7.10", - "requires": { - "chalk": "^4.1.2", - "hash-sum": "^2.0.0", - "he": "^1.2.0", - "lodash.template": "^4.5.0", - "lodash.uniq": "^4.5.0", - "resolve": "^1.22.0", - "serialize-javascript": "^6.0.0", - "source-map": "0.5.6" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4" - }, - "has-flag": { - "version": "4.0.0" - }, - "source-map": { - "version": "0.5.6" - }, - "supports-color": { - "version": "7.2.0", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "web-resource-inliner": { - "version": "4.3.4", - "requires": { - "async": "^3.1.0", - "chalk": "^2.4.2", - "datauri": "^2.0.0", - "htmlparser2": "^4.0.0", - "lodash.unescape": "^4.0.1", - "request": "^2.88.0", - "safer-buffer": "^2.1.2", - "valid-data-url": "^2.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "dom-serializer": { - "version": "1.4.1", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "dependencies": { - "domhandler": { - "version": "4.3.1", - "requires": { - "domelementtype": "^2.2.0" - } - } - } - }, - "domelementtype": { - "version": "2.3.0" - }, - "domhandler": { - "version": "3.3.0", - "requires": { - "domelementtype": "^2.0.1" - } - }, - "domutils": { - "version": "2.8.0", - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "dependencies": { - "domhandler": { - "version": "4.3.1", - "requires": { - "domelementtype": "^2.2.0" - } - } - } - }, - "entities": { - "version": "2.2.0" - }, - "htmlparser2": { - "version": "4.1.0", - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", - "entities": "^2.0.0" - } - } - } - }, - "webidl-conversions": { - "version": "3.0.1", - "peer": true - }, - "whatwg-url": { - "version": "5.0.0", - "peer": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0" - }, - "wrap-ansi": { - "version": "6.2.0", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4" - } - } - }, - "wrappy": { - "version": "1.0.2", - "peer": true - }, - "ws": { - "version": "8.9.0", - "peer": true, - "requires": {} - }, - "xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==" - }, - "xtend": { - "version": "4.0.2" - }, - "y18n": { - "version": "4.0.3" - }, - "yallist": { - "version": "3.1.1" - }, - "yargs": { - "version": "15.4.1", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yauzl": { - "version": "2.10.0", - "peer": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/print/templates/email/invoice-electronic/invoice-electronic.html b/print/templates/email/invoice-electronic/invoice-electronic.html new file mode 100644 index 000000000..fc96e0970 --- /dev/null +++ b/print/templates/email/invoice-electronic/invoice-electronic.html @@ -0,0 +1,13 @@ + + + + + + {{ $t('subject') }} + + +

{{ $t('title') }} {{name}}

+

{{ $t('clientMail') }} {{email}}

+

{{ $t('ticketId') }} {{ticketId}} + + diff --git a/print/templates/email/invoice-electronic/invoice-electronic.js b/print/templates/email/invoice-electronic/invoice-electronic.js new file mode 100644 index 000000000..2e1e739ac --- /dev/null +++ b/print/templates/email/invoice-electronic/invoice-electronic.js @@ -0,0 +1,21 @@ +module.exports = { + name: 'invoice-electronic', + props: { + name: { + type: [String], + required: true + }, + email: { + type: [String], + required: true + }, + ticketId: { + type: [Number], + required: true + }, + url: { + type: [String], + required: true + } + }, +}; diff --git a/print/templates/email/invoice-electronic/locale/en.yml b/print/templates/email/invoice-electronic/locale/en.yml new file mode 100644 index 000000000..5523a2fa3 --- /dev/null +++ b/print/templates/email/invoice-electronic/locale/en.yml @@ -0,0 +1,4 @@ +subject: A electronic invoice has been created +title: A new electronic invoice has been created for the client +clientMail: The client's email is +ticketId: The invoice's ticket is \ No newline at end of file diff --git a/print/templates/email/invoice-electronic/locale/es.yml b/print/templates/email/invoice-electronic/locale/es.yml new file mode 100644 index 000000000..2cbcfbb36 --- /dev/null +++ b/print/templates/email/invoice-electronic/locale/es.yml @@ -0,0 +1,4 @@ +subject: Se ha creado una factura electrónica +title: Se ha creado una nueva factura electrónica para el cliente +clientMail: El correo del cliente es +ticketId: El ticket de la factura es \ No newline at end of file diff --git a/print/templates/email/invoiceIn/locale/en.yml b/print/templates/email/invoiceIn/locale/en.yml index 47ebc3966..e238ecf61 100644 --- a/print/templates/email/invoiceIn/locale/en.yml +++ b/print/templates/email/invoiceIn/locale/en.yml @@ -1,5 +1,5 @@ -subject: Your agricultural invoice -title: Your agricultural invoice +subject: Your agricultural receipt +title: Your agricultural receipt dear: Dear supplier description: Attached you can find agricultural receipt generated from your last deliveries. Please return a signed and stamped copy to our administration department. conclusion: Thanks for your attention! diff --git a/print/templates/email/invoiceIn/locale/es.yml b/print/templates/email/invoiceIn/locale/es.yml index 2698763cf..456122c75 100644 --- a/print/templates/email/invoiceIn/locale/es.yml +++ b/print/templates/email/invoiceIn/locale/es.yml @@ -1,5 +1,5 @@ -subject: Tu factura agrícola -title: Tu factura agrícola +subject: Tu recibo agrícola +title: Tu recibo agrícola dear: Estimado proveedor description: Adjunto puede encontrar recibo agrícola generado de sus últimas entregas. Por favor, devuelva una copia firmada y sellada a nuestro de departamento de administración. conclusion: ¡Gracias por tu atención! diff --git a/print/templates/email/invoiceIn/locale/fr.yml b/print/templates/email/invoiceIn/locale/fr.yml index 1c38f3c25..dd35631e5 100644 --- a/print/templates/email/invoiceIn/locale/fr.yml +++ b/print/templates/email/invoiceIn/locale/fr.yml @@ -1,5 +1,5 @@ -subject: Votre facture agricole -title: Votre facture agricole +subject: Votre reçu agricole +title: Votre reçu agricole dear: Cher Fournisseur description: Vous trouverez en pièce jointe le reçu agricole généré à partir de vos dernières livraisons. Veuillez retourner une copie signée et tamponnée à notre service administratif. conclusion: Merci pour votre attention! diff --git a/print/templates/email/invoiceIn/locale/pt.yml b/print/templates/email/invoiceIn/locale/pt.yml index a43e3a79d..5dffc7acf 100644 --- a/print/templates/email/invoiceIn/locale/pt.yml +++ b/print/templates/email/invoiceIn/locale/pt.yml @@ -1,5 +1,5 @@ -subject: A sua fatura agrícola -title: A sua fatura agrícola +subject: A sua recibo agrícola +title: A sua recibo agrícola dear: Caro Fornecedor description: Em anexo encontra-se o recibo agrícola gerado a partir das suas últimas entregas. Por favor, devolva uma cópia assinada e carimbada ao nosso departamento de administração. conclusion: Obrigado pela atenção. diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 48848c079..f7011ad81 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -82,7 +82,7 @@ module.exports = { return this.rawSqlFromDef(`taxes`, [reference]); }, fetchIntrastat(reference) { - return this.rawSqlFromDef(`intrastat`, [reference, reference, reference, reference, reference]); + return this.rawSqlFromDef(`intrastat`, [reference, reference, reference]); }, fetchRectified(reference) { return this.rawSqlFromDef(`rectified`, [reference]); diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index 7f5fbdf39..f986a9564 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -1,39 +1,26 @@ SELECT * FROM invoiceOut io JOIN invoiceOutSerial ios ON io.serial = ios.code - JOIN - (SELECT - t.refFk, - ir.id code, - ir.description description, - CAST(SUM(IFNULL(i.stems, 1) * s.quantity) AS DECIMAL(10,2)) stems, - CAST(SUM(CAST(IFNULL(i.stems, 1) * s.quantity * IF(ic.grams, ic.grams, i.density * ic.cm3delivery / 1000) / 1000 AS DECIMAL(10,2)) * - IF(sub.weight, sub.weight / vn.invoiceOut_getWeight(?), 1)) AS DECIMAL(10,2)) netKg, - CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) subtotal - FROM vn.ticket t - JOIN vn.sale s ON s.ticketFk = t.id - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk - JOIN vn.intrastat ir ON ir.id = i.intrastatFk - LEFT JOIN ( - SELECT t2.weight - FROM vn.ticket t2 - WHERE refFk = ? AND weight - LIMIT 1 - ) sub ON TRUE - WHERE t.refFk = ? - AND i.intrastatFk - GROUP BY i.intrastatFk - UNION ALL - SELECT - NULL AS refFk, - NULL AS code, - NULL AS description, - 0 AS stems, - 0 AS netKg, - IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) AS subtotal - FROM vn.ticketService ts - JOIN vn.ticket t ON ts.ticketFk = t.id - WHERE t.refFk = ?) sub - WHERE io.`ref` = ? AND ios.isCEE - ORDER BY sub.code; + JOIN( + SELECT ir.id code, + ir.description, + iii.stems, + iii.net netKg, + iii.amount subtotal + FROM vn.invoiceInIntrastat iii + LEFT JOIN vn.invoiceIn ii ON ii.id = iii.invoiceInFk + LEFT JOIN vn.invoiceOut io ON io.ref = ii.supplierRef + LEFT JOIN vn.intrastat ir ON ir.id = iii.intrastatFk + WHERE io.`ref` = ? + UNION ALL + SELECT NULL code, + 'Servicios' description, + 0 stems, + 0 netKg, + IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) subtotal + FROM vn.ticketService ts + JOIN vn.ticket t ON ts.ticketFk = t.id + WHERE t.refFk = ? + ) sub + WHERE io.ref = ? AND ios.isCEE + ORDER BY sub.code; diff --git a/print/templates/reports/item-label/sql/item.sql b/print/templates/reports/item-label/sql/item.sql index 4b042c320..46aacc2fa 100644 --- a/print/templates/reports/item-label/sql/item.sql +++ b/print/templates/reports/item-label/sql/item.sql @@ -3,9 +3,12 @@ SELECT i.name, i.stems, i.size, - b.packing + b.packing, + p.name as 'producer' FROM vn.item i JOIN cache.last_buy clb ON clb.item_id = i.id JOIN vn.buy b ON b.id = clb.buy_id JOIN vn.entry e ON e.id = b.entryFk + JOIN vn.producer p ON p.id = i.producerFk + WHERE i.id = ? AND clb.warehouse_id = ? \ No newline at end of file diff --git a/print/templates/reports/previa-label/assets/css/import.js b/print/templates/reports/previa-label/assets/css/import.js new file mode 100644 index 000000000..37a98dfdd --- /dev/null +++ b/print/templates/reports/previa-label/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/previa-label/assets/css/style.css b/print/templates/reports/previa-label/assets/css/style.css new file mode 100644 index 000000000..1c9074924 --- /dev/null +++ b/print/templates/reports/previa-label/assets/css/style.css @@ -0,0 +1,85 @@ +* { + box-sizing: border-box; + padding-right: 1%; +} +.label { + font-size: 1.2em; + font-family: Arial, Helvetica, sans-serif; +} +.barcode { + float: left; + width: 40%; +} +.barcode h1 { + text-align: center; + font-size: 1.8em; + margin: 0 0 10px 0 +} +.barcode .image { + text-align: center +} +.barcode .image img { + width: 170px +} +.data { + float: left; + width: 60%; +} +.data .header { + background-color: #000; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + margin-bottom: 25px; + text-align: right; + font-size: 1.2em; + padding: 0.2em; + color: #FFF +} +.data .sector, +.data .producer { + text-transform: uppercase; + text-align: right; + font-size: 1.5em; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.data .sector-sm { + text-transform: uppercase; + text-align: right; + font-size: 1.2em; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.data .producer { + text-justify: inter-character; +} +.data .details { + border-top: 4px solid #000; + padding-top: 2px; +} +.data .details .package { + padding-right: 5px; + float: left; + width: 50%; +} +.package .packing, +.package .dated, +.package .labelNumber { + text-align: right +} +.package .packing { + font-size: 1.8em; + font-weight: 400 +} +.data .details .size { + background-color: #000; + text-align: center; + font-size: 3em; + padding: 0.2em 0; + float: left; + width: 50%; + color: #FFF +} \ No newline at end of file diff --git a/print/templates/reports/previa-label/locale/en.yml b/print/templates/reports/previa-label/locale/en.yml new file mode 100644 index 000000000..d380c702a --- /dev/null +++ b/print/templates/reports/previa-label/locale/en.yml @@ -0,0 +1,2 @@ +previous: PREVIOUS +report: Report diff --git a/print/templates/reports/previa-label/locale/es.yml b/print/templates/reports/previa-label/locale/es.yml new file mode 100644 index 000000000..26e83f02e --- /dev/null +++ b/print/templates/reports/previa-label/locale/es.yml @@ -0,0 +1,2 @@ +previous: PREVIA +report: Ticket diff --git a/print/templates/reports/previa-label/options.json b/print/templates/reports/previa-label/options.json new file mode 100644 index 000000000..98c5788b1 --- /dev/null +++ b/print/templates/reports/previa-label/options.json @@ -0,0 +1,11 @@ +{ + "width": "10.4cm", + "height": "4.8cm", + "margin": { + "top": "0cm", + "right": "0cm", + "bottom": "0cm", + "left": "0cm" + }, + "printBackground": true +} \ No newline at end of file diff --git a/print/templates/reports/previa-label/previa-label.html b/print/templates/reports/previa-label/previa-label.html new file mode 100644 index 000000000..1dc9b14d0 --- /dev/null +++ b/print/templates/reports/previa-label/previa-label.html @@ -0,0 +1,26 @@ + + +

+
+

{{previa.saleGroupFk}}

+
+ +
+
+
+
{{ $t('previous') }}
+
+ {{sector.description}} +
+
{{sector.description}}
+
{{ $t('report') }}#{{previa.ticketFk}}
+
+
+
{{previa.itemPackingTypeFk}}
+
{{previa.shippingHour}}:{{previa.shippingMinute}}
+
+
{{previa.items}}
+
+
+
+ \ No newline at end of file diff --git a/print/templates/reports/previa-label/previa-label.js b/print/templates/reports/previa-label/previa-label.js new file mode 100755 index 000000000..7ad5ea961 --- /dev/null +++ b/print/templates/reports/previa-label/previa-label.js @@ -0,0 +1,42 @@ +const Component = require(`vn-print/core/component`); +const reportBody = new Component('report-body'); +const qrcode = require('qrcode'); +const UserError = require('vn-loopback/util/user-error'); + +module.exports = { + name: 'previa-label', + async serverPrefetch() { + this.previa = await this.fetchPrevia(this.id); + this.sector = await this.fetchSector(this.id); + this.barcode = await this.getBarcodeBase64(this.id); + + if (this.previa) + this.previa = this.previa[0]; + + if (!this.sector) + throw new UserError('Something went wrong - no sector found'); + }, + methods: { + fetchPrevia(id) { + return this.findOneFromDef('previa', [id]); + }, + getBarcodeBase64(id) { + const data = String(id); + + return qrcode.toDataURL(data, {margin: 0}); + }, + fetchSector(id) { + return this.findOneFromDef('sector', [id]); + } + }, + components: { + 'report-body': reportBody.build() + }, + props: { + id: { + type: Number, + required: true, + description: 'The saleGroupFk id' + }, + } +}; diff --git a/print/templates/reports/previa-label/sql/previa.sql b/print/templates/reports/previa-label/sql/previa.sql new file mode 100644 index 000000000..f73166f74 --- /dev/null +++ b/print/templates/reports/previa-label/sql/previa.sql @@ -0,0 +1 @@ +CALL vn.previousSticker_get(?) \ No newline at end of file diff --git a/print/templates/reports/previa-label/sql/sector.sql b/print/templates/reports/previa-label/sql/sector.sql new file mode 100644 index 000000000..77e84c033 --- /dev/null +++ b/print/templates/reports/previa-label/sql/sector.sql @@ -0,0 +1,4 @@ +SELECT s.description +FROM vn.saleGroup sg + JOIN vn.sector s ON sg.sectorFk = s.id +WHERE sg.id = ? \ No newline at end of file