diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 8716ec172..c87df5cea 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -30,114 +30,105 @@ module.exports = Self => { Self.sendMail = async(ctx, options) => { const models = Self.app.models; - const $t = ctx.req.__; // $translate - const args = ctx.args; - const myOptions = {}; 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; - function getStartDateOfWeekNumber(week, year) { - const simple = new Date(year, 0, 1 + (week - 1) * 7); - const dow = simple.getDay(); - const weekStart = simple; - if (dow <= 4) - weekStart.setDate(simple.getDate() - simple.getDay() + 1); - else - weekStart.setDate(simple.getDate() + 8 - simple.getDay()); - return weekStart; - } + try { + if (!args.week || !args.year) { + const from = new Date(); + const to = new Date(); - function getTime(timeString) { - const [hours, minutes, seconds] = timeString.split(':'); - return [parseInt(hours), parseInt(minutes), parseInt(seconds)]; - } + const time = await models.Time.findOne({ + where: { + dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} + }, + order: 'week ASC' + }, myOptions); - if (!args.week || !args.year) { - const from = new Date(); - const to = new Date(); + args.week = time.week; + args.year = time.year; + } - const time = await models.Time.findOne({ - where: { - dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} - }, - order: 'week ASC' - }, myOptions); + const started = getStartDateOfWeekNumber(args.week, args.year); + started.setHours(0, 0, 0, 0); - args.week = time.week; - args.year = time.year; - } + const ended = new Date(started); + ended.setDate(started.getDate() + 6); + ended.setHours(23, 59, 59, 999); - const started = getStartDateOfWeekNumber(args.week, args.year); - started.setHours(0, 0, 0, 0); + 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.timeControlCalculate1'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate1'); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.error'); - const ended = new Date(started); - ended.setDate(started.getDate() + 6); - ended.setHours(23, 59, 59, 999); + if (args.workerId) { + await models.WorkerTimeControl.destroyAll({ + userFk: args.workerId, + timed: {between: [started, ended]}, + isSendMail: true + }, myOptions); - 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.timeControlCalculate1'); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate1'); - stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.error'); + const where = { + workerFk: args.workerId, + year: args.year, + week: args.week + }; + await models.WorkerTimeControlMail.updateAll(where, { + updated: new Date(), state: 'SENDED' + }, 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); - - 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); + } - stmts.push(`CREATE TEMPORARY TABLE tmp.timeControlCalculate1 + stmts.push(`CREATE TEMPORARY TABLE tmp.timeControlCalculate1 SELECT * FROM tmp.timeControlCalculate`); - stmts.push(`CREATE TEMPORARY TABLE tmp.timeBusinessCalculate1 + stmts.push(`CREATE TEMPORARY TABLE tmp.timeBusinessCalculate1 SELECT * FROM tmp.timeBusinessCalculate`); - stmt = new ParameterizedSQL(` + stmt = new ParameterizedSQL(` SELECT CONCAT(u.name, '@verdnatura.es') receiver, u.id workerFk, tb.dated, @@ -173,100 +164,80 @@ 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); + const sql = ParameterizedSQL.join(stmts, ';'); + const days = await conn.executeStmt(sql, myOptions); - let previousWorkerFk = days[index][0].workerFk; - let previousReceiver = days[index][0].receiver; + let previousWorkerFk = days[index][0].workerFk; + let previousReceiver = days[index][0].receiver; - for (let day of days[index]) { - if (day.timeWorkDecimal > 0 && day.timeWorkedDecimal == null - && (day.permissionRate ? day.permissionRate : true)) { - if (day.timeTable == null) { - const timed = new Date(day.dated); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(8), - manual: true, - direction: 'in', - isSendMail: true - }, myOptions); - - if (day.timeWorkDecimal >= 5) { + for (let day of days[index]) { + workerFk = day.workerFk; + if (day.timeWorkDecimal > 0 && day.timeWorkedDecimal == null + && (day.permissionRate ? day.permissionRate : true)) { + if (day.timeTable == null) { + const timed = new Date(day.dated); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours(9), + timed: timed.setHours(8), manual: true, - direction: 'middle', + direction: 'in', isSendMail: true }, myOptions); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(9, 20), - manual: true, - direction: 'middle', - isSendMail: true - }, myOptions); - } + if (day.timeWorkDecimal >= 5) { + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(9), + manual: true, + direction: 'middle', + isSendMail: true + }, myOptions); - const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(8 + hoursWork, minutesWork, secondsWork), - manual: true, - direction: 'out', - isSendMail: true - }, myOptions); - } else { - const weekDay = day.dated.getDay(); - const journeys = await models.Journey.find({ - where: { - business_id: day.businessFk, - day_id: weekDay + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(9, 20), + manual: true, + direction: 'middle', + isSendMail: true + }, myOptions); } - }, myOptions); - let timeTableDecimalInSeconds = 0; - for (let journey of journeys) { - const start = new Date(); - const [startHours, startMinutes, startSeconds] = getTime(journey.start); - start.setHours(startHours, startMinutes, startSeconds); + const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(8 + hoursWork, minutesWork, secondsWork), + manual: true, + direction: 'out', + isSendMail: true + }, myOptions); + } else { + const weekDay = day.dated.getDay(); + const journeys = await models.Journey.find({ + where: { + business_id: day.businessFk, + day_id: weekDay + } + }, myOptions); - const end = new Date(); - const [endHours, endMinutes, endSeconds] = getTime(journey.end); - end.setHours(endHours, endMinutes, endSeconds); - - const result = (end - start) / 1000; - timeTableDecimalInSeconds += result; - } - - for (let journey of journeys) { - const timeTableDecimal = timeTableDecimalInSeconds / 3600; - if (day.timeWorkDecimal == timeTableDecimal) { - const timed = new Date(day.dated); + let timeTableDecimalInSeconds = 0; + for (let journey of journeys) { + const start = new Date(); const [startHours, startMinutes, startSeconds] = getTime(journey.start); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(startHours, startMinutes, startSeconds), - manual: true, - isSendMail: true - }, myOptions); + start.setHours(startHours, startMinutes, startSeconds); + const end = new Date(); const [endHours, endMinutes, endSeconds] = getTime(journey.end); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(endHours, endMinutes, endSeconds), - manual: true, - isSendMail: true - }, myOptions); - } else { - const minStart = journeys.reduce(function(prev, curr) { - return curr.start < prev.start ? curr : prev; - }); - if (journey == minStart) { + end.setHours(endHours, endMinutes, endSeconds); + + const result = (end - start) / 1000; + timeTableDecimalInSeconds += result; + } + + for (let journey of journeys) { + const timeTableDecimal = timeTableDecimalInSeconds / 3600; + if (day.timeWorkDecimal == timeTableDecimal) { const timed = new Date(day.dated); const [startHours, startMinutes, startSeconds] = getTime(journey.start); await models.WorkerTimeControl.create({ @@ -276,83 +247,140 @@ module.exports = Self => { isSendMail: true }, myOptions); - const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); + const [endHours, endMinutes, endSeconds] = getTime(journey.end); await models.WorkerTimeControl.create({ userFk: day.workerFk, - timed: timed.setHours( - startHours + hoursWork, startMinutes + minutesWork, startSeconds + secondsWork - ), + timed: timed.setHours(endHours, endMinutes, endSeconds), manual: true, isSendMail: true }, myOptions); + } else { + const minStart = journeys.reduce(function(prev, curr) { + return curr.start < prev.start ? curr : prev; + }); + if (journey == minStart) { + const timed = new Date(day.dated); + const [startHours, startMinutes, startSeconds] = getTime(journey.start); + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(startHours, startMinutes, startSeconds), + manual: true, + isSendMail: true + }, myOptions); + + const [hoursWork, minutesWork, secondsWork] = getTime(day.timeWorkSexagesimal); + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours( + startHours + hoursWork, + startMinutes + minutesWork, + startSeconds + secondsWork + ), + manual: true, + isSendMail: true + }, myOptions); + } + } + + if (day.timeWorkDecimal >= 5) { + const minStart = journeys.reduce(function(prev, curr) { + return curr.start < prev.start ? curr : prev; + }); + if (journey == minStart) { + const timed = new Date(day.dated); + const [startHours, startMinutes, startSeconds] = getTime(journey.start); + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(startHours + 1, startMinutes, startSeconds), + manual: true, + isSendMail: true + }, myOptions); + + await models.WorkerTimeControl.create({ + userFk: day.workerFk, + timed: timed.setHours(startHours + 1, startMinutes + 20, startSeconds), + manual: true, + isSendMail: true + }, myOptions); + } } } + const timed = new Date(day.dated); + const firstWorkerTimeControl = await models.WorkerTimeControl.findOne({ + where: { + userFk: day.workerFk, + timed: {between: [timed.setHours(0, 0, 0, 0), timed.setHours(23, 59, 59, 999)]} + }, + order: 'timed ASC' + }, myOptions); - if (day.timeWorkDecimal >= 5) { - const minStart = journeys.reduce(function(prev, curr) { - return curr.start < prev.start ? curr : prev; - }); - if (journey == minStart) { - const timed = new Date(day.dated); - const [startHours, startMinutes, startSeconds] = getTime(journey.start); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(startHours + 1, startMinutes, startSeconds), - manual: true, - isSendMail: true - }, myOptions); + if (firstWorkerTimeControl) + firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); - await models.WorkerTimeControl.create({ - userFk: day.workerFk, - timed: timed.setHours(startHours + 1, startMinutes + 20, startSeconds), - manual: true, - isSendMail: true - }, myOptions); - } - } + const lastWorkerTimeControl = await models.WorkerTimeControl.findOne({ + where: { + userFk: day.workerFk, + timed: {between: [timed.setHours(0, 0, 0, 0), timed.setHours(23, 59, 59, 999)]} + }, + order: 'timed DESC' + }, myOptions); + + if (lastWorkerTimeControl) + lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); } + } - const timed = new Date(day.dated); - const firstWorkerTimeControl = await models.WorkerTimeControl.findOne({ + const lastDay = days[index][days[index].length - 1]; + if (day.workerFk != previousWorkerFk || day == lastDay) { + const salix = await models.Url.findOne({ where: { - userFk: day.workerFk, - timed: {between: [timed.setHours(0, 0, 0, 0), timed.setHours(23, 59, 59, 999)]} - }, - order: 'timed ASC', - limit: 1 + appName: 'salix', + environment: process.env.NODE_ENV || 'dev' + } }, myOptions); - if (firstWorkerTimeControl) firstWorkerTimeControl.updateAttribute('direction', 'in', myOptions); - - const lastWorkerTimeControl = await models.WorkerTimeControl.findOne({ - where: { - userFk: day.workerFk, - timed: {between: [timed.setHours(0, 0, 0, 0), timed.setHours(23, 59, 59, 999)]} - }, - order: 'timed DESC', - limit: 1 + const timestamp = started.getTime() / 1000; + await models.Mail.create({ + receiver: previousReceiver, + subject: $t('Record of hours week', { + week: args.week, + year: args.year + }), + body: `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}` }, myOptions); - if (lastWorkerTimeControl) lastWorkerTimeControl.updateAttribute('direction', 'out', myOptions); + await models.WorkerTimeControlMail.create({ + workerFk: previousWorkerFk, + week: args.week, + year: args.year + }, myOptions); + + previousWorkerFk = day.workerFk; + previousReceiver = day.receiver; } } - const origin = ctx.req.headers.origin; - const lastDay = days[index][days[index].length - 1]; - if (day.workerFk != previousWorkerFk || day == lastDay) { - await models.Mail.create({ - receiver: previousReceiver, - subject: $t('Record of hours week', { - week: args.week, - year: args.year - }), - body: `${origin}/#!/worker/${previousWorkerFk}/time-control?timestamp=` - }); - previousWorkerFk = day.workerFk; - previousReceiver = day.receiver; - } + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; } - return true; }; + + function getStartDateOfWeekNumber(week, year) { + const simple = new Date(year, 0, 1 + (week - 1) * 7); + const dow = simple.getDay(); + const weekStart = simple; + if (dow <= 4) + weekStart.setDate(simple.getDate() - simple.getDay() + 1); + else + weekStart.setDate(simple.getDate() + 8 - simple.getDay()); + return weekStart; + } + + function getTime(timeString) { + const [hours, minutes, seconds] = timeString.split(':'); + return [parseInt(hours), parseInt(minutes), parseInt(seconds)]; + } }; diff --git a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js new file mode 100644 index 000000000..23dcce262 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js @@ -0,0 +1,61 @@ +module.exports = Self => { + Self.remoteMethodCtx('updateWorkerTimeControlMail', { + description: 'Updates the state of WorkerTimeControlMail', + accessType: 'WRITE', + accepts: [{ + arg: 'workerId', + type: 'number', + required: true + }, + { + arg: 'year', + type: 'number', + required: true + }, + { + arg: 'week', + type: 'number', + required: true + }, + { + arg: 'state', + type: 'string', + required: true + }, + { + arg: 'emailResponse', + type: 'string' + }], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/updateWorkerTimeControlMail`, + verb: 'POST' + } + }); + + Self.updateWorkerTimeControlMail = async(ctx, options) => { + const models = Self.app.models; + const args = ctx.args; + + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const workerTimeControlMail = await models.WorkerTimeControlMail.findOne({ + where: { + workerFk: args.workerId, + year: args.year, + week: args.week + } + }, myOptions); + + return workerTimeControlMail.updateAttributes({ + state: args.state, + emailResponse: args.emailResponse || null + }, myOptions); + }; +}; diff --git a/modules/worker/back/models/worker-time-control-mail.json b/modules/worker/back/models/worker-time-control-mail.json index daf3d5155..0a0c2bf9a 100644 --- a/modules/worker/back/models/worker-time-control-mail.json +++ b/modules/worker/back/models/worker-time-control-mail.json @@ -9,8 +9,7 @@ "properties": { "id": { "id": true, - "type": "number", - "required": true + "type": "number" }, "workerFk": { "type": "number" diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js index 928606b7d..9f802511a 100644 --- a/modules/worker/back/models/worker-time-control.js +++ b/modules/worker/back/models/worker-time-control.js @@ -6,6 +6,7 @@ module.exports = Self => { require('../methods/worker-time-control/deleteTimeEntry')(Self); require('../methods/worker-time-control/updateTimeEntry')(Self); require('../methods/worker-time-control/sendMail')(Self); + require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self); Self.rewriteDbError(function(err) { if (err.code === 'ER_DUP_ENTRY') diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 1b60dcce0..681d420d0 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -81,11 +81,11 @@ + ng-click="$ctrl.isSatisfied()"> + ng-click="reason.show()"> @@ -160,4 +160,21 @@ ng-click="$ctrl.save()"> - \ No newline at end of file + + + + + + + + + + + + \ 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 ebf70e886..9bd9bb571 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -294,6 +294,42 @@ class Controller extends Section { this.$.editEntry.show($event); } + getWeekNumber(currentDate) { + const startDate = new Date(currentDate.getFullYear(), 0, 1); + let days = Math.floor((currentDate - startDate) / + (24 * 60 * 60 * 1000)); + return Math.ceil(days / 7); + } + + isSatisfied() { + const weekNumber = this.getWeekNumber(this.date); + const params = { + workerId: this.worker.id, + year: this.date.getFullYear(), + week: weekNumber, + state: 'CONFIRMED' + }; + const query = `WorkerTimeControls/updateWorkerTimeControlMail`; + this.$http.post(query, params).then(() => { + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + + isUnsatisfied() { + const weekNumber = this.getWeekNumber(this.date); + const params = { + workerId: this.worker.id, + year: this.date.getFullYear(), + week: weekNumber, + state: 'REVISE', + emailResponse: this.reason + }; + const query = `WorkerTimeControls/updateWorkerTimeControlMail`; + this.$http.post(query, params).then(() => { + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + save() { try { const entry = this.selectedRow; diff --git a/modules/worker/front/time-control/locale/es.yml b/modules/worker/front/time-control/locale/es.yml index cace38291..2a3bffc00 100644 --- a/modules/worker/front/time-control/locale/es.yml +++ b/modules/worker/front/time-control/locale/es.yml @@ -12,4 +12,5 @@ Finish at: Termina a las Entry removed: Fichada borrada The entry type can't be empty: El tipo de fichada no puede quedar vacĂ­a Satisfied: Conforme -Not satisfied: No conforme \ No newline at end of file +Not satisfied: No conforme +Reason: Motivo \ No newline at end of file