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-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/.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 0108c50d5..0bf93b35a 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2663,9 +2663,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 @@ -2715,6 +2715,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); @@ -2737,7 +2741,7 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES - (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); + (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`) VALUES diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index c0f10a506..e9d9d0580 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -428,6 +428,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"]', @@ -521,7 +522,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', 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/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/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/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/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/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/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.