diff --git a/CHANGELOG.md b/CHANGELOG.md index 98815430e..f8a04cfe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,20 +5,31 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2302.01] - 2023-01-12 +## [2304.01] - 2023-02-09 ### Added -- [General](Inicio) Permite recuperar la contraseña -- [Ticket](Opciones) Subir albarán a Docuware -- [Ticket](Opciones) Enviar correo con PDF de Docuware -- [Artículo](Datos Básicos) Añadido campo Unidades/Caja +- ### 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 +- + +## [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/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 178b09601..32b369c8d 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -36,19 +36,26 @@ module.exports = Self => { 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 AND ote.type = 'R' - GROUP BY ote.thread_id + 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.state = ? - AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY)`; + 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(','); + con.connect(err => { if (err) throw err; - con.query(sql, [config.oldStatus, config.day], + con.query(sql, [statusIdToClose, config.day], (err, results) => { if (err) throw err; for (const result of results) 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-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/.gitkeep b/db/changes/230401/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index d13eb83ff..27e72708f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2667,9 +2667,9 @@ INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk VALUES (1, 1); -INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`) +INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`) VALUES - (1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13); + (1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13, 28800, 32400); INSERT INTO `vn`.`host` (`id`, `code`, `description`, `warehouseFk`, `bankFk`) VALUES @@ -2745,7 +2745,7 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES - (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); + (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`) VALUES diff --git a/modules/invoiceIn/front/descriptor/index.html b/modules/invoiceIn/front/descriptor/index.html index 40f7dec18..223914c9c 100644 --- a/modules/invoiceIn/front/descriptor/index.html +++ b/modules/invoiceIn/front/descriptor/index.html @@ -36,13 +36,13 @@ ng-if="$ctrl.isAgricultural()" ng-click="$ctrl.showPdfInvoice()" translate> - Show agricultural invoice as PDF + Show agricultural receipt as PDF - Send agricultural invoice as PDF + Send agricultural receipt as PDF diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index d8400dd67..35b43f9f6 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -19,6 +19,6 @@ To book: Contabilizar Total amount: Total importe Total net: Total neto Total stems: Total tallos -Show agricultural invoice as PDF: Ver factura agrícola como PDF -Send agricultural invoice as PDF: Enviar factura agrícola como PDF -New InvoiceIn: Nueva Factura \ No newline at end of file +Show agricultural receipt as PDF: Ver recibo agrícola como PDF +Send agricultural receipt as PDF: Enviar recibo agrícola como PDF +New InvoiceIn: Nueva Factura diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index b38405c1d..78c212e9b 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -32,94 +32,87 @@ module.exports = Self => { const models = Self.app.models; const conn = Self.dataSource.connector; const args = ctx.args; - const $t = ctx.req.__; // $translate let tx; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - const stmts = []; let stmt; - try { - if (!args.week || !args.year) { - const from = new Date(); - const to = new Date(); + if (!args.week || !args.year) { + const from = new Date(); + const to = new Date(); - const time = await models.Time.findOne({ - where: { - dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} - }, - order: 'week ASC' - }, myOptions); + const time = await models.Time.findOne({ + where: { + dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} + }, + order: 'week ASC' + }, myOptions); - args.week = time.week; - args.year = time.year; - } + args.week = time.week; + args.year = time.year; + } - const started = getStartDateOfWeekNumber(args.week, args.year); - started.setHours(0, 0, 0, 0); + const started = getStartDateOfWeekNumber(args.week, args.year); + started.setHours(0, 0, 0, 0); - const ended = new Date(started); - ended.setDate(started.getDate() + 6); - ended.setHours(23, 59, 59, 999); + const ended = new Date(started); + ended.setDate(started.getDate() + 6); + ended.setHours(23, 59, 59, 999); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate'); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate'); - if (args.workerId) { - await models.WorkerTimeControl.destroyAll({ - userFk: args.workerId, - timed: {between: [started, ended]}, - isSendMail: true - }, myOptions); + if (args.workerId) { + await models.WorkerTimeControl.destroyAll({ + userFk: args.workerId, + timed: {between: [started, ended]}, + isSendMail: true + }, myOptions); - const where = { - workerFk: args.workerId, - year: args.year, - week: args.week - }; - await models.WorkerTimeControlMail.updateAll(where, { - updated: new Date(), state: 'SENDED' - }, myOptions); + const where = { + workerFk: args.workerId, + year: args.year, + week: args.week + }; + await models.WorkerTimeControlMail.updateAll(where, { + updated: new Date(), state: 'SENDED' + }, myOptions); - stmt = new ParameterizedSQL( - `CALL vn.timeControl_calculateByUser(?, ?, ?) + stmt = new ParameterizedSQL( + `CALL vn.timeControl_calculateByUser(?, ?, ?) `, [args.workerId, started, ended]); - stmts.push(stmt); + stmts.push(stmt); - stmt = new ParameterizedSQL( - `CALL vn.timeBusiness_calculateByUser(?, ?, ?) + stmt = new ParameterizedSQL( + `CALL vn.timeBusiness_calculateByUser(?, ?, ?) `, [args.workerId, started, ended]); - stmts.push(stmt); - } else { - await models.WorkerTimeControl.destroyAll({ - timed: {between: [started, ended]}, - isSendMail: true - }, myOptions); + stmts.push(stmt); + } else { + await models.WorkerTimeControl.destroyAll({ + timed: {between: [started, ended]}, + isSendMail: true + }, myOptions); - const where = { - year: args.year, - week: args.week - }; - await models.WorkerTimeControlMail.updateAll(where, { - updated: new Date(), state: 'SENDED' - }, myOptions); + const where = { + year: args.year, + week: args.week + }; + await models.WorkerTimeControlMail.updateAll(where, { + updated: new Date(), state: 'SENDED' + }, myOptions); - stmt = new ParameterizedSQL(`CALL vn.timeControl_calculateAll(?, ?)`, [started, ended]); - stmts.push(stmt); + stmt = new ParameterizedSQL(`CALL vn.timeControl_calculateAll(?, ?)`, [started, ended]); + stmts.push(stmt); - stmt = new ParameterizedSQL(`CALL vn.timeBusiness_calculateAll(?, ?)`, [started, ended]); - stmts.push(stmt); - } + stmt = new ParameterizedSQL(`CALL vn.timeBusiness_calculateAll(?, ?)`, [started, ended]); + stmts.push(stmt); + } - stmt = new ParameterizedSQL(` + stmt = new ParameterizedSQL(` SELECT CONCAT(u.name, '@verdnatura.es') receiver, u.id workerFk, tb.dated, @@ -154,25 +147,33 @@ module.exports = Self => { AND w.businessFk ORDER BY u.id, tb.dated `, [args.workerId]); - const index = stmts.push(stmt) - 1; + const index = stmts.push(stmt) - 1; - const sql = ParameterizedSQL.join(stmts, ';'); - const days = await conn.executeStmt(sql, myOptions); + stmts.push('DROP TEMPORARY TABLE tmp.timeControlCalculate'); + stmts.push('DROP TEMPORARY TABLE tmp.timeBusinessCalculate'); - let previousWorkerFk = days[index][0].workerFk; - let previousReceiver = days[index][0].receiver; + const sql = ParameterizedSQL.join(stmts, ';'); + const days = await conn.executeStmt(sql, myOptions); - const workerTimeControlConfig = await models.WorkerTimeControlConfig.findOne(null, myOptions); + let previousWorkerFk = days[index][0].workerFk; + let previousReceiver = days[index][0].receiver; - for (let day of days[index]) { + const workerTimeControlConfig = await models.WorkerTimeControlConfig.findOne(null, myOptions); + + for (let day of days[index]) { + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + try { workerFk = day.workerFk; if (day.timeWorkDecimal > 0 && day.timeWorkedDecimal == null - && (day.permissionRate ? day.permissionRate : true)) { + && (day.permissionRate == null ? true : day.permissionRate)) { if (day.timeTable == null) { const timed = new Date(day.dated); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(8), + timed: timed.setHours(workerTimeControlConfig.teleworkingStart / 3600), manual: true, direction: 'in', isSendMail: true @@ -181,7 +182,7 @@ module.exports = Self => { if (day.timeWorkDecimal >= workerTimeControlConfig.timeToBreakTime / 3600) { await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(9), + timed: timed.setHours(workerTimeControlConfig.teleworkingStartBreakTime / 3600), manual: true, direction: 'middle', isSendMail: true @@ -189,7 +190,10 @@ module.exports = Self => { await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(9, 20), + timed: timed.setHours( + workerTimeControlConfig.teleworkingStartBreakTime / 3600, + workerTimeControlConfig.breakTime / 60 + ), manual: true, direction: 'middle', isSendMail: true @@ -199,7 +203,11 @@ module.exports = Self => { const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(8 + hoursWork, minutesWork, secondsWork), + timed: timed.setHours( + workerTimeControlConfig.teleworkingStart / 3600 + hoursWork, + minutesWork, + secondsWork + ), manual: true, direction: 'out', isSendMail: true @@ -307,7 +315,7 @@ module.exports = Self => { }, myOptions); if (firstWorkerTimeControl) - firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); + await firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); const lastWorkerTimeControl = await models.WorkerTimeControl.findOne({ where: { @@ -318,7 +326,7 @@ module.exports = Self => { }, myOptions); if (lastWorkerTimeControl) - lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); + await lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); } } @@ -339,15 +347,18 @@ module.exports = Self => { previousWorkerFk = day.workerFk; previousReceiver = day.receiver; } + + if (tx) { + await tx.commit(); + delete myOptions.transaction; + } + } catch (e) { + if (tx) await tx.rollback(); + throw e; } - - if (tx) await tx.commit(); - - return true; - } catch (e) { - if (tx) await tx.rollback(); - throw e; } + + return true; }; function getStartDateOfWeekNumber(week, year) { diff --git a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js index 5b2436be9..24bfd6904 100644 --- a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js @@ -10,7 +10,6 @@ describe('workerTimeControl sendMail()', () => { const ctx = {req: activeCtx, args: {}}; it('should fill time control of a worker without records in Journey and with rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { @@ -35,7 +34,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker without records in Journey and without rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const workdayOf20Hours = 3; const tx = await models.WorkerTimeControl.beginTransaction({}); @@ -63,7 +61,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker with records in Journey and with rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { @@ -95,7 +92,6 @@ describe('workerTimeControl sendMail()', () => { }); it('should fill time control of a worker with records in Journey and without rest', async() => { - pending('https://redmine.verdnatura.es/issues/4903'); const tx = await models.WorkerTimeControl.beginTransaction({}); try { diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index 0cf614e57..6feadb936 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -2,7 +2,7 @@ const {Email} = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('weeklyHourRecordEmail', { - description: 'Sends the buyer waste email', + description: 'Sends the weekly hour record', accessType: 'WRITE', accepts: [ { diff --git a/modules/worker/back/models/worker-time-control-config.json b/modules/worker/back/models/worker-time-control-config.json index 4c12ce5d7..b96e2ae3b 100644 --- a/modules/worker/back/models/worker-time-control-config.json +++ b/modules/worker/back/models/worker-time-control-config.json @@ -11,8 +11,17 @@ "id": true, "type": "number" }, + "breakTime": { + "type": "number" + }, "timeToBreakTime": { "type": "number" + }, + "teleworkingStart": { + "type": "number" + }, + "teleworkingStartBreakTime": { + "type": "number" } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 9633751a0..2e0fb9ae8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "9.0.0", + "version": "230401", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", 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.