diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf7d8465a..3dadbafcf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,13 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2310.01] - 2023-03-23
### Added
--
+- (Trabajadores -> Control de horario) Ahora se puede confirmar/no confirmar el registro horario de cada semana desde esta sección
### Changed
--
+-
### Fixed
-- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
+- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
- (General) Al pasar el ratón por encima del icono de "Borrar" en un campo, se hacía más grande afectando a la interfaz
## [2308.01] - 2023-03-09
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index a0c72d726..3ab34e1d5 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2825,4 +2825,11 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create
(1, 1, util.VN_NOW()),
(3, 3, util.VN_NOW());
+INSERT INTO `vn`.`workerTimeControlMail` (`id`, `workerFk`, `year`, `week`, `state`, `updated`, `sendedCounter`, `reason`)
+ VALUES
+ (1, 9, 2000, 49, 'REVISE', util.VN_NOW(), 1, 'test2'),
+ (2, 9, 2000, 50, 'SENDED', util.VN_NOW(), 1, NULL),
+ (3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL),
+ (4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL);
+
diff --git a/front/core/components/calendar/index.html b/front/core/components/calendar/index.html
index 086fe4338..4d02f9ec0 100644
--- a/front/core/components/calendar/index.html
+++ b/front/core/components/calendar/index.html
@@ -24,7 +24,7 @@
@@ -57,4 +57,4 @@
-
\ No newline at end of file
+
diff --git a/front/core/components/calendar/index.js b/front/core/components/calendar/index.js
index 17ccbf041..0e39267a7 100644
--- a/front/core/components/calendar/index.js
+++ b/front/core/components/calendar/index.js
@@ -15,9 +15,9 @@ export default class Calendar extends FormInput {
constructor($element, $scope, vnWeekDays, moment) {
super($element, $scope);
this.weekDays = vnWeekDays.locales;
- this.defaultDate = Date.vnNew();
this.displayControls = true;
this.moment = moment;
+ this.defaultDate = Date.vnNew();
}
/**
@@ -207,14 +207,23 @@ export default class Calendar extends FormInput {
}
repeatLast() {
- if (!this.formatDay) return;
+ if (this.formatDay) {
+ const days = this.element.querySelectorAll('.days > .day');
+ for (let i = 0; i < days.length; i++) {
+ this.formatDay({
+ $day: this.days[i],
+ $element: days[i]
+ });
+ }
+ }
- let days = this.element.querySelectorAll('.days > .day');
- for (let i = 0; i < days.length; i++) {
- this.formatDay({
- $day: this.days[i],
- $element: days[i]
- });
+ if (this.formatWeek) {
+ const weeks = this.element.querySelectorAll('.weeks > .day');
+ for (const week of weeks) {
+ this.formatWeek({
+ $element: week
+ });
+ }
}
}
}
@@ -228,6 +237,7 @@ ngModule.vnComponent('vnCalendar', {
hasEvents: '&?',
getClass: '&?',
formatDay: '&?',
+ formatWeek: '&?',
displayControls: '',
hideYear: '',
hideContiguous: '',
diff --git a/modules/worker/back/methods/worker-time-control/getMailStates.js b/modules/worker/back/methods/worker-time-control/getMailStates.js
new file mode 100644
index 000000000..855b5adc3
--- /dev/null
+++ b/modules/worker/back/methods/worker-time-control/getMailStates.js
@@ -0,0 +1,61 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('getMailStates', {
+ description: 'Get the states of a month about time control mail',
+ accessType: 'READ',
+ accepts: [{
+ arg: 'id',
+ type: 'number',
+ description: 'The worker id',
+ http: {source: 'path'}
+ },
+ {
+ arg: 'month',
+ type: 'number',
+ description: 'The number of the month'
+ },
+ {
+ arg: 'year',
+ type: 'number',
+ description: 'The number of the year'
+ }],
+ returns: [{
+ type: ['object'],
+ root: true
+ }],
+ http: {
+ path: `/:id/getMailStates`,
+ verb: 'GET'
+ }
+ });
+
+ Self.getMailStates = async(ctx, workerId, options) => {
+ const models = Self.app.models;
+ const args = ctx.args;
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ const times = await models.Time.find({
+ fields: ['week'],
+ where: {
+ month: args.month,
+ year: args.year
+ }
+ }, myOptions);
+
+ const weeks = times.map(time => time.week);
+ const weekNumbersSet = new Set(weeks);
+ const weekNumbers = Array.from(weekNumbersSet);
+
+ const workerTimeControlMails = await models.WorkerTimeControlMail.find({
+ where: {
+ workerFk: workerId,
+ year: args.year,
+ week: {inq: weekNumbers}
+ }
+ }, myOptions);
+
+ return workerTimeControlMails;
+ };
+};
diff --git a/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js b/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js
new file mode 100644
index 000000000..cbad32323
--- /dev/null
+++ b/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js
@@ -0,0 +1,29 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('workerTimeControl getMailStates()', () => {
+ const workerId = 9;
+ const ctx = {args: {
+ month: 12,
+ year: 2000
+ }};
+
+ it('should get the states of a month about time control mail', async() => {
+ const tx = await models.WorkerTimeControl.beginTransaction({});
+
+ try {
+ const options = {transaction: tx};
+
+ const response = await models.WorkerTimeControl.getMailStates(ctx, workerId, options);
+
+ expect(response[0].state).toEqual('REVISE');
+ expect(response[1].state).toEqual('SENDED');
+ expect(response[2].state).toEqual('CONFIRMED');
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ });
+});
+
diff --git a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
index a8dc14bb1..642ff90d2 100644
--- a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
+++ b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
@@ -47,6 +47,10 @@ module.exports = Self => {
if (typeof options == 'object')
Object.assign(myOptions, options);
+ const isHimself = userId == args.workerId;
+ if (!isHimself)
+ throw new UserError(`You don't have enough privileges`);
+
const workerTimeControlMail = await models.WorkerTimeControlMail.findOne({
where: {
workerFk: args.workerId,
@@ -60,8 +64,6 @@ module.exports = Self => {
const oldState = workerTimeControlMail.state;
const oldReason = workerTimeControlMail.reason;
- if (oldState == args.state) throw new UserError('Already has this status');
-
await workerTimeControlMail.updateAttributes({
state: args.state,
reason: args.reason || null
diff --git a/modules/worker/back/models/time.json b/modules/worker/back/models/time.json
index df9257540..e2f1161d7 100644
--- a/modules/worker/back/models/time.json
+++ b/modules/worker/back/models/time.json
@@ -14,6 +14,9 @@
"year": {
"type": "number"
},
+ "month": {
+ "type": "number"
+ },
"week": {
"type": "number"
}
diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js
index 7339f5d15..5b13e17f2 100644
--- a/modules/worker/back/models/worker-time-control.js
+++ b/modules/worker/back/models/worker-time-control.js
@@ -8,6 +8,7 @@ module.exports = Self => {
require('../methods/worker-time-control/sendMail')(Self);
require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self);
require('../methods/worker-time-control/weeklyHourRecordEmail')(Self);
+ require('../methods/worker-time-control/getMailStates')(Self);
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html
index cff4d0bc9..c9eacbd82 100644
--- a/modules/worker/front/calendar/index.html
+++ b/modules/worker/front/calendar/index.html
@@ -25,11 +25,11 @@
{{'Contract' | translate}} #{{$ctrl.businessId}}
- {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
+ {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
- {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}}
+ {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}}
@@ -40,11 +40,11 @@
{{'Year' | translate}} {{$ctrl.year}}
- {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
+ {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
- {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
+ {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}}
@@ -66,7 +66,7 @@
order="businessFk DESC"
limit="5">
- #{{businessFk}}
+ #{{businessFk}}
{{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}}
@@ -87,17 +87,17 @@
- Festive
+ Festive
- Current day
+ Current day
-
diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html
index 681d420d0..bd7e68b89 100644
--- a/modules/worker/front/time-control/index.html
+++ b/modules/worker/front/time-control/index.html
@@ -1,7 +1,7 @@
@@ -16,7 +16,7 @@
{{::weekday.dated | date: 'MMMM'}}
-
-
+
-
-
+
-
+
+
+
+
-
+
Hours
-
-
@@ -106,6 +122,8 @@
vn-id="calendar"
class="vn-pt-md"
ng-model="$ctrl.date"
+ format-week="$ctrl.formatWeek($element)"
+ on-move="$ctrl.getMailStates($date)"
has-events="$ctrl.hasEvents($day)">
@@ -166,15 +184,31 @@
vn-id="reason"
on-accept="$ctrl.isUnsatisfied()">
-
-
+
+
+
+
-
+
-
\ No newline at end of file
+
+
+
+
+ Are you sure you want to send it?
+
+
+
+
+
+
diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js
index f7379fea0..9ed454d31 100644
--- a/modules/worker/front/time-control/index.js
+++ b/modules/worker/front/time-control/index.js
@@ -1,6 +1,7 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
+import UserError from 'core/lib/user-error';
class Controller extends Section {
constructor($element, $, vnWeekDays) {
@@ -24,12 +25,31 @@ class Controller extends Section {
}
this.date = initialDate;
+
+ this.getMailStates(this.date);
+ }
+
+ get isHr() {
+ return this.aclService.hasAny(['hr']);
+ }
+
+ get isHimSelf() {
+ const userId = window.localStorage.currentUserWorkerId;
+ return userId == this.$params.id;
}
get worker() {
return this._worker;
}
+ get weekNumber() {
+ return this.getWeekNumber(this.date);
+ }
+
+ set weekNumber(value) {
+ this._weekNumber = value;
+ }
+
set worker(value) {
this._worker = value;
}
@@ -68,6 +88,27 @@ class Controller extends Section {
}
this.fetchHours();
+ this.getWeekData();
+ }
+
+ getWeekData() {
+ const filter = {
+ where: {
+ workerFk: this.$params.id,
+ year: this._date.getFullYear(),
+ week: this.getWeekNumber(this._date)
+ }
+ };
+ this.$http.get('WorkerTimeControlMails', {filter})
+ .then(res => {
+ const workerTimeControlMail = res.data;
+ if (!workerTimeControlMail.length) {
+ this.state = null;
+ return;
+ }
+ this.state = workerTimeControlMail[0].state;
+ this.reason = workerTimeControlMail[0].reason;
+ });
}
/**
@@ -294,42 +335,56 @@ 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);
+ getWeekNumber(date) {
+ const tempDate = new Date(date);
+ let dayOfWeek = tempDate.getDay();
+ dayOfWeek = (dayOfWeek === 0) ? 7 : dayOfWeek;
+ const firstDayOfWeek = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() - (dayOfWeek - 1));
+ const firstDayOfYear = new Date(tempDate.getFullYear(), 0, 1);
+ const differenceInMilliseconds = firstDayOfWeek.getTime() - firstDayOfYear.getTime();
+ const weekNumber = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24 * 7)) + 1;
+ return weekNumber;
}
isSatisfied() {
- const weekNumber = this.getWeekNumber(this.date);
const params = {
workerId: this.worker.id,
year: this.date.getFullYear(),
- week: weekNumber,
+ week: this.weekNumber,
state: 'CONFIRMED'
};
const query = `WorkerTimeControls/updateWorkerTimeControlMail`;
this.$http.post(query, params).then(() => {
+ this.getMailStates(this.date);
+ this.getWeekData();
this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
isUnsatisfied() {
- const weekNumber = this.getWeekNumber(this.date);
+ if (!this.reason) throw new UserError(`You must indicate a reason`);
+
const params = {
workerId: this.worker.id,
year: this.date.getFullYear(),
- week: weekNumber,
+ week: this.weekNumber,
state: 'REVISE',
reason: this.reason
};
const query = `WorkerTimeControls/updateWorkerTimeControlMail`;
this.$http.post(query, params).then(() => {
+ this.getMailStates(this.date);
+ this.getWeekData();
this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
+ changeState(state, reason) {
+ this.state = state;
+ this.reason = reason;
+ this.repaint();
+ }
+
save() {
try {
const entry = this.selectedRow;
@@ -345,6 +400,77 @@ class Controller extends Section {
this.vnApp.showError(this.$t(e.message));
}
}
+
+ resendEmail() {
+ const timestamp = this.date.getTime() / 1000;
+ const url = `${window.location.origin}/#!/worker/${this.worker.id}/time-control?timestamp=${timestamp}`;
+ const params = {
+ recipient: this.worker.user.emailUser.email,
+ week: this.weekNumber,
+ year: this.date.getFullYear(),
+ url: url,
+ };
+ this.$http.post(`WorkerTimeControls/weekly-hour-hecord-email`, params)
+ .then(() => {
+ this.vnApp.showSuccess(this.$t('Email sended'));
+ });
+ }
+
+ getTime(timeString) {
+ const [hours, minutes, seconds] = timeString.split(':');
+ return [parseInt(hours), parseInt(minutes), parseInt(seconds)];
+ }
+
+ getMailStates(date) {
+ const params = {
+ month: date.getMonth() + 1,
+ year: date.getFullYear()
+ };
+ const query = `WorkerTimeControls/${this.$params.id}/getMailStates`;
+ this.$http.get(query, {params})
+ .then(res => {
+ this.workerTimeControlMails = res.data;
+ this.repaint();
+ });
+ }
+
+ formatWeek($element) {
+ const weekNumberHTML = $element.firstElementChild;
+ const weekNumberValue = weekNumberHTML.innerHTML;
+
+ if (!this.workerTimeControlMails) return;
+ const workerTimeControlMail = this.workerTimeControlMails.find(
+ workerTimeControlMail => workerTimeControlMail.week == weekNumberValue
+ );
+
+ if (!workerTimeControlMail) return;
+ const state = workerTimeControlMail.state;
+
+ if (state == 'CONFIRMED') {
+ weekNumberHTML.classList.remove('revise');
+ weekNumberHTML.classList.remove('sended');
+
+ weekNumberHTML.classList.add('confirmed');
+ weekNumberHTML.setAttribute('title', 'Conforme');
+ }
+ if (state == 'REVISE') {
+ weekNumberHTML.classList.remove('confirmed');
+ weekNumberHTML.classList.remove('sended');
+
+ weekNumberHTML.classList.add('revise');
+ weekNumberHTML.setAttribute('title', 'No conforme');
+ }
+ if (state == 'SENDED') {
+ weekNumberHTML.classList.add('sended');
+ weekNumberHTML.setAttribute('title', 'Pendiente');
+ }
+ }
+
+ repaint() {
+ let calendars = this.element.querySelectorAll('vn-calendar');
+ for (let calendar of calendars)
+ calendar.$ctrl.repaint();
+ }
}
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
diff --git a/modules/worker/front/time-control/index.spec.js b/modules/worker/front/time-control/index.spec.js
index b68162d39..0f9b48f6b 100644
--- a/modules/worker/front/time-control/index.spec.js
+++ b/modules/worker/front/time-control/index.spec.js
@@ -5,12 +5,14 @@ describe('Component vnWorkerTimeControl', () => {
let $scope;
let $element;
let controller;
+ let $httpParamSerializer;
beforeEach(ngModule('worker'));
- beforeEach(inject(($componentController, $rootScope, $stateParams, _$httpBackend_) => {
+ beforeEach(inject(($componentController, $rootScope, $stateParams, _$httpBackend_, _$httpParamSerializer_) => {
$stateParams.id = 1;
$httpBackend = _$httpBackend_;
+ $httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new();
$element = angular.element('');
controller = $componentController('vnWorkerTimeControl', {$element, $scope});
@@ -82,6 +84,9 @@ describe('Component vnWorkerTimeControl', () => {
$httpBackend.whenRoute('GET', 'Workers/:id/getWorkedHours')
.respond(response);
+ $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
+ .respond([]);
+
today.setHours(0, 0, 0, 0);
let weekOffset = today.getDay() - 1;
@@ -97,7 +102,6 @@ describe('Component vnWorkerTimeControl', () => {
controller.ended = ended;
controller.getWorkedHours(controller.started, controller.ended);
-
$httpBackend.flush();
expect(controller.weekDays.length).toEqual(7);
@@ -152,5 +156,120 @@ describe('Component vnWorkerTimeControl', () => {
expect(controller.date.toDateString()).toEqual(date.toDateString());
});
});
+
+ describe('getWeekData() ', () => {
+ it(`should make a query an then update the state and reason`, () => {
+ const today = Date.vnNew();
+ const response = [
+ {
+ state: 'SENDED',
+ reason: null
+ }
+ ];
+
+ controller._date = today;
+
+ $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
+ .respond(response);
+
+ controller.getWeekData();
+ $httpBackend.flush();
+
+ expect(controller.state).toBe('SENDED');
+ expect(controller.reason).toBe(null);
+ });
+ });
+
+ describe('isSatisfied() ', () => {
+ it(`should make a query an then call three methods`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller, 'getMailStates').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.date = today;
+ controller.weekNumber = 1;
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
+ controller.isSatisfied();
+ $httpBackend.flush();
+
+ expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
+ expect(controller.getWeekData).toHaveBeenCalled();
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('isUnsatisfied() ', () => {
+ it(`should throw an error is reason is empty`, () => {
+ let error;
+ try {
+ controller.isUnsatisfied();
+ } catch (e) {
+ error = e;
+ }
+
+ expect(error).toBeDefined();
+ expect(error.message).toBe(`You must indicate a reason`);
+ });
+
+ it(`should make a query an then call three methods`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller, 'getMailStates').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.date = today;
+ controller.weekNumber = 1;
+ controller.reason = 'reason';
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
+ controller.isSatisfied();
+ $httpBackend.flush();
+
+ expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
+ expect(controller.getWeekData).toHaveBeenCalled();
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('resendEmail() ', () => {
+ it(`should make a query an then call showSuccess method`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.worker = {user: {emailUser: {email: 'employee@verdnatura.es'}}};
+ controller.date = today;
+ controller.weekNumber = 1;
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/weekly-hour-hecord-email').respond();
+ controller.resendEmail();
+ $httpBackend.flush();
+
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('getMailStates() ', () => {
+ it(`should make a query an then call showSuccess method`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'repaint').mockReturnThis();
+
+ controller.$params = {id: 1};
+
+ $httpBackend.expect('GET', `WorkerTimeControls/1/getMailStates?month=1&year=2001`).respond();
+ controller.getMailStates(today);
+ $httpBackend.flush();
+
+ expect(controller.repaint).toHaveBeenCalled();
+ });
+ });
});
});
diff --git a/modules/worker/front/time-control/locale/es.yml b/modules/worker/front/time-control/locale/es.yml
index 2a3bffc00..091c01baa 100644
--- a/modules/worker/front/time-control/locale/es.yml
+++ b/modules/worker/front/time-control/locale/es.yml
@@ -13,4 +13,10 @@ 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
-Reason: Motivo
\ No newline at end of file
+Reason: Motivo
+Resend: Reenviar
+Email sended: Email enviado
+You must indicate a reason: Debes indicar un motivo
+Send time control email: Enviar email control horario
+Are you sure you want to send it?: ¿Seguro que quieres enviarlo?
+Resend email of this week to the user: Reenviar email de esta semana al usuario
diff --git a/modules/worker/front/time-control/style.scss b/modules/worker/front/time-control/style.scss
index 6a46921a7..9d7545aaf 100644
--- a/modules/worker/front/time-control/style.scss
+++ b/modules/worker/front/time-control/style.scss
@@ -14,7 +14,7 @@ vn-worker-time-control {
align-items: center;
justify-content: center;
padding: 4px 0;
-
+
& > vn-icon {
color: $color-font-secondary;
padding-right: 1px;
@@ -24,8 +24,29 @@ vn-worker-time-control {
.totalBox {
max-width: none
}
+
+}
+
+.reasonDialog{
+ min-width: 500px;
}
.edit-time-entry {
width: 200px
-}
\ No newline at end of file
+}
+
+.right {
+ float: right;
+ }
+
+.confirmed {
+ color: #97B92F;
+}
+
+.revise {
+ color: #f61e1e;
+}
+
+.sended {
+ color: #d19b25;
+}