diff --git a/CHANGELOG.md b/CHANGELOG.md index bafedc760..6533a84ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,56 @@ 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 +## [2306.01] - 2023-02-23 ### Added -- [General](Inicio) Permite recuperar la contraseña +- ### Changed +- (General -> Inicio) Ahora permite recuperar la contraseña tanto con el correo de recuperación como el usuario +### Fixed +- (Monitor de tickets) Cuando ordenas por columna, ya no se queda deshabilitado el botón de 'Actualizar' +- (Zone -> Días de entrega) Al hacer click en un día, muestra correctamente las zonas + +## [2304.01] - 2023-02-09 + +### Added +- (Rutas) Al descargar varias facturas se comprime en un zip +- (Trabajadores -> Nuevo trabajador) Nueva sección +- (Tickets -> Adelantar tickets) Añadidos campos "líneas" y "litros" al ticket origen +- (Tickets -> Adelantar tickets) Nuevo icono muestra cuando las agencias de los tickets origen/destino son distintas + +### Changed +- (Entradas -> Compras) Cambiados los campos "Precio Grouping/Packing" por "PVP" y "Precio" por "Coste" +- (Artículos -> Últimas entradas) Cambiados los campos "P.P.U." y "P.P.P." por "PVP" +- (Rutas -> Sumario/Tickets) Actualizados campos de los tickets +- (Proveedores -> Crear/Editar) Permite añadir Proveedores con la misma razón social pero con países distintos +- (Tickets -> Adelantar tickets) Cambiados selectores de estado por checks "Pendiente origen/destino" +- (Tickets -> Adelantar tickets) Cambiado stock de destino a origen. + +### Fixed +- (Artículos -> Etiquetas) Permite intercambiar la relevancia entre dos etiquetas. +- (Cliente -> Datos Fiscales) No se permite seleccionar 'Notificar vía e-mail' a los clientes sin e-mail +- (Tickets -> Datos básicos) Permite guardar la hora de envío +- (Tickets -> Añadir pago) Eliminado "null" en las referencias +- (Tickets -> Adelantar tickets) Permite ordenar por importe +- (Tickets -> Adelantar tickets) El filtrado por encajado muestra también los tickets sin tipo de encajado + +## [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 ### Removed -- [Tickets](Control clientes) Eliminada sección +- (Tickets -> Control clientes) Eliminada sección diff --git a/back/methods/account/recover-password.js b/back/methods/account/recover-password.js index ddea76829..787a45284 100644 --- a/back/methods/account/recover-password.js +++ b/back/methods/account/recover-password.js @@ -3,9 +3,9 @@ module.exports = Self => { description: 'Send email to the user', accepts: [ { - arg: 'email', + arg: 'user', type: 'string', - description: 'The email of user', + description: 'The user name or email', required: true } ], @@ -15,11 +15,20 @@ module.exports = Self => { } }); - Self.recoverPassword = async function(email) { + Self.recoverPassword = async function(user) { const models = Self.app.models; + const usesEmail = user.indexOf('@') !== -1; + if (!usesEmail) { + const account = await models.Account.findOne({ + fields: ['email'], + where: {name: user} + }); + user = account.email; + } + try { - await models.user.resetPassword({email, emailTemplate: 'recover-password'}); + await models.user.resetPassword({email: user, emailTemplate: 'recover-password'}); } catch (err) { if (err.code === 'EMAIL_NOT_FOUND') return; diff --git a/back/methods/campaign/latest.js b/back/methods/campaign/latest.js index a418f1267..56ab81330 100644 --- a/back/methods/campaign/latest.js +++ b/back/methods/campaign/latest.js @@ -22,7 +22,7 @@ module.exports = Self => { Self.latest = async filter => { const conn = Self.dataSource.connector; - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setFullYear(minDate.getFullYear() - 1); const where = {dated: {gte: minDate}}; diff --git a/back/methods/campaign/spec/latest.spec.js b/back/methods/campaign/spec/latest.spec.js index a71849b59..59e4c1e7a 100644 --- a/back/methods/campaign/spec/latest.spec.js +++ b/back/methods/campaign/spec/latest.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); describe('campaign latest()', () => { it('should return the campaigns from the last year', async() => { - const now = new Date(); + const now = Date.vnNew(); const result = await app.models.Campaign.latest(); const randomIndex = Math.floor(Math.random() * result.length); const campaignDated = result[randomIndex].dated; @@ -12,7 +12,7 @@ describe('campaign latest()', () => { }); it('should return the campaigns from the current year', async() => { - const now = new Date(); + const now = Date.vnNew(); const currentYear = now.getFullYear(); const result = await app.models.Campaign.latest({ where: {dated: {like: `%${currentYear}%`}} diff --git a/back/methods/campaign/spec/upcoming.spec.js b/back/methods/campaign/spec/upcoming.spec.js index 14bffe3cf..2aec5117f 100644 --- a/back/methods/campaign/spec/upcoming.spec.js +++ b/back/methods/campaign/spec/upcoming.spec.js @@ -4,7 +4,7 @@ describe('campaign upcoming()', () => { it('should return the upcoming campaign but from the last year', async() => { const response = await app.models.Campaign.upcoming(); const campaignDated = response.dated; - const now = new Date(); + const now = Date.vnNew(); expect(campaignDated).toEqual(jasmine.any(Date)); expect(campaignDated).toBeLessThanOrEqual(now); diff --git a/back/methods/campaign/upcoming.js b/back/methods/campaign/upcoming.js index 2f1a5a377..c98fee6e5 100644 --- a/back/methods/campaign/upcoming.js +++ b/back/methods/campaign/upcoming.js @@ -14,7 +14,7 @@ module.exports = Self => { }); Self.upcoming = async() => { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setFullYear(minDate.getFullYear() - 1); return Self.findOne({ diff --git a/back/methods/chat/getServiceAuth.js b/back/methods/chat/getServiceAuth.js index 827092109..ff14e76cb 100644 --- a/back/methods/chat/getServiceAuth.js +++ b/back/methods/chat/getServiceAuth.js @@ -21,7 +21,7 @@ module.exports = Self => { if (!this.login) return; - if (Date.now() > this.login.expires) + if (Date.vnNow() > this.login.expires) this.login = await requestToken(); return this.login; @@ -48,7 +48,7 @@ module.exports = Self => { userId: requestData.userId, token: requestData.authToken }, - expires: Date.now() + (1000 * 60 * tokenLifespan) + expires: Date.vnNow() + (1000 * 60 * tokenLifespan) }; } } diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index c5c8feead..915120d49 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -33,7 +33,7 @@ module.exports = Self => { await models.Chat.create({ senderFk: sender.id, recipient: to, - dated: new Date(), + dated: Date.vnNew(), checkUserStatus: 0, message: message, status: 0, diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 075591969..883a1b693 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -49,7 +49,7 @@ module.exports = Self => { await models.Chat.create({ senderFk: sender.id, recipient: `@${recipient.name}`, - dated: new Date(), + dated: Date.vnNew(), checkUserStatus: 1, message: message, status: 0, diff --git a/back/methods/chat/spec/sendQueued.spec.js b/back/methods/chat/spec/sendQueued.spec.js index bbf5a73c7..ed791756b 100644 --- a/back/methods/chat/spec/sendQueued.spec.js +++ b/back/methods/chat/spec/sendQueued.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('Chat sendCheckingPresence()', () => { - const today = new Date(); + const today = Date.vnNew(); today.setHours(6, 0); const chatModel = models.Chat; 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/collection/setSaleQuantity.js b/back/methods/collection/setSaleQuantity.js index b6c56ddc4..4ac3d6d4b 100644 --- a/back/methods/collection/setSaleQuantity.js +++ b/back/methods/collection/setSaleQuantity.js @@ -24,7 +24,7 @@ module.exports = Self => { } }); - Self.setSaleQuantity = async(saleId, quantity) => { + Self.setSaleQuantity = async(saleId, quantity, options) => { const models = Self.app.models; const myOptions = {}; let tx; diff --git a/back/methods/dms/deleteTrashFiles.js b/back/methods/dms/deleteTrashFiles.js index f14e65e9f..239d654ef 100644 --- a/back/methods/dms/deleteTrashFiles.js +++ b/back/methods/dms/deleteTrashFiles.js @@ -32,7 +32,7 @@ module.exports = Self => { where: {code: 'trash'} }, myOptions); - const date = new Date(); + const date = Date.vnNew(); date.setMonth(date.getMonth() - 4); const dmsToDelete = await models.Dms.find({ diff --git a/back/methods/dms/saveSign.js b/back/methods/dms/saveSign.js index f668c5ed2..ed462a301 100644 --- a/back/methods/dms/saveSign.js +++ b/back/methods/dms/saveSign.js @@ -163,7 +163,7 @@ module.exports = Self => { fields: ['alertLevel'] }); - signedTime ? signedTime != undefined : signedTime = new Date(); + signedTime ? signedTime != undefined : signedTime = Date.vnNew(); if (alertLevel >= 2) { let dir; 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..ea9ee3622 --- /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': Date.vnNew(), + '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/edi/updateData.js b/back/methods/edi/updateData.js index c5705513f..232695f4e 100644 --- a/back/methods/edi/updateData.js +++ b/back/methods/edi/updateData.js @@ -230,7 +230,7 @@ module.exports = Self => { UPDATE edi.tableConfig SET updated = ? WHERE fileName = ? - `, [new Date(), baseName], options); + `, [Date.vnNew(), baseName], options); } console.log(`Updated table ${toTable}\n`); diff --git a/back/methods/notification/clean.js b/back/methods/notification/clean.js index bdc6737df..8ce32d389 100644 --- a/back/methods/notification/clean.js +++ b/back/methods/notification/clean.js @@ -32,7 +32,7 @@ module.exports = Self => { if (!config.cleanDays) return; - const cleanDate = new Date(); + const cleanDate = Date.vnNew(); cleanDate.setDate(cleanDate.getDate() - config.cleanDays); await models.NotificationQueue.destroyAll({ diff --git a/back/methods/notification/specs/clean.spec.js b/back/methods/notification/specs/clean.spec.js index 4c9dc563d..857886a64 100644 --- a/back/methods/notification/specs/clean.spec.js +++ b/back/methods/notification/specs/clean.spec.js @@ -10,7 +10,7 @@ describe('Notification Clean()', () => { const notification = await models.Notification.findOne({}, options); const notificationConfig = await models.NotificationConfig.findOne({}); - const cleanDate = new Date(); + const cleanDate = Date.vnNew(); cleanDate.setDate(cleanDate.getDate() - (notificationConfig.cleanDays + 1)); let before; 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/back/models/image.js b/back/models/image.js index d736e924f..37f4ec20d 100644 --- a/back/models/image.js +++ b/back/models/image.js @@ -77,7 +77,7 @@ module.exports = Self => { const newImage = await Self.upsertWithWhere(data, { name: fileName, collectionFk: collectionName, - updated: (new Date).getTime() + updated: Date.vnNow() }, myOptions); // Resizes and saves the image diff --git a/back/models/notificationAcl.json b/back/models/notificationAcl.json index e3e97f52d..a20187961 100644 --- a/back/models/notificationAcl.json +++ b/back/models/notificationAcl.json @@ -6,6 +6,16 @@ "table": "util.notificationAcl" } }, + "properties":{ + "notificationFk": { + "id": true, + "type": "number" + }, + "roleFk":{ + "id": true, + "type": "number" + } + }, "relations": { "notification": { "type": "belongsTo", diff --git a/back/models/notificationSubscription.js b/back/models/notificationSubscription.js new file mode 100644 index 000000000..f1b2811fa --- /dev/null +++ b/back/models/notificationSubscription.js @@ -0,0 +1,62 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.observe('before save', async function(ctx) { + const models = Self.app.models; + const userId = ctx.options.accessToken.userId; + const user = await ctx.instance.userFk; + const modifiedUser = await getUserToModify(null, user, models); + + if (userId != modifiedUser.id && userId != modifiedUser.bossFk) + throw new UserError('You dont have permission to modify this user'); + }); + + Self.remoteMethod('deleteNotification', { + description: 'Deletes a notification subscription', + accepts: [ + { + arg: 'ctx', + type: 'object', + http: {source: 'context'} + }, + { + arg: 'notificationId', + type: 'number', + required: true + }, + ], + returns: { + type: 'object', + root: true + }, + http: { + verb: 'POST', + path: '/deleteNotification' + } + }); + + Self.deleteNotification = async function(ctx, notificationId) { + const models = Self.app.models; + const user = ctx.req.accessToken.userId; + const modifiedUser = await getUserToModify(notificationId, null, models); + + if (user != modifiedUser.id && user != modifiedUser.bossFk) + throw new UserError('You dont have permission to modify this user'); + + await models.NotificationSubscription.destroyById(notificationId); + }; + + async function getUserToModify(notificationId, userFk, models) { + let userToModify = userFk; + if (notificationId) { + const subscription = await models.NotificationSubscription.findById(notificationId); + userToModify = subscription.userFk; + } + return await models.Worker.findOne({ + fields: ['id', 'bossFk'], + where: { + id: userToModify + } + }); + } +}; diff --git a/back/models/notificationSubscription.json b/back/models/notificationSubscription.json index 43fa6db27..a640e0917 100644 --- a/back/models/notificationSubscription.json +++ b/back/models/notificationSubscription.json @@ -7,15 +7,18 @@ } }, "properties": { - "notificationFk": { + "id": { "type": "number", "id": true, - "description": "Identifier" + "description": "Primary key" + }, + "notificationFk": { + "type": "number", + "description": "Foreign key to Notification" }, "userFk": { "type": "number", - "id": true, - "description": "Identifier" + "description": "Foreign key to Account" } }, "relations": { diff --git a/back/models/specs/notificationSubscription.spec.js b/back/models/specs/notificationSubscription.spec.js new file mode 100644 index 000000000..c7f37abed --- /dev/null +++ b/back/models/specs/notificationSubscription.spec.js @@ -0,0 +1,74 @@ +const models = require('vn-loopback/server/server').models; + +describe('loopback model NotificationSubscription', () => { + it('Should fail to delete a notification if the user is not editing itself or a subordinate', async() => { + const tx = await models.NotificationSubscription.beginTransaction({}); + + try { + const options = {transaction: tx}; + const user = 9; + const notificationSubscriptionId = 2; + const ctx = {req: {accessToken: {userId: user}}}; + const notification = await models.NotificationSubscription.findById(notificationSubscriptionId); + + let error; + + try { + await models.NotificationSubscription.deleteNotification(ctx, notification.id, options); + } catch (e) { + error = e; + } + + expect(error.message).toContain('You dont have permission to modify this user'); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('Should delete a notification if the user is editing itself', async() => { + const tx = await models.NotificationSubscription.beginTransaction({}); + + try { + const options = {transaction: tx}; + const user = 9; + const notificationSubscriptionId = 4; + const ctx = {req: {accessToken: {userId: user}}}; + const notification = await models.NotificationSubscription.findById(notificationSubscriptionId); + + await models.NotificationSubscription.deleteNotification(ctx, notification.id, options); + + const deletedNotification = await models.NotificationSubscription.findById(notificationSubscriptionId); + + expect(deletedNotification).toBeNull(); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('Should delete a notification if the user is editing a subordinate', async() => { + const tx = await models.NotificationSubscription.beginTransaction({}); + + try { + const options = {transaction: tx}; + const user = 9; + const notificationSubscriptionId = 5; + const ctx = {req: {accessToken: {userId: user}}}; + const notification = await models.NotificationSubscription.findById(notificationSubscriptionId); + + await models.NotificationSubscription.deleteNotification(ctx, notification.id, options); + + const deletedNotification = await models.NotificationSubscription.findById(notificationSubscriptionId); + + expect(deletedNotification).toBeNull(); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); + 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-ACL_ItemShelvingSale.sql b/db/changes/230201/00-ACL_ItemShelvingSale.sql new file mode 100644 index 000000000..38b65f89a --- /dev/null +++ b/db/changes/230201/00-ACL_ItemShelvingSale.sql @@ -0,0 +1,2 @@ +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`) + VALUES ('ItemShelvingSale','*','*','ALLOW','employee'); diff --git a/db/changes/230201/00-SupplierUniqueKey.sql b/db/changes/230201/00-SupplierUniqueKey.sql new file mode 100644 index 000000000..9c0d4a192 --- /dev/null +++ b/db/changes/230201/00-SupplierUniqueKey.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`supplier` ADD UNIQUE (name, countryFk); diff --git a/db/changes/230201/00-autoincrement_VnReport_VnPrinter.sql b/db/changes/230201/00-autoincrement_VnReport_VnPrinter.sql new file mode 100644 index 000000000..a28bf6e90 --- /dev/null +++ b/db/changes/230201/00-autoincrement_VnReport_VnPrinter.sql @@ -0,0 +1,4 @@ +SET FOREIGN_KEY_CHECKS = 0; +ALTER TABLE `vn`.`report` MODIFY COLUMN id tinyint(3) unsigned NOT NULL AUTO_INCREMENT; +ALTER TABLE `vn`.`printer` MODIFY COLUMN id tinyint(3) unsigned NOT NULL AUTO_INCREMENT; +SET FOREIGN_KEY_CHECKS = 1; 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-validPriorities_ItemConfig.sql b/db/changes/230201/00-validPriorities_ItemConfig.sql new file mode 100644 index 000000000..a793997d0 --- /dev/null +++ b/db/changes/230201/00-validPriorities_ItemConfig.sql @@ -0,0 +1,9 @@ +ALTER TABLE `vn`.`itemConfig` ADD defaultTag INT DEFAULT 56 NOT NULL; +ALTER TABLE `vn`.`itemConfig` ADD CONSTRAINT itemConfig_FK FOREIGN KEY (defaultTag) REFERENCES vn.tag(id); +ALTER TABLE `vn`.`itemConfig` ADD validPriorities varchar(50) DEFAULT '[1,2,3]' NOT NULL; +ALTER TABLE `vn`.`itemConfig` ADD defaultPriority INT DEFAULT 2 NOT NULL; +ALTER TABLE `vn`.`item` MODIFY COLUMN relevancy tinyint(1) DEFAULT 0 NOT NULL COMMENT 'La web ordena de forma descendiente por este campo para mostrar los artículos'; + +INSERT INTO `salix`.`ACL` +(model, property, accessType, permission, principalType, principalId) +VALUES('ItemConfig', '*', 'READ', 'ALLOW', 'ROLE', 'buyer'); 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/230401/00-ACL_tag_update.sql b/db/changes/230401/00-ACL_tag_update.sql new file mode 100644 index 000000000..3c103e990 --- /dev/null +++ b/db/changes/230401/00-ACL_tag_update.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Tag', 'onSubmit', 'WRITE', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/230401/00-acl_notifications.sql b/db/changes/230401/00-acl_notifications.sql new file mode 100644 index 000000000..ab40b16a5 --- /dev/null +++ b/db/changes/230401/00-acl_notifications.sql @@ -0,0 +1,4 @@ +INSERT INTO `salix`.`ACL` (model,property,accessType,principalId) + VALUES + ('NotificationSubscription','*','*','employee'), + ('NotificationAcl','*','READ','employee'); diff --git a/db/changes/230401/00-createWorker.sql b/db/changes/230401/00-createWorker.sql new file mode 100644 index 000000000..7ca2c41ee --- /dev/null +++ b/db/changes/230401/00-createWorker.sql @@ -0,0 +1,24 @@ +UPDATE `salix`.`ACL` +SET accessType='READ' +WHERE model='Worker' + AND property='*' + AND accessType='*' + AND permission='ALLOW' + AND principalType='ROLE' + AND principalId='employee'; + + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Worker', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'hr'), + ('Worker', 'createAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'updateAbsence', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'deleteAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'new', 'WRITE', 'ALLOW', 'ROLE', 'hr'), + ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'hr'); + +ALTER TABLE `vn`.`workerConfig` ADD roleFk int(10) unsigned NOT NULL COMMENT 'Rol por defecto al dar de alta un trabajador nuevo'; +UPDATE `vn`.`workerConfig` + SET roleFk = 1 + WHERE id = 1; + diff --git a/db/changes/230401/00-ticket_canAdvance.sql b/db/changes/230401/00-ticket_canAdvance.sql new file mode 100644 index 000000000..fd9d451bf --- /dev/null +++ b/db/changes/230401/00-ticket_canAdvance.sql @@ -0,0 +1,110 @@ +DROP PROCEDURE IF EXISTS vn.ticket_canAdvance; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT) +BEGIN +/** + * Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar. + * + * @param vDateFuture Fecha de los tickets que se quieren adelantar. + * @param vDateToAdvance Fecha a cuando se quiere adelantar. + * @param vWarehouseFk Almacén + */ + + DECLARE vDateInventory DATE; + + SELECT inventoried INTO vDateInventory FROM vn.config; + + DROP TEMPORARY TABLE IF EXISTS tmp.stock; + CREATE TEMPORARY TABLE tmp.stock + (itemFk INT PRIMARY KEY, + amount INT) + ENGINE = MEMORY; + + INSERT INTO tmp.stock(itemFk, amount) + SELECT itemFk, SUM(quantity) amount FROM + ( + SELECT itemFk, quantity + FROM vn.itemTicketOut + WHERE shipped >= vDateInventory + AND shipped < vDateFuture + AND warehouseFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM vn.itemEntryIn + WHERE landed >= vDateInventory + AND landed < vDateFuture + AND isVirtualStock = FALSE + AND warehouseInFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM vn.itemEntryOut + WHERE shipped >= vDateInventory + AND shipped < vDateFuture + AND warehouseOutFk = vWarehouseFk + ) t + GROUP BY itemFk HAVING amount != 0; + + DROP TEMPORARY TABLE IF EXISTS tmp.filter; + CREATE TEMPORARY TABLE tmp.filter + (INDEX (id)) + SELECT s.ticketFk futureId, + t2.ticketFk id, + count(DISTINCT s.id) saleCount, + t2.state, + t2.isNotValidated, + st.name futureState, + st.isNotValidated futureIsNotValidated, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt, + t2.ipt, + t.workerFk, + CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters, + CAST(COUNT(*) AS DECIMAL(10,0)) `futureLines`, + t2.shipped, + t.shipped futureShipped, + t2.totalWithVat, + t.totalWithVat futureTotalWithVat, + t2.agency, + am.name futureAgency, + t2.lines, + t2.liters, + SUM((s.quantity <= IFNULL(st.amount,0))) hasStock + FROM vn.ticket t + JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.saleVolume sv ON t.id = sv.ticketFk + JOIN (SELECT + t2.id ticketFk, + t2.addressFk, + st.isNotValidated, + st.name state, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt, + t2.shipped, + t2.totalWithVat, + am.name agency, + CAST(SUM(litros) AS DECIMAL(10,0)) liters, + CAST(COUNT(*) AS DECIMAL(10,0)) `lines` + FROM vn.ticket t2 + JOIN vn.saleVolume sv ON t2.id = sv.ticketFk + JOIN vn.sale s ON s.ticketFk = t2.id + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.ticketState ts ON ts.ticketFk = t2.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.agencyMode am ON t2.agencyModeFk = am.id + LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + WHERE t2.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance) + AND t2.warehouseFk = vWarehouseFk + GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.agencyMode am ON t.agencyModeFk = am.id + LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + LEFT JOIN tmp.stock st ON st.itemFk = s.itemFk + WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) + AND t.warehouseFk = vWarehouseFk + GROUP BY t.id; + + DROP TEMPORARY TABLE tmp.stock; +END$$ +DELIMITER ; diff --git a/db/changes/230401/00-uniqueKeyNotificationSubscription.sql b/db/changes/230401/00-uniqueKeyNotificationSubscription.sql new file mode 100644 index 000000000..623ecf770 --- /dev/null +++ b/db/changes/230401/00-uniqueKeyNotificationSubscription.sql @@ -0,0 +1,4 @@ +ALTER TABLE + `util`.`notificationSubscription` +ADD + CONSTRAINT `notificationSubscription_UN` UNIQUE KEY (`notificationFk`, `userFk`); \ No newline at end of file diff --git a/db/changes/230401/00-updateIsToBeMailed.sql b/db/changes/230401/00-updateIsToBeMailed.sql new file mode 100644 index 000000000..1bb177f57 --- /dev/null +++ b/db/changes/230401/00-updateIsToBeMailed.sql @@ -0,0 +1,6 @@ +UPDATE `vn`.`client` + SET isToBeMailed = FALSE + WHERE + mailAddress is NULL + AND email is NULL + AND isToBeMailed = TRUE; diff --git a/db/changes/230401/01-alter_notSubs.sql b/db/changes/230401/01-alter_notSubs.sql new file mode 100644 index 000000000..07ea7c2bf --- /dev/null +++ b/db/changes/230401/01-alter_notSubs.sql @@ -0,0 +1,7 @@ +ALTER TABLE `util`.`notificationSubscription` +ADD `id` int(11) auto_increment NULL, +DROP PRIMARY KEY, +ADD CONSTRAINT PRIMARY KEY (`id`); + +ALTER TABLE `util`.`notificationSubscription` +ADD KEY `notificationSubscription_ibfk_1` (`notificationFk`); diff --git a/db/changes/225001/.gitkeep b/db/changes/230601/.gitkeep similarity index 100% rename from db/changes/225001/.gitkeep rename to db/changes/230601/.gitkeep diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 1ea4fa114..5c7bbf192 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2,7 +2,33 @@ CREATE SCHEMA IF NOT EXISTS `vn2008`; CREATE SCHEMA IF NOT EXISTS `tmp`; UPDATE `util`.`config` - SET `environment`= 'test'; + SET `environment`= 'development'; + +-- FOR MOCK vn.time + +DROP PROCEDURE IF EXISTS `vn`.`mockVnTime`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`mockVnTime`() +BEGIN + + DECLARE vDate DATE; + SET vDate = '2000-01-01'; + + WHILE ( YEAR(vDate) <= 2002 ) DO + INSERT IGNORE INTO vn.`time` (dated, period, `month`, `year`, `day`, week, yearMonth, salesYear) + VALUES (vDate, CONCAT(YEAR(vDate), (WEEK(vDate)+1)), MONTH(vDate), YEAR(vDate), DAY(vDate), WEEK(vDate)+1, CONCAT(YEAR(vDate), MONTH(vDate)), YEAR(vDate)); + + SET vDate = DATE_ADD(vDate, INTERVAL 1 DAY); + END WHILE; + +END$$ +DELIMITER ; + +CALL `vn`.`mockVnTime`(); +DROP PROCEDURE IF EXISTS `vn`.`mockVnTime`; +-- END MOCK vn.time ALTER TABLE `vn`.`itemTaxCountry` AUTO_INCREMENT = 1; ALTER TABLE `vn`.`address` AUTO_INCREMENT = 1; @@ -934,10 +960,10 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL), (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL), (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, NULL), - (10, 7, 7, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (11, 7, 8, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (12, 7, 9, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (13, 1, 10,71, NOW(), 1, 18, NULL, 94, 3, NULL); + (10, 7, 7, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (11, 7, 8, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (12, 7, 9, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (13, 1, 10,71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL); INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) @@ -1143,10 +1169,10 @@ INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `visible`, `grouping`, INSERT INTO `vn`.`itemShelvingSale` (`itemShelvingFk`, `saleFk`, `quantity`, `created`, `userFk`) VALUES - ('1', '1', '1', '', '1106'), - ('2', '2', '5', '', '1106'), - ('1', '7', '1', '', '1106'), - ('2', '8', '5', '', '1106'); + ('1', '1', '1', util.VN_CURDATE(), '1106'), + ('2', '2', '5', util.VN_CURDATE(), '1106'), + ('1', '7', '1', util.VN_CURDATE(), '1106'), + ('2', '8', '5', util.VN_CURDATE(), '1106'); INSERT INTO `vncontrol`.`accion`(`accion_id`, `accion`) VALUES @@ -1215,7 +1241,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), @@ -1779,7 +1805,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`) INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`) VALUES (1, 1, 1, 21, 1, 1, 2, 5), - (2, 1, 1, 21, 7, 2, 2, 5), + (2, 1, 2, 21, 7, 2, 2, 5), (3, 2, 7, 21, 9, 3, 2, 5), (4, 3, 7, 21, 15, 8, 2, 5), (5, 4, 7, 21, 7, 8, 2, 5); @@ -1910,7 +1936,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL +1 YEAR)), '-12-25'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-12-25') as started, CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR)), '-12-25') as ended, CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w`; INSERT INTO `vn`.`business`(`id`, `workerFk`, `companyCodeFk`, `started`, `ended`, `workerBusiness`, `reasonEndFk`, `notes`, `departmentFk`, `workerBusinessProfessionalCategoryFk`, `calendarTypeFk`, `isHourlyLabor`, `workerBusinessAgreementFk`, `workcenterFk`) @@ -1920,7 +1946,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -2 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -2 YEAR)), '-12-25') as started, CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)) as ended, '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w` WHERE `w`.`id` = 1109; @@ -1954,10 +1980,6 @@ INSERT INTO `vn`.`workerBusinessType` (`id`, `name`, `isFullTime`, `isPermanent` (100, 'INDEFINIDO A TIEMPO COMPLETO', 1, 1, 1), (109, 'CONVERSION DE TEMPORAL EN INDEFINIDO T.COMPLETO', 1, 1, 1); -INSERT INTO `vn`.`businessCategory` (`id`, `description`, `rate`) - VALUES - (1, 'basic employee', 1); - UPDATE `vn`.`business` b SET `rate` = 7, `workerBusinessCategoryFk` = 1, @@ -2580,13 +2602,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 @@ -2633,7 +2651,7 @@ INSERT INTO `vn`.`machineWorker` (`workerFk`, `machineFk`, `inTimed`, `outTimed` INSERT INTO `vn`.`zoneExclusion` (`id`, `zoneFk`, `dated`, `created`, `userFk`) VALUES - (1, 1, DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=7, 7, 14) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100), + (1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL (IF(DAYOFWEEK(util.VN_CURDATE())<=7, 7, 14) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100), (2, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL (IF(DAYOFWEEK(util.VN_CURDATE())<=8, 8, 15) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100); INSERT INTO `vn`.`zoneExclusionGeo` (`zoneExclusionFk`, `geoFk`) @@ -2671,9 +2689,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 +2710,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`) @@ -2708,7 +2727,10 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) VALUES (1, 1109), (1, 1110), - (3, 1109); + (3, 1109), + (1,9), + (1,3); + INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) VALUES @@ -2722,6 +2744,10 @@ INSERT INTO `vn`.`collection` (`id`, `created`, `workerFk`, `stateFk`, `itemPack VALUES (3, util.VN_NOW(), 1107, 5, NULL, 0, 0, 1, NULL, NULL); +INSERT INTO `vn`.`itemConfig` (`id`, `isItemTagTriggerDisabled`, `monthToDeactivate`, `wasteRecipients`, `validPriorities`, `defaultPriority`, `defaultTag`) + VALUES + (0, 0, 24, '', '[1,2,3]', 2, 56); + INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `created`, `level`, `wagon`, `smartTagFk`, `usedShelves`, `itemCount`, `liters`) VALUES (9, 3, util.VN_NOW(), NULL, 0, NULL, NULL, NULL, NULL); @@ -2744,16 +2770,20 @@ 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 ('foo', 'master', NULL, NULL), ('bar', 'test', 9, util.VN_NOW()); -INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`) - VALUES - (1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1); +INSERT INTO `vn`.`profileType` (`id`, `name`) + VALUES + (1, 'working'); + +INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) + VALUES + (1, 'S/ ', 1, 442, 1, 1); INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) VALUES @@ -2764,3 +2794,7 @@ INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES (1, 1); +INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) + VALUES + (1, NULL, 1); + diff --git a/db/dump/mockDate.sql b/db/dump/mockDate.sql index c63c2d76c..937da071c 100644 --- a/db/dump/mockDate.sql +++ b/db/dump/mockDate.sql @@ -3,18 +3,17 @@ USE `util`; DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`mockedDate`; -CREATE FUNCTION `util`.`mockedDate`() +CREATE FUNCTION `util`.`mockedDate`() RETURNS DATETIME DETERMINISTIC BEGIN - RETURN NOW(); - -- '2022-01-19 08:00:00' + RETURN CONVERT_TZ('2001-01-01 11:00:00', 'utc', 'Europe/Madrid'); END ;; DELIMITER ; DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`VN_CURDATE`; -CREATE FUNCTION `util`.`VN_CURDATE`() +CREATE FUNCTION `util`.`VN_CURDATE`() RETURNS DATE DETERMINISTIC BEGIN @@ -24,7 +23,7 @@ DELIMITER ; DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`VN_CURTIME`; -CREATE FUNCTION `util`.`VN_CURTIME`() +CREATE FUNCTION `util`.`VN_CURTIME`() RETURNS TIME DETERMINISTIC BEGIN @@ -34,10 +33,10 @@ DELIMITER ; DELIMITER ;; DROP FUNCTION IF EXISTS `util`.`VN_NOW`; -CREATE FUNCTION `util`.`VN_NOW`() +CREATE FUNCTION `util`.`VN_NOW`() RETURNS DATETIME DETERMINISTIC BEGIN - RETURN mockedDate(); + RETURN mockedDate(); END ;; -DELIMITER ; \ No newline at end of file +DELIMITER ; diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 47fdd6d74..4626279e4 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -80202,3 +80202,4 @@ 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/db/tests/vn/buyUltimate.spec.js b/db/tests/vn/buyUltimate.spec.js index e0b3fa568..4c98945c1 100644 --- a/db/tests/vn/buyUltimate.spec.js +++ b/db/tests/vn/buyUltimate.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; describe('buyUltimate()', () => { - const today = new Date(); + const today = Date.vnNew(); it(`should create buyUltimate temporal table and update it's values`, async() => { let stmts = []; let stmt; diff --git a/db/tests/vn/buyUltimateFromInterval.spec.js b/db/tests/vn/buyUltimateFromInterval.spec.js index b5e6970f7..7a4a79d47 100644 --- a/db/tests/vn/buyUltimateFromInterval.spec.js +++ b/db/tests/vn/buyUltimateFromInterval.spec.js @@ -5,7 +5,7 @@ describe('buyUltimateFromInterval()', () => { let today; let future; beforeAll(() => { - let now = new Date(); + let now = Date.vnNew(); now.setHours(0, 0, 0, 0); today = now; diff --git a/db/tests/vn/ticketCalculateClon.spec.js b/db/tests/vn/ticketCalculateClon.spec.js index 03814682d..a3c790492 100644 --- a/db/tests/vn/ticketCalculateClon.spec.js +++ b/db/tests/vn/ticketCalculateClon.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; describe('ticket ticketCalculateClon()', () => { - const today = new Date(); + const today = Date.vnNew(); it('should add the ticket to the order containing the original ticket', async() => { let stmts = []; let stmt; diff --git a/db/tests/vn/ticketCreateWithUser.spec.js b/db/tests/vn/ticketCreateWithUser.spec.js index 1c13be1b3..4aeece564 100644 --- a/db/tests/vn/ticketCreateWithUser.spec.js +++ b/db/tests/vn/ticketCreateWithUser.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; describe('ticket ticketCreateWithUser()', () => { - const today = new Date(); + const today = Date.vnNew(); it('should confirm the procedure creates the expected ticket', async() => { let stmts = []; let stmt; diff --git a/db/tests/vn/timeBusiness_calculateByUser.spec.js b/db/tests/vn/timeBusiness_calculateByUser.spec.js index 441f567ac..5fe51d8f8 100644 --- a/db/tests/vn/timeBusiness_calculateByUser.spec.js +++ b/db/tests/vn/timeBusiness_calculateByUser.spec.js @@ -3,9 +3,9 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; describe('timeBusiness_calculateByUser()', () => { it('should return the expected hours for today', async() => { - let start = new Date(); + let start = Date.vnNew(); start.setHours(0, 0, 0, 0); - let end = new Date(); + let end = Date.vnNew(); end.setHours(0, 0, 0, 0); let stmts = []; diff --git a/db/tests/vn/timeControl_calculateByUser.spec.js b/db/tests/vn/timeControl_calculateByUser.spec.js index 2aa16c7a4..73e00ec3a 100644 --- a/db/tests/vn/timeControl_calculateByUser.spec.js +++ b/db/tests/vn/timeControl_calculateByUser.spec.js @@ -3,11 +3,11 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; describe('timeControl_calculateByUser()', () => { it(`should return today's worked hours`, async() => { - let start = new Date(); + let start = Date.vnNew(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - 1); - let end = new Date(); + let end = Date.vnNew(); end.setHours(0, 0, 0, 0); end.setDate(end.getDate() + 1); @@ -17,7 +17,7 @@ describe('timeControl_calculateByUser()', () => { stmts.push('START TRANSACTION'); stmts.push(` - DROP TEMPORARY TABLE IF EXISTS + DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate, tmp.timeBusinessCalculate `); @@ -48,14 +48,14 @@ describe('timeControl_calculateByUser()', () => { }); it(`should return the worked hours between last sunday and monday`, async() => { - let lastSunday = new Date(); + let lastSunday = Date.vnNew(); let daysSinceSunday = lastSunday.getDay(); if (daysSinceSunday === 0) // this means today is sunday but you need the previous sunday :) daysSinceSunday = 7; lastSunday.setHours(23, 0, 0, 0); lastSunday.setDate(lastSunday.getDate() - daysSinceSunday); - let monday = new Date(); + let monday = Date.vnNew(); let daysSinceMonday = daysSinceSunday - 1; // aiming for monday (today could be monday) monday.setHours(7, 0, 0, 0); monday.setDate(monday.getDate() - daysSinceMonday); @@ -66,7 +66,7 @@ describe('timeControl_calculateByUser()', () => { stmts.push('START TRANSACTION'); stmts.push(` - DROP TEMPORARY TABLE IF EXISTS + DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate, tmp.timeBusinessCalculate `); diff --git a/db/tests/vn/zone_getLanded.spec.js b/db/tests/vn/zone_getLanded.spec.js index 5f82156d3..888d7c132 100644 --- a/db/tests/vn/zone_getLanded.spec.js +++ b/db/tests/vn/zone_getLanded.spec.js @@ -6,7 +6,7 @@ describe('zone zone_getLanded()', () => { let stmts = []; let stmt; stmts.push('START TRANSACTION'); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); let params = { @@ -40,7 +40,7 @@ describe('zone zone_getLanded()', () => { it(`should return data for a shipped tomorrow`, async() => { let stmts = []; let stmt; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); stmts.push('START TRANSACTION'); diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index 7bf56e2c8..7d80c69ee 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -436,7 +436,7 @@ let actions = { }, pickDate: async function(selector, date) { - date = date || new Date(); + date = date || Date.vnNew(); const timeZoneOffset = date.getTimezoneOffset() * 60000; const localDate = (new Date(date.getTime() - timeZoneOffset)) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index e1792ea7b..8f9fcda57 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -31,7 +31,7 @@ export default { }, recoverPassword: { recoverPasswordButton: 'vn-login a[ui-sref="recover-password"]', - email: 'vn-recover-password vn-textfield[ng-model="$ctrl.email"]', + email: 'vn-recover-password vn-textfield[ng-model="$ctrl.user"]', sendEmailButton: 'vn-recover-password vn-submit', }, accountIndex: { @@ -58,6 +58,7 @@ export default { deleteAccount: '.vn-menu [name="deleteUser"]', setPassword: '.vn-menu [name="setPassword"]', activateAccount: '.vn-menu [name="enableAccount"]', + disableAccount: '.vn-menu [name="disableAccount"]', activateUser: '.vn-menu [name="activateUser"]', deactivateUser: '.vn-menu [name="deactivateUser"]', newPassword: 'vn-textfield[ng-model="$ctrl.newPassword"]', @@ -417,8 +418,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"]', @@ -428,6 +429,7 @@ export default { }, itemCreateView: { temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]', + priority: 'vn-autocomplete[ng-model="$ctrl.item.priority"]', type: 'vn-autocomplete[ng-model="$ctrl.item.typeFk"]', intrastat: 'vn-autocomplete[ng-model="$ctrl.item.intrastatFk"]', origin: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]', @@ -463,6 +465,7 @@ export default { generic: 'vn-autocomplete[ng-model="$ctrl.item.genericFk"]', isFragile: 'vn-check[ng-model="$ctrl.item.isFragile"]', longName: 'vn-textfield[ng-model="$ctrl.item.longName"]', + packingOut: 'vn-input-number[ng-model="$ctrl.item.packingOut"]', isActiveCheckbox: 'vn-check[label="Active"]', priceInKgCheckbox: 'vn-check[label="Price in kg"]', newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button', @@ -520,7 +523,7 @@ export default { }, itemLog: { anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr', - fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(3) td.after', + fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(2) td.after', }, ticketSummary: { header: 'vn-ticket-summary > vn-card > h5', @@ -559,15 +562,15 @@ export default { payoutBank: '.vn-dialog vn-autocomplete[ng-model="$ctrl.bankFk"]', payoutDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]', submitPayout: '.vn-dialog button[response="accept"]', - searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr', + searchWeeklyResult: 'vn-ticket-weekly-index vn-card smart-table slot-table table tbody tr', searchResultDate: 'vn-ticket-summary [label=Landed] span', topbarSearch: 'vn-searchbar', moreMenu: 'vn-ticket-index vn-icon-button[icon=more_vert]', - fourthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tbody vn-tr:nth-child(4)', - fiveWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tbody vn-tr:nth-child(5)', - weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr', - firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]', - firstWeeklyTicketAgency: 'vn-ticket-weekly-index vn-tr:nth-child(1) [ng-model="weekly.agencyModeFk"]', + fourthWeeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(4)', + fiveWeeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(5)', + weeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table table tbody tr', + firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(1) vn-icon-button[icon="delete"]', + firstWeeklyTicketAgency: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(1) [ng-model="weekly.agencyModeFk"]', acceptDeleteTurn: '.vn-confirm.shown button[response="accept"]' }, createTicketView: { @@ -678,7 +681,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' @@ -772,8 +778,8 @@ export default { ipt: 'vn-autocomplete[label="Destination IPT"]', tableIpt: 'vn-autocomplete[name="ipt"]', tableFutureIpt: 'vn-autocomplete[name="futureIpt"]', - futureState: 'vn-autocomplete[label="Origin Grouped State"]', - state: 'vn-autocomplete[label="Destination Grouped State"]', + futureState: 'vn-check[label="Pending Origin"]', + state: 'vn-check[label="Pending Destination"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Advance tickets"]', @@ -938,9 +944,9 @@ export default { routeSummary: { header: 'vn-route-summary > vn-card > h5', cost: 'vn-route-summary vn-label-value[label="Cost"]', - firstTicketID: 'vn-route-summary vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2) > span', + firstTicketID: 'vn-route-summary vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(10) > span', firstTicketDescriptor: '.vn-popover.shown vn-ticket-descriptor', - firstAlias: 'vn-route-summary vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(3) > span', + firstAlias: 'vn-route-summary vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(5) > span', firstClientDescriptor: '.vn-popover.shown vn-client-descriptor', goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a', @@ -964,6 +970,7 @@ export default { confirmButton: '.vn-confirm.shown button[response="accept"]' }, workerSummary: { + summaryIcon: 'vn-worker-descriptor a[title="Go to module summary"]', header: 'vn-worker-summary h5', id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span', email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span', @@ -1016,6 +1023,25 @@ export default { furlough: 'vn-worker-calendar > vn-side-menu [name="absenceTypes"] > vn-chip:nth-child(4)', halfFurlough: 'vn-worker-calendar > vn-side-menu [name="absenceTypes"] > vn-chip:nth-child(5)', }, + workerCreate: { + newWorkerButton: 'vn-worker-index a[ui-sref="worker.create"]', + firstname: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.firstName"]', + lastname: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.lastNames"]', + birth: 'vn-worker-create vn-date-picker[ng-model="$ctrl.worker.birth"]', + fi: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.fi"]', + code: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.code"]', + phone: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.phone"]', + city: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.city"]', + postcode: 'vn-worker-create vn-datalist[ng-model="$ctrl.worker.postcode"]', + street: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.street"]', + user: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.name"]', + email: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.email"]', + boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]', + role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]', + iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]', + switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]', + createButton: 'vn-worker-create vn-submit[label="Create"]', + }, invoiceOutIndex: { topbarSearch: 'vn-searchbar', searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr', @@ -1234,6 +1260,21 @@ export default { importBuysButton: 'vn-entry-buy-import button[type="submit"]' }, entryLatestBuys: { + table: 'tbody > tr:not(.empty-rows)', + chip: 'vn-chip > vn-icon', + generalSearchInput: 'vn-textfield[ng-model="$ctrl.filter.search"]', + firstReignIcon: 'vn-horizontal.item-category vn-one', + typeInput: 'vn-autocomplete[ng-model="$ctrl.filter.typeFk"]', + salesPersonInput: 'vn-autocomplete[ng-model="$ctrl.filter.salesPersonFk"]', + supplierInput: 'vn-autocomplete[ng-model="$ctrl.filter.supplierFk"]', + fromInput: 'vn-date-picker[ng-model="$ctrl.filter.from"]', + toInput: 'vn-date-picker[ng-model="$ctrl.filter.to"]', + activeCheck: 'vn-check[ng-model="$ctrl.filter.active"]', + floramondoCheck: 'vn-check[ng-model="$ctrl.filter.floramondo"]', + visibleCheck: 'vn-check[ng-model="$ctrl.filter.visible"]', + addTagButton: 'vn-icon-button[vn-tooltip="Add tag"]', + itemTagInput: 'vn-autocomplete[ng-model="itemTag.tagFk"]', + itemTagValueInput: 'vn-autocomplete[ng-model="itemTag.value"]', firstBuy: 'vn-entry-latest-buys tbody > tr:nth-child(1)', allBuysCheckBox: 'vn-entry-latest-buys thead vn-check', secondBuyCheckBox: 'vn-entry-latest-buys tbody tr:nth-child(2) vn-check[ng-model="buy.checked"]', diff --git a/e2e/helpers/tests.js b/e2e/helpers/tests.js index aac9963dd..992ec051f 100644 --- a/e2e/helpers/tests.js +++ b/e2e/helpers/tests.js @@ -1,6 +1,7 @@ require('@babel/register')({presets: ['@babel/env']}); require('core-js/stable'); require('regenerator-runtime/runtime'); +require('vn-loopback/server/boot/date')(); const axios = require('axios'); const Docker = require('../../db/docker.js'); 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/01-salix/04_recoverPassword.spec.js b/e2e/paths/01-salix/04_recoverPassword.spec.js index e6cb02ab1..aa0389648 100644 --- a/e2e/paths/01-salix/04_recoverPassword.spec.js +++ b/e2e/paths/01-salix/04_recoverPassword.spec.js @@ -26,7 +26,7 @@ describe('RecoverPassword path', async() => { expect(message.text).toContain('Notification sent!'); }); - it('should send email', async() => { + it('should send email using email', async() => { await page.waitForState('login'); await page.waitToClick(selectors.recoverPassword.recoverPasswordButton); @@ -37,4 +37,16 @@ describe('RecoverPassword path', async() => { expect(message.text).toContain('Notification sent!'); }); + + it('should send email using username', async() => { + await page.waitForState('login'); + await page.waitToClick(selectors.recoverPassword.recoverPasswordButton); + + await page.write(selectors.recoverPassword.email, 'BruceWayne'); + await page.waitToClick(selectors.recoverPassword.sendEmailButton); + const message = await page.waitForSnackbar(); + await page.waitForState('login'); + + expect(message.text).toContain('Notification sent!'); + }); }); diff --git a/e2e/paths/02-client/20_credit_insurance.spec.js b/e2e/paths/02-client/20_credit_insurance.spec.js index 904a51145..a4f148b8f 100644 --- a/e2e/paths/02-client/20_credit_insurance.spec.js +++ b/e2e/paths/02-client/20_credit_insurance.spec.js @@ -4,7 +4,7 @@ import getBrowser from '../../helpers/puppeteer'; describe('Client credit insurance path', () => { let browser; let page; - let previousMonth = new Date(); + let previousMonth = Date.vnNew(); previousMonth.setMonth(previousMonth.getMonth() - 1); beforeAll(async() => { diff --git a/e2e/paths/03-worker/01_summary.spec.js b/e2e/paths/03-worker/01_summary.spec.js index 4ea87481a..4e5b0cfa9 100644 --- a/e2e/paths/03-worker/01_summary.spec.js +++ b/e2e/paths/03-worker/01_summary.spec.js @@ -2,68 +2,32 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker summary path', () => { + const workerId = 3; let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'worker'); + const httpDataResponse = page.waitForResponse(response => { + return response.status() === 200 && response.url().includes(`Workers/${workerId}`); + }); await page.accessToSearchResult('agencyNick'); + await httpDataResponse; }); afterAll(async() => { await browser.close(); }); - it('should reach the employee summary section', async() => { - await page.waitForState('worker.card.summary'); - }); - - it('should check the summary contains the name and userName on the header', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.header, 'innerText'); - - expect(result).toEqual('agency agency'); - }); - - it('should check the summary contains the basic data id', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.id, 'innerText'); - - expect(result).toEqual('3'); - }); - - it('should check the summary contains the basic data email', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.email, 'innerText'); - - expect(result).toEqual('agency@verdnatura.es'); - }); - - it('should check the summary contains the basic data department', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.department, 'innerText'); - - expect(result).toEqual('CAMARA'); - }); - - it('should check the summary contains the user data id', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.userId, 'innerText'); - - expect(result).toEqual('3'); - }); - - it('should check the summary contains the user data name', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.userName, 'innerText'); - - expect(result).toEqual('agency'); - }); - - it('should check the summary contains the user data role', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.role, 'innerText'); - - expect(result).toEqual('agency'); - }); - - it('should check the summary contains the user data extension', async() => { - const result = await page.waitToGetProperty(selectors.workerSummary.extension, 'innerText'); - - expect(result).toEqual('1101'); + it('should reach the employee summary section and check all properties', async() => { + expect(await page.getProperty(selectors.workerSummary.header, 'innerText')).toEqual('agency agency'); + expect(await page.getProperty(selectors.workerSummary.id, 'innerText')).toEqual('3'); + expect(await page.getProperty(selectors.workerSummary.email, 'innerText')).toEqual('agency@verdnatura.es'); + expect(await page.getProperty(selectors.workerSummary.department, 'innerText')).toEqual('CAMARA'); + expect(await page.getProperty(selectors.workerSummary.userId, 'innerText')).toEqual('3'); + expect(await page.getProperty(selectors.workerSummary.userName, 'innerText')).toEqual('agency'); + expect(await page.getProperty(selectors.workerSummary.role, 'innerText')).toEqual('agency'); + expect(await page.getProperty(selectors.workerSummary.extension, 'innerText')).toEqual('1101'); }); }); diff --git a/e2e/paths/03-worker/02_basicData.spec.js b/e2e/paths/03-worker/02_basicData.spec.js index c367c8706..66a597dd1 100644 --- a/e2e/paths/03-worker/02_basicData.spec.js +++ b/e2e/paths/03-worker/02_basicData.spec.js @@ -2,13 +2,18 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker basic data path', () => { + const workerId = 1106; let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('hr', 'worker'); + const httpDataResponse = page.waitForResponse(response => { + return response.status() === 200 && response.url().includes(`Workers/${workerId}`); + }); await page.accessToSearchResult('David Charles Haller'); + await httpDataResponse; await page.accessToSection('worker.card.basicData'); }); @@ -16,35 +21,20 @@ describe('Worker basic data path', () => { await browser.close(); }); - it('should edit the form', async() => { - await page.clearInput(selectors.workerBasicData.name); - await page.write(selectors.workerBasicData.name, 'David C.'); - await page.clearInput(selectors.workerBasicData.surname); - await page.write(selectors.workerBasicData.surname, 'H.'); - await page.clearInput(selectors.workerBasicData.phone); - await page.write(selectors.workerBasicData.phone, '444332211'); - await page.waitToClick(selectors.workerBasicData.saveButton); + it('should edit the form and then reload the section and check the data was edited', async() => { + await page.overwrite(selectors.workerBasicData.name, 'David C.'); + await page.overwrite(selectors.workerBasicData.surname, 'H.'); + await page.overwrite(selectors.workerBasicData.phone, '444332211'); + await page.click(selectors.workerBasicData.saveButton); + const message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved!'); - }); - it('should reload the section then check the name was edited', async() => { await page.reloadSection('worker.card.basicData'); - const result = await page.waitToGetProperty(selectors.workerBasicData.name, 'value'); - expect(result).toEqual('David C.'); - }); - - it('should the surname was edited', async() => { - const result = await page.waitToGetProperty(selectors.workerBasicData.surname, 'value'); - - expect(result).toEqual('H.'); - }); - - it('should the phone was edited', async() => { - const result = await page.waitToGetProperty(selectors.workerBasicData.phone, 'value'); - - expect(result).toEqual('444332211'); + expect(await page.waitToGetProperty(selectors.workerBasicData.name, 'value')).toEqual('David C.'); + expect(await page.waitToGetProperty(selectors.workerBasicData.surname, 'value')).toEqual('H.'); + expect(await page.waitToGetProperty(selectors.workerBasicData.phone, 'value')).toEqual('444332211'); }); }); diff --git a/e2e/paths/03-worker/03_pbx.spec.js b/e2e/paths/03-worker/03_pbx.spec.js index f5d2711d1..0e8003c47 100644 --- a/e2e/paths/03-worker/03_pbx.spec.js +++ b/e2e/paths/03-worker/03_pbx.spec.js @@ -16,19 +16,16 @@ describe('Worker pbx path', () => { await browser.close(); }); - it('should receive an error when the extension exceeds 4 characters', async() => { + it('should receive an error when the extension exceeds 4 characters and then sucessfully save the changes', async() => { await page.write(selectors.workerPbx.extension, '55555'); - await page.waitToClick(selectors.workerPbx.saveButton); - const message = await page.waitForSnackbar(); + await page.click(selectors.workerPbx.saveButton); + let message = await page.waitForSnackbar(); expect(message.text).toContain('Extension format is invalid'); - }); - it('should sucessfully save the changes', async() => { - await page.clearInput(selectors.workerPbx.extension); - await page.write(selectors.workerPbx.extension, '4444'); - await page.waitToClick(selectors.workerPbx.saveButton); - const message = await page.waitForSnackbar(); + await page.overwrite(selectors.workerPbx.extension, '4444'); + await page.click(selectors.workerPbx.saveButton); + message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved! User must access web'); }); diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index 4236ae0e4..eb1417ba9 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -21,38 +21,37 @@ describe('Worker time control path', () => { const fourPm = '16:00'; const hankPymId = 1107; - it('should go to the next month', async() => { - const date = new Date(); + it('should go to the next month, go to current month and go 1 month in the past', async() => { + let date = Date.vnNew(); + date.setDate(1); date.setMonth(date.getMonth() + 1); - const month = date.toLocaleString('default', {month: 'long'}); + let month = date.toLocaleString('default', {month: 'long'}); - await page.waitToClick(selectors.workerTimeControl.nextMonthButton); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + await page.click(selectors.workerTimeControl.nextMonthButton); + let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); expect(result).toContain(month); - }); - it('should go to current month', async() => { - const date = new Date(); - const month = date.toLocaleString('default', {month: 'long'}); + date = Date.vnNew(); + date.setDate(1); + month = date.toLocaleString('default', {month: 'long'}); - await page.waitToClick(selectors.workerTimeControl.previousMonthButton); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + await page.click(selectors.workerTimeControl.previousMonthButton); + result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); expect(result).toContain(month); - }); - it('should go 1 month in the past', async() => { - const date = new Date(); + date = Date.vnNew(); + date.setDate(1); date.setMonth(date.getMonth() - 1); const timestamp = Math.round(date.getTime() / 1000); - const month = date.toLocaleString('default', {month: 'long'}); + month = date.toLocaleString('default', {month: 'long'}); await page.loginAndModule('salesBoss', 'worker'); await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); + await page.click(selectors.workerTimeControl.secondWeekDay); - const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); expect(result).toContain(month); }); @@ -115,7 +114,9 @@ describe('Worker time control path', () => { }); it('should change week of month', async() => { - await page.waitToClick(selectors.workerTimeControl.thrirdWeekDay); - await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '00:00 h.'); + await page.click(selectors.workerTimeControl.thrirdWeekDay); + const result = await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText'); + + expect(result).toEqual('00:00 h.'); }); }); diff --git a/e2e/paths/03-worker/05_calendar.spec.js b/e2e/paths/03-worker/05_calendar.spec.js index e97b7fe7c..f0af0a053 100644 --- a/e2e/paths/03-worker/05_calendar.spec.js +++ b/e2e/paths/03-worker/05_calendar.spec.js @@ -1,16 +1,25 @@ +/* eslint-disable max-len */ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Worker calendar path', () => { - let reasonableTimeBetweenClicks = 400; + const reasonableTimeBetweenClicks = 300; + const date = Date.vnNew(); + const lastYear = (date.getFullYear() - 1).toString(); + let browser; let page; + + async function accessAs(user) { + await page.loginAndModule(user, 'worker'); + await page.accessToSearchResult('Charles Xavier'); + await page.accessToSection('worker.card.calendar'); + } + beforeAll(async() => { browser = await getBrowser(); page = browser.page; - await page.loginAndModule('hr', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); + accessAs('hr'); }); afterAll(async() => { @@ -21,48 +30,40 @@ describe('Worker calendar path', () => { it('should set two days as holidays on the calendar and check the total holidays increased by 1.5', async() => { await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); + await page.click(selectors.workerCalendar.penultimateMondayOfJanuary); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.absence); + await page.click(selectors.workerCalendar.absence); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.lastMondayOfMarch); + await page.click(selectors.workerCalendar.lastMondayOfMarch); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.halfHoliday); + await page.click(selectors.workerCalendar.halfHoliday); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.fistMondayOfMay); + await page.click(selectors.workerCalendar.fistMondayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.furlough); + await page.click(selectors.workerCalendar.furlough); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondTuesdayOfMay); + await page.click(selectors.workerCalendar.secondTuesdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondWednesdayOfMay); + await page.click(selectors.workerCalendar.secondWednesdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondThursdayOfMay); + await page.click(selectors.workerCalendar.secondThursdayOfMay); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.halfFurlough); - await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.secondFridayOfJun); + await page.click(selectors.workerCalendar.halfFurlough); await page.waitForTimeout(reasonableTimeBetweenClicks); + await page.click(selectors.workerCalendar.secondFridayOfJun); - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 1.5 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 1.5 '); }); }); describe(`as salesBoss`, () => { - it(`should log in and get to Charles Xavier's calendar`, async() => { - await page.loginAndModule('salesBoss', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); - }); + it(`should log in, get to Charles Xavier's calendar, undo what was done here, and check the total holidays used are back to what it was`, async() => { + accessAs('salesBoss'); - it('should undo what was done here', async() => { - await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); @@ -90,45 +91,24 @@ describe('Worker calendar path', () => { await page.waitToClick(selectors.workerCalendar.halfFurlough); await page.waitForTimeout(reasonableTimeBetweenClicks); await page.waitToClick(selectors.workerCalendar.secondFridayOfJun); - }); - it('should check the total holidays used are back to what it was', async() => { - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 0 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); }); }); describe(`as Charles Xavier`, () => { - it(`should log in and get to his calendar`, async() => { - await page.loginAndModule('CharlesXavier', 'worker'); - await page.accessToSearchResult('Charles Xavier'); - await page.accessToSection('worker.card.calendar'); - }); - - it('should make a futile attempt to add holidays', async() => { - await page.waitForTimeout(reasonableTimeBetweenClicks); + it('should log in and get to his calendar, make a futile attempt to add holidays, check the total holidays used are now the initial ones and use the year selector to go to the previous year', async() => { + accessAs('CharlesXavier'); await page.waitToClick(selectors.workerCalendar.holidays); await page.waitForTimeout(reasonableTimeBetweenClicks); - await page.waitToClick(selectors.workerCalendar.penultimateMondayOfJanuary); - }); - it('should check the total holidays used are now the initial ones', async() => { - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); + await page.click(selectors.workerCalendar.penultimateMondayOfJanuary); - expect(result).toContain(' 0 '); - }); - - it('should use the year selector to go to the previous year', async() => { - const date = new Date(); - const lastYear = (date.getFullYear() - 1).toString(); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); await page.autocompleteSearch(selectors.workerCalendar.year, lastYear); - await page.waitForTimeout(reasonableTimeBetweenClicks); - const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText'); - - expect(result).toContain(' 0 '); + expect(await page.getProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText')).toContain(' 0 '); }); }); }); diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js new file mode 100644 index 000000000..5f6f5cf9f --- /dev/null +++ b/e2e/paths/03-worker/06_create.spec.js @@ -0,0 +1,74 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Worker create path', () => { + let browser; + let page; + let newWorker; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('hr', 'worker'); + await page.waitToClick(selectors.workerCreate.newWorkerButton); + await page.waitForState('worker.create'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should insert default data', async() => { + await page.write(selectors.workerCreate.firstname, 'Victor'); + await page.write(selectors.workerCreate.lastname, 'Von Doom'); + await page.write(selectors.workerCreate.fi, '78457139E'); + await page.write(selectors.workerCreate.phone, '12356789'); + await page.write(selectors.workerCreate.postcode, '46680'); + await page.write(selectors.workerCreate.street, 'S/ Doomstadt'); + await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com'); + await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332'); + await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM'); + + // should check for autocompleted worker code and worker user name + const workerCode = await page + .waitToGetProperty(selectors.workerCreate.code, 'value'); + + newWorker = await page + .waitToGetProperty(selectors.workerCreate.user, 'value'); + + expect(workerCode).toEqual('VVD'); + expect(newWorker).toContain('victorvd'); + + // should fail if necessary data is void + await page.waitToClick(selectors.workerCreate.createButton); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('is a required argument'); + + // should create a new worker and go to worker basic data' + await page.pickDate(selectors.workerCreate.birth, new Date(1962, 8, 5)); + await page.autocompleteSearch(selectors.workerCreate.boss, 'deliveryBoss'); + await page.waitToClick(selectors.workerCreate.createButton); + message = await page.waitForSnackbar(); + await page.waitForState('worker.card.basicData'); + + expect(message.text).toContain('Data saved!'); + + // 'rollback' + await page.loginAndModule('sysadmin', 'account'); + await page.accessToSearchResult(newWorker); + + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.deactivateUser); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('User deactivated!'); + + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.disableAccount); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Account disabled!'); + }); +}); diff --git a/e2e/paths/04-item/02_basic_data.spec.js b/e2e/paths/04-item/02_basic_data.spec.js index a663ea3bb..3cf142816 100644 --- a/e2e/paths/04-item/02_basic_data.spec.js +++ b/e2e/paths/04-item/02_basic_data.spec.js @@ -35,6 +35,7 @@ describe('Item Edit basic data path', () => { await page.waitToClick(selectors.itemBasicData.isActiveCheckbox); await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox); await page.waitToClick(selectors.itemBasicData.isFragile); + await page.write(selectors.itemBasicData.packingOut, '5'); await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); const message = await page.waitForSnackbar(); @@ -128,4 +129,11 @@ describe('Item Edit basic data path', () => { expect(result).toBe('checked'); }); + + it(`should confirm the item packingOut was edited`, async() => { + const result = await page + .waitToGetProperty(selectors.itemBasicData.packingOut, 'value'); + + expect(result).toEqual('5'); + }); }); diff --git a/e2e/paths/04-item/07_create.spec.js b/e2e/paths/04-item/07_create.spec.js index 0820f2db7..33324cdba 100644 --- a/e2e/paths/04-item/07_create.spec.js +++ b/e2e/paths/04-item/07_create.spec.js @@ -36,11 +36,20 @@ describe('Item Create', () => { await page.waitForState('item.create'); }); - it('should create the Infinity Gauntlet item', async() => { + it('should throw an error when insert an invalid priority', async() => { await page.write(selectors.itemCreateView.temporalName, 'Infinity Gauntlet'); await page.autocompleteSearch(selectors.itemCreateView.type, 'Crisantemo'); await page.autocompleteSearch(selectors.itemCreateView.intrastat, 'Coral y materiales similares'); await page.autocompleteSearch(selectors.itemCreateView.origin, 'Holand'); + await page.clearInput(selectors.itemCreateView.priority); + await page.waitToClick(selectors.itemCreateView.createButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Valid priorities'); + }); + + it('should create the Infinity Gauntlet item', async() => { + await page.autocompleteSearch(selectors.itemCreateView.priority, '2'); await page.waitToClick(selectors.itemCreateView.createButton); const message = await page.waitForSnackbar(); diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index fc7aac3d0..1b0f82d83 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -22,10 +22,10 @@ describe('Item fixed prices path', () => { }); it('should fill the fixed price data', async() => { - const now = new Date(); + const now = Date.vnNew(); 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/06_basic_data_steps.spec.js b/e2e/paths/05-ticket/06_basic_data_steps.spec.js index fa901e325..55aec45fb 100644 --- a/e2e/paths/05-ticket/06_basic_data_steps.spec.js +++ b/e2e/paths/05-ticket/06_basic_data_steps.spec.js @@ -93,7 +93,7 @@ describe('Ticket Edit basic data path', () => { it(`should split ticket without negatives`, async() => { const newAgency = 'Gotham247'; - const newDate = new Date(); + const newDate = Date.vnNew(); newDate.setDate(newDate.getDate() - 1); await page.accessToSearchResult('14'); @@ -127,7 +127,7 @@ describe('Ticket Edit basic data path', () => { }); it(`should old ticket have old date and agency`, async() => { - const oldDate = new Date(); + const oldDate = Date.vnNew(); const oldAgency = 'Super-Man delivery'; await page.accessToSearchResult('14'); diff --git a/e2e/paths/05-ticket/14_create_ticket.spec.js b/e2e/paths/05-ticket/14_create_ticket.spec.js index 48b4ebdd0..80c288a01 100644 --- a/e2e/paths/05-ticket/14_create_ticket.spec.js +++ b/e2e/paths/05-ticket/14_create_ticket.spec.js @@ -4,7 +4,7 @@ import getBrowser from '../../helpers/puppeteer'; describe('Ticket create path', () => { let browser; let page; - let nextMonth = new Date(); + let nextMonth = Date.vnNew(); nextMonth.setMonth(nextMonth.getMonth() + 1); beforeAll(async() => { 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/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index 6aaa81591..3a6234fe9 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -50,7 +50,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.ipt); @@ -62,7 +62,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.futureIpt); @@ -70,26 +70,36 @@ describe('Ticket Advance path', () => { await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search with the origin grouped state', async() => { + it('should search with the origin pending state', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.futureState, 'Free'); + await page.waitToClick(selectors.ticketAdvance.futureState); await page.waitToClick(selectors.ticketAdvance.submit); await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(selectors.ticketAdvance.futureState); + await page.waitToClick(selectors.ticketAdvance.futureState); + await page.waitToClick(selectors.ticketAdvance.submit); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketAdvance.futureState); await page.waitToClick(selectors.ticketAdvance.submit); await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); it('should search with the destination grouped state', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.state, 'Free'); + await page.waitToClick(selectors.ticketAdvance.state); await page.waitToClick(selectors.ticketAdvance.submit); await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(selectors.ticketAdvance.state); + await page.waitToClick(selectors.ticketAdvance.state); + await page.waitToClick(selectors.ticketAdvance.submit); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketAdvance.state); await page.waitToClick(selectors.ticketAdvance.submit); await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); @@ -116,42 +126,7 @@ describe('Ticket Advance path', () => { await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search in smart-table with stock', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableStock, '5'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 2); - - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - }); - - it('should search in smart-table with especified Lines', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableLines, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - }); - - it('should search in smart-table with especified Liters', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableLiters, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - }); - - it('should check the three last tickets and move to the future', async() => { + it('should check the one ticket and move to the present', async() => { await page.waitToClick(selectors.ticketAdvance.multiCheck); await page.waitToClick(selectors.ticketAdvance.moveButton); await page.waitToClick(selectors.ticketAdvance.acceptButton); diff --git a/e2e/paths/08-route/02_basic_data.spec.js b/e2e/paths/08-route/02_basic_data.spec.js index b1440f2d1..ff8361499 100644 --- a/e2e/paths/08-route/02_basic_data.spec.js +++ b/e2e/paths/08-route/02_basic_data.spec.js @@ -18,7 +18,7 @@ describe('Route basic Data path', () => { }); it('should edit the route basic data', async() => { - const nextMonth = new Date(); + const nextMonth = Date.vnNew(); nextMonth.setMonth(nextMonth.getMonth() + 1); await page.autocompleteSearch(selectors.routeBasicData.worker, 'adminBossNick'); diff --git a/e2e/paths/09-invoice-in/03_basic_data.spec.js b/e2e/paths/09-invoice-in/03_basic_data.spec.js index 0a28ed191..778b5949c 100644 --- a/e2e/paths/09-invoice-in/03_basic_data.spec.js +++ b/e2e/paths/09-invoice-in/03_basic_data.spec.js @@ -19,7 +19,7 @@ describe('InvoiceIn basic data path', () => { }); it(`should edit the invoiceIn basic data`, async() => { - const now = new Date(); + const now = Date.vnNew(); await page.pickDate(selectors.invoiceInBasicData.issued, now); await page.pickDate(selectors.invoiceInBasicData.operated, now); await page.autocompleteSearch(selectors.invoiceInBasicData.supplier, 'Verdnatura'); diff --git a/e2e/paths/09-invoice-out/02_descriptor.spec.js b/e2e/paths/09-invoice-out/02_descriptor.spec.js index 8d403e083..5169345bc 100644 --- a/e2e/paths/09-invoice-out/02_descriptor.spec.js +++ b/e2e/paths/09-invoice-out/02_descriptor.spec.js @@ -100,7 +100,7 @@ describe('InvoiceOut descriptor path', () => { }); it(`should check the invoiceOut booked in the summary data`, async() => { - let today = new Date(); + let today = Date.vnNew(); let day = today.getDate(); if (day < 10) day = `0${day}`; diff --git a/e2e/paths/10-travel/01_create.spec.js b/e2e/paths/10-travel/01_create.spec.js index e5d812ebd..15da42d5d 100644 --- a/e2e/paths/10-travel/01_create.spec.js +++ b/e2e/paths/10-travel/01_create.spec.js @@ -4,7 +4,7 @@ import getBrowser from '../../helpers/puppeteer'; describe('Travel create path', () => { let browser; let page; - const date = new Date(); + const date = Date.vnNew(); const day = 15; date.setDate(day); diff --git a/e2e/paths/10-travel/02_basic_data_and_log.spec.js b/e2e/paths/10-travel/02_basic_data_and_log.spec.js index a231a70b2..341b38f59 100644 --- a/e2e/paths/10-travel/02_basic_data_and_log.spec.js +++ b/e2e/paths/10-travel/02_basic_data_and_log.spec.js @@ -22,7 +22,7 @@ describe('Travel basic data path', () => { }); it('should set a wrong delivery date then receive an error on submit', async() => { - const lastMonth = new Date(); + const lastMonth = Date.vnNew(); lastMonth.setMonth(lastMonth.getMonth() - 1); await page.pickDate(selectors.travelBasicData.deliveryDate, lastMonth); diff --git a/e2e/paths/10-travel/03_descriptor.spec.js b/e2e/paths/10-travel/03_descriptor.spec.js index f459ef043..77b26b676 100644 --- a/e2e/paths/10-travel/03_descriptor.spec.js +++ b/e2e/paths/10-travel/03_descriptor.spec.js @@ -123,7 +123,7 @@ describe('Travel descriptor path', () => { }); it('should update the landed date to a future date to enable cloneWithEntries', async() => { - const nextMonth = new Date(); + const nextMonth = Date.vnNew(); nextMonth.setMonth(nextMonth.getMonth() + 1); await page.pickDate(selectors.travelBasicData.deliveryDate, nextMonth); await page.waitToClick(selectors.travelBasicData.save); diff --git a/e2e/paths/12-entry/03_latestBuys.spec.js b/e2e/paths/12-entry/03_latestBuys.spec.js index 553d41b95..a73e12659 100644 --- a/e2e/paths/12-entry/03_latestBuys.spec.js +++ b/e2e/paths/12-entry/03_latestBuys.spec.js @@ -4,10 +4,15 @@ import getBrowser from '../../helpers/puppeteer'; describe('Entry lastest buys path', () => { let browser; let page; + const httpRequests = []; beforeAll(async() => { browser = await getBrowser(); page = browser.page; + page.on('request', req => { + if (req.url().includes(`Buys/latestBuysFilter`)) + httpRequests.push(req.url()); + }); await page.loginAndModule('buyer', 'entry'); }); @@ -20,6 +25,87 @@ describe('Entry lastest buys path', () => { await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: false}); }); + it('should filter by name', async() => { + await page.write(selectors.entryLatestBuys.generalSearchInput, 'Melee'); + await page.keyboard.press('Enter'); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('search=Melee')))).toBeDefined(); + }); + + it('should filter by reign and type', async() => { + await page.click(selectors.entryLatestBuys.firstReignIcon); + await page.autocompleteSearch(selectors.entryLatestBuys.typeInput, 'Alstroemeria'); + await page.click(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('categoryFk')))).toBeDefined(); + expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined(); + }); + + it('should filter by from date', async() => { + await page.pickDate(selectors.entryLatestBuys.fromInput, new Date()); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('from')))).toBeDefined(); + }); + + it('should filter by to date', async() => { + await page.pickDate(selectors.entryLatestBuys.toInput, new Date()); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('to')))).toBeDefined(); + }); + + it('should filter by sales person', async() => { + await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick'); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('salesPersonFk')))).toBeDefined(); + }); + + it('should filter by supplier', async() => { + await page.autocompleteSearch(selectors.entryLatestBuys.supplierInput, 'Farmer King'); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('supplierFk')))).toBeDefined(); + }); + + it('should filter by active', async() => { + await page.waitToClick(selectors.entryLatestBuys.activeCheck); + await page.waitToClick(selectors.entryLatestBuys.activeCheck); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('active=true')))).toBeDefined(); + expect(httpRequests.find(req => req.includes(('active=false')))).toBeDefined(); + }); + + it('should filter by visible', async() => { + await page.waitToClick(selectors.entryLatestBuys.visibleCheck); + await page.waitToClick(selectors.entryLatestBuys.visibleCheck); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('visible=true')))).toBeDefined(); + expect(httpRequests.find(req => req.includes(('visible=false')))).toBeDefined(); + }); + + it('should filter by floramondo', async() => { + await page.waitToClick(selectors.entryLatestBuys.floramondoCheck); + await page.waitToClick(selectors.entryLatestBuys.floramondoCheck); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('floramondo=true')))).toBeDefined(); + expect(httpRequests.find(req => req.includes(('floramondo=false')))).toBeDefined(); + }); + + it('should filter by tag Color', async() => { + await page.waitToClick(selectors.entryLatestBuys.addTagButton); + await page.autocompleteSearch(selectors.entryLatestBuys.itemTagInput, 'Color'); + await page.autocompleteSearch(selectors.entryLatestBuys.itemTagValueInput, 'Brown'); + await page.waitToClick(selectors.entryLatestBuys.chip); + + expect(httpRequests.find(req => req.includes(('tags')))).toBeDefined(); + }); + it('should select all lines but one and then check the edit buys button appears', async() => { await page.waitToClick(selectors.entryLatestBuys.allBuysCheckBox); await page.waitToClick(selectors.entryLatestBuys.secondBuyCheckBox); diff --git a/front/core/components/button-menu/index.js b/front/core/components/button-menu/index.js index c19962b08..e9e4e5ab7 100644 --- a/front/core/components/button-menu/index.js +++ b/front/core/components/button-menu/index.js @@ -87,6 +87,7 @@ ngModule.vnComponent('vnButtonMenu', { selectFields: ' { let controller; let $element; - let date = new Date(); + let date = Date.vnNew(); date.setHours(0, 0, 0, 0); date.setDate(1); @@ -48,7 +48,7 @@ describe('Component vnCalendar', () => { it(`should return the selected element, then emit a 'selection' event`, () => { jest.spyOn(controller, 'emit'); - const day = new Date(); + const day = Date.vnNew(); day.setHours(0, 0, 0, 0); const clickEvent = new Event('click'); diff --git a/front/core/components/crud-model/crud-model.js b/front/core/components/crud-model/crud-model.js index 16b837d6a..421a79f9b 100644 --- a/front/core/components/crud-model/crud-model.js +++ b/front/core/components/crud-model/crud-model.js @@ -147,28 +147,17 @@ export default class CrudModel extends ModelProxy { this.moreRows = null; } - /** - * Saves current changes on the server. - * - * @return {Promise} The save request promise - */ - save() { - if (!this.isChanged) - return this.$q.resolve(); + getChanges() { + if (!this.isChanged) return null; - let deletes = []; - let updates = []; - let creates = []; - let orgDeletes = []; - let orgUpdates = []; - let orgCreates = []; + const deletes = []; + const updates = []; + const creates = []; - let pk = this.primaryKey; + const pk = this.primaryKey; - for (let row of this.removed) { + for (let row of this.removed) deletes.push(row.$orgRow[pk]); - orgDeletes.push(row); - } for (let row of this.data) { if (row.$isNew) { @@ -178,7 +167,6 @@ export default class CrudModel extends ModelProxy { data[prop] = row[prop]; } creates.push(row); - orgCreates.push(row); } else if (row.$oldData) { let data = {}; for (let prop in row.$oldData) @@ -187,28 +175,38 @@ export default class CrudModel extends ModelProxy { data, where: {[pk]: row.$orgRow[pk]} }); - orgUpdates.push(row); } } - let changes = {deletes, updates, creates}; + const changes = {deletes, updates, creates}; for (let prop in changes) { if (changes[prop].length === 0) changes[prop] = undefined; } - if (!changes) - return this.$q.resolve(); + return changes; + } + /** + * Saves current changes on the server. + * + * @return {Promise} The save request promise + */ + save() { + const pk = this.primaryKey; + const changes = this.getChanges(); + if (!changes) return this.$q.resolve(); + + const creates = changes.creates || []; let url = this.saveUrl ? this.saveUrl : `${this._url}/crud`; return this.$http.post(url, changes) .then(res => { const created = res.data; // Apply new data to created instances - for (let i = 0; i < orgCreates.length; i++) { - const row = orgCreates[i]; + for (let i = 0; i < creates.length; i++) { + const row = creates[i]; row[pk] = created[i][pk]; for (let prop in row) { diff --git a/front/core/components/date-picker/index.spec.js b/front/core/components/date-picker/index.spec.js index f76396311..13ab1d70a 100644 --- a/front/core/components/date-picker/index.spec.js +++ b/front/core/components/date-picker/index.spec.js @@ -4,7 +4,7 @@ describe('Component vnDatePicker', () => { let $ctrl; let today; - today = new Date(); + today = Date.vnNew(); today.setHours(0, 0, 0, 0); beforeEach(ngModule('vnCore')); diff --git a/front/core/components/icon/icon.js b/front/core/components/icon/icon.js index 38aea0056..8fb79d294 100644 --- a/front/core/components/icon/icon.js +++ b/front/core/components/icon/icon.js @@ -26,7 +26,7 @@ class Icon { Icon.$inject = ['$attrs']; ngModule.vnComponent('vnIcon', { - template: '{{::$ctrl.iconContent}}', + template: '{{::$ctrl.iconContent}}', controller: Icon, bindings: { icon: '@' diff --git a/front/core/components/input-time/index.js b/front/core/components/input-time/index.js index 0d01fbd32..67fa9d6fd 100644 --- a/front/core/components/input-time/index.js +++ b/front/core/components/input-time/index.js @@ -31,7 +31,7 @@ export default class InputTime extends Field { date = this.modelDate ? new Date(this.modelDate) - : new Date(); + : Date.vnNew(); date.setHours(split[0], split[1], 0, 0); } diff --git a/front/core/components/input-time/index.spec.js b/front/core/components/input-time/index.spec.js index abb684df8..7b4f1c823 100644 --- a/front/core/components/input-time/index.spec.js +++ b/front/core/components/input-time/index.spec.js @@ -20,7 +20,7 @@ describe('Component vnInputTime', () => { describe('field() setter', () => { it(`should display the formated the date`, () => { - let date = new Date(); + let date = Date.vnNew(); $ctrl.field = date; let displayed = $filter('date')(date, 'HH:mm'); 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/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index 770dcdf32..ad9883950 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -478,8 +478,8 @@ export default class SmartTable extends Component { const params = {q: JSON.stringify(stateFilter)}; - this.$state.go(this.$state.current.name, params, {location: 'replace'}); - this.refresh(); + this.$state.go(this.$state.current.name, params, {location: 'replace'}) + .then(() => this.refresh()); } applySort() { @@ -499,8 +499,8 @@ export default class SmartTable extends Component { stateFilter.tableOrder = order; const params = {q: JSON.stringify(stateFilter)}; - this.$state.go(this.$state.current.name, params, {location: 'replace'}); - this.refresh(); + this.$state.go(this.$state.current.name, params, {location: 'replace'}) + .then(() => this.refresh()); } filterSanitizer(field) { @@ -589,7 +589,7 @@ export default class SmartTable extends Component { refresh() { this.isRefreshing = true; this.model.refresh() - .then(() => this.isRefreshing = false); + .finally(() => this.isRefreshing = false); } } diff --git a/front/core/components/smart-table/index.spec.js b/front/core/components/smart-table/index.spec.js index 5fd4c33b7..5a1be98e1 100644 --- a/front/core/components/smart-table/index.spec.js +++ b/front/core/components/smart-table/index.spec.js @@ -160,7 +160,7 @@ describe('Component smartTable', () => { describe('applySort()', () => { it('should call the $state go and model refresh without making changes on the model order', () => { controller.$state = { - go: jest.fn(), + go: jest.fn().mockReturnValue(new Promise(resolve => resolve())), current: { name: 'section' } @@ -171,13 +171,12 @@ describe('Component smartTable', () => { expect(controller.model.order).toBeUndefined(); expect(controller.$state.go).toHaveBeenCalled(); - expect(controller.refresh).toHaveBeenCalled(); }); it('should call the $state go and model refresh after setting model order according to the controller sortCriteria', () => { const orderBy = {field: 'myField', sortType: 'ASC'}; controller.$state = { - go: jest.fn(), + go: jest.fn().mockReturnValue(new Promise(resolve => resolve())), current: { name: 'section' } @@ -190,7 +189,6 @@ describe('Component smartTable', () => { expect(controller.model.order).toEqual(`${orderBy.field} ${orderBy.sortType}`); expect(controller.$state.go).toHaveBeenCalled(); - expect(controller.refresh).toHaveBeenCalled(); }); }); @@ -293,12 +291,10 @@ describe('Component smartTable', () => { controller.$inputsScope = { searchProps: {} }; - jest.spyOn(controller, 'refresh'); controller.defaultFilter(); expect(controller.model.addFilter).toHaveBeenCalled(); - expect(controller.refresh).toHaveBeenCalled(); }); }); diff --git a/front/core/components/table/style.scss b/front/core/components/table/style.scss index d0a29a3ba..557268661 100644 --- a/front/core/components/table/style.scss +++ b/front/core/components/table/style.scss @@ -29,7 +29,7 @@ vn-table { & > tbody { display: table-row-group; } - & > vn-tfoot, + & > vn-tfoot, & > .vn-tfoot, & > tfoot { border-top: $border; @@ -42,7 +42,7 @@ vn-table { height: 48px; } vn-thead, .vn-thead, - vn-tbody, .vn-tbody, + vn-tbody, .vn-tbody, vn-tfoot, .vn-tfoot, thead, tbody, tfoot { & > * { @@ -153,6 +153,18 @@ vn-table { background-color: $color-font-bg-dark; color: $color-font-bg; } + &.dark-notice { + background-color: $color-notice; + color: $color-font-bg; + } + &.yellow { + background-color: $color-yellow; + color: $color-font-bg; + } + &.pink { + background-color: $color-pink; + color: $color-font-bg; + } } vn-icon-menu { display: inline-block; @@ -194,7 +206,7 @@ vn-table.scrollable > .vn-table, } vn-thead th, - vn-thead vn-th, + vn-thead vn-th, thead vn-th, thead th { border-bottom: $border; @@ -217,4 +229,4 @@ vn-table.scrollable.lg, .tableWrapper { overflow-x: auto; -} \ No newline at end of file +} diff --git a/front/core/services/date.js b/front/core/services/date.js new file mode 100644 index 000000000..120297951 --- /dev/null +++ b/front/core/services/date.js @@ -0,0 +1,2 @@ +import * as date from 'vn-loopback/server/boot/date'; +date.default(); diff --git a/front/core/services/index.js b/front/core/services/index.js index ff1d438ed..867a13df0 100644 --- a/front/core/services/index.js +++ b/front/core/services/index.js @@ -10,3 +10,4 @@ import './week-days'; import './report'; import './email'; import './file'; +import './date'; diff --git a/front/core/styles/variables.scss b/front/core/styles/variables.scss index c79a8590f..bcc9fab66 100644 --- a/front/core/styles/variables.scss +++ b/front/core/styles/variables.scss @@ -101,6 +101,8 @@ $color-marginal: #222; $color-success: #a3d131; $color-notice: #32b1ce; $color-alert: #fa3939; +$color-pink: #ff99cc; +$color-yellow: #ffff00; $color-button: $color-secondary; $color-spacer: rgba(255, 255, 255, .3); diff --git a/front/package-lock.json b/front/package-lock.json index 256797df0..d0fe4de2d 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -1,15 +1,8 @@ { "name": "salix-front", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, -<<<<<<< HEAD - "dependencies": { - "@uirouter/angularjs": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.29.tgz", - "integrity": "sha512-RImWnBarNixkMto0o8stEaGwZmvhv5cnuOLXyMU2pY8MP2rgEF74ZNJTLeJCW14LR7XDUxVH8Mk8bPI6lxedmQ==", -======= "packages": { "": { "name": "salix-front", @@ -32,8 +25,7 @@ }, "node_modules/@uirouter/angularjs": { "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz", - "integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==", + "license": "MIT", "dependencies": { "@uirouter/core": "6.0.8" }, @@ -46,17 +38,14 @@ }, "node_modules/@uirouter/core": { "version": "6.0.8", - "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz", - "integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==", + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/angular": { "version": "1.8.3", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz", - "integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." + "license": "MIT" }, "node_modules/angular-animate": { "version": "1.8.2", @@ -74,8 +63,7 @@ }, "node_modules/angular-translate": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz", - "integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==", + "license": "MIT", "dependencies": { "angular": "^1.8.0" }, @@ -85,8 +73,7 @@ }, "node_modules/angular-translate-loader-partial": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz", - "integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==", + "license": "MIT", "dependencies": { "angular-translate": "~2.19.0" } @@ -133,8 +120,7 @@ }, "node_modules/moment": { "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "license": "MIT", "engines": { "node": "*" } @@ -179,97 +165,51 @@ "dependencies": { "@uirouter/angularjs": { "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz", - "integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==", ->>>>>>> dev "requires": { "@uirouter/core": "6.0.8" } }, "@uirouter/core": { -<<<<<<< HEAD - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.7.tgz", - "integrity": "sha512-KUTJxL+6q0PiBnFx4/Z+Hsyg0pSGiaW5yZQeJmUxknecjpTbnXkLU8H2EqRn9N2B+qDRa7Jg8RcgeNDPY72O1w==" + "version": "6.0.8" }, "angular": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.2.tgz", - "integrity": "sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw==" -======= - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz", - "integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==" - }, - "angular": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz", - "integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==" ->>>>>>> dev + "version": "1.8.3" }, "angular-animate": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz", - "integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA==" + "version": "1.8.2" }, "angular-moment": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz", - "integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==", "requires": { "moment": ">=2.8.0 <3.0.0" } }, "angular-translate": { -<<<<<<< HEAD - "version": "2.18.4", - "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz", - "integrity": "sha512-KohNrkH6J9PK+VW0L/nsRTcg5Fw70Ajwwe3Jbfm54Pf9u9Fd+wuingoKv+h45mKf38eT+Ouu51FPua8VmZNoCw==", -======= "version": "2.19.0", - "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz", - "integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==", ->>>>>>> dev "requires": { "angular": "^1.8.0" } }, "angular-translate-loader-partial": { -<<<<<<< HEAD - "version": "2.18.4", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.18.4.tgz", - "integrity": "sha512-bsjR+FbB0sdA2528E/ugwKdlPPQhA1looxLxI3otayBTFXBpED33besfSZhYAISLgNMSL038vSssfRUen9qD8w==", -======= "version": "2.19.0", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz", - "integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==", ->>>>>>> dev "requires": { "angular-translate": "~2.19.0" } }, "argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { "sprintf-js": "~1.0.2" } }, "croppie": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz", - "integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ==" + "version": "2.6.5" }, "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "version": "4.0.1" }, "js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -277,45 +217,27 @@ }, "mg-crud": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz", - "integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==", "requires": { "angular": "^1.6.1" } }, "moment": { -<<<<<<< HEAD - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" -======= - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" ->>>>>>> dev + "version": "2.29.4" }, "oclazyload": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz", - "integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ==" + "version": "0.6.3" }, "require-yaml": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz", - "integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==", "requires": { - "js-yaml": "^4.1.0" + "js-yaml": "" }, "dependencies": { "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "version": "2.0.1" }, "js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "requires": { "argparse": "^2.0.1" } @@ -323,14 +245,10 @@ } }, "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "version": "1.0.3" }, "validator": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz", - "integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q==" + "version": "6.3.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/log/style.scss b/front/salix/components/log/style.scss index bc943996d..68cd5a047 100644 --- a/front/salix/components/log/style.scss +++ b/front/salix/components/log/style.scss @@ -42,6 +42,7 @@ vn-log { & > td.after, & > th.after { width: 40%; + white-space: pre-line; } } } diff --git a/front/salix/components/recover-password/index.html b/front/salix/components/recover-password/index.html index 73f5401d9..5121f81bd 100644 --- a/front/salix/components/recover-password/index.html +++ b/front/salix/components/recover-password/index.html @@ -1,7 +1,7 @@
Recover password
La contraseña debe tener al menos {{ length }} caracteres de longitud, 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/front/salix/components/upload-photo/index.js b/front/salix/components/upload-photo/index.js index c47018307..fb115992f 100644 --- a/front/salix/components/upload-photo/index.js +++ b/front/salix/components/upload-photo/index.js @@ -197,7 +197,7 @@ export default class UploadPhoto extends Component { timeout: this.canceler.promise, transformRequest: ([file]) => { const formData = new FormData(); - const now = new Date(); + const now = Date.vnNew(); const timestamp = now.getTime(); const fileName = `${file.name}_${timestamp}`; diff --git a/front/salix/index.js b/front/salix/index.js index 5220f36f6..2488ef9b6 100644 --- a/front/salix/index.js +++ b/front/salix/index.js @@ -1,5 +1,5 @@ import './module'; import './routes'; import './components'; -import './services'; import './styles'; +import 'vn-loopback/server/boot/date'; diff --git a/front/salix/services/index.js b/front/salix/services/index.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/jest-front.js b/jest-front.js index 6d7532260..eabda9110 100644 --- a/jest-front.js +++ b/jest-front.js @@ -14,6 +14,10 @@ import './modules/ticket/front/module.js'; import './modules/travel/front/module.js'; import './modules/worker/front/module.js'; import './modules/shelving/front/module.js'; +import 'vn-loopback/server/boot/date'; + +// Set NODE_ENV +process.env.NODE_ENV = 'development'; core.run(vnInterceptor => { vnInterceptor.setApiPath(null); @@ -39,3 +43,4 @@ window.ngModule = function(moduleName, ...args) { return angular.mock.module(...fns); }; + diff --git a/jest.front.config.js b/jest.front.config.js index a03c61d11..3289df8bb 100644 --- a/jest.front.config.js +++ b/jest.front.config.js @@ -1,5 +1,6 @@ // For a detailed explanation regarding each configuration property, visit: // https://jestjs.io/docs/en/configuration.html +/* eslint max-len: ["error", { "code": 150 }]*/ module.exports = { name: 'front end', diff --git a/loopback/locale/en.json b/loopback/locale/en.json index a406b55a5..c810e5a69 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -67,7 +67,7 @@ "Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})", "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}", - "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", + "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*", "Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", @@ -137,15 +137,18 @@ "Password does not meet requirements": "Password does not meet requirements", "You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies", "Not enough privileges to edit a client": "Not enough privileges to edit a client", - "Claim pickup order sent": "Claim pickup order sent [{{claimId}}]({{{claimUrl}}}) to client *{{clientName}}*", + "Claim pickup order sent": "Claim pickup order sent [{{claimId}}]({{{claimUrl}}}) to client *{{clientName}}*", "You don't have grant privilege": "You don't have grant privilege", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", - "Email verify": "Email verify", + "Email verify": "Email verify", "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})", - "Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production", "App locked": "App locked by user {{userId}}", - "The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified", - "Receipt's bank was not found": "Receipt's bank was not found", - "This receipt was not compensated": "This receipt was not compensated", - "Client's email was not found": "Client's email was not found" + "The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified", + "Receipt's bank was not found": "Receipt's bank was not found", + "This receipt was not compensated": "This receipt was not compensated", + "Client's email was not found": "Client's email was not found", + "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", + "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", + "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", + "Valid priorities: 1,2,3": "Valid priorities: 1,2,3" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ea83b36c4..ad6d53d64 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -84,7 +84,6 @@ "The current ticket can't be modified": "El ticket actual no puede ser modificado", "The current claim can't be modified": "La reclamación actual no puede ser modificada", "The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas", - "Sale(s) blocked, contact production": "Linea(s) bloqueada(s), contacte con produccion", "Please select at least one sale": "Por favor selecciona al menos una linea", "All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket", "NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada", @@ -135,7 +134,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 +251,18 @@ "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" -} \ No newline at end of file + "This worker code already exists": "Este codigo de trabajador ya existe", + "This personal mail already exists": "Este correo personal ya existe", + "This worker already exists": "Este trabajador ya existe", + "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": "El documento PDF Docuware no existe", + "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", + "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", + "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", + "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", + "There is no assigned email for this client": "No hay correo asignado para este cliente" +} + diff --git a/loopback/server/boot/date.js b/loopback/server/boot/date.js new file mode 100644 index 000000000..0875b6d5f --- /dev/null +++ b/loopback/server/boot/date.js @@ -0,0 +1,17 @@ +module.exports = () => { + Date.vnUTC = () => { + const env = process.env.NODE_ENV; + if (!env || env === 'development') + return new Date(Date.UTC(2001, 0, 1, 11)); + + return new Date(Date.UTC()); + }; + + Date.vnNew = () => { + return new Date(Date.vnUTC()); + }; + + Date.vnNow = () => { + return new Date(Date.vnUTC()).getTime(); + }; +}; diff --git a/loopback/util/not-found-error.js b/loopback/util/not-found-error.js new file mode 100644 index 000000000..7a05254f9 --- /dev/null +++ b/loopback/util/not-found-error.js @@ -0,0 +1,9 @@ +module.exports = class NotFoundError extends Error { + constructor(message = 'Not found', code = 'NOT_FOUND', ...translateArgs) { + super(message); + this.name = 'NotFoundError'; + this.statusCode = 404; + this.code = code; + this.translateArgs = translateArgs; + } +}; diff --git a/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js b/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js index 22a48f83e..f0686ffa6 100644 --- a/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js +++ b/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js @@ -95,7 +95,7 @@ module.exports = Self => { }, myOptions); const claim = await models.Claim.findOne(filter, myOptions); - const today = new Date(); + const today = Date.vnNew(); const newRefundTicket = await models.Ticket.create({ clientFk: claim.ticket().clientFk, @@ -172,7 +172,7 @@ module.exports = Self => { async function saveObservation(observation, options) { const query = `INSERT INTO vn.ticketObservation (ticketFk, observationTypeFk, description) VALUES(?, ?, ?) - ON DUPLICATE KEY + ON DUPLICATE KEY UPDATE description = CONCAT(vn.ticketObservation.description, VALUES(description),' ')`; await Self.rawSql(query, [ observation.ticketFk, diff --git a/modules/claim/back/methods/claim/createFromSales.js b/modules/claim/back/methods/claim/createFromSales.js index ba7bda71d..2ce3bc44b 100644 --- a/modules/claim/back/methods/claim/createFromSales.js +++ b/modules/claim/back/methods/claim/createFromSales.js @@ -60,7 +60,7 @@ module.exports = Self => { const landedPlusWeek = new Date(ticket.landed); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); const hasClaimManagerRole = await models.Account.hasRole(userId, 'claimManager', myOptions); - const isClaimable = landedPlusWeek >= new Date(); + const isClaimable = landedPlusWeek >= Date.vnNew(); if (ticket.isDeleted) throw new UserError(`You can't create a claim for a removed ticket`); diff --git a/modules/claim/back/methods/claim/filter.js b/modules/claim/back/methods/claim/filter.js index e86830200..d653229e5 100644 --- a/modules/claim/back/methods/claim/filter.js +++ b/modules/claim/back/methods/claim/filter.js @@ -23,7 +23,7 @@ module.exports = Self => { { arg: 'search', type: 'string', - description: `If it's and integer searchs by id, otherwise it searchs by client name`, + description: `If it's a number searchs by id, otherwise it searchs by client name`, http: {source: 'query'} }, { @@ -34,31 +34,31 @@ module.exports = Self => { }, { arg: 'id', - type: 'integer', + type: 'number', description: 'The claim id', http: {source: 'query'} }, { arg: 'clientFk', - type: 'integer', + type: 'number', description: 'The client id', http: {source: 'query'} }, { arg: 'claimStateFk', - type: 'integer', + type: 'number', description: 'The claim state id', http: {source: 'query'} }, { arg: 'salesPersonFk', - type: 'integer', + type: 'number', description: 'The salesPerson id', http: {source: 'query'} }, { arg: 'attenderFk', - type: 'integer', + type: 'number', description: 'The attender worker id', http: {source: 'query'} }, @@ -67,6 +67,18 @@ module.exports = Self => { type: 'date', description: 'The to date filter', http: {source: 'query'} + }, + { + arg: 'itemFk', + type: 'number', + description: 'The item id', + http: {source: 'query'} + }, + { + arg: 'claimResponsibleFk', + type: 'number', + description: 'The claimResponsible id', + http: {source: 'query'} } ], returns: { @@ -80,33 +92,58 @@ module.exports = Self => { }); Self.filter = async(ctx, filter, options) => { + const models = Self.app.models; const conn = Self.dataSource.connector; + const args = ctx.args; const myOptions = {}; let to; if (typeof options == 'object') Object.assign(myOptions, options); - const where = buildFilter(ctx.args, (param, value) => { + let claimIdsByItemFk = []; + let claimIdsByClaimResponsibleFk = []; + + if (args.itemFk) { + query = `SELECT cb.claimFk + FROM claimBeginning cb + LEFT JOIN sale s ON s.id = cb.saleFk + WHERE s.itemFk = ?`; + const claims = await Self.rawSql(query, [args.itemFk], myOptions); + claimIdsByItemFk = claims.map(claim => claim.claimFk); + } + + if (args.claimResponsibleFk) { + const claims = await models.ClaimDevelopment.find({ + fields: ['claimFk'], + where: {claimResponsibleFk: args.claimResponsibleFk} + }, myOptions); + claimIdsByClaimResponsibleFk = claims.map(claim => claim.claimFk); + } + + const where = buildFilter(args, (param, value) => { switch (param) { case 'search': return /^\d+$/.test(value) ? {'cl.id': value} : { or: [ - {'cl.clientName': {like: `%${value}%`}} + {'c.name': {like: `%${value}%`}} ] }; case 'clientName': - return {'cl.clientName': {like: `%${value}%`}}; + return {'c.name': {like: `%${value}%`}}; case 'clientFk': - return {'cl.clientFk': value}; case 'id': case 'claimStateFk': case 'priority': return {[`cl.${param}`]: value}; + case 'itemFk': + return {'cl.id': {inq: claimIdsByItemFk}}; + case 'claimResponsibleFk': + return {'cl.id': {inq: claimIdsByClaimResponsibleFk}}; case 'salesPersonFk': - return {'cl.salesPersonFk': value}; + return {'c.salesPersonFk': value}; case 'attenderFk': return {'cl.workerFk': value}; case 'created': @@ -118,29 +155,23 @@ module.exports = Self => { } }); - filter = mergeFilters(ctx.args.filter, {where}); + filter = mergeFilters(args.filter, {where}); const stmts = []; const stmt = new ParameterizedSQL( - `SELECT * - FROM ( - SELECT - cl.id, - cl.clientFk, - c.name AS clientName, - cl.workerFk, - u.name AS workerName, - cs.description, - cl.created, - cs.priority, - cl.claimStateFk, - c.salesPersonFk - FROM claim cl - LEFT JOIN client c ON c.id = cl.clientFk - LEFT JOIN worker w ON w.id = cl.workerFk - LEFT JOIN account.user u ON u.id = w.userFk - LEFT JOIN claimState cs ON cs.id = cl.claimStateFk ) cl` + `SELECT + cl.id, + cl.clientFk, + c.name AS clientName, + cl.workerFk, + u.name AS workerName, + cs.description, + cl.created + FROM claim cl + LEFT JOIN client c ON c.id = cl.clientFk + LEFT JOIN account.user u ON u.id = cl.workerFk + LEFT JOIN claimState cs ON cs.id = cl.claimStateFk` ); stmt.merge(conn.makeSuffix(filter)); diff --git a/modules/claim/back/methods/claim/regularizeClaim.js b/modules/claim/back/methods/claim/regularizeClaim.js index ab8ea58a4..672c94947 100644 --- a/modules/claim/back/methods/claim/regularizeClaim.js +++ b/modules/claim/back/methods/claim/regularizeClaim.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('regularizeClaim', { - description: `Imports lines from claimBeginning to a new ticket + description: `Imports lines from claimBeginning to a new ticket with specific shipped, landed dates, agency and company`, accessType: 'WRITE', accepts: [{ @@ -135,10 +135,10 @@ module.exports = Self => { } async function getTicketId(params, options) { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); let ticket = await Self.app.models.Ticket.findOne({ @@ -155,8 +155,8 @@ module.exports = Self => { } async function createTicket(ctx, options) { - ctx.args.shipped = new Date(); - ctx.args.landed = new Date(); + ctx.args.shipped = Date.vnNew(); + ctx.args.landed = Date.vnNew(); ctx.args.agencyModeId = null; ctx.args.routeId = null; diff --git a/modules/claim/back/methods/claim/specs/createFromSales.spec.js b/modules/claim/back/methods/claim/specs/createFromSales.spec.js index 9151c361e..7cf663caf 100644 --- a/modules/claim/back/methods/claim/specs/createFromSales.spec.js +++ b/modules/claim/back/methods/claim/specs/createFromSales.spec.js @@ -54,7 +54,7 @@ describe('Claim createFromSales()', () => { try { const options = {transaction: tx}; - const todayMinusEightDays = new Date(); + const todayMinusEightDays = Date.vnNew(); todayMinusEightDays.setDate(todayMinusEightDays.getDate() - 8); const ticket = await models.Ticket.findById(ticketId, null, options); @@ -85,7 +85,7 @@ describe('Claim createFromSales()', () => { try { const options = {transaction: tx}; - const todayMinusEightDays = new Date(); + const todayMinusEightDays = Date.vnNew(); todayMinusEightDays.setDate(todayMinusEightDays.getDate() - 8); const ticket = await models.Ticket.findById(ticketId, null, options); diff --git a/modules/claim/back/methods/claim/specs/filter.spec.js b/modules/claim/back/methods/claim/specs/filter.spec.js index b26afe8c4..49e258505 100644 --- a/modules/claim/back/methods/claim/specs/filter.spec.js +++ b/modules/claim/back/methods/claim/specs/filter.spec.js @@ -57,4 +57,44 @@ describe('claim filter()', () => { throw e; } }); + + it('should return 3 results filtering by item id', async() => { + const tx = await app.models.Claim.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const result = await app.models.Claim.filter({args: {filter: {}, itemFk: 2}}, null, options); + + expect(result.length).toEqual(3); + expect(result[0].id).toEqual(1); + expect(result[1].id).toEqual(2); + expect(result[2].id).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return 3 results filtering by claimResponsible id', async() => { + const tx = await app.models.Claim.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const result = await app.models.Claim.filter({args: {filter: {}, claimResponsibleFk: 7}}, null, options); + + expect(result.length).toEqual(3); + expect(result[0].id).toEqual(2); + expect(result[1].id).toEqual(3); + expect(result[2].id).toEqual(4); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/claim/back/methods/claim/specs/updateClaim.spec.js b/modules/claim/back/methods/claim/specs/updateClaim.spec.js index 8d888eb40..113df35c9 100644 --- a/modules/claim/back/methods/claim/specs/updateClaim.spec.js +++ b/modules/claim/back/methods/claim/specs/updateClaim.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('Update Claim', () => { - const newDate = new Date(); + const newDate = Date.vnNew(); const originalData = { ticketFk: 3, clientFk: 1101, diff --git a/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js b/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js index 4cd4ce528..12ab45fac 100644 --- a/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js +++ b/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('Update Claim', () => { - const newDate = new Date(); + const newDate = Date.vnNew(); const original = { ticketFk: 3, clientFk: 1101, diff --git a/modules/claim/front/card/index.js b/modules/claim/front/card/index.js index 747eea9e7..4a8677c90 100644 --- a/modules/claim/front/card/index.js +++ b/modules/claim/front/card/index.js @@ -19,10 +19,26 @@ class Controller extends ModuleCard { }, { relation: 'ticket', scope: { - fields: ['agencyModeFk'], - include: { - relation: 'agencyMode' - } + fields: ['zoneFk', 'addressFk'], + include: [ + { + relation: 'zone', + scope: { + fields: ['name'] + } + }, + { + relation: 'address', + scope: { + fields: ['provinceFk'], + include: { + relation: 'province', + scope: { + fields: ['name'] + } + } + } + }] } }, { relation: 'claimState', diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html index 0bbacf94b..f346ecf17 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,27 @@ - {{$ctrl.claim.worker.user.name}} + label="Zone"> + + {{$ctrl.claim.ticket.zone.name}} + + + - {{$ctrl.claim.ticketFk}} @@ -94,12 +102,15 @@ question="Delete claim" message="Are you sure you want to delete this claim?"> - - - \ No newline at end of file + + + diff --git a/modules/claim/front/search-panel/index.html b/modules/claim/front/search-panel/index.html index eec8cd727..151a06c8e 100644 --- a/modules/claim/front/search-panel/index.html +++ b/modules/claim/front/search-panel/index.html @@ -58,8 +58,28 @@ ng-model="filter.created"> + + + {{::id}} - {{::name}} + + + + -
\ No newline at end of file +
diff --git a/modules/claim/front/search-panel/index.js b/modules/claim/front/search-panel/index.js index a7e8fb046..2400b8ede 100644 --- a/modules/claim/front/search-panel/index.js +++ b/modules/claim/front/search-panel/index.js @@ -1,7 +1,14 @@ import ngModule from '../module'; import SearchPanel from 'core/components/searchbar/search-panel'; +class Controller extends SearchPanel { + itemSearchFunc($search) { + return /^\d+$/.test($search) + ? {id: $search} + : {name: {like: '%' + $search + '%'}}; + } +} ngModule.vnComponent('vnClaimSearchPanel', { template: require('./index.html'), - controller: SearchPanel + controller: Controller }); diff --git a/modules/client/back/methods/client/consumptionSendQueued.js b/modules/client/back/methods/client/consumptionSendQueued.js index 77e0e34f2..31b54b21d 100644 --- a/modules/client/back/methods/client/consumptionSendQueued.js +++ b/modules/client/back/methods/client/consumptionSendQueued.js @@ -32,7 +32,7 @@ module.exports = Self => { c.id AS clientFk, c.email AS clientEmail, eu.email salesPersonEmail - FROM client c + FROM client c JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk JOIN ticket t ON t.clientFk = c.id JOIN sale s ON s.ticketFk = t.id @@ -61,10 +61,10 @@ module.exports = Self => { SET status = 'printed', printed = ? WHERE id = ?`, - [new Date(), queue.id]); + [Date.vnNew(), queue.id]); } catch (error) { await Self.rawSql(` - UPDATE clientConsumptionQueue + UPDATE clientConsumptionQueue SET status = ? WHERE id = ?`, [error.message, queue.id]); diff --git a/modules/client/back/methods/client/createReceipt.js b/modules/client/back/methods/client/createReceipt.js index a75ee8844..74fe2211e 100644 --- a/modules/client/back/methods/client/createReceipt.js +++ b/modules/client/back/methods/client/createReceipt.js @@ -51,7 +51,7 @@ module.exports = function(Self) { Self.createReceipt = async(ctx, options) => { const models = Self.app.models; const args = ctx.args; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); let tx; diff --git a/modules/client/back/methods/client/getCard.js b/modules/client/back/methods/client/getCard.js index 21b3140bd..afbe36e49 100644 --- a/modules/client/back/methods/client/getCard.js +++ b/modules/client/back/methods/client/getCard.js @@ -74,7 +74,7 @@ module.exports = function(Self) { ] }, myOptions); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const query = `SELECT vn.clientGetDebt(?, ?) AS debt`; const data = await Self.rawSql(query, [id, date], myOptions); diff --git a/modules/client/back/methods/client/getDebt.js b/modules/client/back/methods/client/getDebt.js index aafdbfa48..5f8a8c569 100644 --- a/modules/client/back/methods/client/getDebt.js +++ b/modules/client/back/methods/client/getDebt.js @@ -25,7 +25,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const query = `SELECT vn.clientGetDebt(?, ?) AS debt`; const [debt] = await Self.rawSql(query, [clientFk, date], myOptions); diff --git a/modules/client/back/methods/client/lastActiveTickets.js b/modules/client/back/methods/client/lastActiveTickets.js index 03616a0e3..d662f75aa 100644 --- a/modules/client/back/methods/client/lastActiveTickets.js +++ b/modules/client/back/methods/client/lastActiveTickets.js @@ -32,14 +32,14 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const ticket = await Self.app.models.Ticket.findById(ticketId, null, myOptions); const query = ` - SELECT + SELECT t.id, t.shipped, - a.name AS agencyName, + a.name AS agencyName, w.name AS warehouseName, ad.nickname AS nickname, ad.city AS city, @@ -52,7 +52,7 @@ module.exports = Self => { JOIN vn.warehouse w ON t.warehouseFk = w.id JOIN vn.address ad ON t.addressFk = ad.id JOIN vn.province pr ON ad.provinceFk = pr.id - WHERE t.shipped >= ? AND t.clientFk = ? AND ts.alertLevel = 0 + WHERE t.shipped >= ? AND t.clientFk = ? AND ts.alertLevel = 0 AND t.id <> ? AND t.warehouseFk = ? ORDER BY t.shipped LIMIT 10`; diff --git a/modules/client/back/methods/client/summary.js b/modules/client/back/methods/client/summary.js index 48cb75f31..caa3d8033 100644 --- a/modules/client/back/methods/client/summary.js +++ b/modules/client/back/methods/client/summary.js @@ -125,7 +125,7 @@ module.exports = Self => { async function getRecoveries(recoveryModel, clientId, options) { const filter = { where: { - and: [{clientFk: clientId}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}] + and: [{clientFk: clientId}, {or: [{finished: null}, {finished: {gt: Date.vnNow()}}]}] }, limit: 1 }; diff --git a/modules/client/back/methods/credit-classification/createWithInsurance.spec.js b/modules/client/back/methods/credit-classification/createWithInsurance.spec.js index 95ff5025f..a5837bb90 100644 --- a/modules/client/back/methods/credit-classification/createWithInsurance.spec.js +++ b/modules/client/back/methods/credit-classification/createWithInsurance.spec.js @@ -23,7 +23,7 @@ describe('Client createWithInsurance', () => { try { const options = {transaction: tx}; - const data = {clientFk: 1101, started: Date.now(), credit: 999, grade: 255}; + const data = {clientFk: 1101, started: Date.vnNow(), credit: 999, grade: 255}; const result = await models.CreditClassification.createWithInsurance(data, options); diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index ce1d89818..748581913 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -51,7 +51,7 @@ module.exports = Self => { const stmts = []; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const stmt = new ParameterizedSQL( `SELECT * @@ -65,14 +65,14 @@ module.exports = Self => { co.created, co.text observation, uw.id workerFk, - uw.name workerName, + uw.name workerName, c.creditInsurance, d.defaulterSinced FROM vn.defaulter d JOIN vn.client c ON c.id = d.clientFk LEFT JOIN vn.clientObservation co ON co.clientFk = c.id LEFT JOIN account.user u ON u.id = c.salesPersonFk - LEFT JOIN account.user uw ON uw.id = co.workerFk + LEFT JOIN account.user uw ON uw.id = co.workerFk WHERE d.created = ? AND d.amount > 0 diff --git a/modules/client/back/methods/recovery/hasActiveRecovery.js b/modules/client/back/methods/recovery/hasActiveRecovery.js index 6b69d99d7..344b6b6ab 100644 --- a/modules/client/back/methods/recovery/hasActiveRecovery.js +++ b/modules/client/back/methods/recovery/hasActiveRecovery.js @@ -27,7 +27,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const query = ` SELECT count(*) AS hasActiveRecovery diff --git a/modules/client/back/models/client-sample.js b/modules/client/back/models/client-sample.js index 787cc2ad8..5e4393042 100644 --- a/modules/client/back/models/client-sample.js +++ b/modules/client/back/models/client-sample.js @@ -41,7 +41,7 @@ module.exports = Self => { // Disable old mandate if (oldMandate) - oldMandate.updateAttribute('finished', new Date()); + oldMandate.updateAttribute('finished', Date.vnNew()); // Create a new mandate await models.Mandate.create({ diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index e07993f79..2d8e7bd27 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -141,6 +141,16 @@ module.exports = Self => { done(); } + Self.validateAsync('isToBeMailed', isToBeMailed, { + message: 'There is no assigned email for this client' + }); + + function isToBeMailed(err, done) { + if (this.isToBeMailed == true && !this.email) + err(); + done(); + } + Self.validateAsync('defaultAddressFk', isActive, {message: 'Unable to default a disabled consignee'} ); diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index 935129574..68d19209d 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -4,7 +4,7 @@ import Dialog from 'core/components/dialog'; class Controller extends Dialog { constructor($element, $, $transclude, vnReport) { super($element, $, $transclude); - + this.viewReceipt = true; this.vnReport = vnReport; this.receipt = {}; } @@ -59,16 +59,17 @@ class Controller extends Dialog { if (value) { const accountingType = value.accountingType; - if (this.originalDescription) { - this.receipt.description = - `${accountingType && accountingType.receiptDescription}, ${this.originalDescription}`; - } else { - this.receipt.description = - `${accountingType && accountingType.receiptDescription}`; - } + + this.receipt.description = []; + if (accountingType.receiptDescription != null && accountingType.receiptDescription != '') + this.receipt.description.push(accountingType.receiptDescription); + if (this.originalDescription) + this.receipt.description.push(this.originalDescription); + this.receipt.description.join(', '); + this.maxAmount = accountingType && accountingType.maxAmount; - this.receipt.payed = new Date(); + this.receipt.payed = Date.vnNew(); if (accountingType.daysInFuture) this.receipt.payed.setDate(this.receipt.payed.getDate() + accountingType.daysInFuture); } diff --git a/modules/client/front/balance/create/index.spec.js b/modules/client/front/balance/create/index.spec.js index fa6b48ea4..c0464b12b 100644 --- a/modules/client/front/balance/create/index.spec.js +++ b/modules/client/front/balance/create/index.spec.js @@ -38,7 +38,7 @@ describe('Client', () => { } }; - expect(controller.receipt.description).toEqual('Cash, Albaran: 1, 2'); + expect(controller.receipt.description.join(',')).toEqual('Cash,Albaran: 1, 2'); }); }); @@ -75,6 +75,7 @@ describe('Client', () => { jest.spyOn(controller.vnReport, 'show'); controller.$params = {id: 1101}; + controller.viewReceipt = false; $httpBackend.expect('POST', `Clients/1101/createReceipt`).respond({id: 1}); controller.responseHandler('accept'); diff --git a/modules/client/front/consumption/index.js b/modules/client/front/consumption/index.js index d9b657318..eb3a10dd6 100644 --- a/modules/client/front/consumption/index.js +++ b/modules/client/front/consumption/index.js @@ -17,11 +17,11 @@ class Controller extends Section { } setDefaultFilter() { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); minDate.setMonth(minDate.getMonth() - 2); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); this.filterParams = { diff --git a/modules/client/front/consumption/index.spec.js b/modules/client/front/consumption/index.spec.js index 33cbce58f..f2acddbca 100644 --- a/modules/client/front/consumption/index.spec.js +++ b/modules/client/front/consumption/index.spec.js @@ -26,7 +26,7 @@ describe('Client', () => { it('should call the window.open function', () => { jest.spyOn(window, 'open').mockReturnThis(); - const now = new Date(); + const now = Date.vnNew(); controller.$.model.userParams = { from: now, to: now @@ -49,7 +49,7 @@ describe('Client', () => { describe('sendEmail()', () => { it('should make a GET query sending the report', () => { - const now = new Date(); + const now = Date.vnNew(); controller.$.model.userParams = { from: now, to: now diff --git a/modules/client/front/credit-insurance/create/index.js b/modules/client/front/credit-insurance/create/index.js index 83dc18806..e3138e459 100644 --- a/modules/client/front/credit-insurance/create/index.js +++ b/modules/client/front/credit-insurance/create/index.js @@ -5,7 +5,7 @@ class Controller extends Section { constructor($element, $) { super($element, $); this.creditClassification = { - started: this.$filter('date')(new Date(), 'yyyy-MM-dd HH:mm') + started: this.$filter('date')(Date.vnNew(), 'yyyy-MM-dd HH:mm') }; } diff --git a/modules/client/front/credit-insurance/create/index.spec.js b/modules/client/front/credit-insurance/create/index.spec.js index 36a91ceca..c50afd5cf 100644 --- a/modules/client/front/credit-insurance/create/index.spec.js +++ b/modules/client/front/credit-insurance/create/index.spec.js @@ -24,7 +24,7 @@ describe('Client', () => { describe('onSubmit()', () => { it('should perform a POST query', () => { - let started = new Date(); + let started = Date.vnNew(); controller.creditClassification = { started: started, credit: 300, diff --git a/modules/client/front/credit-insurance/index/index.js b/modules/client/front/credit-insurance/index/index.js index 5f59c918a..b40025c65 100644 --- a/modules/client/front/credit-insurance/index/index.js +++ b/modules/client/front/credit-insurance/index/index.js @@ -52,7 +52,7 @@ class Controller extends Section { } returnDialog() { - let params = {finished: Date.now()}; + let params = {finished: Date.vnNow()}; this.$http.patch(`CreditClassifications/${this.classificationId}`, params).then(() => { this._getClassifications(this.client.id); }); diff --git a/modules/client/front/credit-insurance/index/index.spec.js b/modules/client/front/credit-insurance/index/index.spec.js index 8629db684..af072691a 100644 --- a/modules/client/front/credit-insurance/index/index.spec.js +++ b/modules/client/front/credit-insurance/index/index.spec.js @@ -39,7 +39,7 @@ describe('Client', () => { it(`should return false if finds a classification without due date`, () => { controller.classifications = [ - {finished: Date.now()}, + {finished: Date.vnNow()}, {finished: null} ]; @@ -50,8 +50,8 @@ describe('Client', () => { it(`should return true if all classifications are defined with due date`, () => { controller.classifications = [ - {finished: Date.now()}, - {finished: Date.now()} + {finished: Date.vnNow()}, + {finished: Date.vnNow()} ]; let result = controller.canCreateNew(); diff --git a/modules/client/front/credit-insurance/insurance/create/index.js b/modules/client/front/credit-insurance/insurance/create/index.js index 94de53352..9eae5bfa9 100644 --- a/modules/client/front/credit-insurance/insurance/create/index.js +++ b/modules/client/front/credit-insurance/insurance/create/index.js @@ -5,7 +5,7 @@ class Controller extends Section { constructor($element, $) { super($element, $); this.insurance = { - created: this.$filter('date')(new Date(), 'yyyy-MM-dd HH:mm:ss') + created: this.$filter('date')(Date.vnNew(), 'yyyy-MM-dd HH:mm:ss') }; } diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 4beadfda6..bfadc5c6a 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -82,7 +82,7 @@ export default class Controller extends Section { chipColor(date) { const day = 24 * 60 * 60 * 1000; - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); const observationShipped = new Date(date); diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index 0732c68a1..f92378d08 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -38,14 +38,14 @@ describe('client defaulter', () => { describe('chipColor()', () => { it('should return undefined when the date is the present', () => { - let today = new Date(); + let today = Date.vnNew(); let result = controller.chipColor(today); expect(result).toEqual(undefined); }); it('should return warning when the date is 10 days in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 11); let result = controller.chipColor(pastDate); @@ -53,7 +53,7 @@ describe('client defaulter', () => { }); it('should return alert when the date is 20 days in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 21); let result = controller.chipColor(pastDate); diff --git a/modules/client/front/greuge/create/index.js b/modules/client/front/greuge/create/index.js index dcc0fa522..147ad9bcb 100644 --- a/modules/client/front/greuge/create/index.js +++ b/modules/client/front/greuge/create/index.js @@ -5,7 +5,7 @@ class Controller extends Section { constructor(...args) { super(...args); this.greuge = { - shipped: new Date(), + shipped: Date.vnNew(), clientFk: this.$params.id }; } diff --git a/modules/client/front/notification/index.spec.js b/modules/client/front/notification/index.spec.js index 4e754f6ad..e1de104be 100644 --- a/modules/client/front/notification/index.spec.js +++ b/modules/client/front/notification/index.spec.js @@ -39,7 +39,7 @@ describe('Client notification', () => { describe('campaignSelection() setter', () => { it('should set the campaign from and to properties', () => { - const dated = new Date(); + const dated = Date.vnNew(); controller.campaignSelection = { dated: dated, scopeDays: 14 @@ -61,8 +61,8 @@ describe('Client notification', () => { controller.$.filters = {hide: () => {}}; controller.campaign = { - from: new Date(), - to: new Date() + from: Date.vnNew(), + to: Date.vnNew() }; const data = controller.$.model.data; diff --git a/modules/client/front/recovery/create/index.js b/modules/client/front/recovery/create/index.js index 4fd05eaa0..1779d647e 100644 --- a/modules/client/front/recovery/create/index.js +++ b/modules/client/front/recovery/create/index.js @@ -5,7 +5,7 @@ class Controller extends Section { constructor($element, $) { super($element, $); this.recovery = { - started: new Date() + started: Date.vnNew() }; } diff --git a/modules/client/front/recovery/index/index.js b/modules/client/front/recovery/index/index.js index d53ded805..e89b6832c 100644 --- a/modules/client/front/recovery/index/index.js +++ b/modules/client/front/recovery/index/index.js @@ -4,7 +4,7 @@ import Section from 'salix/components/section'; class Controller extends Section { setFinished(recovery) { if (!recovery.finished) { - let params = {finished: Date.now()}; + let params = {finished: Date.vnNow()}; this.$http.patch(`Recoveries/${recovery.id}`, params).then( () => this.$.model.refresh() ); diff --git a/modules/client/front/summary/index.js b/modules/client/front/summary/index.js index 1f22612d2..877579e33 100644 --- a/modules/client/front/summary/index.js +++ b/modules/client/front/summary/index.js @@ -100,7 +100,7 @@ class Controller extends Summary { } chipColor(date) { - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); const ticketShipped = new Date(date); diff --git a/modules/client/front/summary/index.spec.js b/modules/client/front/summary/index.spec.js index 0261cef45..a05d48518 100644 --- a/modules/client/front/summary/index.spec.js +++ b/modules/client/front/summary/index.spec.js @@ -76,14 +76,14 @@ describe('Client', () => { describe('chipColor()', () => { it('should return warning when the date is the present', () => { - let today = new Date(); + let today = Date.vnNew(); let result = controller.chipColor(today); expect(result).toEqual('warning'); }); it('should return success when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.chipColor(futureDate); @@ -91,7 +91,7 @@ describe('Client', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.chipColor(pastDate); diff --git a/modules/client/front/unpaid/index.js b/modules/client/front/unpaid/index.js index a8ff64386..fcf620b54 100644 --- a/modules/client/front/unpaid/index.js +++ b/modules/client/front/unpaid/index.js @@ -4,7 +4,7 @@ import Section from 'salix/components/section'; export default class Controller extends Section { setDefaultDate(hasData) { if (hasData && !this.clientUnpaid.dated) - this.clientUnpaid.dated = new Date(); + this.clientUnpaid.dated = Date.vnNew(); } } diff --git a/modules/client/front/unpaid/index.spec.js b/modules/client/front/unpaid/index.spec.js index bfeb7df19..0f6460a03 100644 --- a/modules/client/front/unpaid/index.spec.js +++ b/modules/client/front/unpaid/index.spec.js @@ -14,7 +14,7 @@ describe('client unpaid', () => { describe('setDefaultDate()', () => { it(`should not set today date if has dated`, () => { const hasData = true; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); controller.clientUnpaid = { diff --git a/modules/entry/back/methods/entry/latestBuysFilter.js b/modules/entry/back/methods/entry/latestBuysFilter.js index b920f4b58..30d47a2a3 100644 --- a/modules/entry/back/methods/entry/latestBuysFilter.js +++ b/modules/entry/back/methods/entry/latestBuysFilter.js @@ -150,10 +150,10 @@ module.exports = Self => { const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); stmt = new ParameterizedSQL(` - SELECT + SELECT i.image, i.id AS itemFk, i.size, @@ -209,7 +209,7 @@ module.exports = Self => { LEFT JOIN itemType t ON t.id = i.typeFk LEFT JOIN intrastat intr ON intr.id = i.intrastatFk LEFT JOIN origin ori ON ori.id = i.originFk - LEFT JOIN entry e ON e.id = b.entryFk AND e.created >= DATE_SUB(? ,INTERVAL 1 YEAR) + LEFT JOIN entry e ON e.id = b.entryFk AND e.created >= DATE_SUB(? ,INTERVAL 1 YEAR) LEFT JOIN supplier s ON s.id = e.supplierFk` , [userConfig.warehouseFk, date]); diff --git a/modules/entry/back/methods/entry/specs/latestBuysFilter.spec.js b/modules/entry/back/methods/entry/specs/latestBuysFilter.spec.js index 9b1e60532..0578fcdd4 100644 --- a/modules/entry/back/methods/entry/specs/latestBuysFilter.spec.js +++ b/modules/entry/back/methods/entry/specs/latestBuysFilter.spec.js @@ -332,10 +332,10 @@ describe('Entry latests buys filter()', () => { const options = {transaction: tx}; try { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); - const to = new Date(); + const to = Date.vnNew(); to.setHours(23, 59, 59, 999); const ctx = { diff --git a/modules/entry/front/latest-buys-search-panel/index.html b/modules/entry/front/latest-buys-search-panel/index.html index 8cfab622a..bc04ccd7e 100644 --- a/modules/entry/front/latest-buys-search-panel/index.html +++ b/modules/entry/front/latest-buys-search-panel/index.html @@ -1,198 +1,243 @@ - -
-
- - - - - - - - - -
{{name}}
-
- {{category.name}} -
-
> -
-
- - - - - {{name}}: {{nickname}} - - - - - - - - - - - - - - - - - - - Tags - - - - - - - - - - - - - - - - - More fields - - - - - - - - -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - - -
-
+ + + + + + + + + + + + + + + + + + +
{{name}}
+
+ {{category.name}} +
> +
+
+ + + + + {{name}}: {{nickname}} + + + + + + + + + + + + + + + + + + Tags + + + + + + + + + + + + + +
+ + Id/Name: {{$ctrl.filter.search}} + + + {{category.selection.name}} + + + {{type.selection.name}} + + + Sales person: {{salesPerson.selection.nickname}} + + + Supplier: {{supplier.selection.name}} + + + From: {{$ctrl.filter.from | date:'dd/MM/yyyy'}} + + + To: {{$ctrl.filter.to | date:'dd/MM/yyyy'}} + + + Active: {{$ctrl.filter.active ? '✓' : '✗'}} + + + Floramondo: {{$ctrl.filter.floramondo ? '✓' : '✗'}} + + + Visible: {{$ctrl.filter.visible ? '✓' : '✗'}} + + + {{$ctrl.showTagInfo(chipTag)}} + + +
+
diff --git a/modules/entry/front/latest-buys-search-panel/index.js b/modules/entry/front/latest-buys-search-panel/index.js index 83dc88724..a5a062302 100644 --- a/modules/entry/front/latest-buys-search-panel/index.js +++ b/modules/entry/front/latest-buys-search-panel/index.js @@ -1,67 +1,61 @@ import ngModule from '../module'; import SearchPanel from 'core/components/searchbar/search-panel'; +import './style.scss'; class Controller extends SearchPanel { constructor($element, $) { super($element, $); - let model = 'Item'; - let moreFields = ['description', 'name']; + } - let properties; - let validations = window.validations; + $onInit() { + this.filter = { + isActive: true, + tags: [] + }; + } - if (validations && validations[model]) - properties = validations[model].properties; - else - properties = {}; - - this.moreFields = []; - for (let field of moreFields) { - let prop = properties[field]; - this.moreFields.push({ - name: field, - label: prop ? prop.description : field, - type: prop ? prop.type : null - }); + changeCategory(id) { + if (this.filter.categoryFk != id) { + this.filter.categoryFk = id; + this.applyFilters(); } } - get filter() { - let filter = this.$.filter; - - for (let fieldFilter of this.fieldFilters) - filter[fieldFilter.name] = fieldFilter.value; - - return filter; + removeItemFilter(param) { + this.filter[param] = null; + if (param == 'categoryFk') this.filter['typeFk'] = null; + this.applyFilters(); } - set filter(value) { - if (!value) - value = {}; - if (!value.tags) - value.tags = [{}]; + removeTag(tag) { + const index = this.filter.tags.indexOf(tag); + if (index > -1) this.filter.tags.splice(index, 1); + this.applyFilters(); + } - this.fieldFilters = []; - for (let field of this.moreFields) { - if (value[field.name] != undefined) { - this.fieldFilters.push({ - name: field.name, - value: value[field.name], - info: field - }); - } + onKeyPress($event) { + if ($event.key === 'Enter') + this.applyFilters(); + } + + applyFilters() { + for (let i = 0; i < this.filter.tags.length; i++) { + if (!this.filter.tags[i].value) + this.filter.tags.splice(i, 1); } - - this.$.filter = value; + return this.model.applyFilter({}, this.filter); } - removeField(index, field) { - this.fieldFilters.splice(index, 1); - delete this.$.filter[field]; + showTagInfo(itemTag) { + if (!itemTag.tagFk) return itemTag.value; + return `${this.tags.find(tag => tag.id == itemTag.tagFk).name}: ${itemTag.value}`; } } ngModule.component('vnLatestBuysSearchPanel', { template: require('./index.html'), - controller: Controller + controller: Controller, + bindings: { + model: '<' + } }); diff --git a/modules/entry/front/latest-buys-search-panel/index.spec.js b/modules/entry/front/latest-buys-search-panel/index.spec.js index 9e187a25a..4cc4aa6dc 100644 --- a/modules/entry/front/latest-buys-search-panel/index.spec.js +++ b/modules/entry/front/latest-buys-search-panel/index.spec.js @@ -10,50 +10,46 @@ describe('Entry', () => { beforeEach(angular.mock.inject($componentController => { $element = angular.element(``); controller = $componentController('vnLatestBuysSearchPanel', {$element}); + controller.model = {applyFilter: () => {}}; })); - describe('filter() setter', () => { - it(`should set the tags property to the scope filter with an empty array`, () => { - const expectedFilter = { - tags: [{}] - }; - controller.filter = null; + describe('removeItemFilter()', () => { + it(`should remove param from filter`, () => { + controller.filter = {tags: [], categoryFk: 1, typeFk: 1}; + const expectFilter = {tags: [], categoryFk: null, typeFk: null}; - expect(controller.filter).toEqual(expectedFilter); - }); + controller.removeItemFilter('categoryFk'); - it(`should set the tags property to the scope filter with an array of tags`, () => { - const expectedFilter = { - description: 'My item', - tags: [{}] - }; - const expectedFieldFilter = [{ - info: { - label: 'description', - name: 'description', - type: null - }, - name: 'description', - value: 'My item' - }]; - controller.filter = { - description: 'My item' - }; - - expect(controller.filter).toEqual(expectedFilter); - expect(controller.fieldFilters).toEqual(expectedFieldFilter); + expect(controller.filter).toEqual(expectFilter); }); }); - describe('removeField()', () => { - it(`should remove the description property from the fieldFilters and from the scope filter`, () => { - const expectedFilter = {tags: [{}]}; - controller.filter = {description: 'My item'}; + describe('removeTag()', () => { + it(`should remove tag from filter`, () => { + const tag = {tagFk: 1, value: 'Value'}; + controller.filter = {tags: [tag]}; + const expectFilter = {tags: []}; - controller.removeField(0, 'description'); + controller.removeTag(tag); - expect(controller.filter).toEqual(expectedFilter); - expect(controller.fieldFilters).toEqual([]); + expect(controller.filter).toEqual(expectFilter); + }); + }); + + describe('showTagInfo()', () => { + it(`should show tag value`, () => { + const tag = {value: 'Value'}; + const result = controller.showTagInfo(tag); + + expect(result).toEqual('Value'); + }); + + it(`should show tag name and value`, () => { + const tag = {tagFk: 1, value: 'Value'}; + controller.tags = [{id: 1, name: 'tagName'}]; + const result = controller.showTagInfo(tag); + + expect(result).toEqual('tagName: Value'); }); }); }); diff --git a/modules/entry/front/latest-buys-search-panel/style.scss b/modules/entry/front/latest-buys-search-panel/style.scss new file mode 100644 index 000000000..ec189c7e4 --- /dev/null +++ b/modules/entry/front/latest-buys-search-panel/style.scss @@ -0,0 +1,70 @@ +@import "variables"; + +vn-latest-buys-search-panel vn-side-menu div { + & > .input { + padding-left: $spacing-md; + padding-right: $spacing-md; + border-color: $color-spacer; + border-bottom: $border-thin; + } + & > .horizontal { + grid-auto-flow: column; + grid-column-gap: $spacing-sm; + align-items: center; + } + & > .checks { + padding: $spacing-md; + flex-wrap: wrap; + border-color: $color-spacer; + border-bottom: $border-thin; + } + & > .tags { + padding: $spacing-md; + padding-bottom: 0%; + padding-top: 0%; + align-items: center; + } + & > .chips { + display: flex; + flex-wrap: wrap; + padding: $spacing-md; + overflow: hidden; + max-width: 100%; + border-color: $color-spacer; + border-top: $border-thin; + } + & > .item-category { + padding: $spacing-sm; + justify-content: flex-start; + align-items: flex-start; + flex-wrap: wrap; + + vn-autocomplete[vn-id="category"] { + display: none; + } + + & > vn-one { + padding: $spacing-sm; + min-width: 33.33%; + text-align: center; + box-sizing: border-box; + + & > vn-icon { + padding: $spacing-sm; + background-color: $color-font-secondary; + border-radius: 50%; + cursor: pointer; + + &.active { + background-color: $color-main; + color: #fff; + } + & > i:before { + font-size: 2.6rem; + width: 16px; + height: 16px; + } + } + } + } +} diff --git a/modules/entry/front/latest-buys/index.html b/modules/entry/front/latest-buys/index.html index fc44ddfc2..727b19220 100644 --- a/modules/entry/front/latest-buys/index.html +++ b/modules/entry/front/latest-buys/index.html @@ -7,17 +7,11 @@ on-data-change="$ctrl.reCheck()" auto-load="true">
- - - + + + - + - {{$ctrl.entryData.travel.ref}} @@ -114,8 +114,7 @@ Grouping Buying value Import - Grouping price - Packing price + PVP @@ -125,19 +124,18 @@ {{::line.packageFk | dashIfEmpty}} {{::line.weight}} - + {{::line.packing | dashIfEmpty}} - + {{::line.grouping | dashIfEmpty}} {{::line.buyingValue | currency: 'EUR':2}} {{::line.quantity * line.buyingValue | currency: 'EUR':2}} - {{::line.price2 | currency: 'EUR':2}} - {{::line.price3 | currency: 'EUR':2}} + {{::line.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::line.price3 | currency: 'EUR':2 | dashIfEmpty}} @@ -195,7 +193,7 @@ vn-id="item-descriptor" warehouse-fk="$ctrl.vnConfig.warehouseFk"> - diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js index 401b8dab0..adab3cbeb 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js @@ -146,8 +146,8 @@ describe('InvoiceIn filter()', () => { const options = {transaction: tx}; try { - const from = new Date(); - const to = new Date(); + const from = Date.vnNew(); + const to = Date.vnNew(); from.setHours(0, 0, 0, 0); to.setHours(23, 59, 59, 999); to.setDate(to.getDate() + 1); diff --git a/modules/invoiceIn/front/basic-data/index.spec.js b/modules/invoiceIn/front/basic-data/index.spec.js index 09aa08293..98710ac35 100644 --- a/modules/invoiceIn/front/basic-data/index.spec.js +++ b/modules/invoiceIn/front/basic-data/index.spec.js @@ -78,7 +78,7 @@ describe('InvoiceIn', () => { description: 'This is a description', files: [{ lastModified: 1668673957761, - lastModifiedDate: new Date(), + lastModifiedDate: Date.vnNew(), name: 'file-example.png', size: 19653, type: 'image/png', 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/descriptor/index.js b/modules/invoiceIn/front/descriptor/index.js index 4dc89a459..e005211a3 100644 --- a/modules/invoiceIn/front/descriptor/index.js +++ b/modules/invoiceIn/front/descriptor/index.js @@ -75,7 +75,7 @@ class Controller extends Descriptor { filter: { where: { invoiceInFk: id, - dueDated: {gte: new Date()} + dueDated: {gte: Date.vnNew()} } }}) .then(res => { diff --git a/modules/invoiceIn/front/dueDay/index.js b/modules/invoiceIn/front/dueDay/index.js index 3cc1c81e8..ee9b13e5c 100644 --- a/modules/invoiceIn/front/dueDay/index.js +++ b/modules/invoiceIn/front/dueDay/index.js @@ -4,7 +4,7 @@ import Section from 'salix/components/section'; class Controller extends Section { add() { this.$.model.insert({ - dueDated: new Date(), + dueDated: Date.vnNew(), bankFk: this.vnConfig.local.bankFk }); } 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/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index d42184ae5..f3c7a5093 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -60,9 +60,9 @@ module.exports = Self => { try { query = ` SELECT MAX(issued) issued - FROM vn.invoiceOut io - JOIN vn.time t ON t.dated = io.issued - WHERE io.serial = 'A' + FROM vn.invoiceOut io + JOIN vn.time t ON t.dated = io.issued + WHERE io.serial = 'A' AND t.year = YEAR(?) AND io.companyFk = ?`; const [maxIssued] = await Self.rawSql(query, [ @@ -77,7 +77,7 @@ module.exports = Self => { if (args.invoiceDate < args.maxShipped) args.maxShipped = args.invoiceDate; - const minShipped = new Date(); + const minShipped = Date.vnNew(); minShipped.setFullYear(minShipped.getFullYear() - 1); minShipped.setMonth(1); minShipped.setDate(1); @@ -131,11 +131,11 @@ module.exports = Self => { const models = Self.app.models; const args = ctx.args; const query = `SELECT DISTINCT clientFk AS id - FROM ticket t + FROM ticket t JOIN ticketPackaging tp ON t.id = tp.ticketFk JOIN client c ON c.id = t.clientFk WHERE t.shipped BETWEEN '2017-11-21' AND ? - AND t.clientFk >= ? + AND t.clientFk >= ? AND (t.clientFk <= ? OR ? IS NULL) AND c.isActive`; return models.InvoiceOut.rawSql(query, [ @@ -149,16 +149,16 @@ module.exports = Self => { async function getInvoiceableClients(ctx, options) { const models = Self.app.models; const args = ctx.args; - const minShipped = new Date(); + const minShipped = Date.vnNew(); minShipped.setFullYear(minShipped.getFullYear() - 1); const query = `SELECT c.id, SUM(IFNULL ( - s.quantity * + s.quantity * s.price * (100-s.discount)/100, - 0) + 0) + IFNULL(ts.quantity * ts.price,0) ) AS sumAmount, c.hasToInvoiceByAddress, @@ -170,7 +170,7 @@ module.exports = Self => { LEFT JOIN ticketService ts ON ts.ticketFk = t.id JOIN address a ON a.id = t.addressFk JOIN client c ON c.id = t.clientFk - WHERE ISNULL(t.refFk) AND c.id >= ? + WHERE ISNULL(t.refFk) AND c.id >= ? AND (t.clientFk <= ? OR ? IS NULL) AND t.shipped BETWEEN ? AND util.dayEnd(?) AND t.companyFk = ? AND c.hasToInvoice diff --git a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js index 297afa8e8..a458aa18e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js @@ -108,14 +108,14 @@ module.exports = Self => { throw new UserError(`This client is not invoiceable`); // Can't invoice tickets into future - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 1); if (maxShipped >= tomorrow) throw new UserError(`Can't invoice to future`); const maxInvoiceDate = await getMaxIssued(args.serial, companyId, myOptions); - if (new Date() < maxInvoiceDate) + if (Date.vnNew() < maxInvoiceDate) throw new UserError(`Can't invoice to past`); if (ticketId) { @@ -155,7 +155,7 @@ module.exports = Self => { async function isInvoiceable(clientId, options) { const models = Self.app.models; const query = `SELECT (hasToInvoice AND isTaxDataChecked) AS invoiceable - FROM client + FROM client WHERE id = ?`; const [result] = await models.InvoiceOut.rawSql(query, [clientId], options); @@ -172,12 +172,12 @@ module.exports = Self => { async function getMaxIssued(serial, companyId, options) { const models = Self.app.models; - const query = `SELECT MAX(issued) AS issued - FROM invoiceOut + const query = `SELECT MAX(issued) AS issued + FROM invoiceOut WHERE serial = ? AND companyFk = ?`; const [maxIssued] = await models.InvoiceOut.rawSql(query, [serial, companyId], options); - const maxInvoiceDate = maxIssued && maxIssued.issued || new Date(); + const maxInvoiceDate = maxIssued && maxIssued.issued || Date.vnNew(); return maxInvoiceDate; } diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js index ee3310368..26eae45ac 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/createPdf.spec.js @@ -11,7 +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/4875'); + pending('https://redmine.verdnatura.es/issues/5035'); const invoiceId = 1; spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js index 4d1833635..0f62a6876 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js @@ -13,7 +13,6 @@ describe('InvoiceOut downloadZip()', () => { }; it('should return part of link to dowloand the zip', async() => { - pending('https://redmine.verdnatura.es/issues/4875'); const tx = await models.InvoiceOut.beginTransaction({}); try { @@ -31,6 +30,8 @@ describe('InvoiceOut downloadZip()', () => { }); it('should return an error if the size of the files is too large', async() => { + pending('https://redmine.verdnatura.es/issues/5035'); + const tx = await models.InvoiceOut.beginTransaction({}); let error; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js index 7b5886236..d3d789393 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('InvoiceOut filter()', () => { - let today = new Date(); + let today = Date.vnNew(); today.setHours(2, 0, 0, 0); it('should return the invoice out matching ref', async() => { @@ -51,7 +51,6 @@ describe('InvoiceOut filter()', () => { }); it('should return the invoice out matching hasPdf', async() => { - pending('https://redmine.verdnatura.es/issues/4875'); const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; @@ -67,7 +66,7 @@ describe('InvoiceOut filter()', () => { const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options); - expect(result.length).toEqual(1); + expect(result.length).toBeGreaterThanOrEqual(1); await tx.rollback(); } catch (e) { diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js index 5f890de26..9a0574dba 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/invoiceClient.spec.js @@ -5,7 +5,7 @@ describe('InvoiceOut invoiceClient()', () => { const clientId = 1101; const addressId = 121; const companyFk = 442; - const minShipped = new Date(); + const minShipped = Date.vnNew(); minShipped.setFullYear(minShipped.getFullYear() - 1); minShipped.setMonth(1); minShipped.setDate(1); @@ -33,8 +33,8 @@ describe('InvoiceOut invoiceClient()', () => { ctx.args = { clientId: clientId, addressId: addressId, - invoiceDate: new Date(), - maxShipped: new Date(), + invoiceDate: Date.vnNew(), + maxShipped: Date.vnNew(), companyFk: companyFk, minShipped: minShipped }; diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 1c0919288..389fcf81b 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -17,12 +17,12 @@ target="_blank" name="showInvoicePdf" translate> - Show as PDF + as PDF - Show as CSV + as CSV diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index 488c1a3f8..df0ba57cf 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -2,6 +2,8 @@ Show invoice...: Ver factura... Send invoice...: Enviar factura... Send PDF invoice: Enviar factura en PDF Send CSV invoice: Enviar factura en CSV +as PDF: como PDF +as CSV: como CSV Delete Invoice: Eliminar factura Clone Invoice: Clonar factura Book invoice: Asentar factura diff --git a/modules/invoiceOut/front/index/global-invoicing/index.js b/modules/invoiceOut/front/index/global-invoicing/index.js index f772a4936..0c5773adc 100644 --- a/modules/invoiceOut/front/index/global-invoicing/index.js +++ b/modules/invoiceOut/front/index/global-invoicing/index.js @@ -6,7 +6,7 @@ class Controller extends Dialog { constructor($element, $, $transclude) { super($element, $, $transclude); this.invoice = { - maxShipped: new Date() + maxShipped: Date.vnNew() }; this.clientsNumber = 'allClients'; } diff --git a/modules/invoiceOut/front/index/global-invoicing/index.spec.js b/modules/invoiceOut/front/index/global-invoicing/index.spec.js index e88b0b1d4..aa9674b0e 100644 --- a/modules/invoiceOut/front/index/global-invoicing/index.spec.js +++ b/modules/invoiceOut/front/index/global-invoicing/index.spec.js @@ -76,8 +76,8 @@ describe('InvoiceOut', () => { jest.spyOn(controller.vnApp, 'showError'); controller.invoice = { - invoiceDate: new Date(), - maxShipped: new Date() + invoiceDate: Date.vnNew(), + maxShipped: Date.vnNew() }; controller.responseHandler('accept'); @@ -88,14 +88,14 @@ describe('InvoiceOut', () => { it('should make an http POST query and then call to the showSuccess() method', () => { jest.spyOn(controller.vnApp, 'showSuccess'); - const minShipped = new Date(); + const minShipped = Date.vnNew(); minShipped.setFullYear(minShipped.getFullYear() - 1); minShipped.setMonth(1); minShipped.setDate(1); minShipped.setHours(0, 0, 0, 0); controller.invoice = { - invoiceDate: new Date(), - maxShipped: new Date(), + invoiceDate: Date.vnNew(), + maxShipped: Date.vnNew(), fromClientId: 1101, toClientId: 1101, companyFk: 442, diff --git a/modules/invoiceOut/front/index/manual/index.js b/modules/invoiceOut/front/index/manual/index.js index ed50e37da..3abe4b825 100644 --- a/modules/invoiceOut/front/index/manual/index.js +++ b/modules/invoiceOut/front/index/manual/index.js @@ -8,7 +8,7 @@ class Controller extends Dialog { this.isInvoicing = false; this.invoice = { - maxShipped: new Date() + maxShipped: Date.vnNew() }; } 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/methods/fixed-price/specs/upsertFixedPrice.spec.js b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js index 68eacfbad..5c3fec7d6 100644 --- a/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js +++ b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('upsertFixedPrice()', () => { - const now = new Date(); + const now = Date.vnNew(); const fixedPriceId = 1; let originalFixedPrice; diff --git a/modules/item/back/methods/item-image-queue/downloadImages.js b/modules/item/back/methods/item-image-queue/downloadImages.js index 05b223598..0f57856c7 100644 --- a/modules/item/back/methods/item-image-queue/downloadImages.js +++ b/modules/item/back/methods/item-image-queue/downloadImages.js @@ -27,7 +27,7 @@ module.exports = Self => { }); for (let image of images) { - const currentStamp = new Date().getTime(); + const currentStamp = Date.vnNew().getTime(); const updatedStamp = image.updated.getTime(); const graceTime = Math.abs(currentStamp - updatedStamp); const maxTTL = 3600 * 48 * 1000; // 48 hours in ms; @@ -97,7 +97,7 @@ module.exports = Self => { await row.updateAttributes({ error: error, attempts: row.attempts + 1, - updated: new Date() + updated: Date.vnNew() }); } diff --git a/modules/item/back/methods/item-shelving-sale/filter.js b/modules/item/back/methods/item-shelving-sale/filter.js new file mode 100644 index 000000000..12029d33d --- /dev/null +++ b/modules/item/back/methods/item-shelving-sale/filter.js @@ -0,0 +1,49 @@ + +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; + +module.exports = Self => { + Self.remoteMethod('filter', { + description: 'Returns all item shelving sale matching with the filter', + accessType: 'READ', + accepts: [{ + arg: 'filter', + type: 'object', + description: 'Filter defining where and paginated data' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/filter`, + verb: 'GET' + } + }); + + Self.filter = async(filter, options) => { + const conn = Self.dataSource.connector; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const stmt = new ParameterizedSQL(` + SELECT iss.created, + iss.saleFk, + iss.quantity, + iss.userFk, + ish.shelvingFk, + p.code, + u.name + FROM itemShelvingSale iss + LEFT JOIN itemShelving ish ON iss.itemShelvingFk = ish.id + LEFT JOIN shelving s ON ish.shelvingFk = s.code + LEFT JOIN parking p ON s.parkingFk = p.id + LEFT JOIN account.user u ON u.id = iss.userFk` + ); + + stmt.merge(conn.makeSuffix(filter)); + + return conn.executeStmt(stmt); + }; +}; diff --git a/modules/item/back/methods/item/getVisibleAvailable.js b/modules/item/back/methods/item/getVisibleAvailable.js index b291ad9b4..612f64022 100644 --- a/modules/item/back/methods/item/getVisibleAvailable.js +++ b/modules/item/back/methods/item/getVisibleAvailable.js @@ -29,7 +29,7 @@ module.exports = Self => { } }); - Self.getVisibleAvailable = async(id, warehouseFk, dated = new Date(), options) => { + Self.getVisibleAvailable = async(id, warehouseFk, dated = Date.vnNew(), options) => { const myOptions = {}; if (typeof options == 'object') diff --git a/modules/item/back/methods/item/getWasteByItem.js b/modules/item/back/methods/item/getWasteByItem.js index b93d534da..56b90b04a 100644 --- a/modules/item/back/methods/item/getWasteByItem.js +++ b/modules/item/back/methods/item/getWasteByItem.js @@ -32,7 +32,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const wastes = await Self.rawSql(` SELECT *, 100 * dwindle / total AS percentage @@ -43,7 +43,7 @@ module.exports = Self => { sum(ws.saleTotal) AS total, sum(ws.saleWaste) AS dwindle FROM bs.waste ws - WHERE buyer = ? AND family = ? + WHERE buyer = ? AND family = ? AND year = YEAR(TIMESTAMPADD(WEEK,-1, ?)) AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1) GROUP BY buyer, itemFk diff --git a/modules/item/back/methods/item/getWasteByWorker.js b/modules/item/back/methods/item/getWasteByWorker.js index 4c3c64a91..8fa351eed 100644 --- a/modules/item/back/methods/item/getWasteByWorker.js +++ b/modules/item/back/methods/item/getWasteByWorker.js @@ -19,7 +19,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const wastes = await Self.rawSql(` SELECT *, 100 * dwindle / total AS percentage diff --git a/modules/item/back/methods/item/new.js b/modules/item/back/methods/item/new.js index fae37836f..0057cb50f 100644 --- a/modules/item/back/methods/item/new.js +++ b/modules/item/back/methods/item/new.js @@ -37,7 +37,8 @@ module.exports = Self => { 'typeFk', 'intrastatFk', 'originFk', - 'relevancy' + 'priority', + 'tag' ]; for (const key in params) { @@ -46,10 +47,14 @@ module.exports = Self => { } try { + const itemConfig = await models.ItemConfig.findOne({fields: ['validPriorities']}, myOptions); + if (!itemConfig.validPriorities.includes(params.priority)) + throw new UserError(`Valid priorities: ${[...itemConfig.validPriorities]}`); + const provisionalName = params.provisionalName; delete params.provisionalName; - const itemType = await models.ItemType.findById(params.typeFk, myOptions); + const itemType = await models.ItemType.findById(params.typeFk, {fields: ['isLaid']}, myOptions); params.isLaid = itemType.isLaid; @@ -63,13 +68,14 @@ module.exports = Self => { await Self.rawSql(query, null, myOptions); - let nameTag = await models.Tag.findOne({where: {name: 'Nombre temporal'}}); + const nameTag = await models.Tag.findById(params.tag, {fields: ['id']}, myOptions); let newTags = []; - newTags.push({itemFk: item.id, tagFk: nameTag.id, value: provisionalName, priority: '2'}); + newTags.push({itemFk: item.id, tagFk: nameTag.id, value: provisionalName, priority: item.priority}); typeTags.forEach(typeTag => { - newTags.push({itemFk: item.id, tagFk: typeTag.tagFk, value: '', priority: typeTag.priority}); + if (nameTag.id != typeTag.tagFk) + newTags.push({itemFk: item.id, tagFk: typeTag.tagFk, value: '', priority: typeTag.priority}); }); await models.ItemTag.create(newTags, myOptions); diff --git a/modules/item/back/methods/item/regularize.js b/modules/item/back/methods/item/regularize.js index 0878e3242..dfbcaa69f 100644 --- a/modules/item/back/methods/item/regularize.js +++ b/modules/item/back/methods/item/regularize.js @@ -94,8 +94,8 @@ module.exports = Self => { } async function createTicket(ctx, options) { - ctx.args.shipped = new Date(); - ctx.args.landed = new Date(); + ctx.args.shipped = Date.vnNew(); + ctx.args.landed = Date.vnNew(); ctx.args.companyId = null; ctx.args.agencyModeId = null; ctx.args.routeId = null; @@ -106,10 +106,10 @@ module.exports = Self => { } async function getTicketId(params, options) { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); let ticket = await Self.app.models.Ticket.findOne({ diff --git a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js index 8e4864ee8..13b2417d7 100644 --- a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js +++ b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js @@ -8,7 +8,7 @@ describe('item getVisibleAvailable()', () => { try { const itemFk = 1; const warehouseFk = 1; - const dated = new Date(); + const dated = Date.vnNew(); const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options); @@ -29,7 +29,7 @@ describe('item getVisibleAvailable()', () => { try { const itemFk = 1; const warehouseFk = 1; - const dated = new Date(); + const dated = Date.vnNew(); dated.setDate(dated.getDate() - 1); const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options); diff --git a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js index 25e661aee..00488e534 100644 --- a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js +++ b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js @@ -1,9 +1,9 @@ const {models} = require('vn-loopback/server/server'); describe('item lastEntriesFilter()', () => { it('should return one entry for the given item', async() => { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); const tx = await models.Item.beginTransaction({}); @@ -23,11 +23,11 @@ describe('item lastEntriesFilter()', () => { }); it('should return five entries for the given item', async() => { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); minDate.setMonth(minDate.getMonth() - 2, 1); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); const tx = await models.Item.beginTransaction({}); diff --git a/modules/item/back/methods/item/specs/new.spec.js b/modules/item/back/methods/item/specs/new.spec.js index 7364faa7d..e34ab2cf5 100644 --- a/modules/item/back/methods/item/specs/new.spec.js +++ b/modules/item/back/methods/item/specs/new.spec.js @@ -11,7 +11,8 @@ describe('item new()', () => { originFk: 1, provisionalName: 'planta', typeFk: 2, - relevancy: 0 + priority: 2, + tag: 1 }; let item = await models.Item.new(itemParams, options); @@ -20,7 +21,7 @@ describe('item new()', () => { item.isLaid = itemType.isLaid; - const temporalNameTag = await models.Tag.findOne({where: {name: 'Nombre temporal'}}, options); + const temporalNameTag = await models.Tag.findById(itemParams.tag, {fields: ['id']}, options); const temporalName = await models.ItemTag.findOne({ where: { @@ -31,7 +32,7 @@ describe('item new()', () => { item = await models.Item.findById(item.id, null, options); - itemType = await models.ItemType.findById(item.typeFk, options); + itemType = await models.ItemType.findById(item.typeFk, {fields: ['isLaid']}, options); item.isLaid = itemType.isLaid; diff --git a/modules/item/back/methods/tag/onSubmit.js b/modules/item/back/methods/tag/onSubmit.js new file mode 100644 index 000000000..7abbe60d4 --- /dev/null +++ b/modules/item/back/methods/tag/onSubmit.js @@ -0,0 +1,81 @@ + +module.exports = function(Self) { + Self.remoteMethodCtx('onSubmit', { + description: 'Save model changes', + accessType: 'WRITE', + accepts: [ + { + arg: 'creates', + type: ['object'], + description: 'The itemTags records to create' + }, { + arg: 'deletes', + type: ['number'], + description: 'The itemTags ids to delete' + }, { + arg: 'updates', + type: ['object'], + description: 'The itemTags records to update' + }, { + arg: 'maxPriority', + type: 'number', + description: 'The maxPriority value' + } + ], + returns: { + root: true, + type: 'object' + }, + http: { + verb: 'PATCH', + path: '/onSubmit' + } + }); + + Self.onSubmit = async(ctx, options) => { + const models = Self.app.models; + const args = ctx.args; + let tx; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + if (args.deletes) { + for (const itemTagId of args.deletes) + await models.ItemTag.destroyById(itemTagId, myOptions); + } + + if (args.updates) { + for (const row of args.updates) { + if (row.data.priority) { + const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions); + await itemTag.updateAttributes({ + priority: row.data.priority + args.maxPriority + }, myOptions); + } + } + for (const row of args.updates) { + const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions); + await itemTag.updateAttributes(row.data, myOptions); + } + } + + if (args.creates) { + for (const itemTag of args.creates) + await models.ItemTag.create(itemTag, myOptions); + } + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/item/back/methods/tag/specs/onSubmit.spec.js b/modules/item/back/methods/tag/specs/onSubmit.spec.js new file mode 100644 index 000000000..f24aad7e4 --- /dev/null +++ b/modules/item/back/methods/tag/specs/onSubmit.spec.js @@ -0,0 +1,96 @@ +const models = require('vn-loopback/server/server').models; + +describe('tag onSubmit()', () => { + it('should delete a tag', async() => { + const tx = await models.Item.beginTransaction({}); + const options = {transaction: tx}; + + try { + const deletes = [40]; + const ctx = { + args: { + deletes: deletes + } + }; + await models.Tag.onSubmit(ctx, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should update a tag', async() => { + const tx = await models.Item.beginTransaction({}); + const options = {transaction: tx}; + + try { + const updates = [{data: {value: 'Container Test'}, where: {id: 36}}]; + const ctx = { + args: { + updates: updates + } + }; + await models.Tag.onSubmit(ctx, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should create a tag', async() => { + const tx = await models.Item.beginTransaction({}); + const options = {transaction: tx}; + + try { + const creates = [{ + 'itemFk': '6', + 'priority': 8, + '$orgIndex': null, + '$oldData': null, + '$isNew': true, + 'tagFk': 3, + 'value': 'madera' + }]; + const ctx = { + args: { + creates: creates + } + }; + await models.Tag.onSubmit(ctx, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should swap priority for two tags', async() => { + const tx = await models.Item.beginTransaction({}); + const options = {transaction: tx}; + + try { + const updates = [ + {data: {priority: 2}, where: {id: 36}}, + {data: {priority: 1}, where: {id: 37}} + ]; + const ctx = { + args: { + updates: updates, + maxPriority: 7, + + } + }; + await models.Tag.onSubmit(ctx, options); + + 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-config.json b/modules/item/back/models/item-config.json index 364879986..36d25e0bb 100644 --- a/modules/item/back/models/item-config.json +++ b/modules/item/back/models/item-config.json @@ -16,6 +16,22 @@ "wasteRecipients": { "type": "string", "description": "Buyers waste report recipients" + }, + "validPriorities": { + "type": "array" + }, + "defaultPriority": { + "type": "int" + }, + "defaultTag": { + "type": "int" + } + }, + "relations": { + "tag": { + "type": "belongsTo", + "model": "Tag", + "foreignKey": "defaultTag" } } -} \ No newline at end of file +} 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/back/models/item-shelving-sale.js b/modules/item/back/models/item-shelving-sale.js new file mode 100644 index 000000000..b89be9f00 --- /dev/null +++ b/modules/item/back/models/item-shelving-sale.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/item-shelving-sale/filter')(Self); +}; diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index 951a4553a..0890350da 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -12,21 +12,12 @@ "id": true, "description": "Identifier" }, - "shelve": { - "type": "string" - }, "shelvingFk": { "type": "string" }, "itemFk": { "type": "number" }, - "deep": { - "type": "number" - }, - "quantity": { - "type": "number" - }, "created": { "type": "date" } @@ -41,6 +32,11 @@ "type": "belongsTo", "model": "Account", "foreignKey": "userFk" - } + }, + "shelving": { + "type": "belongsTo", + "model": "Shelving", + "foreignKey": "shelvingFk" + } } } diff --git a/modules/item/back/models/tag.js b/modules/item/back/models/tag.js index 43fbc0db3..92760e34f 100644 --- a/modules/item/back/models/tag.js +++ b/modules/item/back/models/tag.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/tag/filterValue')(Self); + require('../methods/tag/onSubmit')(Self); }; diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html index 8d1afe4e1..fd21ab240 100644 --- a/modules/item/front/basic-data/index.html +++ b/modules/item/front/basic-data/index.html @@ -1,6 +1,6 @@ - - @@ -95,7 +95,7 @@ @@ -108,15 +108,15 @@ @@ -124,10 +124,17 @@ + + - @@ -225,12 +232,12 @@ - \ No newline at end of file + diff --git a/modules/item/front/create/index.html b/modules/item/front/create/index.html index 6deaab1cd..15e212250 100644 --- a/modules/item/front/create/index.html +++ b/modules/item/front/create/index.html @@ -16,10 +16,24 @@ + + + + { + if (res.data) { + const dataRow = res.data[0]; + dataRow.validPriorities.forEach(priority => { + this.validPriorities.push({priority}); + }); + this.item = { + priority: dataRow.defaultPriority, + tag: dataRow.defaultTag + }; + } + }); } onSubmit() { diff --git a/modules/item/front/descriptor/index.js b/modules/item/front/descriptor/index.js index 133b11b48..b88f24456 100644 --- a/modules/item/front/descriptor/index.js +++ b/modules/item/front/descriptor/index.js @@ -80,7 +80,7 @@ class Controller extends Descriptor { } onUploadResponse() { - const timestamp = new Date().getTime(); + const timestamp = Date.vnNew().getTime(); const src = this.$rootScope.imagePath('catalog', '200x200', this.item.id); const zoomSrc = this.$rootScope.imagePath('catalog', '1600x900', this.item.id); const newSrc = `${src}&t=${timestamp}`; diff --git a/modules/item/front/diary/index.js b/modules/item/front/diary/index.js index c997ea491..1e93f9f16 100644 --- a/modules/item/front/diary/index.js +++ b/modules/item/front/diary/index.js @@ -7,7 +7,7 @@ class Controller extends Section { super($element, $scope); this.$anchorScroll = $anchorScroll; this.$location = $location; - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); this.today = today.toJSON(); } 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..5f28e22b1 100644 --- a/modules/item/front/fixed-price/index.spec.js +++ b/modules/item/front/fixed-price/index.spec.js @@ -24,7 +24,7 @@ describe('fixed price', () => { }); it('should perform an http request to update the price', () => { - const now = new Date(); + const now = Date.vnNew(); jest.spyOn(controller.vnApp, 'showSuccess'); $httpBackend.expectPATCH('FixedPrices/upsertFixedPrice').respond(); @@ -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/item/front/last-entries/index.html b/modules/item/front/last-entries/index.html index 0348d4f66..1c2db10a5 100644 --- a/modules/item/front/last-entries/index.html +++ b/modules/item/front/last-entries/index.html @@ -9,15 +9,15 @@ - + @@ -35,8 +35,7 @@ Warehouse Landed Entry - P.P.U - P.P.P + PVP Label Packing Grouping @@ -51,7 +50,7 @@ - @@ -65,30 +64,31 @@ {{::entry.entryFk | dashIfEmpty}} - {{::entry.price2 | dashIfEmpty}} - {{::entry.price3 | dashIfEmpty}} + + {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}} + {{entry.stickers | dashIfEmpty}} - + {{::entry.packing | dashIfEmpty}} - + {{::entry.grouping | dashIfEmpty}} {{::entry.stems | dashIfEmpty}} {{::entry.quantity}} - - {{::entry.cost | dashIfEmpty}} + {{::$ctrl.$t('Cost')}}: {{::entry.buyingValue | currency: 'EUR':2 | dashIfEmpty}}
+ {{::$ctrl.$t('Package')}}: {{::entry.packageValue | currency: 'EUR':2 | dashIfEmpty}}
+ {{::$ctrl.$t('Freight')}}: {{::entry.freightValue | currency: 'EUR':2 | dashIfEmpty}}
+ {{::$ctrl.$t('Comission')}}: {{::entry.comissionValue | currency: 'EUR':2 | dashIfEmpty}}"> + {{::entry.cost | currency: 'EUR':2 | dashIfEmpty}}
{{::entry.weight | dashIfEmpty}} @@ -113,24 +113,24 @@ ng-click="contextmenu.filterBySelection()"> Filter by selection - Exclude selection - Remove filter - Remove all filters - Copy value - \ No newline at end of file + diff --git a/modules/item/front/last-entries/index.js b/modules/item/front/last-entries/index.js index 014761da9..0c6804838 100644 --- a/modules/item/front/last-entries/index.js +++ b/modules/item/front/last-entries/index.js @@ -5,11 +5,11 @@ class Controller extends Section { constructor($element, $) { super($element, $); - const from = new Date(); + const from = Date.vnNew(); from.setDate(from.getDate() - 75); from.setHours(0, 0, 0, 0); - const to = new Date(); + const to = Date.vnNew(); to.setDate(to.getDate() + 10); to.setHours(23, 59, 59, 59); diff --git a/modules/item/front/locale/es.yml b/modules/item/front/locale/es.yml index 88ab031e1..0fc014742 100644 --- a/modules/item/front/locale/es.yml +++ b/modules/item/front/locale/es.yml @@ -44,6 +44,7 @@ Weight/Piece: Peso/tallo Search items by id, name or barcode: Buscar articulos por identificador, nombre o codigo de barras SalesPerson: Comercial Concept: Concepto +Units/Box: Unidades/Caja # Sections Items: Artículos @@ -61,4 +62,4 @@ Item diary: Registro de compra-venta Last entries: Últimas entradas Tags: Etiquetas Waste breakdown: Desglose de mermas -Waste breakdown by item: Desglose de mermas por artículo \ No newline at end of file +Waste breakdown by item: Desglose de mermas por artículo diff --git a/modules/item/front/request-search-panel/index.spec.js b/modules/item/front/request-search-panel/index.spec.js index 2fb339209..56c76eabf 100644 --- a/modules/item/front/request-search-panel/index.spec.js +++ b/modules/item/front/request-search-panel/index.spec.js @@ -15,7 +15,7 @@ describe(' Component vnRequestSearchPanel', () => { it('should clear the scope days when setting the from property', () => { controller.filter.scopeDays = 1; - controller.from = new Date(); + controller.from = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.from).toBeDefined(); @@ -26,7 +26,7 @@ describe(' Component vnRequestSearchPanel', () => { it('should clear the scope days when setting the to property', () => { controller.filter.scopeDays = 1; - controller.to = new Date(); + controller.to = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.to).toBeDefined(); @@ -35,8 +35,8 @@ describe(' Component vnRequestSearchPanel', () => { describe('scopeDays() setter', () => { it('should clear the date range when setting the scopeDays property', () => { - controller.filter.from = new Date(); - controller.filter.to = new Date(); + controller.filter.from = Date.vnNew(); + controller.filter.to = Date.vnNew(); controller.scopeDays = 1; diff --git a/modules/item/front/request/index.js b/modules/item/front/request/index.js index 2fe08ada6..747cbeff2 100644 --- a/modules/item/front/request/index.js +++ b/modules/item/front/request/index.js @@ -7,10 +7,10 @@ export default class Controller extends Section { super($element, $); if (!this.$state.q) { - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); - const nextWeek = new Date(); + const nextWeek = Date.vnNew(); nextWeek.setHours(23, 59, 59, 59); nextWeek.setDate(nextWeek.getDate() + 7); @@ -27,7 +27,7 @@ export default class Controller extends Section { $params.scopeDays = 1; if (typeof $params.scopeDays === 'number') { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); const to = new Date(from.getTime()); @@ -82,7 +82,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); let timeTicket = new Date(date); timeTicket.setHours(0, 0, 0, 0); diff --git a/modules/item/front/request/index.spec.js b/modules/item/front/request/index.spec.js index 0fc061023..aadeaddca 100644 --- a/modules/item/front/request/index.spec.js +++ b/modules/item/front/request/index.spec.js @@ -93,7 +93,7 @@ describe('Item', () => { }); it(`should return "warning" if date is today`, () => { - let date = new Date(); + let date = Date.vnNew(); let result = controller.compareDate(date); expect(result).toEqual('warning'); diff --git a/modules/item/front/tags/index.html b/modules/item/front/tags/index.html index c040b9984..f9b5370fa 100644 --- a/modules/item/front/tags/index.html +++ b/modules/item/front/tags/index.html @@ -19,7 +19,7 @@ data="tags" auto-load="true"> -
+ - \ No newline at end of file + diff --git a/modules/item/front/tags/index.js b/modules/item/front/tags/index.js index 3b3cd58ef..bfa1f3f46 100644 --- a/modules/item/front/tags/index.js +++ b/modules/item/front/tags/index.js @@ -29,11 +29,17 @@ class Controller extends Section { } onSubmit() { - this.$.watcher.check(); - this.$.model.save().then(() => { + const changes = this.$.model.getChanges(); + const data = { + creates: changes.creates, + deletes: changes.deletes, + updates: changes.updates, + maxPriority: this.getHighestPriority() + }; + this.$http.patch(`Tags/onSubmit`, data).then(() => { + this.$.model.refresh(); this.$.watcher.notifySaved(); this.$.watcher.updateOriginalData(); - this.card.reload(); }); } } diff --git a/modules/mdb/back/methods/mdbApp/lock.js b/modules/mdb/back/methods/mdbApp/lock.js index 98e61fb53..a12a93814 100644 --- a/modules/mdb/back/methods/mdbApp/lock.js +++ b/modules/mdb/back/methods/mdbApp/lock.js @@ -51,7 +51,7 @@ module.exports = Self => { const updatedMdbApp = await mdbApp.updateAttributes({ userFk: userId, - locked: new Date() + locked: Date.vnNew() }, myOptions); if (tx) await tx.commit(); 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/back/methods/sales-monitor/clientsFilter.js b/modules/monitor/back/methods/sales-monitor/clientsFilter.js index 09ea24eb1..13e38f8e1 100644 --- a/modules/monitor/back/methods/sales-monitor/clientsFilter.js +++ b/modules/monitor/back/methods/sales-monitor/clientsFilter.js @@ -34,7 +34,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const stmt = new ParameterizedSQL(` SELECT @@ -51,7 +51,7 @@ module.exports = Self => { JOIN account.user u ON c.salesPersonFk = u.id LEFT JOIN sharingCart sc ON sc.workerFk = c.salesPersonFk AND ? BETWEEN sc.started AND sc.ended - LEFT JOIN workerTeamCollegues wtc + LEFT JOIN workerTeamCollegues wtc ON wtc.collegueFk = IFNULL(sc.workerSubstitute, c.salesPersonFk)`, [date]); diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index 7be130dda..881fc637a 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -104,7 +104,7 @@ module.exports = Self => { const userId = ctx.req.accessToken.userId; const conn = Self.dataSource.connector; const models = Self.app.models; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const args = ctx.args; const myOptions = {}; diff --git a/modules/monitor/back/methods/sales-monitor/specs/clientsFilter.spec.js b/modules/monitor/back/methods/sales-monitor/specs/clientsFilter.spec.js index bcb37830c..febfc5357 100644 --- a/modules/monitor/back/methods/sales-monitor/specs/clientsFilter.spec.js +++ b/modules/monitor/back/methods/sales-monitor/specs/clientsFilter.spec.js @@ -8,8 +8,8 @@ describe('SalesMonitor clientsFilter()', () => { const options = {transaction: tx}; const ctx = {req: {accessToken: {userId: 18}}, args: {}}; - const from = new Date(); - const to = new Date(); + const from = Date.vnNew(); + const to = Date.vnNew(); from.setHours(0, 0, 0, 0); to.setHours(23, 59, 59, 59); @@ -35,9 +35,9 @@ describe('SalesMonitor clientsFilter()', () => { try { const options = {transaction: tx}; const ctx = {req: {accessToken: {userId: 18}}, args: {}}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); - const today = new Date(); + const today = Date.vnNew(); yesterday.setHours(0, 0, 0, 0); today.setHours(23, 59, 59, 59); diff --git a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js index d2e1a5bec..4e0fb85b7 100644 --- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js +++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js @@ -26,9 +26,9 @@ describe('SalesMonitor salesFilter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 9}}, args: { @@ -54,10 +54,10 @@ describe('SalesMonitor salesFilter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 9}}, args: { @@ -205,10 +205,10 @@ describe('SalesMonitor salesFilter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 18}}, args: {}}; @@ -234,10 +234,10 @@ describe('SalesMonitor salesFilter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 18}}, args: {}}; diff --git a/modules/monitor/front/index/clients/index.js b/modules/monitor/front/index/clients/index.js index 58613f09d..ac3ce9140 100644 --- a/modules/monitor/front/index/clients/index.js +++ b/modules/monitor/front/index/clients/index.js @@ -5,7 +5,7 @@ export default class Controller extends Section { constructor($element, $) { super($element, $); - const date = new Date(); + const date = Date.vnNew(); this.dateFrom = date; this.dateTo = date; this.filter = { @@ -64,9 +64,9 @@ export default class Controller extends Section { let from = this.dateFrom; let to = this.dateTo; if (!from) - from = new Date(); + from = Date.vnNew(); if (!to) - to = new Date(); + to = Date.vnNew(); const minHour = new Date(from); minHour.setHours(0, 0, 0, 0); const maxHour = new Date(to); diff --git a/modules/monitor/front/index/orders/index.js b/modules/monitor/front/index/orders/index.js index e3a47f68b..40100b79f 100644 --- a/modules/monitor/front/index/orders/index.js +++ b/modules/monitor/front/index/orders/index.js @@ -26,7 +26,7 @@ export default class Controller extends Section { } chipColor(date) { - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); const orderLanded = new Date(date); diff --git a/modules/monitor/front/index/search-panel/index.spec.js b/modules/monitor/front/index/search-panel/index.spec.js index f862e8d77..18cf1abfc 100644 --- a/modules/monitor/front/index/search-panel/index.spec.js +++ b/modules/monitor/front/index/search-panel/index.spec.js @@ -38,7 +38,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => { it('should clear the scope days when setting the from property', () => { controller.filter.scopeDays = 1; - controller.from = new Date(); + controller.from = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.from).toBeDefined(); @@ -49,7 +49,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => { it('should clear the scope days when setting the to property', () => { controller.filter.scopeDays = 1; - controller.to = new Date(); + controller.to = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.to).toBeDefined(); @@ -58,8 +58,8 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => { describe('scopeDays() setter', () => { it('should clear the date range when setting the scopeDays property', () => { - controller.filter.from = new Date(); - controller.filter.to = new Date(); + controller.filter.from = Date.vnNew(); + controller.filter.to = Date.vnNew(); controller.scopeDays = 1; 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}} { let params = controller.fetchParams({ scopeDays: 2 }); - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); const to = new Date(from.getTime()); to.setDate(to.getDate() + params.scopeDays); @@ -66,14 +66,14 @@ describe('Component vnMonitorSalesTickets', () => { describe('compareDate()', () => { it('should return warning when the date is the present', () => { - let today = new Date(); + let today = Date.vnNew(); let result = controller.compareDate(today); expect(result).toEqual('warning'); }); it('should return sucess when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.compareDate(futureDate); @@ -81,7 +81,7 @@ describe('Component vnMonitorSalesTickets', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.compareDate(pastDate); @@ -99,7 +99,7 @@ describe('Component vnMonitorSalesTickets', () => { describe('dateRange()', () => { it('should return two dates with the hours at the start and end of the given date', () => { - const now = new Date(); + const now = Date.vnNew(); const today = now.getDate(); diff --git a/modules/order/back/methods/order/specs/new.spec.js b/modules/order/back/methods/order/specs/new.spec.js index 5873189f8..f11367579 100644 --- a/modules/order/back/methods/order/specs/new.spec.js +++ b/modules/order/back/methods/order/specs/new.spec.js @@ -9,7 +9,7 @@ describe('order new()', () => { try { const options = {transaction: tx}; - const landed = new Date(); + const landed = Date.vnNew(); const addressFk = 6; const agencyModeFk = 1; @@ -30,7 +30,7 @@ describe('order new()', () => { try { const options = {transaction: tx}; - const landed = new Date(); + const landed = Date.vnNew(); const addressFk = 121; const agencyModeFk = 1; diff --git a/modules/order/front/basic-data/index.spec.js b/modules/order/front/basic-data/index.spec.js index 01009d085..21dee0765 100644 --- a/modules/order/front/basic-data/index.spec.js +++ b/modules/order/front/basic-data/index.spec.js @@ -46,7 +46,7 @@ describe('Order', () => { it('should set agencyModeFk to null and get the available agencies if the order has landed and client', async() => { controller.order.agencyModeFk = 999; controller.order.addressFk = 999; - controller.order.landed = new Date(); + controller.order.landed = Date.vnNew(); const expectedAgencies = [{id: 1}, {id: 2}]; diff --git a/modules/order/front/catalog/index.js b/modules/order/front/catalog/index.js index 5fdd2e238..c0777ebc9 100644 --- a/modules/order/front/catalog/index.js +++ b/modules/order/front/catalog/index.js @@ -157,7 +157,7 @@ class Controller extends Section { * Apply order to model */ applyOrder() { - if (this.typeId || this.tagGroups.length > 0) + if (this.typeId || this.tagGroups.length > 0 || this.itemName) this.$.model.addFilter(null, {orderBy: this.getOrderBy()}); } diff --git a/modules/order/front/index/index.js b/modules/order/front/index/index.js index a8e6e977e..750f2e226 100644 --- a/modules/order/front/index/index.js +++ b/modules/order/front/index/index.js @@ -8,7 +8,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); date = new Date(date); diff --git a/modules/order/front/index/index.spec.js b/modules/order/front/index/index.spec.js index 5b85b3333..abe336478 100644 --- a/modules/order/front/index/index.spec.js +++ b/modules/order/front/index/index.spec.js @@ -26,14 +26,14 @@ describe('Component vnOrderIndex', () => { describe('compareDate()', () => { it('should return warning when the date is the present', () => { - let curDate = new Date(); + let curDate = Date.vnNew(); let result = controller.compareDate(curDate); expect(result).toEqual('warning'); }); it('should return sucess when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.compareDate(futureDate); @@ -41,7 +41,7 @@ describe('Component vnOrderIndex', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.compareDate(pastDate); diff --git a/modules/route/back/methods/agency-term/filter.js b/modules/route/back/methods/agency-term/filter.js index 0ecec7e88..9d1268958 100644 --- a/modules/route/back/methods/agency-term/filter.js +++ b/modules/route/back/methods/agency-term/filter.js @@ -74,35 +74,35 @@ module.exports = Self => { filter = mergeFilters(filter, {where}); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const stmts = []; const stmt = new ParameterizedSQL( `SELECT * FROM ( - SELECT r.id routeFk, - r.created, - r.agencyModeFk, + SELECT r.id routeFk, + r.created, + r.agencyModeFk, am.name agencyModeName, - am.agencyFk, + am.agencyFk, a.name agencyAgreement, SUM(t.packages) packages, r.m3, - r.kmEnd - r.kmStart kmTotal, - CAST(IFNULL(sat.routePrice, - (sat.kmPrice * (GREATEST(r.kmEnd - r.kmStart , sat.minimumKm)) - + GREATEST(r.m3 , sat.minimumM3) * sat.m3Price) - + sat.packagePrice * SUM(t.packages) ) + r.kmEnd - r.kmStart kmTotal, + CAST(IFNULL(sat.routePrice, + (sat.kmPrice * (GREATEST(r.kmEnd - r.kmStart , sat.minimumKm)) + + GREATEST(r.m3 , sat.minimumM3) * sat.m3Price) + + sat.packagePrice * SUM(t.packages) ) AS DECIMAL(10,2)) price, r.invoiceInFk, sat.supplierFk, s.name supplierName FROM vn.route r - LEFT JOIN vn.agencyMode am ON r.agencyModeFk = am.id + LEFT JOIN vn.agencyMode am ON r.agencyModeFk = am.id LEFT JOIN vn.agency a ON am.agencyFk = a.id LEFT JOIN vn.ticket t ON t.routeFk = r.id LEFT JOIN vn.supplierAgencyTerm sat ON sat.agencyFk = a.id - LEFT JOIN vn.supplier s ON s.id = sat.supplierFk + LEFT JOIN vn.supplier s ON s.id = sat.supplierFk WHERE r.created > DATE_ADD(?, INTERVAL -2 MONTH) AND sat.supplierFk IS NOT NULL GROUP BY r.id ) a` diff --git a/modules/route/back/methods/agency-term/specs/filter.spec.js b/modules/route/back/methods/agency-term/specs/filter.spec.js index d6c00e585..41e696157 100644 --- a/modules/route/back/methods/agency-term/specs/filter.spec.js +++ b/modules/route/back/methods/agency-term/specs/filter.spec.js @@ -3,7 +3,7 @@ const models = require('vn-loopback/server/server').models; describe('AgencyTerm filter()', () => { const authUserId = 9; - const today = new Date(); + const today = Date.vnNew(); today.setHours(2, 0, 0, 0); it('should return all results matching the filter', async() => { @@ -57,10 +57,10 @@ describe('AgencyTerm filter()', () => { const options = {transaction: tx}; try { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); - const to = new Date(); + const to = Date.vnNew(); to.setHours(23, 59, 59, 999); const ctx = { diff --git a/modules/route/back/methods/route/downloadZip.js b/modules/route/back/methods/route/downloadZip.js new file mode 100644 index 000000000..597f1d1f6 --- /dev/null +++ b/modules/route/back/methods/route/downloadZip.js @@ -0,0 +1,62 @@ +const JSZip = require('jszip'); + +module.exports = Self => { + Self.remoteMethodCtx('downloadZip', { + description: 'Download a zip file with multiple routes pdfs', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'string', + description: 'The routes ids', + } + ], + 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: '/downloadZip', + verb: 'GET' + } + }); + + Self.downloadZip = async function(ctx, id, options) { + const models = Self.app.models; + const myOptions = {}; + const zip = new JSZip(); + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const ids = id.split(','); + for (let id of ids) { + ctx.args.id = id; + const routePdf = await models.Route.driverRoutePdf(ctx, id); + const fileName = extractFileName(routePdf[2]); + const body = routePdf[0]; + + zip.file(fileName, body); + } + + const stream = zip.generateNodeStream({streamFiles: true}); + + return [stream, 'application/zip', `filename="download.zip"`]; + }; + + function extractFileName(str) { + const matches = str.match(/"(.*?)"/); + return matches ? matches[1] : str; + } +}; diff --git a/modules/route/back/methods/route/getTickets.js b/modules/route/back/methods/route/getTickets.js index 708644c1a..1eb9e27f5 100644 --- a/modules/route/back/methods/route/getTickets.js +++ b/modules/route/back/methods/route/getTickets.js @@ -50,14 +50,17 @@ module.exports = Self => { am.name AS agencyModeName, u.nickname AS userNickname, vn.ticketTotalVolume(t.id) AS volume, - tob.description + tob.description, + GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt FROM vn.route r JOIN ticket t ON t.routeFk = r.id + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.item i ON i.id = s.itemFk LEFT JOIN ticketState ts ON ts.ticketFk = t.id LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN warehouse wh ON wh.id = t.warehouseFk LEFT JOIN observationType ot ON ot.code = 'delivery' - LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id + LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id AND tob.observationTypeFk = ot.id LEFT JOIN address a ON a.id = t.addressFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk @@ -70,7 +73,9 @@ module.exports = Self => { const where = filter.where; where['r.id'] = filter.id; - stmt.merge(conn.makeSuffix(filter)); + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(conn.makeGroupBy('t.id')); + stmt.merge(conn.makeOrderBy(filter.order)); const tickets = await conn.executeStmt(stmt, myOptions); diff --git a/modules/route/back/methods/route/specs/clone.spec.js b/modules/route/back/methods/route/specs/clone.spec.js index d1fc6b297..9192854f8 100644 --- a/modules/route/back/methods/route/specs/clone.spec.js +++ b/modules/route/back/methods/route/specs/clone.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('route clone()', () => { - const createdDate = new Date(); + const createdDate = Date.vnNew(); it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => { const ids = [996, 997, 998, 999]; diff --git a/modules/route/back/methods/route/specs/filter.spec.js b/modules/route/back/methods/route/specs/filter.spec.js index 9d481f21e..18c0ca04f 100644 --- a/modules/route/back/methods/route/specs/filter.spec.js +++ b/modules/route/back/methods/route/specs/filter.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models; describe('Route filter()', () => { - const today = new Date(); + const today = Date.vnNew(); today.setHours(2, 0, 0, 0); it('should return the routes matching "search"', async() => { @@ -23,10 +23,10 @@ describe('Route filter()', () => { const options = {transaction: tx}; try { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); - const to = new Date(); + const to = Date.vnNew(); to.setHours(23, 59, 59, 999); const ctx = { args: { diff --git a/modules/route/back/methods/route/specs/getSuggestedTickets.spec.js b/modules/route/back/methods/route/specs/getSuggestedTickets.spec.js index bb38cb50e..0acc6c1a7 100644 --- a/modules/route/back/methods/route/specs/getSuggestedTickets.spec.js +++ b/modules/route/back/methods/route/specs/getSuggestedTickets.spec.js @@ -23,7 +23,7 @@ describe('route getSuggestedTickets()', () => { await ticketInRoute.updateAttributes({ routeFk: null, - landed: new Date() + landed: Date.vnNew() }, options); const result = await models.Route.getSuggestedTickets(routeID, options); diff --git a/modules/route/back/methods/route/specs/insertTicket.spec.js b/modules/route/back/methods/route/specs/insertTicket.spec.js index 7c60e755f..19d02e1ef 100644 --- a/modules/route/back/methods/route/specs/insertTicket.spec.js +++ b/modules/route/back/methods/route/specs/insertTicket.spec.js @@ -23,7 +23,7 @@ describe('route insertTicket()', () => { const ticketInRoute = await app.models.Ticket.findById(ticketId, null, options); await ticketInRoute.updateAttributes({ routeFk: null, - landed: new Date() + landed: Date.vnNew() }, options); const result = await app.models.Route.insertTicket(routeId, ticketId, options); diff --git a/modules/route/back/methods/route/updateWorkCenter.js b/modules/route/back/methods/route/updateWorkCenter.js index 7796fba41..75169ce7e 100644 --- a/modules/route/back/methods/route/updateWorkCenter.js +++ b/modules/route/back/methods/route/updateWorkCenter.js @@ -33,12 +33,13 @@ module.exports = Self => { } try { + const date = Date.vnNew(); const [result] = await Self.rawSql(` SELECT IFNULL(wl.workCenterFk, r.defaultWorkCenterFk) AS commissionWorkCenter FROM vn.routeConfig r LEFT JOIN vn.workerLabour wl ON wl.workerFk = ? - AND CURDATE() BETWEEN wl.started AND IFNULL(wl.ended, CURDATE()); - `, [userId], myOptions); + AND ? BETWEEN wl.started AND IFNULL(wl.ended, ?); + `, [userId, date, date], myOptions); const route = await models.Route.findById(id, null, myOptions); await route.updateAttribute('commissionWorkCenterFk', result.commissionWorkCenter, myOptions); diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 08cabd30e..883f4597e 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -13,6 +13,7 @@ module.exports = Self => { require('../methods/route/driverRoutePdf')(Self); require('../methods/route/driverRouteEmail')(Self); require('../methods/route/sendSms')(Self); + require('../methods/route/downloadZip')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' diff --git a/modules/route/front/index/index.js b/modules/route/front/index/index.js index 9258c8fac..7c19a26cd 100644 --- a/modules/route/front/index/index.js +++ b/modules/route/front/index/index.js @@ -34,17 +34,27 @@ export default class Controller extends Section { } showRouteReport() { - const routes = []; + const routesIds = []; for (let route of this.checked) - routes.push(route.id); - const routesId = routes.join(','); + routesIds.push(route.id); + const stringRoutesIds = routesIds.join(','); - this.vnReport.show(`Routes/${routesId}/driver-route-pdf`); + if (this.checked.length <= 1) { + const url = `api/Routes/${stringRoutesIds}/driver-route-pdf?access_token=${this.vnToken.token}`; + window.open(url, '_blank'); + } else { + const serializedParams = this.$httpParamSerializer({ + access_token: this.vnToken.token, + id: stringRoutesIds + }); + const url = `api/Routes/downloadZip?${serializedParams}`; + window.open(url, '_blank'); + } } openClonationDialog() { this.$.clonationDialog.show(); - this.createdDate = new Date(); + this.createdDate = Date.vnNew(); } cloneSelectedRoutes() { diff --git a/modules/route/front/index/index.spec.js b/modules/route/front/index/index.spec.js index 05dd56433..399ece714 100644 --- a/modules/route/front/index/index.spec.js +++ b/modules/route/front/index/index.spec.js @@ -44,23 +44,21 @@ describe('Component vnRouteIndex', () => { describe('showRouteReport()', () => { it('should call to the vnReport show method', () => { - controller.vnReport.show = jest.fn(); + jest.spyOn(window, 'open').mockReturnThis(); const data = controller.$.model.data; data[0].checked = true; data[2].checked = true; - const routeIds = '1,3'; - controller.showRouteReport(); - expect(controller.vnReport.show).toHaveBeenCalledWith(`Routes/${routeIds}/driver-route-pdf`); + expect(window.open).toHaveBeenCalled(); }); }); describe('cloneSelectedRoutes()', () => { it('should perform an http request to Routes/clone', () => { - controller.createdDate = new Date(); + controller.createdDate = Date.vnNew(); $httpBackend.expect('POST', 'Routes/clone').respond(); controller.cloneSelectedRoutes(); diff --git a/modules/route/front/main/index.js b/modules/route/front/main/index.js index 938f81bcc..8c57bbad6 100644 --- a/modules/route/front/main/index.js +++ b/modules/route/front/main/index.js @@ -3,11 +3,11 @@ import ModuleMain from 'salix/components/module-main'; export default class Route extends ModuleMain { $postLink() { - const to = new Date(); + const to = Date.vnNew(); to.setDate(to.getDate() + 1); to.setHours(0, 0, 0, 0); - const from = new Date(); + const from = Date.vnNew(); from.setDate(from.getDate()); from.setHours(0, 0, 0, 0); @@ -21,7 +21,7 @@ export default class Route extends ModuleMain { $params.scopeDays = 1; if (typeof $params.scopeDays === 'number') { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); const to = new Date(from.getTime()); diff --git a/modules/route/front/main/index.spec.js b/modules/route/front/main/index.spec.js index e5724b493..0c16a7b1f 100644 --- a/modules/route/front/main/index.spec.js +++ b/modules/route/front/main/index.spec.js @@ -15,7 +15,7 @@ describe('Route Component vnRoute', () => { let params = controller.fetchParams({ scopeDays: 2 }); - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); const to = new Date(from.getTime()); to.setDate(to.getDate() + params.scopeDays); diff --git a/modules/route/front/search-panel/index.spec.js b/modules/route/front/search-panel/index.spec.js index 16e1a5cfc..ae15e16e4 100644 --- a/modules/route/front/search-panel/index.spec.js +++ b/modules/route/front/search-panel/index.spec.js @@ -15,7 +15,7 @@ describe('Route Component vnRouteSearchPanel', () => { it('should clear the scope days when setting the from property', () => { controller.filter.scopeDays = 1; - controller.from = new Date(); + controller.from = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.from).toBeDefined(); @@ -26,7 +26,7 @@ describe('Route Component vnRouteSearchPanel', () => { it('should clear the scope days when setting the to property', () => { controller.filter.scopeDays = 1; - controller.to = new Date(); + controller.to = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.to).toBeDefined(); @@ -35,8 +35,8 @@ describe('Route Component vnRouteSearchPanel', () => { describe('scopeDays() setter', () => { it('should clear the date range when setting the scopeDays property', () => { - controller.filter.from = new Date(); - controller.filter.to = new Date(); + controller.filter.from = Date.vnNew(); + controller.filter.to = Date.vnNew(); controller.scopeDays = 1; diff --git a/modules/route/front/sms/index.js b/modules/route/front/sms/index.js index d8b1fc134..f466adea7 100644 --- a/modules/route/front/sms/index.js +++ b/modules/route/front/sms/index.js @@ -26,7 +26,7 @@ class Controller extends Component { throw new Error(`The message it's too long`); this.$http.post(`Routes/sendSms`, this.sms).then(res => { - 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/route/front/summary/index.html b/modules/route/front/summary/index.html index 86f558634..a64ad4ff7 100644 --- a/modules/route/front/summary/index.html +++ b/modules/route/front/summary/index.html @@ -10,26 +10,26 @@ - - - - - {{$ctrl.summary.route.worker.user.name}} - @@ -40,35 +40,35 @@ - - - -

- Ticket

-

Ticket @@ -77,45 +77,49 @@ Order - Ticket id - Alias + Street + City + PC + Client + Warehouse Packages - Warehouse - PC - Street + Packaging + Ticket {{ticket.priority | dashIfEmpty}} + {{ticket.street}} + {{ticket.city}} + {{ticket.postalCode}} + + + {{ticket.nickname}} + + + {{ticket.warehouseName}} + {{ticket.packages}} + {{ticket.volume}} + {{ticket.ipt}} - {{ticket.id}} - - {{ticket.nickname}} - - - {{ticket.packages}} - {{ticket.volume}} - {{ticket.warehouseName}} - {{ticket.postalCode}} - {{ticket.street}} - - - + + @@ -123,12 +127,12 @@ - - diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index dae894ac7..18d6fb160 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -6,9 +6,9 @@ data="$ctrl.tickets" auto-load="true"> - -
@@ -25,18 +25,18 @@ vn-tooltip="Open buscaman" icon="icon-buscaman"> - - - City PC Client + Warehouse Packages + Packaging Ticket @@ -100,8 +102,10 @@ {{::ticket.nickname}} + {{ticket.warehouseName}} {{::ticket.packages}} {{::ticket.volume | number:2}} + {{::ticket.ipt}}
- - @@ -160,7 +164,7 @@ - - - \ No newline at end of file + diff --git a/modules/shelving/front/routes.json b/modules/shelving/front/routes.json index 09a8e389b..4059e5095 100644 --- a/modules/shelving/front/routes.json +++ b/modules/shelving/front/routes.json @@ -1,12 +1,12 @@ { "module": "shelving", "name": "Shelvings", - "icon" : "contact_support", + "icon" : "icon-inventory", "dependencies": ["worker"], "validations" : true, "menus": { "main": [ - {"state": "shelving.index", "icon": "contact_support"} + {"state": "shelving.index", "icon": "icon-inventory"} ], "card": [ {"state": "shelving.card.basicData", "icon": "settings"}, @@ -20,7 +20,7 @@ "abstract": true, "component": "vn-shelving", "description": "Shelvings" - }, + }, { "url": "/index?q", "state": "shelving.index", @@ -32,13 +32,13 @@ "state": "shelving.create", "component": "vn-shelving-create", "description": "New shelving" - }, + }, { "url": "/:id", "state": "shelving.card", "abstract": true, "component": "vn-shelving-card" - }, + }, { "url": "/summary", "state": "shelving.card.summary", @@ -47,7 +47,7 @@ "params": { "shelving": "$ctrl.shelving" } - }, + }, { "url": "/basic-data", "state": "shelving.card.basicData", @@ -56,7 +56,7 @@ "params": { "shelving": "$ctrl.shelving" } - }, + }, { "url" : "/log", "state": "shelving.card.log", @@ -64,4 +64,4 @@ "description": "Log" } ] -} \ No newline at end of file +} diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index 44549c65c..4e509aafc 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -16,10 +16,6 @@ module.exports = Self => { message: 'The social name cannot be empty' }); - Self.validatesUniquenessOf('name', { - message: 'The supplier name must be unique' - }); - if (this.city) { Self.validatesPresenceOf('city', { message: 'City cannot be empty' @@ -117,6 +113,27 @@ module.exports = Self => { throw new UserError('You can not modify is pay method checked'); }); + Self.validateAsync('name', 'countryFk', hasSupplierSameName, { + message: 'A supplier with the same name already exists. Change the country.' + }); + + async function hasSupplierSameName(err, done) { + if (!this.name || !this.countryFk) done(); + const supplier = await Self.app.models.Supplier.findOne( + { + where: { + name: this.name, + countryFk: this.countryFk + }, + fields: ['id'] + }); + + if (supplier && supplier.id != this.id) + err(); + + done(); + } + Self.observe('before save', async function(ctx) { const changes = ctx.data || ctx.instance; const orgData = ctx.currentInstance; diff --git a/modules/supplier/front/agency-term/index/index.html b/modules/supplier/front/agency-term/index/index.html index 9d53226c5..44c6deba9 100644 --- a/modules/supplier/front/agency-term/index/index.html +++ b/modules/supplier/front/agency-term/index/index.html @@ -24,36 +24,42 @@ diff --git a/modules/supplier/front/consumption/index.js b/modules/supplier/front/consumption/index.js index 8de6a1e71..9af0d1747 100644 --- a/modules/supplier/front/consumption/index.js +++ b/modules/supplier/front/consumption/index.js @@ -11,11 +11,11 @@ class Controller extends Section { } setDefaultFilter() { - const minDate = new Date(); + const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); minDate.setMonth(minDate.getMonth() - 2); - const maxDate = new Date(); + const maxDate = Date.vnNew(); maxDate.setHours(23, 59, 59, 59); this.filterParams = { diff --git a/modules/supplier/front/consumption/index.spec.js b/modules/supplier/front/consumption/index.spec.js index ebf19ccec..0ac531a68 100644 --- a/modules/supplier/front/consumption/index.spec.js +++ b/modules/supplier/front/consumption/index.spec.js @@ -28,7 +28,7 @@ describe('Supplier', () => { it('should call the window.open function', () => { jest.spyOn(window, 'open').mockReturnThis(); - const now = new Date(); + const now = Date.vnNew(); controller.$.model.userParams = { from: now, to: now @@ -86,7 +86,7 @@ describe('Supplier', () => { {id: 1, email: 'batman@gothamcity.com'} ]); - const now = new Date(); + const now = Date.vnNew(); controller.$.model.userParams = { from: now, to: now diff --git a/modules/supplier/front/descriptor/index.js b/modules/supplier/front/descriptor/index.js index a26d9c510..9f23ce68c 100644 --- a/modules/supplier/front/descriptor/index.js +++ b/modules/supplier/front/descriptor/index.js @@ -13,7 +13,7 @@ class Controller extends Descriptor { get entryFilter() { if (!this.supplier) return null; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const from = new Date(date.getTime()); diff --git a/modules/ticket/back/methods/expedition/specs/moveExpeditions.spec.js b/modules/ticket/back/methods/expedition/specs/moveExpeditions.spec.js index 67919e76c..ac397d38e 100644 --- a/modules/ticket/back/methods/expedition/specs/moveExpeditions.spec.js +++ b/modules/ticket/back/methods/expedition/specs/moveExpeditions.spec.js @@ -14,7 +14,7 @@ describe('ticket moveExpeditions()', () => { const options = {transaction: tx}; myCtx.args = { clientId: 1101, - landed: new Date(), + landed: Date.vnNew(), warehouseId: 1, addressId: 121, agencyModeId: 1, diff --git a/modules/ticket/back/methods/sale-tracking/listSaleTracking.js b/modules/ticket/back/methods/sale-tracking/listSaleTracking.js index c0d63ef62..98743d8cc 100644 --- a/modules/ticket/back/methods/sale-tracking/listSaleTracking.js +++ b/modules/ticket/back/methods/sale-tracking/listSaleTracking.js @@ -36,7 +36,7 @@ module.exports = Self => { st.originalQuantity, st.created, st.workerFk, - u.nickname userNickname, + u.name, ste.name AS state FROM saleTracking st JOIN sale s ON s.id = st.saleFk @@ -48,24 +48,6 @@ module.exports = Self => { const trackings = await Self.rawStmt(stmt, myOptions); - const salesFilter = { - include: [ - { - relation: 'item' - } - ], - where: {ticketFk: filter.where.ticketFk} - }; - - const sales = await Self.app.models.Sale.find(salesFilter, myOptions); - - for (const tracking of trackings) { - for (const sale of sales) { - if (tracking.itemFk == sale.itemFk) - tracking.item = sale.item(); - } - } - return trackings; }; }; diff --git a/modules/ticket/back/methods/sale/canEdit.js b/modules/ticket/back/methods/sale/canEdit.js index f44bd6743..3091ebca7 100644 --- a/modules/ticket/back/methods/sale/canEdit.js +++ b/modules/ticket/back/methods/sale/canEdit.js @@ -56,6 +56,13 @@ module.exports = Self => { const shouldEditCloned = canEditCloned || !hasSaleCloned; const shouldEditFloramondo = canEditFloramondo || !hasSaleFloramondo; - return shouldEditTracked && shouldEditCloned && shouldEditFloramondo; + if (!shouldEditTracked) + throw new UserError('It is not possible to modify tracked sales'); + if (!shouldEditCloned) + throw new UserError('It is not possible to modify cloned sales'); + if (!shouldEditFloramondo) + throw new UserError('It is not possible to modify sales that their articles are from Floramondo'); + + return true; }; }; diff --git a/modules/ticket/back/methods/sale/deleteSales.js b/modules/ticket/back/methods/sale/deleteSales.js index c045b9197..5d1463a66 100644 --- a/modules/ticket/back/methods/sale/deleteSales.js +++ b/modules/ticket/back/methods/sale/deleteSales.js @@ -43,9 +43,7 @@ module.exports = Self => { try { const saleIds = sales.map(sale => sale.id); - const canEditSales = await models.Sale.canEdit(ctx, saleIds, myOptions); - if (!canEditSales) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, saleIds, myOptions); const ticket = await models.Ticket.findById(ticketId, { include: { diff --git a/modules/ticket/back/methods/sale/getClaimableFromTicket.js b/modules/ticket/back/methods/sale/getClaimableFromTicket.js index ecbc52b94..c51781f59 100644 --- a/modules/ticket/back/methods/sale/getClaimableFromTicket.js +++ b/modules/ticket/back/methods/sale/getClaimableFromTicket.js @@ -24,24 +24,24 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const query = ` - SELECT - s.id AS saleFk, - t.id AS ticketFk, + SELECT + s.id AS saleFk, + t.id AS ticketFk, t.landed, - s.concept, - s.itemFk, - s.quantity, - s.price, - s.discount, + s.concept, + s.itemFk, + s.quantity, + s.price, + s.discount, t.nickname - FROM vn.ticket t + FROM vn.ticket t INNER JOIN vn.sale s ON s.ticketFk = t.id LEFT JOIN vn.claimBeginning cb ON cb.saleFk = s.id - WHERE (t.landed) >= TIMESTAMPADD(DAY, -7, ?) + WHERE (t.landed) >= TIMESTAMPADD(DAY, -7, ?) AND t.id = ? AND cb.id IS NULL ORDER BY t.landed DESC, t.id DESC`; diff --git a/modules/ticket/back/methods/sale/recalculatePrice.js b/modules/ticket/back/methods/sale/recalculatePrice.js index 38c68d7f6..2c8e6768b 100644 --- a/modules/ticket/back/methods/sale/recalculatePrice.js +++ b/modules/ticket/back/methods/sale/recalculatePrice.js @@ -37,9 +37,7 @@ module.exports = Self => { try { const salesIds = sales.map(sale => sale.id); - const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions); - if (!canEditSale) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, salesIds, myOptions); const query = ` DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales; diff --git a/modules/ticket/back/methods/sale/refund.js b/modules/ticket/back/methods/sale/refund.js index c0c431636..febef9730 100644 --- a/modules/ticket/back/methods/sale/refund.js +++ b/modules/ticket/back/methods/sale/refund.js @@ -64,7 +64,7 @@ module.exports = Self => { const refundTickets = []; - const now = new Date(); + const now = Date.vnNew(); const mappedTickets = new Map(); for (let ticketId of ticketsIds) { diff --git a/modules/ticket/back/methods/sale/reserve.js b/modules/ticket/back/methods/sale/reserve.js index 648e6de23..2dc368af6 100644 --- a/modules/ticket/back/methods/sale/reserve.js +++ b/modules/ticket/back/methods/sale/reserve.js @@ -51,9 +51,7 @@ module.exports = Self => { try { const salesIds = sales.map(sale => sale.id); - const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions); - if (!canEditSale) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, salesIds, myOptions); let changesMade = ''; const promises = []; diff --git a/modules/ticket/back/methods/sale/salePreparingList.js b/modules/ticket/back/methods/sale/salePreparingList.js new file mode 100644 index 000000000..e6e7d5164 --- /dev/null +++ b/modules/ticket/back/methods/sale/salePreparingList.js @@ -0,0 +1,33 @@ +module.exports = Self => { + Self.remoteMethodCtx('salePreparingList', { + description: 'Returns a list with the lines of a ticket and its different states of preparation', + accessType: 'READ', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/:id/salePreparingList`, + verb: 'GET' + } + }); + + Self.salePreparingList = async(ctx, id, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + query = `CALL vn.salePreparingList(?)`; + const [sales] = await Self.rawSql(query, [id], myOptions); + + return sales; + }; +}; diff --git a/modules/ticket/back/methods/sale/specs/canEdit.spec.js b/modules/ticket/back/methods/sale/specs/canEdit.spec.js index 2aa873df5..58d8f0635 100644 --- a/modules/ticket/back/methods/sale/specs/canEdit.spec.js +++ b/modules/ticket/back/methods/sale/specs/canEdit.spec.js @@ -50,7 +50,7 @@ describe('sale canEdit()', () => { it('should return false if any of the sales has a saleTracking record', async() => { const tx = await models.Sale.beginTransaction({}); - + let error; try { const options = {transaction: tx}; @@ -59,15 +59,15 @@ describe('sale canEdit()', () => { const sales = [31]; - const result = await models.Sale.canEdit(ctx, sales, options); - - expect(result).toEqual(false); - + await models.Sale.canEdit(ctx, sales, options); await tx.rollback(); } catch (e) { await tx.rollback(); - throw e; + error = e; } + + expect(error).toEqual( + new Error('It is not possible to modify tracked sales')); }); }); @@ -75,22 +75,22 @@ describe('sale canEdit()', () => { const saleCloned = [29]; it('should return false if any of the sales is cloned', async() => { const tx = await models.Sale.beginTransaction({}); - + let error; try { const options = {transaction: tx}; const buyerId = 35; const ctx = {req: {accessToken: {userId: buyerId}}}; - const result = await models.Sale.canEdit(ctx, saleCloned, options); - - expect(result).toEqual(false); - + await models.Sale.canEdit(ctx, saleCloned, options); await tx.rollback(); } catch (e) { await tx.rollback(); - throw e; + error = e; } + + expect(error).toEqual( + new Error('It is not possible to modify cloned sales')); }); it('should return true if any of the sales is cloned and has the correct role', async() => { @@ -130,7 +130,7 @@ describe('sale canEdit()', () => { it('should return false if any of the sales isFloramondo', async() => { const tx = await models.Sale.beginTransaction({}); const sales = [26]; - + let error; try { const options = {transaction: tx}; @@ -140,15 +140,15 @@ describe('sale canEdit()', () => { const saleToEdit = await models.Sale.findById(sales[0], null, options); await saleToEdit.updateAttribute('itemFk', 9, options); - const result = await models.Sale.canEdit(ctx, sales, options); - - expect(result).toEqual(false); - + await models.Sale.canEdit(ctx, sales, options); await tx.rollback(); } catch (e) { await tx.rollback(); - throw e; + error = e; } + + expect(error).toEqual( + new Error('It is not possible to modify sales that their articles are from Floramondo')); }); it('should return true if any of the sales is of isFloramondo and has the correct role', async() => { diff --git a/modules/ticket/back/methods/sale/updateConcept.js b/modules/ticket/back/methods/sale/updateConcept.js index 0730f85e2..dcd25dcbb 100644 --- a/modules/ticket/back/methods/sale/updateConcept.js +++ b/modules/ticket/back/methods/sale/updateConcept.js @@ -40,10 +40,7 @@ module.exports = Self => { try { const currentLine = await models.Sale.findById(id, null, myOptions); - const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); - - if (!canEditSale) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, [id], myOptions); const line = await currentLine.updateAttributes({concept: newConcept}, myOptions); diff --git a/modules/ticket/back/methods/sale/updatePrice.js b/modules/ticket/back/methods/sale/updatePrice.js index 8f27e1af5..505de5180 100644 --- a/modules/ticket/back/methods/sale/updatePrice.js +++ b/modules/ticket/back/methods/sale/updatePrice.js @@ -66,9 +66,7 @@ module.exports = Self => { const sale = await models.Sale.findById(id, filter, myOptions); - const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); - if (!canEditSale) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, [id], myOptions); const oldPrice = sale.price; const userId = ctx.req.accessToken.userId; diff --git a/modules/ticket/back/methods/sale/updateQuantity.js b/modules/ticket/back/methods/sale/updateQuantity.js index 8cf0720ce..d2927c65c 100644 --- a/modules/ticket/back/methods/sale/updateQuantity.js +++ b/modules/ticket/back/methods/sale/updateQuantity.js @@ -41,9 +41,7 @@ module.exports = Self => { } try { - const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); - if (!canEditSale) - throw new UserError(`Sale(s) blocked, please contact production`); + await models.Sale.canEdit(ctx, [id], myOptions); const filter = { include: { 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/state/editableStates.js b/modules/ticket/back/methods/state/editableStates.js index 2c90ac43b..115876f26 100644 --- a/modules/ticket/back/methods/state/editableStates.js +++ b/modules/ticket/back/methods/state/editableStates.js @@ -24,7 +24,7 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - let statesList = await models.State.find({where: filter.where}, myOptions); + let statesList = await models.State.find(filter, myOptions); const isProduction = await models.Account.hasRole(userId, 'production', myOptions); const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson', myOptions); const isAdministrative = await models.Account.hasRole(userId, 'administrative', myOptions); diff --git a/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js b/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js index 746e1b7fc..175bc4e4b 100644 --- a/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js +++ b/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js @@ -9,7 +9,7 @@ describe('ticket changeState()', () => { accessToken: {userId: 9}, }; const ctx = {req: activeCtx}; - const now = new Date(); + const now = Date.vnNew(); const sampleTicket = { shipped: now, landed: now, diff --git a/modules/ticket/back/methods/ticket/canBeInvoiced.js b/modules/ticket/back/methods/ticket/canBeInvoiced.js index a009d63cf..6b8f9e71a 100644 --- a/modules/ticket/back/methods/ticket/canBeInvoiced.js +++ b/modules/ticket/back/methods/ticket/canBeInvoiced.js @@ -43,7 +43,7 @@ module.exports = function(Self) { ticketBases => ticketBases.hasSomeNegativeBase ); - const today = new Date(); + const today = Date.vnNew(); const invalidTickets = tickets.some(ticket => { const shipped = new Date(ticket.shipped); diff --git a/modules/ticket/back/methods/ticket/closeAll.js b/modules/ticket/back/methods/ticket/closeAll.js index 327278c2b..3726d85b7 100644 --- a/modules/ticket/back/methods/ticket/closeAll.js +++ b/modules/ticket/back/methods/ticket/closeAll.js @@ -17,14 +17,14 @@ module.exports = Self => { }); Self.closeAll = async() => { - const toDate = new Date(); + const toDate = Date.vnNew(); toDate.setHours(0, 0, 0, 0); toDate.setDate(toDate.getDate() - 1); - const todayMinDate = new Date(); + const todayMinDate = Date.vnNew(); todayMinDate.setHours(0, 0, 0, 0); - const todayMaxDate = new Date(); + const todayMaxDate = Date.vnNew(); todayMaxDate.setHours(23, 59, 59, 59); // Prevent closure for current day @@ -32,7 +32,7 @@ module.exports = Self => { throw new UserError('You cannot close tickets for today'); const tickets = await Self.rawSql(` - SELECT + SELECT t.id, t.clientFk, t.companyFk, @@ -53,7 +53,7 @@ module.exports = Self => { JOIN country co ON co.id = p.countryFk LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk WHERE al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered') - AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) + AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?) AND t.refFk IS NULL GROUP BY t.id diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index a2add2e82..262b3fd74 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -137,7 +137,7 @@ module.exports = Self => { Self.filter = async(ctx, filter, options) => { const userId = ctx.req.accessToken.userId; const conn = Self.dataSource.connector; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const models = Self.app.models; const args = ctx.args; @@ -295,10 +295,10 @@ module.exports = Self => { stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); stmt = new ParameterizedSQL(` - CREATE TEMPORARY TABLE tmp.sale_getProblems + CREATE TEMPORARY TABLE tmp.sale_getProblems (INDEX (ticketFk)) ENGINE = MEMORY - SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped + SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped FROM tmp.filter f LEFT JOIN alertLevel al ON al.id = f.alertLevel WHERE (al.code = 'FREE' OR f.alertLevel IS NULL) @@ -350,7 +350,7 @@ module.exports = Self => { const ticketsIndex = stmts.push(stmt) - 1; stmts.push( - `DROP TEMPORARY TABLE + `DROP TEMPORARY TABLE tmp.filter, tmp.ticket_problems`); diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 19571bb51..1e1646cba 100644 --- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js +++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js @@ -50,14 +50,14 @@ module.exports = Self => { required: false }, { - arg: 'state', - type: 'string', + arg: 'isNotValidated', + type: 'boolean', description: 'Origin state', required: false }, { - arg: 'futureState', - type: 'string', + arg: 'futureIsNotValidated', + type: 'boolean', description: 'Destination state', required: false }, @@ -92,13 +92,23 @@ module.exports = Self => { 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}; - case 'state': - return {'f.stateCode': {like: `%${value}%`}}; - case 'futureState': - return {'f.futureStateCode': {like: `%${value}%`}}; + return {or: + [ + {'f.futureIpt': {like: `%${value}%`}}, + {'f.futureIpt': null} + ] + }; + case 'isNotValidated': + return {'f.isNotValidated': value}; + case 'futureIsNotValidated': + return {'f.futureIsNotValidated': value}; } }); 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/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index 4e9c22a24..9739f5985 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -26,7 +26,7 @@ module.exports = function(Self) { Self.makeInvoice = async(ctx, ticketsIds, options) => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; - const date = new Date(); + const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const myOptions = {}; diff --git a/modules/ticket/back/methods/ticket/restore.js b/modules/ticket/back/methods/ticket/restore.js index c9bb126fd..722c3294e 100644 --- a/modules/ticket/back/methods/ticket/restore.js +++ b/modules/ticket/back/methods/ticket/restore.js @@ -38,7 +38,7 @@ module.exports = Self => { }] }, myOptions); - const now = new Date(); + const now = Date.vnNew(); const maxDate = new Date(ticket.updated); maxDate.setHours(maxDate.getHours() + 1); @@ -56,7 +56,7 @@ module.exports = Self => { await models.Chat.sendCheckingPresence(ctx, salesPersonId, message); } - const fullYear = new Date().getFullYear(); + const fullYear = Date.vnNew().getFullYear(); const newShipped = ticket.shipped; const newLanded = ticket.landed; newShipped.setFullYear(fullYear); diff --git a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js index 8b7e1685d..806f80227 100644 --- a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js +++ b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js @@ -61,7 +61,7 @@ describe('ticket canBeInvoiced()', () => { const ticket = await models.Ticket.findById(ticketId, null, options); - const shipped = new Date(); + const shipped = Date.vnNew(); shipped.setDate(shipped.getDate() + 1); await ticket.updateAttribute('shipped', shipped, options); diff --git a/modules/ticket/back/methods/ticket/specs/componentUpdate.spec.js b/modules/ticket/back/methods/ticket/specs/componentUpdate.spec.js index 3a9c2db50..d65c87654 100644 --- a/modules/ticket/back/methods/ticket/specs/componentUpdate.spec.js +++ b/modules/ticket/back/methods/ticket/specs/componentUpdate.spec.js @@ -4,8 +4,8 @@ const LoopBackContext = require('loopback-context'); describe('ticket componentUpdate()', () => { const userID = 1101; const ticketID = 11; - const today = new Date(); - const tomorrow = new Date(); + const today = Date.vnNew(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 1); @@ -19,11 +19,11 @@ describe('ticket componentUpdate()', () => { beforeAll(async() => { const deliveryComponenet = await models.Component.findOne({where: {code: 'delivery'}}); deliveryComponentId = deliveryComponenet.id; - componentOfSaleSeven = `SELECT value - FROM vn.saleComponent + componentOfSaleSeven = `SELECT value + FROM vn.saleComponent WHERE saleFk = 7 AND componentFk = ${deliveryComponentId}`; - componentOfSaleEight = `SELECT value - FROM vn.saleComponent + componentOfSaleEight = `SELECT value + FROM vn.saleComponent WHERE saleFk = 8 AND componentFk = ${deliveryComponentId}`; [componentValue] = await models.SaleComponent.rawSql(componentOfSaleSeven); firstvalueBeforeChange = componentValue.value; diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index 688b0de61..6cc1a3ad2 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -26,9 +26,9 @@ describe('ticket filter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 9}}, args: { @@ -54,10 +54,10 @@ describe('ticket filter()', () => { try { const options = {transaction: tx}; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); yesterday.setHours(0, 0, 0, 0); - const today = new Date(); + const today = Date.vnNew(); today.setHours(23, 59, 59, 59); const ctx = {req: {accessToken: {userId: 9}}, args: { diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js index aab053127..11571bede 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -1,9 +1,9 @@ const models = require('vn-loopback/server/server').models; describe('TicketFuture getTicketsAdvance()', () => { - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); - let tomorrow = new Date(); + let tomorrow = Date.vnNew(); tomorrow.setDate(today.getDate() + 1); it('should return the tickets passing the required data', async() => { @@ -29,7 +29,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the origin grouped state', async() => { + it('should return the tickets matching the origin pending state', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -39,7 +39,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - state: 'OK' + futureIsNotValidated: true }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -54,7 +54,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the destination grouped state', async() => { + it('should return the tickets matching the destination pending state', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -64,13 +64,13 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - futureState: 'FREE' + isNotValidated: true }; const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsAdvance(ctx, options); - expect(result.length).toBeGreaterThan(0); + expect(result.length).toEqual(0); await tx.rollback(); } catch (e) { @@ -89,7 +89,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - ipt: 'Vertical' + ipt: 'V' }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -114,7 +114,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - tfIpt: 'Vertical' + tfIpt: 'V' }; const ctx = {req: {accessToken: {userId: 9}}, args}; diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js index c05ba764d..44896493f 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('ticket getTicketsFuture()', () => { - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); it('should return the tickets passing the required data', async() => { @@ -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/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js index 275484f67..6b533e47c 100644 --- a/modules/ticket/back/methods/ticket/specs/merge.spec.js +++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js @@ -5,8 +5,8 @@ describe('ticket merge()', () => { const tickets = [{ originId: 13, destinationId: 12, - originShipped: new Date(), - destinationShipped: new Date(), + originShipped: Date.vnNew(), + destinationShipped: Date.vnNew(), workerFk: 1 }]; diff --git a/modules/ticket/back/methods/ticket/specs/new.spec.js b/modules/ticket/back/methods/ticket/specs/new.spec.js index fce7cdceb..0a2f93bc4 100644 --- a/modules/ticket/back/methods/ticket/specs/new.spec.js +++ b/modules/ticket/back/methods/ticket/specs/new.spec.js @@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models; let UserError = require('vn-loopback/util/user-error'); describe('ticket new()', () => { - const today = new Date(); + const today = Date.vnNew(); const ctx = {req: {accessToken: {userId: 1}}}; it('should throw an error if the client isnt frozen and isnt active', async() => { diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js index 5470382f9..1db1b6eaa 100644 --- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js +++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js @@ -8,7 +8,7 @@ describe('sale priceDifference()', () => { try { const options = {transaction: tx}; - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 1); const ctx = {req: {accessToken: {userId: 1106}}}; @@ -45,8 +45,8 @@ describe('sale priceDifference()', () => { const ctx = {req: {accessToken: {userId: 1106}}}; ctx.args = { id: 1, - landed: new Date(), - shipped: new Date(), + landed: Date.vnNew(), + shipped: Date.vnNew(), addressId: 121, zoneId: 3, warehouseId: 1 @@ -68,7 +68,7 @@ describe('sale priceDifference()', () => { try { const options = {transaction: tx}; - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 1); const ctx = {req: {accessToken: {userId: 1106}}}; diff --git a/modules/ticket/back/methods/ticket/specs/restore.spec.js b/modules/ticket/back/methods/ticket/specs/restore.spec.js index bd976d124..3b35ae2b4 100644 --- a/modules/ticket/back/methods/ticket/specs/restore.spec.js +++ b/modules/ticket/back/methods/ticket/specs/restore.spec.js @@ -24,8 +24,8 @@ describe('ticket restore()', () => { let error; const tx = await app.models.Ticket.beginTransaction({}); - const now = new Date(); - now.setHours(now.getHours() - 1); + const now = Date.vnNew(); + now.setHours(now.getHours() - 1.1); try { const options = {transaction: tx}; @@ -46,7 +46,7 @@ describe('ticket restore()', () => { it('should restore the ticket making its state no longer deleted', async() => { const tx = await app.models.Ticket.beginTransaction({}); - const now = new Date(); + const now = Date.vnNew(); try { const options = {transaction: tx}; 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/back/models/sale.js b/modules/ticket/back/models/sale.js index ae247fc24..bab201fdd 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -1,5 +1,6 @@ module.exports = Self => { require('../methods/sale/getClaimableFromTicket')(Self); + require('../methods/sale/salePreparingList')(Self); require('../methods/sale/reserve')(Self); require('../methods/sale/deleteSales')(Self); require('../methods/sale/updatePrice')(Self); diff --git a/modules/ticket/front/advance-search-panel/index.html b/modules/ticket/front/advance-search-panel/index.html index e8d5dc60d..dfe1f6b08 100644 --- a/modules/ticket/front/advance-search-panel/index.html +++ b/modules/ticket/front/advance-search-panel/index.html @@ -39,26 +39,18 @@ - - - {{name}} - - - - - {{name}} - - + + + + { - for (let state of res.data) { - groupedStates.push({ - id: state.id, - code: state.code, - name: this.$t(state.code) - }); - } - this.groupedStates = groupedStates; - }); - } - getItemPackingTypes() { let itemPackingTypes = []; - this.$http.get('ItemPackingTypes').then(res => { + 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-search-panel/locale/es.yml b/modules/ticket/front/advance-search-panel/locale/es.yml index 3dce7dae5..4ea2fc737 100644 --- a/modules/ticket/front/advance-search-panel/locale/es.yml +++ b/modules/ticket/front/advance-search-panel/locale/es.yml @@ -1 +1,3 @@ Advance tickets: Adelantar tickets +Pending Origin: Pendiente origen +Pending Destination: Pendiente destino diff --git a/modules/ticket/front/advance/index.html b/modules/ticket/front/advance/index.html index f63c0fbf7..3dd52b909 100644 --- a/modules/ticket/front/advance/index.html +++ b/modules/ticket/front/advance/index.html @@ -32,8 +32,8 @@ - Origin - Destination + Origin + Destination @@ -43,19 +43,30 @@ check-field="checked"> + + ID Date - + IPT State - + + Liters + + + Stock + + + Lines + + Import @@ -64,7 +75,7 @@ Date - + IPT @@ -73,13 +84,10 @@ Liters - - Stock - Lines - + Import @@ -92,6 +100,13 @@ vn-click-stop> + + + + + {{::ticket.futureLiters | dashIfEmpty}} + {{::ticket.hasStock | dashIfEmpty}} + {{::ticket.futureLines | dashIfEmpty}} {{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} @@ -136,7 +154,6 @@ {{::ticket.liters | dashIfEmpty}} - {{::ticket.hasStock | dashIfEmpty}} {{::ticket.lines | dashIfEmpty}} diff --git a/modules/ticket/front/advance/index.js b/modules/ticket/front/advance/index.js index 1404f9472..779ada81a 100644 --- a/modules/ticket/front/advance/index.js +++ b/modules/ticket/front/advance/index.js @@ -1,5 +1,6 @@ import ngModule from '../module'; import Section from 'salix/components/section'; +import './style.scss'; export default class Controller extends Section { constructor($element, $) { @@ -39,6 +40,7 @@ export default class Controller extends Section { field: 'ipt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } @@ -47,6 +49,7 @@ export default class Controller extends Section { field: 'futureIpt', autocomplete: { url: 'ItemPackingTypes', + where: `{isActive: true}`, showField: 'description', valueField: 'code' } @@ -60,7 +63,7 @@ export default class Controller extends Section { } setDefaultFilter() { - let today = new Date(); + let today = Date.vnNew(); const tomorrow = new Date(today); tomorrow.setDate(tomorrow.getDate() + 1); this.filterParams = { @@ -72,7 +75,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); let timeTicket = new Date(date); timeTicket.setHours(0, 0, 0, 0); @@ -126,6 +129,11 @@ export default class Controller extends Section { }); } + agencies(futureAgency, agency) { + return this.$t(`Origin agency`, {agency: futureAgency}) + + '
' + this.$t(`Destination agency`, {agency: agency}); + } + moveTicketsAdvance() { let ticketsToMove = []; this.checked.forEach(ticket => { @@ -155,6 +163,10 @@ export default class Controller extends Section { return {'liters': value}; case 'lines': return {'lines': value}; + case 'futureLiters': + return {'futureLiters': value}; + case 'futureLines': + return {'futureLines': value}; case 'ipt': return {'ipt': value}; case 'futureIpt': diff --git a/modules/ticket/front/advance/index.spec.js b/modules/ticket/front/advance/index.spec.js index c5a04daee..6874f914b 100644 --- a/modules/ticket/front/advance/index.spec.js +++ b/modules/ticket/front/advance/index.spec.js @@ -26,14 +26,14 @@ describe('Component vnTicketAdvance', () => { describe('compareDate()', () => { it('should return warning when the date is the present', () => { - let today = new Date(); + let today = Date.vnNew(); let result = controller.compareDate(today); expect(result).toEqual('warning'); }); it('should return sucess when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.compareDate(futureDate); @@ -41,7 +41,7 @@ describe('Component vnTicketAdvance', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.compareDate(pastDate); @@ -81,7 +81,7 @@ describe('Component vnTicketAdvance', () => { describe('dateRange()', () => { it('should return two dates with the hours at the start and end of the given date', () => { - const now = new Date(); + const now = Date.vnNew(); const today = now.getDate(); diff --git a/modules/ticket/front/advance/locale/es.yml b/modules/ticket/front/advance/locale/es.yml index b444fbdd3..da22cd433 100644 --- a/modules/ticket/front/advance/locale/es.yml +++ b/modules/ticket/front/advance/locale/es.yml @@ -4,3 +4,6 @@ Advance confirmation: ¿Desea adelantar {{checked}} tickets? Success: Tickets movidos correctamente Lines: Líneas Liters: Litros +Item Packing Type: Encajado +Origin agency: "Agencia origen: {{agency}}" +Destination agency: "Agencia destino: {{agency}}" diff --git a/modules/ticket/front/advance/style.scss b/modules/ticket/front/advance/style.scss new file mode 100644 index 000000000..8fa9de438 --- /dev/null +++ b/modules/ticket/front/advance/style.scss @@ -0,0 +1,7 @@ +@import "variables"; + +vn-ticket-advance{ + vn-icon { + color: #f7931e + } +} diff --git a/modules/ticket/front/basic-data/step-one/index.js b/modules/ticket/front/basic-data/step-one/index.js index f532265e2..99782de44 100644 --- a/modules/ticket/front/basic-data/step-one/index.js +++ b/modules/ticket/front/basic-data/step-one/index.js @@ -75,8 +75,10 @@ class Controller extends Component { } set shipped(value) { + if (new Date(this.ticket.shipped).toDateString() != value.toDateString()) + value.setHours(0, 0, 0, 0); + this.ticket.shipped = value; - this.ticket.shipped.setHours(0, 0, 0, 0); this.getLanded({ shipped: value, addressFk: this.ticket.addressFk, diff --git a/modules/ticket/front/basic-data/step-one/index.spec.js b/modules/ticket/front/basic-data/step-one/index.spec.js index 2b14c18cc..30946dab0 100644 --- a/modules/ticket/front/basic-data/step-one/index.spec.js +++ b/modules/ticket/front/basic-data/step-one/index.spec.js @@ -67,7 +67,7 @@ describe('Ticket', () => { jest.spyOn(controller, 'getShipped'); controller.ticket.addressFk = 99; controller.addressId = 100; - const landed = new Date(); + const landed = Date.vnNew(); const expectedResult = { landed: landed, addressFk: 100, @@ -101,7 +101,7 @@ describe('Ticket', () => { describe('shipped() getter', () => { it('should return the shipped property', () => { - const shipped = new Date(); + const shipped = Date.vnNew(); controller.ticket.shipped = shipped; expect(controller.shipped).toEqual(shipped); @@ -111,7 +111,7 @@ describe('Ticket', () => { describe('shipped() setter', () => { it('should set shipped property and call getLanded() method ', () => { jest.spyOn(controller, 'getLanded'); - const shipped = new Date(); + const shipped = Date.vnNew(); const expectedResult = { shipped: shipped, addressFk: 121, @@ -126,7 +126,7 @@ describe('Ticket', () => { describe('landed() getter', () => { it('should return the landed property', () => { - const landed = new Date(); + const landed = Date.vnNew(); controller.ticket.landed = landed; expect(controller.landed).toEqual(landed); @@ -136,7 +136,7 @@ describe('Ticket', () => { describe('landed() setter', () => { it('should set shipped property and call getShipped() method ', () => { jest.spyOn(controller, 'getShipped'); - const landed = new Date(); + const landed = Date.vnNew(); const expectedResult = { landed: landed, addressFk: 121, @@ -161,7 +161,7 @@ describe('Ticket', () => { it('should set agencyModeId property and call getLanded() method', () => { jest.spyOn(controller, 'getLanded'); controller.$.agencyMode = {selection: {warehouseFk: 1}}; - const shipped = new Date(); + const shipped = Date.vnNew(); const agencyModeId = 8; const expectedResult = { shipped: shipped, @@ -177,7 +177,7 @@ describe('Ticket', () => { it('should do nothing if attempting to set the same agencyMode id', () => { jest.spyOn(controller, 'getShipped'); - const landed = new Date(); + const landed = Date.vnNew(); const agencyModeId = 7; const expectedResult = { landed: landed, @@ -278,8 +278,8 @@ describe('Ticket', () => { agencyModeFk: 1, companyFk: 442, warehouseFk: 1, - shipped: new Date(), - landed: new Date() + shipped: Date.vnNew(), + landed: Date.vnNew() }; expect(controller.isFormInvalid()).toBeFalsy(); @@ -288,7 +288,7 @@ describe('Ticket', () => { describe('onStepChange()', () => { it('should call onStepChange method and return a NO_AGENCY_AVAILABLE signal error', async() => { - let landed = new Date(); + let landed = Date.vnNew(); landed.setHours(0, 0, 0, 0); controller._ticket = { @@ -299,7 +299,7 @@ describe('Ticket', () => { agencyModeFk: 1, companyFk: 442, warehouseFk: 1, - shipped: new Date(), + shipped: Date.vnNew(), landed: landed }; @@ -314,8 +314,8 @@ describe('Ticket', () => { describe('getLanded()', () => { it('should return an available landed date', async() => { - const shipped = new Date(); - const expectedResult = {landed: new Date()}; + const shipped = Date.vnNew(); + const expectedResult = {landed: Date.vnNew()}; const params = { shipped: shipped, addressFk: 121, @@ -336,8 +336,8 @@ describe('Ticket', () => { describe('getShipped()', () => { it('should return an available shipped date', async() => { - const landed = new Date(); - const expectedResult = {shipped: new Date()}; + const landed = Date.vnNew(); + const expectedResult = {shipped: Date.vnNew()}; const params = { landed: landed, addressFk: 121, @@ -358,7 +358,7 @@ describe('Ticket', () => { describe('zoneWhere() getter', () => { it('should return an object containing filter properties', async() => { - const shipped = new Date(); + const shipped = Date.vnNew(); controller.ticket.shipped = shipped; const expectedResult = { 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..ff029db78 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 }); @@ -184,7 +177,7 @@ class Controller extends Section { get canRestoreTicket() { const isDeleted = this.ticket.isDeleted; - const now = new Date(); + const now = Date.vnNew(); const maxDate = new Date(this.ticket.updated); maxDate.setHours(maxDate.getHours() + 1); @@ -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..babc22038 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -43,7 +43,7 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { describe('canRestoreTicket() getter', () => { it('should return true for a ticket deleted within the last hour', () => { controller.ticket.isDeleted = true; - controller.ticket.updated = new Date(); + controller.ticket.updated = Date.vnNew(); const result = controller.canRestoreTicket; @@ -51,7 +51,7 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { }); it('should return false for a ticket deleted more than one hour ago', () => { - const pastHour = new Date(); + const pastHour = Date.vnNew(); pastHour.setHours(pastHour.getHours() - 2); controller.ticket.isDeleted = true; @@ -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/expedition/index.js b/modules/ticket/front/expedition/index.js index 7ffe2fe5e..2d4432fe8 100644 --- a/modules/ticket/front/expedition/index.js +++ b/modules/ticket/front/expedition/index.js @@ -4,7 +4,7 @@ import Section from 'salix/components/section'; class Controller extends Section { constructor($element, $scope) { super($element, $scope); - this.landed = new Date(); + this.landed = Date.vnNew(); this.newRoute = null; } diff --git a/modules/ticket/front/expedition/index.spec.js b/modules/ticket/front/expedition/index.spec.js index 5a538b1c8..71e32151c 100644 --- a/modules/ticket/front/expedition/index.spec.js +++ b/modules/ticket/front/expedition/index.spec.js @@ -76,7 +76,7 @@ describe('Ticket', () => { it('should make a query and then call to the $state go() method', () => { jest.spyOn(controller.$state, 'go').mockReturnThis(); - const landed = new Date(); + const landed = Date.vnNew(); const ticket = { clientFk: 1101, landed: landed, 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..81ef08825 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' } @@ -55,7 +57,7 @@ export default class Controller extends Section { } setDefaultFilter() { - const today = new Date(); + const today = Date.vnNew(); this.filterParams = { originDated: today, @@ -66,7 +68,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); let timeTicket = new Date(date); timeTicket.setHours(0, 0, 0, 0); diff --git a/modules/ticket/front/future/index.spec.js b/modules/ticket/front/future/index.spec.js index c609a4891..188421298 100644 --- a/modules/ticket/front/future/index.spec.js +++ b/modules/ticket/front/future/index.spec.js @@ -2,7 +2,7 @@ import './index.js'; import crudModel from 'core/mocks/crud-model'; describe('Component vnTicketFuture', () => { - const today = new Date(); + const today = Date.vnNew(); let controller; let $httpBackend; @@ -32,7 +32,7 @@ describe('Component vnTicketFuture', () => { }); it('should return sucess when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.compareDate(futureDate); @@ -40,7 +40,7 @@ describe('Component vnTicketFuture', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.compareDate(pastDate); diff --git a/modules/ticket/front/index/index.js b/modules/ticket/front/index/index.js index 3039a2a03..42332ccc8 100644 --- a/modules/ticket/front/index/index.js +++ b/modules/ticket/front/index/index.js @@ -90,7 +90,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); let timeTicket = new Date(date); timeTicket.setHours(0, 0, 0, 0); diff --git a/modules/ticket/front/index/index.spec.js b/modules/ticket/front/index/index.spec.js index 03071654e..5046387b0 100644 --- a/modules/ticket/front/index/index.spec.js +++ b/modules/ticket/front/index/index.spec.js @@ -31,14 +31,14 @@ describe('Component vnTicketIndex', () => { describe('compareDate()', () => { it('should return warning when the date is the present', () => { - let today = new Date(); + let today = Date.vnNew(); let result = controller.compareDate(today); expect(result).toEqual('warning'); }); it('should return sucess when the date is in the future', () => { - let futureDate = new Date(); + let futureDate = Date.vnNew(); futureDate = futureDate.setDate(futureDate.getDate() + 10); let result = controller.compareDate(futureDate); @@ -46,7 +46,7 @@ describe('Component vnTicketIndex', () => { }); it('should return undefined when the date is in the past', () => { - let pastDate = new Date(); + let pastDate = Date.vnNew(); pastDate = pastDate.setDate(pastDate.getDate() - 10); let result = controller.compareDate(pastDate); diff --git a/modules/ticket/front/main/index.js b/modules/ticket/front/main/index.js index 1b807216b..3f9482fc4 100644 --- a/modules/ticket/front/main/index.js +++ b/modules/ticket/front/main/index.js @@ -22,7 +22,7 @@ export default class Ticket extends ModuleMain { $params.scopeDays = 1; if (typeof $params.scopeDays === 'number') { - const from = new Date(); + const from = Date.vnNew(); from.setHours(0, 0, 0, 0); const to = new Date(from.getTime()); diff --git a/modules/ticket/front/package/index.js b/modules/ticket/front/package/index.js index ed13f12d8..fd67ce583 100644 --- a/modules/ticket/front/package/index.js +++ b/modules/ticket/front/package/index.js @@ -6,7 +6,7 @@ class Controller extends Section { this.$.model.insert({ packagingFk: null, quantity: null, - created: new Date(), + created: Date.vnNew(), ticketFk: this.$params.id }); } diff --git a/modules/ticket/front/sale-tracking/index.html b/modules/ticket/front/sale-tracking/index.html index fc585650a..c21eaa46a 100644 --- a/modules/ticket/front/sale-tracking/index.html +++ b/modules/ticket/front/sale-tracking/index.html @@ -1,10 +1,11 @@ @@ -12,33 +13,29 @@ - + Is checked Item - Description + Description Quantity - Original - Worker - State - Created + - - - - + + + + + + + - - {{sale.itemFk | zeroFill:6}} + {{::sale.item.id}} - +
{{::sale.item.name}} @@ -53,16 +50,18 @@ {{::sale.quantity}} - {{::sale.originalQuantity}} - - - {{::sale.userNickname | dashIfEmpty}} - + + + + + - {{::sale.state}} - {{::sale.created | date: 'dd/MM/yyyy HH:mm'}} @@ -70,8 +69,95 @@ + warehouse-fk="$ctrl.ticket.warehouseFk" + ticket-fk="$ctrl.ticket.id"> - - \ No newline at end of file + + + + + + + + + + Quantity + Original + Worker + State + Created + + + + + {{::saleTracking.quantity}} + {{::saleTracking.originalQuantity}} + + + {{::saleTracking.name | dashIfEmpty}} + + + {{::saleTracking.state}} + {{::saleTracking.created | date: 'dd/MM/yyyy HH:mm'}} + + + + + + + + + + + + + + + + + + Quantity + Worker + Shelving + Parking + Created + + + + + {{::itemShelvingSale.quantity}} + + + {{::itemShelvingSale.name | dashIfEmpty}} + + + {{::itemShelvingSale.shelvingFk}} + {{::itemShelvingSale.code}} + {{::itemShelvingSale.created | date: 'dd/MM/yyyy HH:mm'}} + + + + + + + + diff --git a/modules/ticket/front/sale-tracking/index.js b/modules/ticket/front/sale-tracking/index.js index 394ef4f1e..d1c80f30f 100644 --- a/modules/ticket/front/sale-tracking/index.js +++ b/modules/ticket/front/sale-tracking/index.js @@ -1,12 +1,100 @@ import ngModule from '../module'; import Section from 'salix/components/section'; +import './style.scss'; -class Controller extends Section {} +class Controller extends Section { + constructor($element, $) { + super($element, $); + this.filter = { + include: [ + { + relation: 'item' + }, { + relation: 'saleTracking', + scope: { + fields: ['isChecked'] + } + } + ] + }; + } + + get sales() { + return this._sales; + } + + set sales(value) { + this._sales = value; + if (value) { + const query = `Sales/${this.$params.id}/salePreparingList`; + this.$http.get(query) + .then(res => { + this.salePreparingList = res.data; + for (const salePreparing of this.salePreparingList) { + for (const sale of this.sales) { + if (salePreparing.saleFk == sale.id) + sale.preparingList = salePreparing; + } + } + }); + } + } + + showItemDescriptor(event, sale) { + this.quicklinks = { + btnThree: { + icon: 'icon-transaction', + state: `item.card.diary({ + id: ${sale.item.id}, + warehouseFk: ${this.ticket.warehouseFk}, + lineFk: ${sale.id} + })`, + tooltip: 'Item diary' + } + }; + this.$.itemDescriptor.show(event.target, sale.item.id); + } + + chipHasSaleGroupDetail(hasSaleGroupDetail) { + if (hasSaleGroupDetail) return 'pink'; + else return 'message'; + } + + chipIsPreviousSelected(isPreviousSelected) { + if (isPreviousSelected) return 'notice'; + else return 'message'; + } + + chipIsPrevious(isPrevious) { + if (isPrevious) return 'dark-notice'; + else return 'message'; + } + + chipIsPrepared(isPrepared) { + if (isPrepared) return 'warning'; + else return 'message'; + } + + chipIsControled(isControled) { + if (isControled) return 'yellow'; + else return 'message'; + } + + showSaleTracking(sale) { + this.saleId = sale.id; + this.$.saleTracking.show(); + } + + showItemShelvingSale(sale) { + this.saleId = sale.id; + this.$.itemShelvingSale.show(); + } +} ngModule.vnComponent('vnTicketSaleTracking', { template: require('./index.html'), controller: Controller, bindings: { - ticket: '<', - }, + ticket: '<' + } }); diff --git a/modules/ticket/front/sale-tracking/locale/es.yml b/modules/ticket/front/sale-tracking/locale/es.yml new file mode 100644 index 000000000..eabc0a04d --- /dev/null +++ b/modules/ticket/front/sale-tracking/locale/es.yml @@ -0,0 +1,6 @@ +ItemShelvings sale: Carros línea +has saleGroupDetail: tiene detalle grupo lineas +is previousSelected: es previa seleccionada +is previous: es previa +is prepared: esta preparado +is controled: esta controlado diff --git a/modules/ticket/front/sale-tracking/style.scss b/modules/ticket/front/sale-tracking/style.scss new file mode 100644 index 000000000..6d8b3db69 --- /dev/null +++ b/modules/ticket/front/sale-tracking/style.scss @@ -0,0 +1,7 @@ +@import "variables"; + +.chip { + display: inline-block; + min-width: 15px; + min-height: 25px; +} diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index c624b1a95..fe259cf87 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -22,6 +22,7 @@ disabled="!$ctrl.isEditable" label="State" value-field="code" + fields="['id', 'name', 'alertLevel', 'code']" url="States/editableStates" on-change="$ctrl.changeState(value)"> @@ -30,7 +31,7 @@ ng-click="moreOptions.show($event)" ng-show="$ctrl.hasSelectedSales()"> - - @@ -68,6 +69,7 @@ Disc Amount Packaging + @@ -84,13 +86,13 @@ vn-tooltip="{{::$ctrl.$t('Claim')}}: {{::sale.claim.claimFk}}"> - - @@ -108,21 +110,21 @@ - - {{::sale.visible}} - {{::sale.available}} @@ -195,7 +197,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 +206,22 @@ {{::sale.item.itemPackingTypeFk | dashIfEmpty}} + + + + + + + @@ -383,8 +401,8 @@ - {{::ticket.id}} @@ -392,22 +410,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 +459,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..f3fb89d04 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -51,7 +51,7 @@ class Controller extends Section { const hasClaimManagerRole = this.aclService.hasAny(['claimManager']); - return landedPlusWeek >= new Date() || hasClaimManagerRole; + return landedPlusWeek >= Date.vnNew() || hasClaimManagerRole; } return false; } @@ -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/index.spec.js b/modules/ticket/front/sale/index.spec.js index fbee966fd..8585503cc 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -15,9 +15,9 @@ describe('Ticket', () => { const ticket = { id: 1, clientFk: 1101, - shipped: new Date(), - landed: new Date(), - created: new Date(), + shipped: Date.vnNew(), + landed: Date.vnNew(), + created: Date.vnNew(), client: {salesPersonFk: 1}, address: {mobile: 111111111} }; 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/ticket/front/search-panel/index.spec.js b/modules/ticket/front/search-panel/index.spec.js index 41c32c047..df320b55b 100644 --- a/modules/ticket/front/search-panel/index.spec.js +++ b/modules/ticket/front/search-panel/index.spec.js @@ -38,7 +38,7 @@ describe('Ticket Component vnTicketSearchPanel', () => { it('should clear the scope days when setting the from property', () => { controller.filter.scopeDays = 1; - controller.from = new Date(); + controller.from = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.from).toBeDefined(); @@ -49,7 +49,7 @@ describe('Ticket Component vnTicketSearchPanel', () => { it('should clear the scope days when setting the to property', () => { controller.filter.scopeDays = 1; - controller.to = new Date(); + controller.to = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.to).toBeDefined(); @@ -58,8 +58,8 @@ describe('Ticket Component vnTicketSearchPanel', () => { describe('scopeDays() setter', () => { it('should clear the date range when setting the scopeDays property', () => { - controller.filter.from = new Date(); - controller.filter.to = new Date(); + controller.filter.from = Date.vnNew(); + controller.filter.to = Date.vnNew(); controller.scopeDays = 1; diff --git a/modules/ticket/front/summary/index.html b/modules/ticket/front/summary/index.html index fe49a301f..af44ed67c 100644 --- a/modules/ticket/front/summary/index.html +++ b/modules/ticket/front/summary/index.html @@ -1,6 +1,6 @@
- - Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} + Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} ({{$ctrl.summary.client.id}}) - {{$ctrl.summary.nickname}} - -
- - {{$ctrl.summary.client.salesPersonUser.name}} - @@ -47,11 +48,11 @@ {{$ctrl.summary.zone.name}} - - {{$ctrl.summary.routeFk}} @@ -66,17 +67,17 @@ - - -

- Sale @@ -146,13 +147,13 @@ vn-tooltip="{{::$ctrl.$t('Claim')}}: {{::sale.claimBeginning.claimFk}}"> - - @@ -170,22 +171,22 @@ - {{sale.itemFk | zeroFill:6}} - {{::sale.visible}} - {{::sale.available}} @@ -216,7 +217,7 @@

- Packages @@ -241,7 +242,7 @@

- Service @@ -276,7 +277,7 @@

- Purchase request @@ -304,7 +305,7 @@ {{::request.quantity}} {{::request.price}} - @@ -336,9 +337,9 @@ - - - \ No newline at end of file + diff --git a/modules/ticket/front/weekly/index.html b/modules/ticket/front/weekly/index.html index 3c739d5f9..ca3b6e662 100644 --- a/modules/ticket/front/weekly/index.html +++ b/modules/ticket/front/weekly/index.html @@ -17,87 +17,110 @@ model="model"> - - - - - - Ticket ID - Client - Shipment - Agency - Warehouse - Salesperson - - - - - - - - {{weekly.ticketFk}} - - - - - {{::weekly.clientName}} - - - - - - - - - - - {{::weekly.warehouseName}} - - - {{::weekly.userName}} - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Ticket ID + + Client + + Shipment + + Agency + + Warehouse + + Salesperson +
+ + {{weekly.ticketFk}} + + + + {{::weekly.clientName}} + + + + + + + + {{weekly.warehouseName}} + + {{::weekly.userName}} + + + + +
+
+
+
@@ -112,4 +135,4 @@ on-accept="$ctrl.onDeleteWeeklyAccept($data)" question="This ticket will be removed from weekly tickets! Continue anyway?" message="You are going to delete this weekly ticket"> - + \ No newline at end of file diff --git a/modules/ticket/front/weekly/index.js b/modules/ticket/front/weekly/index.js index 71365c4b3..a10ff7184 100644 --- a/modules/ticket/front/weekly/index.js +++ b/modules/ticket/front/weekly/index.js @@ -1,3 +1,4 @@ + import ngModule from '../module'; import Section from 'salix/components/section'; @@ -15,6 +16,44 @@ export default class Controller extends Section { {id: 5, name: 'Saturday'}, {id: 6, name: 'Sunday'} ]; + + this.smartTableOptions = { + activeButtons: { + search: true, + shownColumns: true, + }, + columns: [ + { + field: 'ticketFk', + searchable: false + }, + { + field: 'clientName', + }, + { + field: 'weekDay', + searchable: false, + }, + { + field: 'agencyModeFk', + searchable: false, + }, + { + field: 'warehouseFk', + searchable: false, + }, + { + field: 'nickname', + }, + ] + }; + } + + exprBuilder(param, value) { + switch (param) { + case 'clientName': return {'c.name': value}; + case 'nickName': return {'u.name': value}; + } } onUpdate(ticketFk, field, value) { diff --git a/modules/travel/back/methods/thermograph/createThermograph.js b/modules/travel/back/methods/thermograph/createThermograph.js index 23d9d6037..75d967628 100644 --- a/modules/travel/back/methods/thermograph/createThermograph.js +++ b/modules/travel/back/methods/thermograph/createThermograph.js @@ -40,7 +40,7 @@ module.exports = Self => { const models = Self.app.models; let tx; const myOptions = {}; - const date = new Date(); + const date = Date.vnNew(); if (typeof options == 'object') Object.assign(myOptions, options); diff --git a/modules/travel/back/methods/travel/cloneWithEntries.js b/modules/travel/back/methods/travel/cloneWithEntries.js index 611f4e429..e5b6b1580 100644 --- a/modules/travel/back/methods/travel/cloneWithEntries.js +++ b/modules/travel/back/methods/travel/cloneWithEntries.js @@ -39,8 +39,8 @@ module.exports = Self => { 'ref' ] }); - const started = new Date(); - const ended = new Date(); + const started = Date.vnNew(); + const ended = Date.vnNew(); if (!travel) throw new UserError('Travel not found'); diff --git a/modules/travel/back/methods/travel/specs/cloneWithEntries.spec.js b/modules/travel/back/methods/travel/specs/cloneWithEntries.spec.js index 2e79ff193..0e434e048 100644 --- a/modules/travel/back/methods/travel/specs/cloneWithEntries.spec.js +++ b/modules/travel/back/methods/travel/specs/cloneWithEntries.spec.js @@ -49,7 +49,7 @@ describe('Travel cloneWithEntries()', () => { pending('#2687 - Cannot make a data rollback because of the triggers'); const warehouseThree = 3; const agencyModeOne = 1; - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); travelBefore = await models.Travel.findById(travelId); diff --git a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js index 3693aae82..599851b55 100644 --- a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js +++ b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js @@ -95,10 +95,10 @@ describe('Travel extraCommunityFilter()', () => { }); it('should return the routes matching "shipped from" and "landed to"', async() => { - const from = new Date(); + const from = Date.vnNew(); from.setDate(from.getDate() - 2); from.setHours(0, 0, 0, 0); - const to = new Date(); + const to = Date.vnNew(); to.setHours(23, 59, 59, 999); to.setDate(to.getDate() + 7); const ctx = { diff --git a/modules/travel/back/methods/travel/specs/filter.spec.js b/modules/travel/back/methods/travel/specs/filter.spec.js index c739866a0..1a6ee895c 100644 --- a/modules/travel/back/methods/travel/specs/filter.spec.js +++ b/modules/travel/back/methods/travel/specs/filter.spec.js @@ -54,8 +54,8 @@ describe('Travel filter()', () => { }); it('should return the routes matching "shipped from" and "shipped to"', async() => { - const from = new Date(); - const to = new Date(); + const from = Date.vnNew(); + const to = Date.vnNew(); from.setHours(0, 0, 0, 0); to.setHours(23, 59, 59, 999); to.setDate(to.getDate() + 1); diff --git a/modules/travel/front/create/index.spec.js b/modules/travel/front/create/index.spec.js index e3f85d9ae..cdff8cfb9 100644 --- a/modules/travel/front/create/index.spec.js +++ b/modules/travel/front/create/index.spec.js @@ -53,7 +53,7 @@ describe('Travel Component vnTravelCreate', () => { it(`should do nothing if there's no response data.`, () => { controller.travel = {agencyModeFk: 4}; - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); const query = `travels/getAverageDays?agencyModeFk=${controller.travel.agencyModeFk}`; $httpBackend.expectGET(query).respond(undefined); @@ -67,7 +67,7 @@ describe('Travel Component vnTravelCreate', () => { it(`should fill the fields when it's selected a date and agency.`, () => { controller.travel = {agencyModeFk: 1}; - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 9); const expectedResponse = { id: 8, 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..920339469 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -25,12 +25,12 @@ class Controller extends Section { this.droppableElement = 'tbody[vn-droppable]'; const twoDays = 2; - const shippedFrom = new Date(); + const shippedFrom = Date.vnNew(); shippedFrom.setDate(shippedFrom.getDate() - twoDays); shippedFrom.setHours(0, 0, 0, 0); const sevenDays = 7; - const landedTo = new Date(); + const landedTo = Date.vnNew(); landedTo.setDate(landedTo.getDate() + sevenDays); landedTo.setHours(23, 59, 59, 59); @@ -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/travel/front/index/index.js b/modules/travel/front/index/index.js index 50036831f..7701289b7 100644 --- a/modules/travel/front/index/index.js +++ b/modules/travel/front/index/index.js @@ -20,7 +20,7 @@ export default class Controller extends Section { } compareDate(date) { - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); date = new Date(date); diff --git a/modules/travel/front/index/index.spec.js b/modules/travel/front/index/index.spec.js index 9abe46a64..9083c4519 100644 --- a/modules/travel/front/index/index.spec.js +++ b/modules/travel/front/index/index.spec.js @@ -50,7 +50,7 @@ describe('Travel Component vnTravelIndex', () => { describe('compareDate()', () => { it('should return warning if the date passed to compareDate() is todays', () => { - const today = new Date(); + const today = Date.vnNew(); const result = controller.compareDate(today); @@ -58,7 +58,7 @@ describe('Travel Component vnTravelIndex', () => { }); it('should return success if the date passed to compareDate() is in the future', () => { - const tomorrow = new Date(); + const tomorrow = Date.vnNew(); tomorrow.setDate(tomorrow.getDate() + 1); const result = controller.compareDate(tomorrow); @@ -67,7 +67,7 @@ describe('Travel Component vnTravelIndex', () => { }); it('should return undefined if the date passed to compareDate() is in the past', () => { - const yesterday = new Date(); + const yesterday = Date.vnNew(); yesterday.setDate(yesterday.getDate() - 1); const result = controller.compareDate(yesterday); diff --git a/modules/travel/front/main/index.js b/modules/travel/front/main/index.js index d6f103033..fbaf78c16 100644 --- a/modules/travel/front/main/index.js +++ b/modules/travel/front/main/index.js @@ -15,7 +15,7 @@ export default class Travel extends ModuleMain { $params.scopeDays = 1; if (typeof $params.scopeDays === 'number') { - const shippedFrom = new Date(); + const shippedFrom = Date.vnNew(); shippedFrom.setHours(0, 0, 0, 0); const shippedTo = new Date(shippedFrom.getTime()); diff --git a/modules/travel/front/main/index.spec.js b/modules/travel/front/main/index.spec.js index 6d9db4dc8..bf5a27b41 100644 --- a/modules/travel/front/main/index.spec.js +++ b/modules/travel/front/main/index.spec.js @@ -15,7 +15,7 @@ describe('Travel Component vnTravel', () => { let params = controller.fetchParams({ scopeDays: 2 }); - const shippedFrom = new Date(); + const shippedFrom = Date.vnNew(); shippedFrom.setHours(0, 0, 0, 0); const shippedTo = new Date(shippedFrom.getTime()); shippedTo.setDate(shippedTo.getDate() + params.scopeDays); diff --git a/modules/travel/front/search-panel/index.spec.js b/modules/travel/front/search-panel/index.spec.js index a1f3c36b3..884f4fb17 100644 --- a/modules/travel/front/search-panel/index.spec.js +++ b/modules/travel/front/search-panel/index.spec.js @@ -15,7 +15,7 @@ describe('Travel Component vnTravelSearchPanel', () => { it('should clear the scope days when setting the from property', () => { controller.filter.scopeDays = 1; - controller.shippedFrom = new Date(); + controller.shippedFrom = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.shippedFrom).toBeDefined(); @@ -26,7 +26,7 @@ describe('Travel Component vnTravelSearchPanel', () => { it('should clear the scope days when setting the to property', () => { controller.filter.scopeDays = 1; - controller.shippedTo = new Date(); + controller.shippedTo = Date.vnNew(); expect(controller.filter.scopeDays).toBeNull(); expect(controller.shippedTo).toBeDefined(); @@ -35,8 +35,8 @@ describe('Travel Component vnTravelSearchPanel', () => { describe('scopeDays() setter', () => { it('should clear the date range when setting the scopeDays property', () => { - controller.filter.shippedFrom = new Date(); - controller.filter.shippedTo = new Date(); + controller.filter.shippedFrom = Date.vnNew(); + controller.filter.shippedTo = Date.vnNew(); controller.scopeDays = 1; diff --git a/modules/worker/back/methods/calendar/absences.js b/modules/worker/back/methods/calendar/absences.js index ddf38a604..8420ed770 100644 --- a/modules/worker/back/methods/calendar/absences.js +++ b/modules/worker/back/methods/calendar/absences.js @@ -35,12 +35,12 @@ module.exports = Self => { Self.absences = async(ctx, workerFk, businessFk, year, options) => { const models = Self.app.models; - const started = new Date(); + const started = Date.vnNew(); started.setFullYear(year); started.setMonth(0); started.setDate(1); - const ended = new Date(); + const ended = Date.vnNew(); ended.setFullYear(year); ended.setMonth(12); ended.setDate(0); diff --git a/modules/worker/back/methods/calendar/specs/absences.spec.js b/modules/worker/back/methods/calendar/specs/absences.spec.js index 2180a5312..365773182 100644 --- a/modules/worker/back/methods/calendar/specs/absences.spec.js +++ b/modules/worker/back/methods/calendar/specs/absences.spec.js @@ -6,7 +6,7 @@ describe('Worker absences()', () => { const workerId = 1106; const businessId = 1106; - const now = new Date(); + const now = Date.vnNew(); const year = now.getFullYear(); const [absences] = await app.models.Calendar.absences(ctx, workerId, businessId, year); @@ -22,7 +22,7 @@ describe('Worker absences()', () => { const businessId = 1106; const ctx = {req: {accessToken: {userId: 9}}}; - const now = new Date(); + const now = Date.vnNew(); const year = now.getFullYear(); const tx = await app.models.Calendar.beginTransaction({}); @@ -55,15 +55,15 @@ describe('Worker absences()', () => { const workerId = 1106; const userId = 1106; - const today = new Date(); + const today = Date.vnNew(); // getting how many days in a year - const yearStart = new Date(); + const yearStart = Date.vnNew(); yearStart.setHours(0, 0, 0, 0); yearStart.setMonth(0); yearStart.setDate(1); - const yearEnd = new Date(); + const yearEnd = Date.vnNew(); const currentYear = yearEnd.getFullYear(); yearEnd.setFullYear(currentYear + 1); yearEnd.setHours(0, 0, 0, 0); @@ -92,7 +92,7 @@ describe('Worker absences()', () => { // normal test begins const contract = await app.models.WorkerLabour.findById(businessId, null, options); - const startingContract = new Date(); + const startingContract = Date.vnNew(); startingContract.setHours(0, 0, 0, 0); startingContract.setMonth(today.getMonth()); startingContract.setDate(1); diff --git a/modules/worker/back/methods/holiday/getByWarehouse.js b/modules/worker/back/methods/holiday/getByWarehouse.js index 093885d13..50029e62b 100644 --- a/modules/worker/back/methods/holiday/getByWarehouse.js +++ b/modules/worker/back/methods/holiday/getByWarehouse.js @@ -17,7 +17,7 @@ module.exports = Self => { }); Self.getByWarehouse = async warehouseFk => { - let beginningYear = new Date(); + let beginningYear = Date.vnNew(); beginningYear.setMonth(0); beginningYear.setDate(1); beginningYear.setHours(0, 0, 0, 0); diff --git a/modules/worker/back/methods/worker-time-control-mail/checkInbox.js b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js index 7825f38b8..4d9f98cc3 100644 --- a/modules/worker/back/methods/worker-time-control-mail/checkInbox.js +++ b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js @@ -93,7 +93,7 @@ module.exports = Self => { }; async function emailConfirm(buffer) { - const now = new Date(); + const now = Date.vnNew(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -121,7 +121,7 @@ module.exports = Self => { } async function emailReply(buffer, emailBody) { - const now = new Date(); + const now = Date.vnNew(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index b38405c1d..579a83112 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 = Date.vnNew(); + const to = Date.vnNew(); - 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: Date.vnNew(), 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: Date.vnNew(), 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 @@ -215,11 +223,11 @@ module.exports = Self => { let timeTableDecimalInSeconds = 0; for (let journey of journeys) { - const start = new Date(); + const start = Date.vnNew(); const [startHours, startMinutes, startSeconds] = getTime(journey.start); start.setHours(startHours, startMinutes, startSeconds, 0); - const end = new Date(); + const end = Date.vnNew(); const [endHours, endMinutes, endSeconds] = getTime(journey.end); end.setHours(endHours, endMinutes, endSeconds, 0); @@ -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/filter.spec.js b/modules/worker/back/methods/worker-time-control/specs/filter.spec.js index 927d83df3..0c4d229f2 100644 --- a/modules/worker/back/methods/worker-time-control/specs/filter.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/filter.spec.js @@ -3,9 +3,9 @@ const models = require('vn-loopback/server/server').models; describe('workerTimeControl filter()', () => { it('should return 1 result filtering by id', async() => { const ctx = {req: {accessToken: {userId: 1106}}, args: {workerFk: 1106}}; - const firstHour = new Date(); + const firstHour = Date.vnNew(); firstHour.setHours(7, 0, 0, 0); - const lastHour = new Date(); + const lastHour = Date.vnNew(); lastHour.setDate(lastHour.getDate() + 1); lastHour.setHours(15, 0, 0, 0); @@ -21,9 +21,9 @@ describe('workerTimeControl filter()', () => { it('should return a privilege error for a non subordinate worker', async() => { const ctx = {req: {accessToken: {userId: 1107}}, args: {workerFk: 1106}}; - const firstHour = new Date(); + const firstHour = Date.vnNew(); firstHour.setHours(7, 0, 0, 0); - const lastHour = new Date(); + const lastHour = Date.vnNew(); lastHour.setDate(lastHour.getDate() + 1); lastHour.setHours(15, 0, 0, 0); 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/specs/timeEntry.spec.js b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js index e9924c67b..e90c849b7 100644 --- a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js @@ -35,7 +35,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { let error; try { - ctx.args = {timed: new Date(), direction: 'in'}; + ctx.args = {timed: Date.vnNew(), direction: 'in'}; await models.WorkerTimeControl.addTimeEntry(ctx, workerId); } catch (e) { error = e; @@ -52,7 +52,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { let error; try { - ctx.args = {timed: new Date(), direction: 'in'}; + ctx.args = {timed: Date.vnNew(), direction: 'in'}; await models.WorkerTimeControl.addTimeEntry(ctx, workerId); } catch (e) { error = e; @@ -71,7 +71,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { try { const options = {transaction: tx}; - const todayAtOne = new Date(); + const todayAtOne = Date.vnNew(); todayAtOne.setHours(1, 0, 0, 0); ctx.args = {timed: todayAtOne, direction: 'in'}; @@ -95,7 +95,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { try { const options = {transaction: tx}; - const todayAtOne = new Date(); + const todayAtOne = Date.vnNew(); todayAtOne.setHours(1, 0, 0, 0); ctx.args = {timed: todayAtOne, direction: 'in'}; @@ -123,7 +123,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { try { const options = {transaction: tx}; - const todayAtOne = new Date(); + const todayAtOne = Date.vnNew(); todayAtOne.setHours(1, 0, 0, 0); ctx.args = {timed: todayAtOne, direction: 'in'}; @@ -151,7 +151,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { try { const options = {transaction: tx}; - const todayAtOne = new Date(); + const todayAtOne = Date.vnNew(); todayAtOne.setHours(1, 0, 0, 0); ctx.args = {timed: todayAtOne, direction: 'in'}; @@ -179,7 +179,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { try { const options = {transaction: tx}; - const todayAtOne = new Date(); + const todayAtOne = Date.vnNew(); todayAtOne.setHours(1, 0, 0, 0); ctx.args = {timed: todayAtOne, direction: 'in'}; @@ -204,7 +204,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { pending('https://redmine.verdnatura.es/issues/4707'); activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - const date = new Date(); + const date = Date.vnNew(); date.setDate(date.getDate() - 16); date.setHours(8, 0, 0); let error; @@ -227,7 +227,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { it('should fail to add a time entry for a worker without an existing contract', async() => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - const date = new Date(); + const date = Date.vnNew(); date.setFullYear(date.getFullYear() - 2); let error; @@ -252,7 +252,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -282,7 +282,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -316,7 +316,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -350,7 +350,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -384,7 +384,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -421,7 +421,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -456,7 +456,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -493,7 +493,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = jessicaJonesId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -528,7 +528,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = jessicaJonesId; - let date = new Date(); + let date = Date.vnNew(); date.setDate(date.getDate() - 21); date = weekDay(date, monday); let error; @@ -565,7 +565,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setMonth(date.getMonth() - 2); date.setDate(1); let error; @@ -600,7 +600,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setMonth(date.getMonth() - 2); date.setDate(1); let error; @@ -634,7 +634,7 @@ describe('workerTimeControl add/delete timeEntry()', () => { activeCtx.accessToken.userId = salesBossId; const workerId = hankPymId; - let date = new Date(); + let date = Date.vnNew(); date.setMonth(date.getMonth() - 2); date.setDate(1); let error; 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/methods/worker/activeContract.js b/modules/worker/back/methods/worker/activeContract.js index 05dcee6b5..d3d439cd0 100644 --- a/modules/worker/back/methods/worker/activeContract.js +++ b/modules/worker/back/methods/worker/activeContract.js @@ -27,7 +27,7 @@ module.exports = Self => { if (!isSubordinate) throw new UserError(`You don't have enough privileges`); - const now = new Date(); + const now = Date.vnNew(); return models.WorkerLabour.findOne({ where: { diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index 1467d6d6b..43a9f4d23 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -80,8 +80,8 @@ module.exports = Self => { if (hasHoursRecorded && isNotHalfAbsence) throw new UserError(`The worker has hours recorded that day`); - const date = new Date(); - const now = new Date(); + const date = Date.vnNew(); + const now = Date.vnNew(); date.setHours(0, 0, 0, 0); const [result] = await Self.rawSql( `SELECT COUNT(*) halfHolidayCounter diff --git a/modules/worker/back/methods/worker/holidays.js b/modules/worker/back/methods/worker/holidays.js index 7f093a330..9c214e0f7 100644 --- a/modules/worker/back/methods/worker/holidays.js +++ b/modules/worker/back/methods/worker/holidays.js @@ -45,13 +45,13 @@ module.exports = Self => { if (!isSubordinate) throw new UserError(`You don't have enough privileges`); - const started = new Date(); + const started = Date.vnNew(); started.setFullYear(args.year); started.setMonth(0); started.setDate(1); started.setHours(0, 0, 0, 0); - const ended = new Date(); + const ended = Date.vnNew(); ended.setFullYear(args.year); ended.setMonth(12); ended.setDate(0); diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js new file mode 100644 index 000000000..a7bb883cd --- /dev/null +++ b/modules/worker/back/methods/worker/new.js @@ -0,0 +1,256 @@ +/* eslint max-len: ["error", { "code": 130 }]*/ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('new', { + description: 'Creates a new worker and returns the id', + accessType: 'WRITE', + accepts: [ + { + arg: 'fi', + type: 'string', + description: `The worker fi`, + required: true, + }, + { + arg: 'name', + type: 'string', + description: `The user name`, + required: true, + }, + { + arg: 'firstName', + type: 'string', + description: `The worker firstname`, + required: true, + }, + { + arg: 'lastNames', + type: 'string', + description: `The worker lastnames`, + required: true, + }, + { + arg: 'email', + type: 'string', + description: `The worker email`, + required: true, + }, + { + arg: 'street', + type: 'string', + description: `The worker address`, + required: true, + }, + { + arg: 'city', + type: 'string', + description: `The worker city`, + required: true, + }, + { + arg: 'provinceFk', + type: 'number', + description: `The worker province`, + required: true, + }, + { + arg: 'iban', + type: 'string', + description: `The worker iban`, + required: true, + }, + { + arg: 'bankEntityFk', + type: 'number', + description: `The worker bank entity`, + required: true, + }, + { + arg: 'companyFk', + type: 'number', + description: `The worker company`, + required: true, + }, + { + arg: 'postcode', + type: 'string', + description: `The worker postcode`, + required: true, + }, + { + arg: 'phone', + type: 'string', + description: `The worker phone`, + required: true, + }, + { + arg: 'code', + type: 'string', + description: `The worker code`, + required: true, + }, + { + arg: 'bossFk', + type: 'number', + description: `The worker boss`, + required: true, + }, + { + arg: 'birth', + type: 'date', + description: `The worker birth`, + required: true, + } + ], + returns: { + type: 'number', + root: true, + }, + http: { + path: `/new`, + verb: 'POST', + }, + }); + + Self.new = async(ctx, options) => { + const models = Self.app.models; + const myOptions = {}; + const args = ctx.args; + + let tx; + + if (typeof options == 'object') Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + let client; + + try { + client = await models.Client.findOne( + { + where: {fi: args.fi}, + }, + myOptions + ); + + if (!client) { + const nickname = args.firstName.concat(' ', args.lastNames); + const workerConfig = await models.WorkerConfig.findOne({fields: ['roleFk']}); + const [randomPassword] = await models.Worker.rawSql( + 'SELECT account.passwordGenerate() as password;' + ); + + const user = await models.Account.create( + { + name: args.name, + nickname, + password: randomPassword.password, + email: args.email, + roleFk: workerConfig.roleFk, + }, + myOptions + ); + + await models.UserAccount.create( + { + id: user.id, + }, + myOptions + ); + + await models.Worker.rawSql( + 'CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [ + args.firstName, + args.lastNames, + args.fi, + args.street, + args.postalCode, + args.city, + args.provinceFk, + args.companyFk, + args.phone, + args.email, + user.id, + ], + myOptions + ); + + const address = await models.Address.create( + { + clientFk: user.id, + street: args.street, + city: args.city, + provinceFk: args.provinceFk, + postalCode: args.postalCode, + mobile: args.phone, + nickname: nickname, + isDefaultAddress: true, + }, + myOptions + ); + + client = await models.Client.findById( + user.id, + {fields: ['id', 'name', 'socialName', 'street', 'city', 'iban', 'bankEntityFk', 'defaultAddressFk']}, + myOptions + ); + + await client.updateAttributes( + { + iban: args.iban, + bankEntityFk: args.bankEntityFk, + defaultAddressFk: address.id, + }, + myOptions + ); + } + + const user = await models.Account.findById(client.id, null, myOptions); + await user.updateAttribute('email', args.email, myOptions); + + await models.Worker.rawSql( + 'CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', + [ + args.firstName, + args.lastNames, + args.code, + args.bossFk, + client.id, + args.fi, + args.birth, + ], + myOptions + ); + + if (tx) await tx.commit(); + } catch (error) { + if (tx) await tx.rollback(); + const code = error.code; + const message = error.sqlMessage; + + if (code === 'ER_DUP_ENTRY' && message.includes(`for key 'mail'`)) + throw new UserError(`This personal mail already exists`); + + if (code === 'ER_DUP_ENTRY' && message.includes(`CodigoTrabajador_UNIQUE`)) + throw new UserError(`This worker code already exists`); + + if (code === 'ER_DUP_ENTRY' && message.includes(`PRIMARY`)) + throw new UserError(`This worker already exists`); + + throw error; + } + + await models.user.resetPassword({ + email: args.email, + emailTemplate: 'worker-welcome', + id: client.id + }); + + return {id: client.id}; + }; +}; diff --git a/modules/worker/back/methods/worker/specs/createAbsence.spec.js b/modules/worker/back/methods/worker/specs/createAbsence.spec.js index 7214e815e..346e43c51 100644 --- a/modules/worker/back/methods/worker/specs/createAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/createAbsence.spec.js @@ -10,7 +10,7 @@ describe('Worker createAbsence()', () => { args: { businessFk: 18, absenceTypeId: 1, - dated: new Date() + dated: Date.vnNew() } }; @@ -45,7 +45,7 @@ describe('Worker createAbsence()', () => { args: { businessFk: 18, absenceTypeId: 1, - dated: new Date() + dated: Date.vnNew() } }; ctx.req.__ = value => { @@ -82,7 +82,7 @@ describe('Worker createAbsence()', () => { id: 1, businessFk: 1, absenceTypeId: 6, - dated: new Date() + dated: Date.vnNew() } }; const workerId = 1; @@ -111,7 +111,7 @@ describe('Worker createAbsence()', () => { id: 1106, businessFk: 1106, absenceTypeId: 1, - dated: new Date() + dated: Date.vnNew() } }; const workerId = 1106; diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index a105669cf..0f3f913dc 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -28,7 +28,7 @@ describe('Worker deleteAbsence()', () => { const createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, - dated: new Date() + dated: Date.vnNew() }, options); ctx.args = {absenceId: createdAbsence.id}; @@ -59,7 +59,7 @@ describe('Worker deleteAbsence()', () => { const createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, - dated: new Date() + dated: Date.vnNew() }, options); ctx.args = {absenceId: createdAbsence.id}; diff --git a/modules/worker/back/methods/worker/specs/getWorkedHours.spec.js b/modules/worker/back/methods/worker/specs/getWorkedHours.spec.js index 054a829e5..f5b06cc9e 100644 --- a/modules/worker/back/methods/worker/specs/getWorkedHours.spec.js +++ b/modules/worker/back/methods/worker/specs/getWorkedHours.spec.js @@ -3,10 +3,10 @@ const models = require('vn-loopback/server/server').models; describe('Worker getWorkedHours()', () => { it(`should return the expected hours and the worked hours of a given date`, async() => { const workerID = 1106; - const started = new Date(); + const started = Date.vnNew(); started.setHours(0, 0, 0, 0); - const ended = new Date(); + const ended = Date.vnNew(); ended.setHours(23, 59, 59, 999); const [result] = await models.Worker.getWorkedHours(workerID, started, ended); diff --git a/modules/worker/back/methods/worker/specs/holidays.spec.js b/modules/worker/back/methods/worker/specs/holidays.spec.js index d8310b738..f23b247ca 100644 --- a/modules/worker/back/methods/worker/specs/holidays.spec.js +++ b/modules/worker/back/methods/worker/specs/holidays.spec.js @@ -17,7 +17,7 @@ describe('Worker holidays()', () => { }); it('should now get the absence calendar for a full year contract', async() => { - const now = new Date(); + const now = Date.vnNew(); const year = now.getFullYear(); ctx.args = {businessFk: businessId, year: year}; @@ -29,7 +29,7 @@ describe('Worker holidays()', () => { }); it('should now get the payed holidays calendar for a worker', async() => { - const now = new Date(); + const now = Date.vnNew(); const year = now.getFullYear(); ctx.args = {businessFk: businessId, year: year}; diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js new file mode 100644 index 000000000..f695ab80e --- /dev/null +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -0,0 +1,139 @@ +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); + +describe('Worker new', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + const employeeId = 1; + const defaultWorker = { + fi: '78457139E', + name: 'defaultWorker', + firstName: 'default', + lastNames: 'worker', + email: 'defaultWorker@mydomain.com', + street: 'S/ defaultWorkerStreet', + city: 'defaultWorkerCity', + provinceFk: 1, + iban: 'ES8304879798578129532677', + bankEntityFk: 128, + companyFk: 442, + postcode: '46680', + phone: '123456789', + code: 'DWW', + bossFk: 9, + birth: '2022-12-11T23:00:00.000Z' + }; + + it('should return error if personal mail already exists', async() => { + const user = await models.Account.findById(employeeId, {fields: ['email']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {email: user.email}) + }; + + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This personal mail already exists'); + }); + + it('should return error if worker code already exists', async() => { + const worker = await models.Worker.findById(employeeId, {fields: ['code']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {code: worker.code}) + }; + + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This worker code already exists'); + }); + + it('should return error if worker already exists', async() => { + const worker = await models.Client.findById(employeeId, {fields: ['fi']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {fi: worker.fi}) + }; + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This worker already exists'); + }); + + it('should create a new worker', async() => { + const newWorker = await models.Worker.new({args: defaultWorker}); + + await models.Worker.destroyById(newWorker.id); + await models.Address.destroyAll({clientFk: newWorker.id}); + await models.Mandate.destroyAll({clientFk: newWorker.id}); + await models.Client.destroyById(newWorker.id); + await models.Account.destroyById(newWorker.id); + + expect(newWorker.id).toBeDefined(); + }); + + it('should create a new worker in client', async() => { + const bruceWayneId = 1101; + const client = await models.Client.findById(bruceWayneId, {fields: ['fi', 'email']}); + + const newWorkerData = { + args: Object.assign( + {}, + defaultWorker, + { + fi: client.fi, + email: client.email + }) + }; + const newWorker = await models.Worker.new(newWorkerData); + + await models.Worker.destroyById(newWorker.id); + + expect(newWorker.id).toEqual(bruceWayneId); + }); +}); diff --git a/modules/worker/back/methods/worker/specs/updateAbsence.spec.js b/modules/worker/back/methods/worker/specs/updateAbsence.spec.js index 6339b3163..a624fc1d3 100644 --- a/modules/worker/back/methods/worker/specs/updateAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/updateAbsence.spec.js @@ -21,7 +21,7 @@ describe('Worker updateAbsence()', () => { createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, - dated: new Date() + dated: Date.vnNew() }); }); diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index 3f3416504..7e03c8a23 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -1,7 +1,7 @@ { "AbsenceType": { "dataSource": "vn" - }, + }, "Calendar": { "dataSource": "vn" }, @@ -16,13 +16,19 @@ }, "Department": { "dataSource": "vn" - }, + }, + "Device": { + "dataSource": "vn" + }, "EducationLevel": { "dataSource": "vn" }, "Journey": { "dataSource": "vn" }, + "ProfileType":{ + "dataSource": "vn" + }, "Time": { "dataSource": "vn" }, @@ -32,39 +38,42 @@ "WorkCenterHoliday": { "dataSource": "vn" }, - "WorkerDms": { + "Worker": { "dataSource": "vn" }, - "Worker": { + "WorkerConfig": { + "dataSource": "vn" + }, + "WorkerDepartment": { + "dataSource": "vn" + }, + "WorkerDisableExcluded": { + "dataSource": "vn" + }, + "WorkerDms": { "dataSource": "vn" }, "WorkerLabour": { "dataSource": "vn" }, + "WorkerLog": { + "dataSource": "vn" + }, "WorkerMana": { "dataSource": "vn" }, + "WorkerMedia": { + "dataSource": "vn" + }, "WorkerTeam": { "dataSource": "vn" }, "WorkerTeamCollegues": { "dataSource": "vn" }, - "WorkerMedia": { - "dataSource": "vn" - }, - "WorkerDepartment": { - "dataSource": "vn" - }, "WorkerTimeControl": { "dataSource": "vn" }, - "Device": { - "dataSource": "vn" - }, - "WorkerLog": { - "dataSource": "vn" - }, "WorkerTimeControlConfig": { "dataSource": "vn" }, @@ -73,9 +82,6 @@ }, "WorkerTimeControlMail": { "dataSource": "vn" - }, - "WorkerDisableExcluded": { - "dataSource": "vn" } } diff --git a/modules/worker/back/models/profile-type.json b/modules/worker/back/models/profile-type.json new file mode 100644 index 000000000..d1d750de8 --- /dev/null +++ b/modules/worker/back/models/profile-type.json @@ -0,0 +1,19 @@ +{ + "name": "ProfileType", + "base": "VnModel", + "options": { + "mysql": { + "table": "profileType" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + } + } +} diff --git a/modules/worker/back/models/worker-config.json b/modules/worker/back/models/worker-config.json new file mode 100644 index 000000000..05cdfef42 --- /dev/null +++ b/modules/worker/back/models/worker-config.json @@ -0,0 +1,27 @@ +{ + "name": "WorkerConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "roleFk": { + "type": "number" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} 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/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index ec6c4af28..e66259cd0 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -13,4 +13,5 @@ module.exports = Self => { require('../methods/worker/contracts')(Self); require('../methods/worker/holidays')(Self); require('../methods/worker/activeContract')(Self); + require('../methods/worker/new')(Self); }; diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 3d41707ce..e3a941dd3 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -52,6 +52,9 @@ }, "mobileExtension": { "type" : "number" + }, + "code": { + "type" : "string" } }, "relations": { @@ -91,4 +94,4 @@ "foreignKey": "sectorFk" } } -} \ No newline at end of file +} diff --git a/modules/worker/front/calendar/index.js b/modules/worker/front/calendar/index.js index 95e1fc134..4ca0fc929 100644 --- a/modules/worker/front/calendar/index.js +++ b/modules/worker/front/calendar/index.js @@ -5,7 +5,7 @@ import './style.scss'; class Controller extends Section { constructor($element, $) { super($element, $); - this.date = new Date(); + this.date = Date.vnNew(); this.events = {}; this.buildYearFilter(); } @@ -15,7 +15,7 @@ class Controller extends Section { } set year(value) { - const newYear = new Date(); + const newYear = Date.vnNew(); newYear.setFullYear(value); this.date = newYear; @@ -76,7 +76,7 @@ class Controller extends Section { } buildYearFilter() { - const now = new Date(); + const now = Date.vnNew(); now.setFullYear(now.getFullYear() + 1); const maxYear = now.getFullYear(); diff --git a/modules/worker/front/calendar/index.spec.js b/modules/worker/front/calendar/index.spec.js index 1da4066d9..586a7223d 100644 --- a/modules/worker/front/calendar/index.spec.js +++ b/modules/worker/front/calendar/index.spec.js @@ -6,7 +6,7 @@ describe('Worker', () => { let $httpParamSerializer; let $scope; let controller; - let year = new Date().getFullYear(); + let year = Date.vnNew().getFullYear(); beforeEach(ngModule('worker')); @@ -67,7 +67,7 @@ describe('Worker', () => { controller.getIsSubordinate = jest.fn(); controller.getActiveContract = jest.fn(); - let today = new Date(); + let today = Date.vnNew(); let tomorrow = new Date(today.getTime()); tomorrow.setDate(tomorrow.getDate() + 1); @@ -105,7 +105,7 @@ describe('Worker', () => { describe('getContractHolidays()', () => { it(`should return the worker holidays amount and then set the contractHolidays property`, () => { - const today = new Date(); + const today = Date.vnNew(); const year = today.getFullYear(); const serializedParams = $httpParamSerializer({year}); @@ -119,7 +119,7 @@ describe('Worker', () => { describe('formatDay()', () => { it(`should set the day element style`, () => { - const today = new Date(); + const today = Date.vnNew(); controller.events[today.getTime()] = { name: 'Holiday', @@ -170,7 +170,7 @@ describe('Worker', () => { it(`should call to the create() method`, () => { jest.spyOn(controller, 'create').mockReturnThis(); - const selectedDay = new Date(); + const selectedDay = Date.vnNew(); const $event = { target: { closest: () => { @@ -188,7 +188,7 @@ describe('Worker', () => { it(`should call to the delete() method`, () => { jest.spyOn(controller, 'delete').mockReturnThis(); - const selectedDay = new Date(); + const selectedDay = Date.vnNew(); const expectedEvent = { dated: selectedDay, type: 'holiday', @@ -212,7 +212,7 @@ describe('Worker', () => { it(`should call to the edit() method`, () => { jest.spyOn(controller, 'edit').mockReturnThis(); - const selectedDay = new Date(); + const selectedDay = Date.vnNew(); const expectedEvent = { dated: selectedDay, type: 'leaveOfAbsence', @@ -238,7 +238,7 @@ describe('Worker', () => { it(`should make a HTTP POST query and then call to the repaintCanceller() method`, () => { jest.spyOn(controller, 'repaintCanceller').mockReturnThis(); - const dated = new Date(); + const dated = Date.vnNew(); const calendarElement = {}; const expectedResponse = {id: 10}; @@ -287,7 +287,7 @@ describe('Worker', () => { const expectedParams = {absenceId: 10}; const calendarElement = {}; - const selectedDay = new Date(); + const selectedDay = Date.vnNew(); const expectedEvent = { dated: selectedDay, type: 'leaveOfAbsence', diff --git a/modules/worker/front/create/index.html b/modules/worker/front/create/index.html new file mode 100644 index 000000000..5f5ab9d07 --- /dev/null +++ b/modules/worker/front/create/index.html @@ -0,0 +1,194 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + {{code}} - {{town.name}} ({{town.province.name}}, + {{town.province.country.country}}) + + + + + + + + {{name}} ({{country.country}}) + + + + + + {{name}}, {{province.name}} + ({{province.country.country}}) + + + + + + + + + + + + + + + + + + + + + + {{bic}} {{name}} + + + + + + + + + + + + + +
+ + + diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js new file mode 100644 index 000000000..7e837fe02 --- /dev/null +++ b/modules/worker/front/create/index.js @@ -0,0 +1,127 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.worker = {companyFk: this.vnConfig.user.companyFk}; + } + + onSubmit() { + return this.$.watcher.submit().then(json => { + this.$state.go('worker.card.basicData', {id: json.data.id}); + }); + } + + autofillBic() { + if (!this.worker || !this.worker.iban) return; + + let bankEntityId = parseInt(this.worker.iban.substr(4, 4)); + let filter = {where: {id: bankEntityId}}; + + if (this.ibanCountry != 'ES') return; + + this.$http.get(`BankEntities`, {filter}).then(response => { + const hasData = response.data && response.data[0]; + + if (hasData) + this.worker.bankEntityFk = response.data[0].id; + else if (!hasData) + this.worker.bankEntityFk = null; + }); + } + + generateCodeUser() { + if (!this.worker.firstName || !this.worker.lastNames) return; + + const totalName = this.worker.firstName.concat(' ' + this.worker.lastNames).toLowerCase(); + const totalNameArray = totalName.split(' '); + let newCode = ''; + + for (let part of totalNameArray) + newCode += part.charAt(0); + + this.worker.code = newCode.toUpperCase().slice(0, 3); + this.worker.name = totalNameArray[0] + newCode.slice(1); + + if (!this.worker.companyFk) + this.worker.companyFk = this.vnConfig.user.companyFk; + } + + get province() { + return this._province; + } + + // Province auto complete + set province(selection) { + this._province = selection; + + if (!selection) return; + + const country = selection.country; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; + } + + get town() { + return this._town; + } + + // Town auto complete + set town(selection) { + this._town = selection; + + if (!selection) return; + + const province = selection.province; + const country = province.country; + const postcodes = selection.postcodes; + + if (!this.worker.provinceFk) + this.worker.provinceFk = province.id; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; + + if (postcodes.length === 1) + this.worker.postcode = postcodes[0].code; + } + + get postcode() { + return this._postcode; + } + + // Postcode auto complete + set postcode(selection) { + this._postcode = selection; + + if (!selection) return; + + const town = selection.town; + const province = town.province; + const country = province.country; + + if (!this.worker.city) + this.worker.city = town.name; + + if (!this.worker.provinceFk) + this.worker.provinceFk = province.id; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; + } + + onResponse(response) { + this.worker.postcode = response.code; + this.worker.city = response.city; + this.worker.provinceFk = response.provinceFk; + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnWorkerCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/create/index.spec.js b/modules/worker/front/create/index.spec.js new file mode 100644 index 000000000..c2e9acce0 --- /dev/null +++ b/modules/worker/front/create/index.spec.js @@ -0,0 +1,133 @@ +import './index'; + +describe('Worker', () => { + describe('Component vnWorkerCreate', () => { + let $scope; + let $state; + let controller; + + beforeEach(ngModule('worker')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $state = _$state_; + $scope.watcher = { + submit: () => { + return { + then: callback => { + callback({data: {id: '1234'}}); + } + }; + } + }; + const $element = angular.element(''); + controller = $componentController('vnWorkerCreate', {$element, $scope}); + controller.worker = {}; + controller.vnConfig = {user: {companyFk: 1}}; + })); + + describe('onSubmit()', () => { + it(`should call submit() on the watcher then expect a callback`, () => { + jest.spyOn($state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('worker.card.basicData', {id: '1234'}); + }); + }); + + describe('province() setter', () => { + it(`should set countryFk property`, () => { + controller.worker.countryFk = null; + controller.province = { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }; + + expect(controller.worker.countryFk).toEqual(2); + }); + }); + + describe('town() setter', () => { + it(`should set provinceFk property`, () => { + controller.town = { + provinceFk: 1, + code: 46001, + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }, + postcodes: [] + }; + + expect(controller.worker.provinceFk).toEqual(1); + }); + + it(`should set provinceFk property and fill the postalCode if there's just one`, () => { + controller.town = { + provinceFk: 1, + code: 46001, + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }, + postcodes: [{code: '46001'}] + }; + + expect(controller.worker.provinceFk).toEqual(1); + expect(controller.worker.postcode).toEqual('46001'); + }); + }); + + describe('postcode() setter', () => { + it(`should set the town, provinceFk and contryFk properties`, () => { + controller.postcode = { + townFk: 1, + code: 46001, + town: { + id: 1, + name: 'New York', + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + } + } + }; + + expect(controller.worker.city).toEqual('New York'); + expect(controller.worker.provinceFk).toEqual(1); + expect(controller.worker.countryFk).toEqual(2); + }); + }); + + describe('generateCodeUser()', () => { + it(`should generate worker code, name and company `, () => { + controller.worker = { + firstName: 'default', + lastNames: 'generate worker' + }; + + controller.generateCodeUser(); + + expect(controller.worker.code).toEqual('DGW'); + expect(controller.worker.name).toEqual('defaultgw'); + expect(controller.worker.companyFk).toEqual(controller.vnConfig.user.companyFk); + }); + }); + }); +}); diff --git a/modules/worker/front/create/locale/es.yml b/modules/worker/front/create/locale/es.yml new file mode 100644 index 000000000..8c79d770c --- /dev/null +++ b/modules/worker/front/create/locale/es.yml @@ -0,0 +1,12 @@ +Firstname: Nombre +Lastname: Apellidos +Fi: DNI/NIF/NIE +Birth: Fecha de nacimiento +Code: Código de trabajador +Province: Provincia +City: Población +ProfileType: Tipo de perfil +Street: Dirección +Postcode: Código postal +Web user: Usuario Web +Access permission: Permiso de acceso diff --git a/modules/worker/front/descriptor/index.js b/modules/worker/front/descriptor/index.js index 2ff032def..ef2f64e85 100644 --- a/modules/worker/front/descriptor/index.js +++ b/modules/worker/front/descriptor/index.js @@ -82,7 +82,7 @@ class Controller extends Descriptor { } onUploadResponse() { - const timestamp = new Date().getTime(); + const timestamp = Date.vnNew().getTime(); const src = this.$rootScope.imagePath('user', '520x520', this.worker.id); const zoomSrc = this.$rootScope.imagePath('user', '1600x1600', this.worker.id); const newSrc = `${src}&t=${timestamp}`; diff --git a/modules/worker/front/index.js b/modules/worker/front/index.js index f703e7c21..97126407c 100644 --- a/modules/worker/front/index.js +++ b/modules/worker/front/index.js @@ -4,6 +4,7 @@ import './main'; import './index/'; import './summary'; import './card'; +import './create'; import './descriptor'; import './descriptor-popover'; import './search-panel'; diff --git a/modules/worker/front/index/index.html b/modules/worker/front/index/index.html index 98df416b4..7044ca551 100644 --- a/modules/worker/front/index/index.html +++ b/modules/worker/front/index/index.html @@ -6,23 +6,23 @@ class="vn-w-sm">
+ + + - \ No newline at end of file + diff --git a/modules/worker/front/index/locale/es.yml b/modules/worker/front/index/locale/es.yml new file mode 100644 index 000000000..df6383273 --- /dev/null +++ b/modules/worker/front/index/locale/es.yml @@ -0,0 +1 @@ +New worker: Nuevo trabajador diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index ca33eaa76..dad55512b 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -16,7 +16,7 @@ {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.dms.index", "icon": "cloud_upload"}, { - "icon": "icon-wiki", + "icon": "icon-wiki", "external":true, "url": "http://wiki.verdnatura.es", "description": "Wikipedia" @@ -134,6 +134,13 @@ "worker": "$ctrl.worker" }, "acl": ["hr"] + }, + { + "url": "/create", + "state": "worker.create", + "component": "vn-worker-create", + "description": "New worker", + "acl": ["hr"] } ] -} \ No newline at end of file +} diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index c3d3e5eab..f7379fea0 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -16,7 +16,7 @@ class Controller extends Section { $postLink() { const timestamp = this.$params.timestamp; - let initialDate = new Date(); + let initialDate = Date.vnNew(); if (timestamp) { initialDate = new Date(timestamp * 1000); @@ -199,7 +199,7 @@ class Controller extends Section { getFinishTime() { if (!this.weekDays) return; - let today = new Date(); + let today = Date.vnNew(); today.setHours(0, 0, 0, 0); let todayInWeek = this.weekDays.find(day => day.dated.getTime() === today.getTime()); diff --git a/modules/worker/front/time-control/index.spec.js b/modules/worker/front/time-control/index.spec.js index 4f317a5e6..b68162d39 100644 --- a/modules/worker/front/time-control/index.spec.js +++ b/modules/worker/front/time-control/index.spec.js @@ -18,7 +18,7 @@ describe('Component vnWorkerTimeControl', () => { describe('date() setter', () => { it(`should set the weekDays, the date in the controller and call fetchHours`, () => { - let today = new Date(); + let today = Date.vnNew(); jest.spyOn(controller, 'fetchHours').mockReturnThis(); controller.date = today; @@ -33,7 +33,7 @@ describe('Component vnWorkerTimeControl', () => { describe('hours() setter', () => { it(`should set hours data at it's corresponding week day`, () => { - let today = new Date(); + let today = Date.vnNew(); jest.spyOn(controller, 'fetchHours').mockReturnThis(); controller.date = today; @@ -64,7 +64,7 @@ describe('Component vnWorkerTimeControl', () => { describe('getWorkedHours() ', () => { it('should set the weekdays expected and worked hours plus the total worked hours', () => { - let today = new Date(); + let today = Date.vnNew(); jest.spyOn(controller, 'fetchHours').mockReturnThis(); controller.date = today; @@ -117,7 +117,7 @@ describe('Component vnWorkerTimeControl', () => { describe('save() ', () => { it(`should make a query an then call to the fetchHours() method`, () => { controller.fetchHours = jest.fn(); - controller.selectedRow = {id: 1, timed: new Date(), direction: 'in'}; + controller.selectedRow = {id: 1, timed: Date.vnNew(), direction: 'in'}; controller.$.editEntry = { hide: () => {} }; diff --git a/modules/zone/back/methods/agency/specs/getAgenciesWithWarehouse.spec.js b/modules/zone/back/methods/agency/specs/getAgenciesWithWarehouse.spec.js index bc7aa1ed9..4f79b2315 100644 --- a/modules/zone/back/methods/agency/specs/getAgenciesWithWarehouse.spec.js +++ b/modules/zone/back/methods/agency/specs/getAgenciesWithWarehouse.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('Agency getAgenciesWithWarehouse()', () => { - const today = new Date(); + const today = Date.vnNew(); it('should return the agencies that can handle the given delivery request', async() => { const tx = await app.models.Zone.beginTransaction({}); diff --git a/modules/zone/back/methods/agency/specs/getLanded.spec.js b/modules/zone/back/methods/agency/specs/getLanded.spec.js index c199b2ba6..e2e6b3eb3 100644 --- a/modules/zone/back/methods/agency/specs/getLanded.spec.js +++ b/modules/zone/back/methods/agency/specs/getLanded.spec.js @@ -3,7 +3,7 @@ const models = require('vn-loopback/server/server').models; describe('agency getLanded()', () => { it('should return a landing date', async() => { const ctx = {req: {accessToken: {userId: 1}}}; - const shipped = new Date(); + const shipped = Date.vnNew(); shipped.setDate(shipped.getDate() + 1); const addressFk = 121; const agencyModeFk = 7; diff --git a/modules/zone/back/methods/agency/specs/getShipped.spec.js b/modules/zone/back/methods/agency/specs/getShipped.spec.js index f2b36fc94..43e2c1208 100644 --- a/modules/zone/back/methods/agency/specs/getShipped.spec.js +++ b/modules/zone/back/methods/agency/specs/getShipped.spec.js @@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server'); describe('agency getShipped()', () => { it('should return a shipment date', async() => { - const landed = new Date(); + const landed = Date.vnNew(); landed.setDate(landed.getDate() + 1); const addressFk = 121; const agencyModeFk = 7; @@ -25,7 +25,7 @@ describe('agency getShipped()', () => { }); it('should not return a shipment date', async() => { - const newDate = new Date(); + const newDate = Date.vnNew(); newDate.setMonth(newDate.getMonth() - 1); const landed = newDate; const addressFk = 121; diff --git a/modules/zone/back/methods/agency/specs/landsThatDay.spec.js b/modules/zone/back/methods/agency/specs/landsThatDay.spec.js index 7d207b383..ea10e708f 100644 --- a/modules/zone/back/methods/agency/specs/landsThatDay.spec.js +++ b/modules/zone/back/methods/agency/specs/landsThatDay.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('Agency landsThatDay()', () => { - const today = new Date(); + const today = Date.vnNew(); it('should return a list of agencies that can land a shipment on a day for an address', async() => { const tx = await app.models.Agency.beginTransaction({}); diff --git a/modules/zone/back/methods/zone/deleteZone.js b/modules/zone/back/methods/zone/deleteZone.js index fb228bcf4..e3846132b 100644 --- a/modules/zone/back/methods/zone/deleteZone.js +++ b/modules/zone/back/methods/zone/deleteZone.js @@ -22,7 +22,7 @@ module.exports = Self => { const models = Self.app.models; const token = ctx.req.accessToken; const userId = token.userId; - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); let tx; diff --git a/modules/zone/back/methods/zone/getZoneClosing.js b/modules/zone/back/methods/zone/getZoneClosing.js index 2a0088203..76706b55c 100644 --- a/modules/zone/back/methods/zone/getZoneClosing.js +++ b/modules/zone/back/methods/zone/getZoneClosing.js @@ -31,7 +31,7 @@ module.exports = Self => { Object.assign(myOptions, options); query = ` - SELECT * + SELECT * FROM ( SELECT DISTINCT z.id, @@ -40,18 +40,21 @@ module.exports = Self => { IFNULL(ze.hour, z.hour) as hour, IFNULL(ze.price, z.price) as price FROM vn.zone z - JOIN agencyMode am ON am.id = z.agencyModeFk - LEFT JOIN zoneEvent ze ON ze.zoneFk = z.id - WHERE - ( - dated = ? - OR ? BETWEEN started AND ended - OR INSTR(weekDays, SUBSTRING(DAYNAME(?), 1, 3) ) > 0 - ) + JOIN vn.agencyMode am ON am.id = z.agencyModeFk + LEFT JOIN vn.zoneEvent ze ON ze.zoneFk = z.id + WHERE (( + ze.type = 'day' + AND ze.dated = ? + ) OR ( + ze.type != 'day' + AND ze.weekDays & (1 << WEEKDAY(?)) + AND (ze.started IS NULL OR ? >= ze.started) + AND (ze.ended IS NULL OR ? <= ze.ended) + )) AND z.id IN (?) ORDER BY type='day' DESC, type='range' DESC, type='indefinitely' DESC) z GROUP BY z.id`; - return Self.rawSql(query, [date, date, date, zoneIds], myOptions); + return Self.rawSql(query, [date, date, date, date, zoneIds], myOptions); }; }; diff --git a/modules/zone/back/methods/zone/specs/exclusionGeo.spec.js b/modules/zone/back/methods/zone/specs/exclusionGeo.spec.js index 3a345f2ce..a34132be4 100644 --- a/modules/zone/back/methods/zone/specs/exclusionGeo.spec.js +++ b/modules/zone/back/methods/zone/specs/exclusionGeo.spec.js @@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models; describe('zone exclusionGeo()', () => { const zoneId = 1; - const today = new Date(); + const today = Date.vnNew(); it(`should show an error when location isn't selected`, async() => { const tx = await models.Zone.beginTransaction({}); diff --git a/modules/zone/back/methods/zone/specs/getEventsFiltered.spec.js b/modules/zone/back/methods/zone/specs/getEventsFiltered.spec.js index 8160ee05e..6fd6bb994 100644 --- a/modules/zone/back/methods/zone/specs/getEventsFiltered.spec.js +++ b/modules/zone/back/methods/zone/specs/getEventsFiltered.spec.js @@ -6,7 +6,7 @@ describe('zone getEventsFiltered()', () => { try { const options = {transaction: tx}; - const today = new Date(); + const today = Date.vnNew(); const result = await models.Zone.getEventsFiltered(10, today, today, options); @@ -26,7 +26,7 @@ describe('zone getEventsFiltered()', () => { try { const options = {transaction: tx}; - const today = new Date(); + const today = Date.vnNew(); const result = await models.Zone.getEventsFiltered(9, today, today, options); @@ -45,7 +45,7 @@ describe('zone getEventsFiltered()', () => { try { const options = {transaction: tx}; - const date = new Date(); + const date = Date.vnNew(); date.setFullYear(date.getFullYear() - 2); const dateTomorrow = new Date(date.setDate(date.getDate() + 1)); diff --git a/modules/zone/back/methods/zone/specs/getZoneClosing.spec.js b/modules/zone/back/methods/zone/specs/getZoneClosing.spec.js index 4fb4b4e5c..cdd6fe584 100644 --- a/modules/zone/back/methods/zone/specs/getZoneClosing.spec.js +++ b/modules/zone/back/methods/zone/specs/getZoneClosing.spec.js @@ -6,7 +6,7 @@ describe('zone getZoneClosing()', () => { try { const options = {transaction: tx}; - const date = new Date(); + const date = Date.vnNew(); const today = date.toISOString().split('T')[0]; const result = await models.Zone.getZoneClosing([1, 2, 3], today, options); diff --git a/modules/zone/back/methods/zone/specs/includingExpired.spec.js b/modules/zone/back/methods/zone/specs/includingExpired.spec.js index 98fdc272d..121a84887 100644 --- a/modules/zone/back/methods/zone/specs/includingExpired.spec.js +++ b/modules/zone/back/methods/zone/specs/includingExpired.spec.js @@ -50,7 +50,7 @@ describe('zone includingExpired()', () => { it('should return an array containing available zones', async() => { const ctx = {req: {accessToken: {userId: 1}}}; const where = { - shipped: new Date(), + shipped: Date.vnNew(), addressFk: addressId, agencyModeFk: inhousePickupId, warehouseFk: warehouseId diff --git a/modules/zone/front/calendar/index.js b/modules/zone/front/calendar/index.js index 3bc7158ef..288a8f328 100644 --- a/modules/zone/front/calendar/index.js +++ b/modules/zone/front/calendar/index.js @@ -8,7 +8,7 @@ class Controller extends Component { this.vnWeekDays = vnWeekDays; this.nMonths = 4; - let date = new Date(); + let date = Date.vnNew(); date.setDate(1); date.setHours(0, 0, 0, 0); this.date = date; diff --git a/modules/zone/front/calendar/index.spec.js b/modules/zone/front/calendar/index.spec.js index 338f47917..43280a9e8 100644 --- a/modules/zone/front/calendar/index.spec.js +++ b/modules/zone/front/calendar/index.spec.js @@ -22,7 +22,7 @@ describe('component vnZoneCalendar', () => { it('should set the month property and then call the refreshEvents() method', () => { jest.spyOn(controller, 'refreshEvents').mockReturnThis(); - controller.date = new Date(); + controller.date = Date.vnNew(); expect(controller.refreshEvents).toHaveBeenCalledWith(); expect(controller.months.length).toEqual(4); @@ -31,7 +31,7 @@ describe('component vnZoneCalendar', () => { describe('step()', () => { it('should set the date month to 4 months backwards', () => { - const now = new Date(); + const now = Date.vnNew(); now.setDate(15); now.setMonth(now.getMonth() - 4); @@ -44,7 +44,7 @@ describe('component vnZoneCalendar', () => { }); it('should set the date month to 4 months forwards', () => { - const now = new Date(); + const now = Date.vnNew(); now.setDate(15); now.setMonth(now.getMonth() + 4); @@ -63,13 +63,13 @@ describe('component vnZoneCalendar', () => { controller.data = { exclusions: [{ - dated: new Date() + dated: Date.vnNew() }], events: [{ - dated: new Date() + dated: Date.vnNew() }], geoExclusions: [{ - dated: new Date() + dated: Date.vnNew() }], }; @@ -85,9 +85,9 @@ describe('component vnZoneCalendar', () => { describe('refreshEvents()', () => { it('should fill the days property with the events.', () => { controller.data = []; - controller.firstDay = new Date(); + controller.firstDay = Date.vnNew(); - const lastDay = new Date(); + const lastDay = Date.vnNew(); lastDay.setDate(lastDay.getDate() + 10); controller.lastDay = lastDay; @@ -114,7 +114,7 @@ describe('component vnZoneCalendar', () => { jest.spyOn(controller, 'emit'); const $event = {}; - const $days = [new Date()]; + const $days = [Date.vnNew()]; const $type = 'day'; const $weekday = 1; @@ -136,7 +136,7 @@ describe('component vnZoneCalendar', () => { describe('hasEvents()', () => { it('should return true for an existing event on a date', () => { - const dated = new Date(); + const dated = Date.vnNew(); controller.days[dated.getTime()] = true; @@ -148,7 +148,7 @@ describe('component vnZoneCalendar', () => { describe('getClass()', () => { it('should return the className "excluded" for an excluded date', () => { - const dated = new Date(); + const dated = Date.vnNew(); controller.exclusions = []; controller.exclusions[dated.getTime()] = true; @@ -159,7 +159,7 @@ describe('component vnZoneCalendar', () => { }); it('should return the className "geoExcluded" for a date with geo excluded', () => { - const dated = new Date(); + const dated = Date.vnNew(); controller.geoExclusions = []; controller.geoExclusions[dated.getTime()] = true; diff --git a/modules/zone/front/create/index.js b/modules/zone/front/create/index.js index 859204d8d..db337a9a3 100644 --- a/modules/zone/front/create/index.js +++ b/modules/zone/front/create/index.js @@ -7,7 +7,7 @@ export default class Controller extends Section { travelingDays: 0, price: 0.20, bonus: 0.20, - hour: new Date() + hour: Date.vnNew() }; } diff --git a/modules/zone/front/delivery-days/index.spec.js b/modules/zone/front/delivery-days/index.spec.js index 63c87fbea..28705880c 100644 --- a/modules/zone/front/delivery-days/index.spec.js +++ b/modules/zone/front/delivery-days/index.spec.js @@ -103,7 +103,7 @@ describe('Zone Component vnZoneDeliveryDays', () => { const target = document.createElement('div'); target.dispatchEvent(event); - const day = new Date(); + const day = Date.vnNew(); const events = [ {zoneFk: 1}, {zoneFk: 2}, diff --git a/modules/zone/front/descriptor/index.js b/modules/zone/front/descriptor/index.js index 08ada0606..3f4863a60 100644 --- a/modules/zone/front/descriptor/index.js +++ b/modules/zone/front/descriptor/index.js @@ -28,7 +28,7 @@ class Controller extends Descriptor { onDelete() { const $t = this.$translate.instant; - const today = new Date(); + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); const filter = {where: {zoneFk: this.id, shipped: {gte: today}}}; this.$http.get(`Tickets`, {filter}).then(res => { diff --git a/modules/zone/front/events/index.spec.js b/modules/zone/front/events/index.spec.js index b4ff800d6..558d97b6f 100644 --- a/modules/zone/front/events/index.spec.js +++ b/modules/zone/front/events/index.spec.js @@ -68,7 +68,7 @@ describe('component vnZoneEvents', () => { it('should call the createInclusion() method', () => { jest.spyOn(controller, 'createInclusion').mockReturnThis(); - const weekday = {dated: new Date()}; + const weekday = {dated: Date.vnNew()}; const days = [weekday]; const type = 'EventType'; const events = []; @@ -114,7 +114,7 @@ describe('component vnZoneEvents', () => { jest.spyOn(controller, 'createExclusion').mockReturnThis(); const weekday = {}; - const days = [{dated: new Date()}]; + const days = [{dated: Date.vnNew()}]; const type = 'EventType'; const events = []; const exclusions = []; @@ -156,7 +156,7 @@ describe('component vnZoneEvents', () => { it('shoud set the excludeSelected property and then call the excludeDialog show() method', () => { controller.$.excludeDialog = {show: jest.fn()}; - const days = [new Date()]; + const days = [Date.vnNew()]; controller.createExclusion(days); expect(controller.excludeSelected).toBeDefined(); @@ -170,7 +170,7 @@ describe('component vnZoneEvents', () => { controller.$.includeDialog = {show: jest.fn()}; const type = 'weekday'; - const days = [new Date()]; + const days = [Date.vnNew()]; const weekday = 1; controller.createInclusion(type, days, weekday); @@ -187,7 +187,7 @@ describe('component vnZoneEvents', () => { controller.$.includeDialog = {show: jest.fn()}; const type = 'nonListedType'; - const days = [new Date()]; + const days = [Date.vnNew()]; const weekday = 1; controller.createInclusion(type, days, weekday); 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..f9828624d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "9.0.0", + "version": "23.06.01", "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/core/mixins/vn-report.js b/print/core/mixins/vn-report.js new file mode 100644 index 000000000..4831d8cd9 --- /dev/null +++ b/print/core/mixins/vn-report.js @@ -0,0 +1,23 @@ +const Component = require(`vn-print/core/component`); +const reportHeader = new Component('report-header'); +const reportFooter = new Component('report-footer'); +const reportBody = new Component('report-body'); +const NotFoundError = require('vn-loopback/util/not-found-error'); + +module.exports = { + components: { + 'report-body': reportBody.build(), + 'report-header': reportHeader.build(), + 'report-footer': reportFooter.build() + }, + methods: { + checkMainEntity: function(entity) { + if (entity == null) + throw new NotFoundError(); + }, + formatDate: function(date, format) { + const filters = this.$options.filters; + return filters.date(date, format); + } + }, +}; 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/buyer-week-waste/buyer-week-waste.js b/print/templates/email/buyer-week-waste/buyer-week-waste.js index 9d4fe1ce1..1ae40cd98 100755 --- a/print/templates/email/buyer-week-waste/buyer-week-waste.js +++ b/print/templates/email/buyer-week-waste/buyer-week-waste.js @@ -13,7 +13,7 @@ module.exports = { dated: function() { const filters = this.$options.filters; - return filters.date(new Date(), '%d-%m-%Y'); + return filters.date(Date.vnNew(), '%d-%m-%Y'); } }, methods: { diff --git a/print/templates/email/email-verify/email-verify.js b/print/templates/email/email-verify/email-verify.js index 7f0b80a13..4f2b29266 100755 --- a/print/templates/email/email-verify/email-verify.js +++ b/print/templates/email/email-verify/email-verify.js @@ -10,7 +10,7 @@ module.exports = { }, props: { url: { - type: [String], + type: String, required: true } } 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/email/osticket-report/osticket-report.js b/print/templates/email/osticket-report/osticket-report.js index eb9c76a89..0d39947d5 100755 --- a/print/templates/email/osticket-report/osticket-report.js +++ b/print/templates/email/osticket-report/osticket-report.js @@ -37,7 +37,7 @@ module.exports = { dated: function() { const filters = this.$options.filters; - return filters.date(new Date(), '%d-%m-%Y'); + return filters.date(Date.vnNew(), '%d-%m-%Y'); }, startedTime: function() { return new Date(this.started).getTime(); diff --git a/print/templates/email/printer-setup/locale/es.yml b/print/templates/email/printer-setup/locale/es.yml index 77a3a7299..7361e5ed3 100644 --- a/print/templates/email/printer-setup/locale/es.yml +++ b/print/templates/email/printer-setup/locale/es.yml @@ -8,8 +8,8 @@ description: https://www.youtube.com/watch?v=qhb0kgQF3o8. También necesitarás el QLabel, el programa para imprimir las cintas. - downloadFrom: Puedes descargarlo desde este enlace https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01 + downloadFrom: Puedes descargarlo desde este enlace https://cdn.verdnatura.es/public/QLabel_IV_V1.37_Install_en.exe downloadDriver: En este enlace puedes descargar el driver de la impresora https://es.seagullscientific.com/support/downloads/drivers/godex/download/ sections: diff --git a/print/templates/email/recover-password/recover-password.js b/print/templates/email/recover-password/recover-password.js index b589411a9..d8448f370 100755 --- a/print/templates/email/recover-password/recover-password.js +++ b/print/templates/email/recover-password/recover-password.js @@ -10,7 +10,7 @@ module.exports = { }, props: { url: { - type: [String], + type: String, required: true } } diff --git a/print/templates/email/worker-welcome/assets/css/import.js b/print/templates/email/worker-welcome/assets/css/import.js new file mode 100644 index 000000000..4b4bb7086 --- /dev/null +++ b/print/templates/email/worker-welcome/assets/css/import.js @@ -0,0 +1,11 @@ +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/email.css`]) + .mergeStyles(); diff --git a/print/templates/email/worker-welcome/locale/es.yml b/print/templates/email/worker-welcome/locale/es.yml new file mode 100644 index 000000000..d53a4e1f0 --- /dev/null +++ b/print/templates/email/worker-welcome/locale/es.yml @@ -0,0 +1,8 @@ +subject: Bienvenido a Verdnatura +title: "¡Te damos la bienvenida!" +dearWorker: Estimado trabajador +workerData: 'Estos son los datos de tu usuario de Verdnatura. + Usuario: {0}. Haz click aquí para + establecer tu contraseña + .' diff --git a/print/templates/email/worker-welcome/sql/worker.sql b/print/templates/email/worker-welcome/sql/worker.sql new file mode 100644 index 000000000..f75d135d9 --- /dev/null +++ b/print/templates/email/worker-welcome/sql/worker.sql @@ -0,0 +1,7 @@ +SELECT + u.id, + u.name, + e.email +FROM account.user u + LEFT JOIN account.emailUser e ON e.userFk = u.id +WHERE u.id = ?; diff --git a/print/templates/email/worker-welcome/worker-welcome.html b/print/templates/email/worker-welcome/worker-welcome.html new file mode 100644 index 000000000..fbb05d149 --- /dev/null +++ b/print/templates/email/worker-welcome/worker-welcome.html @@ -0,0 +1,9 @@ + +

+
+

{{ $t('title', [id]) }}

+

{{ $t('dearWorker') }},

+

+
+
+ diff --git a/print/templates/email/worker-welcome/worker-welcome.js b/print/templates/email/worker-welcome/worker-welcome.js new file mode 100755 index 000000000..043a172a1 --- /dev/null +++ b/print/templates/email/worker-welcome/worker-welcome.js @@ -0,0 +1,27 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); + +module.exports = { + name: 'worker-welcome', + async serverPrefetch() { + this.worker = await this.fetchWorker(this.id); + }, + methods: { + fetchWorker(id) { + return this.findOneFromDef('worker', [id]); + }, + }, + components: { + 'email-body': emailBody.build(), + }, + props: { + id: { + type: Number, + required: true + }, + url: { + type: String, + required: true + } + } +}; diff --git a/print/templates/reports/balance-compensation/balance-compensation.html b/print/templates/reports/balance-compensation/balance-compensation.html index 59af1bd11..1e9aa5661 100644 --- a/print/templates/reports/balance-compensation/balance-compensation.html +++ b/print/templates/reports/balance-compensation/balance-compensation.html @@ -3,7 +3,7 @@
-

{{$t('Place')}} {{currentDate()}}

+

{{$t('Place')}} {{formatDate(new Date(), '%d-%m-%Y')}}

{{$t('Compensation') | uppercase}}

{{$t('In one hand')}}:

@@ -17,7 +17,7 @@

{{$t('Agree') | uppercase}}

- {{$t('Date')}} {{client.payed | date('%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} € + {{$t('Date')}} {{formatDate(client.payed, '%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} € {{$t('From client')}} {{client.name}} {{$t('Toclient')}} {{company.name}}.

diff --git a/print/templates/reports/balance-compensation/balance-compensation.js b/print/templates/reports/balance-compensation/balance-compensation.js index 98a9cf577..bae7c5c3c 100644 --- a/print/templates/reports/balance-compensation/balance-compensation.js +++ b/print/templates/reports/balance-compensation/balance-compensation.js @@ -1,28 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'balance-compensation', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.company = await this.fetchCompany(this.id); - }, - methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchCompany(id) { - return this.findOneFromDef('company', [id]); - }, - - currentDate() { - const current = new Date(); - const date = `${current.getDate()}/${current.getMonth() + 1}/${current.getFullYear()}`; - return date; - } - }, - components: { - 'report-body': reportBody.build() + this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); + this.company = await this.findOneFromDef('company', [this.id]); }, props: { id: { diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.html b/print/templates/reports/campaign-metrics/campaign-metrics.html index e86d4cd3b..57d616a29 100644 --- a/print/templates/reports/campaign-metrics/campaign-metrics.html +++ b/print/templates/reports/campaign-metrics/campaign-metrics.html @@ -13,11 +13,11 @@ {{$t('From')}} - {{from | date('%d-%m-%Y')}} + {{formatDate(from, '%d-%m-%Y')}} {{$t('To')}} - {{to | date('%d-%m-%Y')}} + {{formatDate(to, '%d-%m-%Y')}} diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.js b/print/templates/reports/campaign-metrics/campaign-metrics.js index 14a4b6a9b..45bca88dc 100755 --- a/print/templates/reports/campaign-metrics/campaign-metrics.js +++ b/print/templates/reports/campaign-metrics/campaign-metrics.js @@ -1,27 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'campaign-metrics', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.sales = await this.fetchSales(this.id, this.from, this.to); - - if (!this.client) - throw new Error('Something went wrong'); - }, - methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchSales(id, from, to) { - return this.rawSqlFromDef('sales', [id, from, to]); - }, - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() + this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); + this.sales = await this.rawSqlFromDef('sales', [this.id, this.from, this.to]); }, props: { id: { diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.html b/print/templates/reports/claim-pickup-order/claim-pickup-order.html index b14f5410c..000568ef2 100644 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.html +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.html @@ -20,7 +20,7 @@ {{$t('date')}} - {{dated}} + {{formatDate(new Date(), '%d-%m-%Y')}} diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.js b/print/templates/reports/claim-pickup-order/claim-pickup-order.js index 5c7002e47..cc5cec1ea 100755 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.js +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.js @@ -1,34 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'claim-pickup-order', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.sales = await this.fetchSales(this.id); - - if (!this.client) - throw new Error('Something went wrong'); - }, - computed: { - dated: function() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%d-%m-%Y'); - } - }, - methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchSales(id) { - return this.rawSqlFromDef('sales', [id]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() + this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); + this.sales = await this.rawSqlFromDef('sales', [this.id]); }, props: { id: { @@ -36,5 +14,5 @@ module.exports = { required: true, description: 'The claim id' } - } + }, }; diff --git a/print/templates/reports/client-debt-statement/client-debt-statement.html b/print/templates/reports/client-debt-statement/client-debt-statement.html index 962af021d..fb7bfd625 100644 --- a/print/templates/reports/client-debt-statement/client-debt-statement.html +++ b/print/templates/reports/client-debt-statement/client-debt-statement.html @@ -13,7 +13,7 @@ {{$t('date')}} - {{dated}} + {{formatDate(new Date(), '%d-%m-%Y');}} @@ -44,7 +44,7 @@ - {{sale.issued | date('%d-%m-%Y')}} + {{formatDate(sale.issued, '%d-%m-%Y');}} {{sale.ref}} {{sale.debtOut}} {{sale.debtIn}} diff --git a/print/templates/reports/client-debt-statement/client-debt-statement.js b/print/templates/reports/client-debt-statement/client-debt-statement.js index 45b97518f..a74595200 100755 --- a/print/templates/reports/client-debt-statement/client-debt-statement.js +++ b/print/templates/reports/client-debt-statement/client-debt-statement.js @@ -1,44 +1,18 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'client-debt-statement', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.sales = await this.fetchSales(this.id, this.from); - - if (!this.client) - throw new Error('Something went wrong'); - }, - computed: { - dated: function() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%d-%m-%Y'); - } + this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); + this.sales = await this.rawSqlFromDef('sales', + [this.from, this.id, this.from, this.id, this.from, this.id, this.from, this.id, this.from, this.id]); }, data() { return {totalBalance: 0.00}; }, methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchSales(id, from) { - return this.rawSqlFromDef('sales', [ - from, - id, - from, - id, - from, - id, - from, - id, - from, - id - ]); - }, getBalance(sale) { if (sale.debtOut) this.totalBalance += parseFloat(sale.debtOut); @@ -63,10 +37,6 @@ module.exports = { return debtIn.toFixed(2); }, }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() - }, props: { id: { type: Number, diff --git a/print/templates/reports/collection-label/collection-label.js b/print/templates/reports/collection-label/collection-label.js index e73afaeea..74024bb56 100644 --- a/print/templates/reports/collection-label/collection-label.js +++ b/print/templates/reports/collection-label/collection-label.js @@ -1,11 +1,10 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); const jsBarcode = require('jsbarcode'); const {DOMImplementation, XMLSerializer} = require('xmldom'); -const UserError = require('vn-loopback/util/user-error'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'collection-label', + mixins: [vnReport], props: { id: { type: Number, @@ -30,8 +29,7 @@ module.exports = { ticketIds = [this.id]; this.labelsData = await this.rawSqlFromDef('labelsData', [ticketIds]); - if (!this.labelsData.length) - throw new UserError('Empty data source'); + this.checkMainEntity(this.labelsData); }, methods: { getBarcode(id) { @@ -62,7 +60,4 @@ module.exports = { return value; }, }, - components: { - 'report-body': reportBody.build() - }, }; diff --git a/print/templates/reports/credit-request/credit-request.html b/print/templates/reports/credit-request/credit-request.html index d5e336809..c8e3f8c34 100644 --- a/print/templates/reports/credit-request/credit-request.html +++ b/print/templates/reports/credit-request/credit-request.html @@ -159,6 +159,6 @@

diff --git a/print/templates/reports/credit-request/credit-request.js b/print/templates/reports/credit-request/credit-request.js index c1aa74e1b..75e0b2263 100755 --- a/print/templates/reports/credit-request/credit-request.js +++ b/print/templates/reports/credit-request/credit-request.js @@ -1,20 +1,7 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body') -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); -const rptCreditRequest = { +module.exports = { name: 'credit-request', - computed: { - dated: function() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%d-%m-%Y'); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() - } + mixins: [vnReport], }; -module.exports = rptCreditRequest; diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index 06653c949..9f217ba22 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -20,7 +20,7 @@ {{$t('date')}} - {{ticket.shipped | date('%d-%m-%Y')}} + {{formatDate(ticket.shipped, '%d-%m-%Y')}} {{$t('packages')}} @@ -231,7 +231,7 @@
{{$t('digitalSignature')}}
-
{{signature.created | date('%d-%m-%Y')}}
+
{{formatDate(signature.created, '%d-%m-%Y')}}

diff --git a/print/templates/reports/delivery-note/delivery-note.js b/print/templates/reports/delivery-note/delivery-note.js index 1a1a57c59..d9544a58c 100755 --- a/print/templates/reports/delivery-note/delivery-note.js +++ b/print/templates/reports/delivery-note/delivery-note.js @@ -1,25 +1,21 @@ const config = require(`vn-print/core/config`); -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); const md5 = require('md5'); const fs = require('fs-extra'); module.exports = { name: 'delivery-note', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.ticket = await this.fetchTicket(this.id); - this.sales = await this.fetchSales(this.id); - this.address = await this.fetchAddress(this.id); - this.services = await this.fetchServices(this.id); - this.taxes = await this.fetchTaxes(this.id); - this.packagings = await this.fetchPackagings(this.id); - this.signature = await this.fetchSignature(this.id); - - if (!this.ticket) - throw new Error('Something went wrong'); + this.ticket = await this.findOneFromDef('ticket', [this.id]); + this.checkMainEntity(this.ticket); + this.client = await this.findOneFromDef('client', [this.id]); + this.sales = await this.rawSqlFromDef('sales', [this.id]); + this.address = await this.findOneFromDef(`address`, [this.id]); + this.services = await this.rawSqlFromDef('services', [this.id]); + this.taxes = await this.rawSqlFromDef('taxes', [this.id]); + this.packagings = await this.rawSqlFromDef('packagings', [this.id]); + this.signature = await this.findOneFromDef('signature', [this.id]); }, data() { return {totalBalance: 0.00}; @@ -61,31 +57,6 @@ module.exports = { } }, methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchTicket(id) { - return this.findOneFromDef('ticket', [id]); - }, - fetchAddress(id) { - return this.findOneFromDef(`address`, [id]); - }, - fetchSignature(id) { - return this.findOneFromDef('signature', [id]); - }, - fetchTaxes(id) { - return this.findOneFromDef(`taxes`, [id]); - }, - fetchSales(id) { - return this.rawSqlFromDef('sales', [id]); - }, - fetchPackagings(id) { - return this.rawSqlFromDef('packagings', [id]); - }, - fetchServices(id) { - return this.rawSqlFromDef('services', [id]); - }, - getSubTotal() { let subTotal = 0.00; this.sales.forEach(sale => { @@ -125,11 +96,6 @@ module.exports = { ).join(', '); } }, - components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build(), - 'report-footer': reportFooter.build() - }, props: { id: { type: Number, diff --git a/print/templates/reports/driver-route/driver-route.html b/print/templates/reports/driver-route/driver-route.html index 48489de6f..1475b8e77 100644 --- a/print/templates/reports/driver-route/driver-route.html +++ b/print/templates/reports/driver-route/driver-route.html @@ -16,13 +16,13 @@ {{$t('date')}} - {{route.created | date('%d-%m-%Y')}} + {{formatDate(route.created, '%d-%m-%Y')}} {{$t('vehicle')}} {{route.vehicleTradeMark}} {{route.vehicleModel}} {{$t('time')}} - {{route.time | date('%H:%M')}} + {{formatDate(route.time, '%H:%M')}} {{route.plateNumber}} diff --git a/print/templates/reports/driver-route/driver-route.js b/print/templates/reports/driver-route/driver-route.js index 1b2e8871a..c166e3809 100755 --- a/print/templates/reports/driver-route/driver-route.js +++ b/print/templates/reports/driver-route/driver-route.js @@ -1,9 +1,8 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'driver-route', + mixins: [vnReport], async serverPrefetch() { let ids = this.id; @@ -11,8 +10,8 @@ module.exports = { if (hasMultipleRoutes) ids = this.id.split(','); - const routes = await this.fetchRoutes(ids); - const tickets = await this.fetchTickets(ids); + const routes = await this.rawSqlFromDef('routes', [ids]); + const tickets = await this.rawSqlFromDef('tickets', [ids, ids]); const map = new Map(); @@ -27,20 +26,7 @@ module.exports = { this.routes = routes; - if (!this.routes) - throw new Error('Something went wrong'); - }, - methods: { - fetchRoutes(ids) { - return this.rawSqlFromDef('routes', [ids]); - }, - fetchTickets(ids) { - return this.rawSqlFromDef('tickets', [ids, ids]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() + this.checkMainEntity(this.routes); }, props: { id: { diff --git a/print/templates/reports/entry-order/entry-order.html b/print/templates/reports/entry-order/entry-order.html index 26294787b..5d362dea9 100644 --- a/print/templates/reports/entry-order/entry-order.html +++ b/print/templates/reports/entry-order/entry-order.html @@ -16,7 +16,7 @@ {{$t('date')}} - {{entry.landed | date('%d-%m-%Y')}} + {{formatDate(entry.landed,'%d-%m-%Y')}} {{$t('ref')}} diff --git a/print/templates/reports/entry-order/entry-order.js b/print/templates/reports/entry-order/entry-order.js index 22c5b55fe..d31ad1a36 100755 --- a/print/templates/reports/entry-order/entry-order.js +++ b/print/templates/reports/entry-order/entry-order.js @@ -1,31 +1,18 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'entry-order', + mixins: [vnReport], async serverPrefetch() { - this.supplier = await this.fetchSupplier(this.id); - this.entry = await this.fetchEntry(this.id); - this.buys = await this.fetchBuys(this.id); - - if (!this.entry) - throw new Error('Something went wrong'); + this.entry = await this.findOneFromDef('entry', [this.id]); + this.checkMainEntity(this.entry); + this.supplier = await this.findOneFromDef('supplier', [this.id]); + this.buys = await this.rawSqlFromDef('buys', [this.id]); }, data() { return {totalBalance: 0.00}; }, methods: { - fetchSupplier(id) { - return this.findOneFromDef('supplier', [id]); - }, - fetchEntry(id) { - return this.findOneFromDef('entry', [id]); - }, - fetchBuys(id) { - return this.rawSqlFromDef('buys', [id]); - }, getTotal() { let total = 0.00; this.buys.forEach(buy => { @@ -35,11 +22,6 @@ module.exports = { return total; } }, - components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build(), - 'report-footer': reportFooter.build() - }, props: { id: { type: Number, diff --git a/print/templates/reports/expedition-pallet-label/expedition-pallet-label.js b/print/templates/reports/expedition-pallet-label/expedition-pallet-label.js index 0e8c297e8..88645309d 100644 --- a/print/templates/reports/expedition-pallet-label/expedition-pallet-label.js +++ b/print/templates/reports/expedition-pallet-label/expedition-pallet-label.js @@ -1,12 +1,11 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); +const vnReport = require('../../../core/mixins/vn-report.js'); const jsBarcode = require('jsbarcode'); const {DOMImplementation, XMLSerializer} = require('xmldom'); -const UserError = require('vn-loopback/util/user-error'); const qrcode = require('qrcode'); module.exports = { name: 'expedition-pallet-label', + mixins: [vnReport], props: { id: { type: Number, @@ -27,14 +26,13 @@ module.exports = { let QRdata = JSON.stringify({ company: 'vnl', user: this.userFk, - created: new Date(), + created: Date.vnNew(), table: 'expeditionPallet', id: this.id }); this.QR = await this.getQR(QRdata); - if (!this.labelsData.length) - throw new UserError('Empty data source'); + this.checkMainEntity(this.labelsData); }, methods: { getQR(id) { @@ -56,7 +54,4 @@ module.exports = { return xmlSerializer.serializeToString(svgNode); }, }, - components: { - 'report-body': reportBody.build() - }, }; diff --git a/print/templates/reports/exportation/exportation.html b/print/templates/reports/exportation/exportation.html index 920e32a48..0800c024d 100644 --- a/print/templates/reports/exportation/exportation.html +++ b/print/templates/reports/exportation/exportation.html @@ -3,7 +3,7 @@

{{$t('title')}}

{{$t('toAttention')}}

-

+

  • @@ -32,4 +32,4 @@ - \ No newline at end of file + diff --git a/print/templates/reports/exportation/exportation.js b/print/templates/reports/exportation/exportation.js index 9f39aa1a1..123b350ee 100755 --- a/print/templates/reports/exportation/exportation.js +++ b/print/templates/reports/exportation/exportation.js @@ -1,33 +1,13 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'exportation', + mixins: [vnReport], async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.reference); - - if (!this.invoice) - throw new Error('Something went wrong'); - + this.invoice = await this.findOneFromDef('invoice', [this.reference]); + this.checkMainEntity(this.invoice); this.company = await this.findOneFromDef('company', [this.invoice.companyFk]); }, - methods: { - fetchInvoice(reference) { - return this.findOneFromDef('invoice', [reference]); - } - }, - computed: { - issued: function() { - const filters = this.$options.filters; - - return filters.date(this.invoice.issued, '%d-%m-%Y'); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() - }, props: { reference: { type: Number, diff --git a/print/templates/reports/extra-community/extra-community.html b/print/templates/reports/extra-community/extra-community.html index 6a46cc689..cd61a4f4d 100644 --- a/print/templates/reports/extra-community/extra-community.html +++ b/print/templates/reports/extra-community/extra-community.html @@ -26,7 +26,7 @@ {{$t('shipped')}} - {{travel.shipped | date('%d-%m-%Y')}} + {{formatDate(travel.shipped, '%d-%m-%Y')}} {{$t('physicalKg')}} {{travel.loadedKg | number($i18n.locale)}} @@ -62,6 +62,6 @@
diff --git a/print/templates/reports/extra-community/extra-community.js b/print/templates/reports/extra-community/extra-community.js index 4dfe6e278..9941faa35 100755 --- a/print/templates/reports/extra-community/extra-community.js +++ b/print/templates/reports/extra-community/extra-community.js @@ -1,12 +1,10 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); const db = require(`vn-print/core/database`); module.exports = { name: 'extra-community', + mixins: [vnReport], async serverPrefetch() { - this.filters = this.$options.filters; const args = { landedTo: this.landedEnd, shippedFrom: this.shippedStart, @@ -21,8 +19,9 @@ module.exports = { }; const travels = await this.fetchTravels(args); + this.checkMainEntity(travels); const travelIds = travels.map(travel => travel.id); - const entries = await this.fetchEntries(travelIds); + const entries = await this.rawSqlFromDef('entries', [travelIds]); const map = new Map(); for (let travel of travels) @@ -35,23 +34,15 @@ module.exports = { } this.travels = travels; - - if (!this.travels) - throw new Error('Something went wrong'); }, computed: { - dated: function() { - return this.filters.date(new Date(), '%d-%m-%Y'); - }, landedEnd: function() { if (!this.landedTo) return; - - return this.filters.date(this.landedTo, '%Y-%m-%d'); + return formatDate(this.landedTo, '%Y-%m-%d'); }, shippedStart: function() { if (!this.shippedFrom) return; - - return this.filters.date(this.shippedFrom, '%Y-%m-%d'); + return formatDate(this.shippedFrom, '%Y-%m-%d'); } }, methods: { @@ -83,25 +74,17 @@ module.exports = { query = db.merge(query, where); query = db.merge(query, 'GROUP BY t.id'); query = db.merge(query, ` - ORDER BY - shipped ASC, - landed ASC, - travelFk, - loadPriority, - agencyModeFk, + ORDER BY + shipped ASC, + landed ASC, + travelFk, + loadPriority, + agencyModeFk, evaNotes `); return this.rawSql(query); }, - - fetchEntries(travelIds) { - return this.rawSqlFromDef('entries', [travelIds]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() }, props: [ 'landedTo', diff --git a/print/templates/reports/incoterms-authorization/incoterms-authorization.js b/print/templates/reports/incoterms-authorization/incoterms-authorization.js index bfe675985..53425487e 100755 --- a/print/templates/reports/incoterms-authorization/incoterms-authorization.js +++ b/print/templates/reports/incoterms-authorization/incoterms-authorization.js @@ -1,23 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'incoterms-authorization', + mixins: [vnReport], async serverPrefetch() { this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); this.company = await this.findOneFromDef('company', [this.companyId]); - if (!this.client) - throw new Error('Something went wrong'); - }, - computed: { - issued: function() { - return new Date(); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() }, props: { id: { diff --git a/print/templates/reports/invoice-incoterms/invoice-incoterms.html b/print/templates/reports/invoice-incoterms/invoice-incoterms.html index 20c9ad440..1915828ba 100644 --- a/print/templates/reports/invoice-incoterms/invoice-incoterms.html +++ b/print/templates/reports/invoice-incoterms/invoice-incoterms.html @@ -20,7 +20,7 @@ {{$t('date')}} - {{invoice.issued | date('%d-%m-%Y')}} + {{formatDate(invoice.issued, '%d-%m-%Y')}} diff --git a/print/templates/reports/invoice-incoterms/invoice-incoterms.js b/print/templates/reports/invoice-incoterms/invoice-incoterms.js index 3afc50376..fcaffe5de 100755 --- a/print/templates/reports/invoice-incoterms/invoice-incoterms.js +++ b/print/templates/reports/invoice-incoterms/invoice-incoterms.js @@ -1,34 +1,13 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'invoice-incoterms', + mixins: [vnReport], async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.reference); - this.client = await this.fetchClient(this.reference); - this.incoterms = await this.fetchIncoterms(this.reference); - - if (!this.invoice) - throw new Error('Something went wrong'); - }, - computed: { - - }, - methods: { - fetchInvoice(reference) { - return this.findOneFromDef('invoice', [reference]); - }, - fetchClient(reference) { - return this.findOneFromDef('client', [reference]); - }, - fetchIncoterms(reference) { - return this.findOneFromDef('incoterms', [reference, reference, reference]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build() + this.invoice = await this.findOneFromDef('invoice', [this.reference]); + this.checkMainEntity(this.invoice); + this.client = await this.findOneFromDef('client', [this.reference]); + this.incoterms = await this.findOneFromDef('incoterms', [this.reference, this.reference, this.reference]); }, props: { reference: { diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index d23bba1e9..60d06d528 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -21,7 +21,7 @@ {{$t('date')}} - {{invoice.issued | date('%d-%m-%Y')}} + {{formatDate(invoice.issued, '%d-%m-%Y')}} @@ -53,7 +53,7 @@ {{row.ref}} - {{row.issued | date}} + {{formatDate(row.issued, '%d-%m-%Y')}} {{row.amount | currency('EUR', $i18n.locale)}} {{row.description}} @@ -75,7 +75,7 @@
- {{ticket.shipped | date}} + {{formatDate(ticket.shipped, '%d-%m-%Y')}}
diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 48848c079..7b572d970 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -1,22 +1,21 @@ -const Component = require(`vn-print/core/component`); const Report = require(`vn-print/core/report`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); const invoiceIncoterms = new Report('invoice-incoterms'); module.exports = { name: 'invoice', + mixins: [vnReport], async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.reference); - this.client = await this.fetchClient(this.reference); - this.taxes = await this.fetchTaxes(this.reference); - this.intrastat = await this.fetchIntrastat(this.reference); - this.rectified = await this.fetchRectified(this.reference); - this.hasIncoterms = await this.fetchHasIncoterms(this.reference); + this.invoice = await this.findOneFromDef('invoice', [this.reference]); + this.checkMainEntity(this.invoice); + this.client = await this.findOneFromDef('client', [this.reference]); + this.taxes = await this.rawSqlFromDef(`taxes`, [this.reference]); + this.intrastat = await this.rawSqlFromDef(`intrastat`, [this.reference, this.reference, this.reference]); + this.rectified = await this.rawSqlFromDef(`rectified`, [this.reference]); + this.hasIncoterms = await this.findValueFromDef(`hasIncoterms`, [this.reference]); - const tickets = await this.fetchTickets(this.reference); - const sales = await this.fetchSales(this.reference); + const tickets = await this.rawSqlFromDef('tickets', [this.reference]); + const sales = await this.rawSqlFromDef('sales', [this.reference, this.reference]); const map = new Map(); @@ -33,9 +32,6 @@ module.exports = { } this.tickets = tickets; - - if (!this.invoice) - throw new Error('Something went wrong'); }, data() { return {totalBalance: 0.00}; @@ -66,30 +62,6 @@ module.exports = { } }, methods: { - fetchInvoice(reference) { - return this.findOneFromDef('invoice', [reference]); - }, - fetchClient(reference) { - return this.findOneFromDef('client', [reference]); - }, - fetchTickets(reference) { - return this.rawSqlFromDef('tickets', [reference]); - }, - fetchSales(reference) { - return this.rawSqlFromDef('sales', [reference, reference]); - }, - fetchTaxes(reference) { - return this.rawSqlFromDef(`taxes`, [reference]); - }, - fetchIntrastat(reference) { - return this.rawSqlFromDef(`intrastat`, [reference, reference, reference, reference, reference]); - }, - fetchRectified(reference) { - return this.rawSqlFromDef(`rectified`, [reference]); - }, - fetchHasIncoterms(reference) { - return this.findValueFromDef(`hasIncoterms`, [reference]); - }, saleImport(sale) { const price = sale.quantity * sale.price; @@ -111,9 +83,6 @@ module.exports = { } }, components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build(), - 'report-footer': reportFooter.build(), 'invoice-incoterms': invoiceIncoterms.build() }, props: { 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/invoiceIn/invoiceIn.html b/print/templates/reports/invoiceIn/invoiceIn.html index f101f7408..22988b654 100644 --- a/print/templates/reports/invoiceIn/invoiceIn.html +++ b/print/templates/reports/invoiceIn/invoiceIn.html @@ -19,7 +19,7 @@ {{$t('date')}} - {{invoice.created | date('%d-%m-%Y')}} + {{formatDate(invoice.created, '%d-%m-%Y')}} @@ -54,7 +54,7 @@
- {{entry.landed | date}} + {{formatDate(entry.landed, '%d-%m-%Y')}}
diff --git a/print/templates/reports/invoiceIn/invoiceIn.js b/print/templates/reports/invoiceIn/invoiceIn.js index 03549c276..c59f4da7d 100755 --- a/print/templates/reports/invoiceIn/invoiceIn.js +++ b/print/templates/reports/invoiceIn/invoiceIn.js @@ -1,15 +1,14 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'invoiceIn', + mixins: [vnReport], async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.id); + this.invoice = await this.findOneFromDef('invoice', [this.id]); + this.checkMainEntity(this.invoice); this.taxes = await this.fetchTaxes(this.id); - let defaultTax = await this.fetchDefaultTax(); + let defaultTax = await this.findOneFromDef('defaultTax'); if (defaultTax) { defaultTax = Object.assign(defaultTax, { @@ -19,11 +18,8 @@ module.exports = { this.taxes.push(defaultTax); } - if (!this.invoice) - throw new Error('Something went wrong'); - - const entries = await this.fetchEntry(this.id); - const buys = await this.fetchBuy(this.id); + const entries = await this.rawSqlFromDef('entry', [this.id]); + const buys = await this.rawSqlFromDef('buy', [this.id]); const map = new Map(); @@ -41,21 +37,7 @@ module.exports = { this.entries = entries; }, - computed: { - }, methods: { - fetchInvoice(id) { - return this.findOneFromDef('invoice', [id]); - }, - fetchEntry(id) { - return this.rawSqlFromDef('entry', [id]); - }, - fetchBuy(id) { - return this.rawSqlFromDef('buy', [id]); - }, - fetchDefaultTax() { - return this.findOneFromDef('defaultTax'); - }, async fetchTaxes(id) { const taxes = await this.rawSqlFromDef(`taxes`, [id]); return this.taxVat(taxes); @@ -95,11 +77,6 @@ module.exports = { return base + vat; } }, - components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build(), - 'report-footer': reportFooter.build(), - }, props: { id: { type: Number, diff --git a/print/templates/reports/item-label/item-label.html b/print/templates/reports/item-label/item-label.html index 49593f7dd..66509ab38 100644 --- a/print/templates/reports/item-label/item-label.html +++ b/print/templates/reports/item-label/item-label.html @@ -16,7 +16,7 @@
{{packing()}}
-
{{dated}}
+
{{formatDate(new Date(), '%W/%d')}}
{{labelPage}}
{{item.size}}
diff --git a/print/templates/reports/item-label/item-label.js b/print/templates/reports/item-label/item-label.js index 6341bd11a..c5b9cdfd7 100755 --- a/print/templates/reports/item-label/item-label.js +++ b/print/templates/reports/item-label/item-label.js @@ -1,24 +1,17 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); +const vnReport = require('../../../core/mixins/vn-report.js'); const qrcode = require('qrcode'); module.exports = { name: 'item-label', + mixins: [vnReport], async serverPrefetch() { - this.item = await this.fetchItem(this.id, this.warehouseId); + this.item = await this.findOneFromDef('item', [this.id, this.warehouseId]); + this.checkMainEntity(this.item); this.tags = await this.fetchItemTags(this.id); this.barcode = await this.getBarcodeBase64(this.id); - - if (!this.item) - throw new Error('Something went wrong'); }, computed: { - dated() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%W/%d'); - }, labelPage() { const labelNumber = this.labelNumber ? this.labelNumber : 1; const totalLabels = this.totalLabels ? this.totalLabels : 1; @@ -27,9 +20,6 @@ module.exports = { } }, methods: { - fetchItem(id, warehouseId) { - return this.findOneFromDef('item', [id, warehouseId]); - }, fetchItemTags(id) { return this.rawSqlFromDef('itemTags', [id]).then(rows => { const tags = {}; @@ -48,9 +38,6 @@ module.exports = { return `${this.item.packing}x${stems}`; } }, - components: { - 'report-body': reportBody.build() - }, props: { id: { type: Number, 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/letter-debtor/letter-debtor.html b/print/templates/reports/letter-debtor/letter-debtor.html index 962af021d..30fbbe003 100644 --- a/print/templates/reports/letter-debtor/letter-debtor.html +++ b/print/templates/reports/letter-debtor/letter-debtor.html @@ -13,7 +13,7 @@ {{$t('date')}} - {{dated}} + {{formatDate(new Date(), '%d-%m-%Y')}} @@ -44,7 +44,7 @@ - {{sale.issued | date('%d-%m-%Y')}} + {{formatDate(sale.issued, '%d-%m-%Y')}} {{sale.ref}} {{sale.debtOut}} {{sale.debtIn}} diff --git a/print/templates/reports/letter-debtor/letter-debtor.js b/print/templates/reports/letter-debtor/letter-debtor.js index 749fde4ed..4446b13ae 100755 --- a/print/templates/reports/letter-debtor/letter-debtor.js +++ b/print/templates/reports/letter-debtor/letter-debtor.js @@ -1,36 +1,17 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'letter-debtor', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.sales = await this.fetchSales(this.id, this.companyId); - - if (!this.client) - throw new Error('Something went wrong'); - }, - computed: { - dated: function() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%d-%m-%Y'); - } + this.client = await this.findOneFromDef('client', [this.id]); + this.checkMainEntity(this.client); + this.sales = await this.findOneFromDef('sales', [this.id, this.companyId]); }, data() { return {totalBalance: 0.00}; }, methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchSales(id, companyId) { - return this.findOneFromDef('sales', [ - id, - companyId - ]); - }, getBalance(sale) { if (sale.debtOut) this.totalBalance += parseFloat(sale.debtOut); @@ -57,10 +38,6 @@ module.exports = { return debtIn.toFixed(2); }, }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() - }, props: { id: { type: Number, 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..833a15499 --- /dev/null +++ b/print/templates/reports/previa-label/previa-label.js @@ -0,0 +1,30 @@ +const vnReport = require('../../../core/mixins/vn-report.js'); +const qrcode = require('qrcode'); + +module.exports = { + name: 'previa-label', + mixins: [vnReport], + async serverPrefetch() { + this.sector = await this.findOneFromDef('sector', [this.id]); + this.checkMainEntity(this.sector); + this.previa = await this.findOneFromDef('previa', [this.id]); + this.barcode = await this.getBarcodeBase64(this.id); + + if (this.previa) + this.previa = this.previa[0]; + }, + methods: { + getBarcodeBase64(id) { + const data = String(id); + + return qrcode.toDataURL(data, {margin: 0}); + }, + }, + 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 diff --git a/print/templates/reports/receipt/receipt.html b/print/templates/reports/receipt/receipt.html index e0bab5ecf..be0bfc375 100644 --- a/print/templates/reports/receipt/receipt.html +++ b/print/templates/reports/receipt/receipt.html @@ -4,9 +4,9 @@

{{$t('title')}}

- Recibo de {{client.socialName}}, la cantidad de - {{receipt.amountPaid}} € en concepto de 'entrega a cuenta', quedando pendiente en - la cuenta del cliente un saldo de {{receipt.amountUnpaid}} €. + Recibo #{{receipt.id}} de {{client.socialName}}, + la cantidad de {{receipt.amountPaid}} € + en concepto de 'entrega a cuenta'.

diff --git a/print/templates/reports/receipt/receipt.js b/print/templates/reports/receipt/receipt.js index 9a9ccd452..89a431adf 100755 --- a/print/templates/reports/receipt/receipt.js +++ b/print/templates/reports/receipt/receipt.js @@ -1,27 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'receipt', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id); - this.receipt = await this.fetchReceipt(this.id); - - if (!this.receipt) - throw new Error('Something went wrong'); - }, - methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); - }, - fetchReceipt(id) { - return this.findOneFromDef('receipt', [id]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() + this.receipt = await this.findOneFromDef('receipt', [this.id]); + this.checkMainEntity(this.receipt); + this.client = await this.findOneFromDef('client', [this.id]); }, props: { id: { diff --git a/print/templates/reports/receipt/sql/receipt.sql b/print/templates/reports/receipt/sql/receipt.sql index b8f5a4112..4094d25b3 100644 --- a/print/templates/reports/receipt/sql/receipt.sql +++ b/print/templates/reports/receipt/sql/receipt.sql @@ -1,11 +1,10 @@ -SELECT - r.id, - r.amountPaid, - cr.amount AS amountUnpaid, - r.payed, +SELECT + r.id, + r.amountPaid, + r.payed, r.companyFk FROM receipt r JOIN client c ON c.id = r.clientFk JOIN vn.clientRisk cr ON cr.clientFk = c.id AND cr.companyFk = r.companyFk -WHERE r.id = ? \ No newline at end of file +WHERE r.id = ? diff --git a/print/templates/reports/sepa-core/sepa-core.html b/print/templates/reports/sepa-core/sepa-core.html index f2326e43c..a8c270ad5 100644 --- a/print/templates/reports/sepa-core/sepa-core.html +++ b/print/templates/reports/sepa-core/sepa-core.html @@ -147,7 +147,7 @@ {{$t('client.signLocation')}} - {{dated}}, {{client.province}} + {{formatDate(new Date(), '%d-%m-%Y')}}, {{client.province}} {{$t('client.sign')}} diff --git a/print/templates/reports/sepa-core/sepa-core.js b/print/templates/reports/sepa-core/sepa-core.js index ee8a64842..0e19d2a6a 100755 --- a/print/templates/reports/sepa-core/sepa-core.js +++ b/print/templates/reports/sepa-core/sepa-core.js @@ -1,44 +1,12 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportHeader = new Component('report-header'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); -const rptSepaCore = { +module.exports = { name: 'sepa-core', + mixins: [vnReport], async serverPrefetch() { - this.client = await this.fetchClient(this.id, this.companyId); - this.supplier = await this.fetchSupplier(this.id, this.companyId); - - if (!this.client) - throw new Error('Something went wrong'); - }, - computed: { - dated: function() { - const filters = this.$options.filters; - - return filters.date(new Date(), '%d-%m-%Y'); - } - }, - methods: { - fetchClient(id, companyId) { - return this.findOneFromDef('client', [ - companyId, - companyId, - id - ]); - }, - fetchSupplier(id, companyId) { - return this.findOneFromDef('supplier', [ - companyId, - companyId, - id - ]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-header': reportHeader.build(), - 'report-footer': reportFooter.build() + this.client = await this.findOneFromDef('client', [this.companyId, this.companyId, this.id]); + this.checkMainEntity(this.client); + this.supplier = await this.findOneFromDef('supplier', [this.companyId, this.companyId, this.id]); }, props: { id: { @@ -52,5 +20,3 @@ const rptSepaCore = { } } }; - -module.exports = rptSepaCore; diff --git a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html index baff51bfe..08b27d0bd 100644 --- a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html +++ b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html @@ -13,11 +13,11 @@ {{$t('From')}} - {{from | date('%d-%m-%Y')}} + {{formatDate(from, '%d-%m-%Y')}} {{$t('To')}} - {{to | date('%d-%m-%Y')}} + {{formatDate(to, '%d-%m-%Y')}} @@ -38,7 +38,7 @@

{{$t('entry')}} {{entry.id}} - {{$t('dated')}} {{entry.shipped | date('%d-%m-%Y')}} + {{$t('dated')}} {{formatDate(entry.shipped, '%d-%m-%Y')}} {{$t('reference')}} {{entry.reference}}

diff --git a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js index f6fb4bd4e..32a7e9b0a 100755 --- a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js +++ b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js @@ -1,19 +1,19 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); -const reportFooter = new Component('report-footer'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'supplier-campaign-metrics', + mixins: [vnReport], async serverPrefetch() { - this.supplier = await this.fetchSupplier(this.id); - let entries = await this.fetchEntries(this.id, this.from, this.to); + this.supplier = await this.findOneFromDef('supplier', [this.id]); + this.checkMainEntity(this.supplier); + let entries = await this.rawSqlFromDef('entries', [this.id, this.from, this.to]); const entriesId = []; for (let entry of entries) entriesId.push(entry.id); - const buys = await this.fetchBuys(entriesId); + const buys = await this.rawSqlFromDef('buys', [entriesId]); const entriesMap = new Map(); for (let entry of entries) @@ -29,23 +29,6 @@ module.exports = { } this.entries = entries; - if (!this.supplier) - throw new Error('Something went wrong'); - }, - methods: { - fetchSupplier(supplierId) { - return this.findOneFromDef('supplier', [supplierId]); - }, - fetchEntries(supplierId, from, to) { - return this.rawSqlFromDef('entries', [supplierId, from, to]); - }, - fetchBuys(entriesId) { - return this.rawSqlFromDef('buys', [entriesId]); - } - }, - components: { - 'report-body': reportBody.build(), - 'report-footer': reportFooter.build() }, props: { id: { diff --git a/print/templates/reports/vehicle-event-expired/vehicle-event-expired.html b/print/templates/reports/vehicle-event-expired/vehicle-event-expired.html index 65776851d..7435f272d 100644 --- a/print/templates/reports/vehicle-event-expired/vehicle-event-expired.html +++ b/print/templates/reports/vehicle-event-expired/vehicle-event-expired.html @@ -16,7 +16,7 @@ - +
{{vehicleEvent.numberPlate}} {{vehicleEvent.description}}{{vehicleEvent.finished | date('%d-%m-%Y')}}{{formatDate(vehicleEvent.finished, '%d-%m-%Y')}}
diff --git a/print/templates/reports/vehicle-event-expired/vehicle-event-expired.js b/print/templates/reports/vehicle-event-expired/vehicle-event-expired.js index ab6cffc00..b49e770a5 100755 --- a/print/templates/reports/vehicle-event-expired/vehicle-event-expired.js +++ b/print/templates/reports/vehicle-event-expired/vehicle-event-expired.js @@ -1,21 +1,10 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); - +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'vehicle-event-expired', + mixins: [vnReport], async serverPrefetch() { - this.vehicleEvents = await this.fetchVehicleEvent(this.eventIds); - - if (!this.vehicleEvents) - throw new Error('Something went wrong'); - }, - methods: { - fetchVehicleEvent(vehicleEventIds) { - return this.rawSqlFromDef('vehicleEvents', [vehicleEventIds]); - }, - }, - components: { - 'report-body': reportBody.build() + this.vehicleEvents = await this.rawSqlFromDef('vehicleEvents', [this.eventIds]); + this.checkMainEntity(this.vehicleEvents); }, props: { eventIds: { diff --git a/print/templates/reports/zone/zone.html b/print/templates/reports/zone/zone.html index 54c55e168..fe42fb2ad 100644 --- a/print/templates/reports/zone/zone.html +++ b/print/templates/reports/zone/zone.html @@ -1,5 +1,5 @@
{{zone.agencyName}}
{{zone.id}}
-
{{zone.plateNumber}} {{zone.time | date('%H:%M')}}
+
{{zone.plateNumber}} {{formatDate(zone.time, '%H:%M')}}
diff --git a/print/templates/reports/zone/zone.js b/print/templates/reports/zone/zone.js index 720542cd6..5baa41b8e 100755 --- a/print/templates/reports/zone/zone.js +++ b/print/templates/reports/zone/zone.js @@ -1,21 +1,11 @@ -const Component = require(`vn-print/core/component`); -const reportBody = new Component('report-body'); +const vnReport = require('../../../core/mixins/vn-report.js'); module.exports = { name: 'zone', + mixins: [vnReport], async serverPrefetch() { - this.zone = await this.fetchZone(this.id); - - if (!this.zone) - throw new Error('Something went wrong'); - }, - methods: { - fetchZone(id) { - return this.findOneFromDef('zone', [id]); - } - }, - components: { - 'report-body': reportBody.build() + this.zone = await this.findOneFromDef('zone', [this.id]); + this.checkMainEntity(this.zone); }, props: { id: {