2019-05-17 11:27:51 +00:00
|
|
|
import ngModule from '../module';
|
2020-03-18 11:55:22 +00:00
|
|
|
import Section from 'salix/components/section';
|
2019-05-17 11:27:51 +00:00
|
|
|
import './style.scss';
|
2020-03-18 11:55:22 +00:00
|
|
|
|
|
|
|
class Controller extends Section {
|
2019-11-05 10:57:05 +00:00
|
|
|
constructor($element, $, vnWeekDays) {
|
|
|
|
super($element, $);
|
2019-05-17 11:27:51 +00:00
|
|
|
this.weekDays = [];
|
2019-10-23 15:38:35 +00:00
|
|
|
this.weekdayNames = vnWeekDays.locales;
|
2021-06-17 13:09:04 +00:00
|
|
|
this.entryDirections = [
|
|
|
|
{code: 'in', description: this.$t('In')},
|
|
|
|
{code: 'middle', description: this.$t('Intermediate')},
|
|
|
|
{code: 'out', description: this.$t('Out')}
|
|
|
|
];
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
$postLink() {
|
|
|
|
this.date = new Date();
|
|
|
|
}
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2021-06-11 08:58:00 +00:00
|
|
|
get worker() {
|
|
|
|
return this._worker;
|
|
|
|
}
|
|
|
|
|
|
|
|
set worker(value) {
|
|
|
|
this._worker = value;
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
this.getActiveContract()
|
|
|
|
.then(() => this.getAbsences());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 11:27:51 +00:00
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* The current selected date
|
2019-05-17 11:27:51 +00:00
|
|
|
*/
|
2019-10-23 15:38:35 +00:00
|
|
|
get date() {
|
|
|
|
return this._date;
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
set date(value) {
|
|
|
|
this._date = value;
|
|
|
|
value.setHours(0, 0, 0, 0);
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
let weekOffset = value.getDay() - 1;
|
|
|
|
if (weekOffset < 0) weekOffset = 6;
|
|
|
|
|
|
|
|
let started = new Date(value.getTime());
|
|
|
|
started.setDate(started.getDate() - weekOffset);
|
|
|
|
this.started = started;
|
|
|
|
|
|
|
|
let ended = new Date(started.getTime());
|
2019-11-05 07:59:48 +00:00
|
|
|
ended.setHours(23, 59, 59, 59);
|
|
|
|
ended.setDate(ended.getDate() + 6);
|
2019-10-23 15:38:35 +00:00
|
|
|
this.ended = ended;
|
|
|
|
|
2019-11-05 07:59:48 +00:00
|
|
|
this.weekDays = [];
|
|
|
|
let dayIndex = new Date(started.getTime());
|
|
|
|
|
|
|
|
while (dayIndex < ended) {
|
|
|
|
this.weekDays.push({
|
|
|
|
dated: new Date(dayIndex.getTime())
|
|
|
|
});
|
|
|
|
dayIndex.setDate(dayIndex.getDate() + 1);
|
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
this.fetchHours();
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-10-23 15:38:35 +00:00
|
|
|
* Worker hours data
|
2019-05-17 11:27:51 +00:00
|
|
|
*/
|
|
|
|
get hours() {
|
|
|
|
return this._hours;
|
|
|
|
}
|
|
|
|
|
|
|
|
set hours(value) {
|
|
|
|
this._hours = value;
|
|
|
|
|
2019-11-05 07:59:48 +00:00
|
|
|
for (const weekDay of this.weekDays) {
|
|
|
|
if (value) {
|
|
|
|
let day = weekDay.dated.getDay();
|
|
|
|
weekDay.hours = value
|
|
|
|
.filter(hour => new Date(hour.timed).getDay() == day)
|
|
|
|
.sort((a, b) => new Date(a.timed) - new Date(b.timed));
|
|
|
|
} else
|
|
|
|
weekDay.hours = null;
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 08:58:00 +00:00
|
|
|
getActiveContract() {
|
|
|
|
return this.$http.get(`Workers/${this.worker.id}/activeContract`)
|
|
|
|
.then(res => this.businessId = res.data.businessFk);
|
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
fetchHours() {
|
2019-11-05 10:57:05 +00:00
|
|
|
const params = {workerFk: this.$params.id};
|
2019-10-23 15:38:35 +00:00
|
|
|
const filter = {
|
|
|
|
where: {and: [
|
|
|
|
{timed: {gte: this.started}},
|
2019-11-05 07:59:48 +00:00
|
|
|
{timed: {lte: this.ended}}
|
2019-10-23 15:38:35 +00:00
|
|
|
]}
|
|
|
|
};
|
2019-12-31 13:01:05 +00:00
|
|
|
this.$.model.applyFilter(filter, params).then(() => {
|
|
|
|
this.getWorkedHours(this.started, this.ended);
|
|
|
|
});
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:38:35 +00:00
|
|
|
hasEvents(day) {
|
|
|
|
return day >= this.started && day < this.ended;
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-12-31 13:01:05 +00:00
|
|
|
getAbsences() {
|
2021-06-11 08:58:00 +00:00
|
|
|
const fullYear = this.started.getFullYear();
|
2019-12-31 13:01:05 +00:00
|
|
|
let params = {
|
2021-06-11 08:58:00 +00:00
|
|
|
businessFk: this.businessId,
|
|
|
|
year: fullYear
|
2019-12-31 13:01:05 +00:00
|
|
|
};
|
|
|
|
|
2020-08-10 12:29:25 +00:00
|
|
|
return this.$http.get(`Calendars/absences`, {params})
|
2019-12-31 13:01:05 +00:00
|
|
|
.then(res => this.onData(res.data));
|
|
|
|
}
|
|
|
|
|
|
|
|
onData(data) {
|
|
|
|
const events = {};
|
|
|
|
|
|
|
|
let addEvent = (day, event) => {
|
|
|
|
events[new Date(day).getTime()] = event;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (data.holidays) {
|
|
|
|
data.holidays.forEach(holiday => {
|
|
|
|
const holidayDetail = holiday.detail && holiday.detail.description;
|
|
|
|
const holidayType = holiday.type && holiday.type.name;
|
|
|
|
const holidayName = holidayDetail || holidayType;
|
|
|
|
|
|
|
|
addEvent(holiday.dated, {
|
|
|
|
name: holidayName,
|
|
|
|
color: '#ff0'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (data.absences) {
|
|
|
|
data.absences.forEach(absence => {
|
|
|
|
const type = absence.absenceType;
|
|
|
|
addEvent(absence.dated, {
|
|
|
|
name: type.name,
|
|
|
|
color: type.rgb
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.weekDays.forEach(day => {
|
|
|
|
const timestamp = day.dated.getTime();
|
|
|
|
if (events[timestamp])
|
|
|
|
day.event = events[timestamp];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-11-05 07:59:48 +00:00
|
|
|
getWorkedHours(from, to) {
|
2019-11-14 13:20:05 +00:00
|
|
|
this.weekTotalHours = null;
|
|
|
|
let weekTotalHours = 0;
|
2019-11-05 07:59:48 +00:00
|
|
|
let params = {
|
2019-11-05 10:57:05 +00:00
|
|
|
id: this.$params.id,
|
2019-11-05 07:59:48 +00:00
|
|
|
from: from,
|
|
|
|
to: to
|
|
|
|
};
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-05 10:57:05 +00:00
|
|
|
const query = `Workers/${this.$params.id}/getWorkedHours`;
|
2019-11-05 07:59:48 +00:00
|
|
|
return this.$http.get(query, {params}).then(res => {
|
|
|
|
const workDays = res.data;
|
|
|
|
const map = new Map();
|
|
|
|
|
|
|
|
for (const workDay of workDays) {
|
|
|
|
workDay.dated = new Date(workDay.dated);
|
|
|
|
map.set(workDay.dated, workDay);
|
2019-11-14 13:20:05 +00:00
|
|
|
weekTotalHours += workDay.workedHours;
|
2019-11-05 07:59:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const weekDay of this.weekDays) {
|
|
|
|
const workDay = workDays.find(day => {
|
|
|
|
let from = new Date(day.dated);
|
|
|
|
from.setHours(0, 0, 0, 0);
|
|
|
|
|
|
|
|
let to = new Date(day.dated);
|
|
|
|
to.setHours(23, 59, 59, 59);
|
|
|
|
|
|
|
|
return weekDay.dated >= from && weekDay.dated <= to;
|
|
|
|
});
|
2019-11-14 13:20:05 +00:00
|
|
|
|
|
|
|
if (workDay) {
|
|
|
|
weekDay.expectedHours = workDay.expectedHours;
|
|
|
|
weekDay.workedHours = workDay.workedHours;
|
|
|
|
}
|
2019-11-05 07:59:48 +00:00
|
|
|
}
|
2019-11-14 13:20:05 +00:00
|
|
|
this.weekTotalHours = weekTotalHours;
|
2019-11-05 07:59:48 +00:00
|
|
|
});
|
|
|
|
}
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-05 07:59:48 +00:00
|
|
|
getFinishTime() {
|
2019-11-05 10:57:05 +00:00
|
|
|
if (!this.weekDays) return;
|
|
|
|
|
|
|
|
let today = new Date();
|
|
|
|
today.setHours(0, 0, 0, 0);
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-05 10:57:05 +00:00
|
|
|
let todayInWeek = this.weekDays.find(day => day.dated.getTime() === today.getTime());
|
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
|
|
|
|
const remainingTime = todayInWeek.workedHours ? ((todayInWeek.expectedHours - todayInWeek.workedHours) * 1000) : null;
|
|
|
|
const lastKnownEntry = todayInWeek.hours[todayInWeek.hours.length - 1];
|
|
|
|
const lastKnownTime = new Date(lastKnownEntry.timed).getTime();
|
|
|
|
const finishTimeStamp = lastKnownTime && remainingTime ? lastKnownTime + remainingTime : null;
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
if (finishTimeStamp) {
|
|
|
|
let finishDate = new Date(finishTimeStamp);
|
|
|
|
let hour = finishDate.getHours();
|
|
|
|
let minute = finishDate.getMinutes();
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
if (hour < 10) hour = `0${hour}`;
|
|
|
|
if (minute < 10) minute = `0${minute}`;
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
return `${hour}:${minute} h.`;
|
|
|
|
}
|
2019-11-05 07:59:48 +00:00
|
|
|
}
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
set weekTotalHours(totalHours) {
|
|
|
|
this._weekTotalHours = this.formatHours(totalHours);
|
|
|
|
}
|
2019-11-05 07:59:48 +00:00
|
|
|
|
2019-11-14 13:20:05 +00:00
|
|
|
get weekTotalHours() {
|
|
|
|
return this._weekTotalHours;
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 12:46:36 +00:00
|
|
|
formatHours(timestamp = 0) {
|
2019-11-05 07:59:48 +00:00
|
|
|
let hour = Math.floor(timestamp / 3600);
|
|
|
|
let min = Math.floor(timestamp / 60 - 60 * hour);
|
2019-05-17 11:27:51 +00:00
|
|
|
|
|
|
|
if (hour < 10) hour = `0${hour}`;
|
|
|
|
if (min < 10) min = `0${min}`;
|
|
|
|
|
|
|
|
return `${hour}:${min}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
showAddTimeDialog(weekday) {
|
2019-10-31 14:24:28 +00:00
|
|
|
const timed = new Date(weekday.dated.getTime());
|
|
|
|
timed.setHours(0, 0, 0, 0);
|
2019-05-21 10:56:29 +00:00
|
|
|
|
2021-06-17 13:09:04 +00:00
|
|
|
this.newTimeEntry = {
|
|
|
|
workerFk: this.$params.id,
|
|
|
|
timed: timed
|
|
|
|
};
|
2019-05-17 11:27:51 +00:00
|
|
|
this.selectedWeekday = weekday;
|
|
|
|
this.$.addTimeDialog.show();
|
|
|
|
}
|
|
|
|
|
2020-07-29 08:47:48 +00:00
|
|
|
addTime() {
|
2021-06-18 10:32:37 +00:00
|
|
|
try {
|
|
|
|
const entry = this.newTimeEntry;
|
|
|
|
if (!entry.direction)
|
|
|
|
throw new Error(`The entry type can't be empty`);
|
|
|
|
|
|
|
|
const query = `WorkerTimeControls/${this.worker.id}/addTimeEntry`;
|
|
|
|
this.$http.post(query, entry)
|
|
|
|
.then(() => this.fetchHours());
|
|
|
|
} catch (e) {
|
|
|
|
this.vnApp.showError(this.$t(e.message));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
2019-11-05 07:59:48 +00:00
|
|
|
|
2021-06-17 13:09:04 +00:00
|
|
|
showDeleteDialog($event, hour) {
|
|
|
|
$event.preventDefault();
|
|
|
|
|
2019-11-05 07:59:48 +00:00
|
|
|
this.timeEntryToDelete = hour;
|
|
|
|
this.$.deleteEntryDialog.show();
|
|
|
|
}
|
|
|
|
|
2019-11-05 10:57:05 +00:00
|
|
|
deleteTimeEntry() {
|
2019-11-05 07:59:48 +00:00
|
|
|
const entryId = this.timeEntryToDelete.id;
|
|
|
|
|
2019-11-05 10:57:05 +00:00
|
|
|
this.$http.post(`WorkerTimeControls/${entryId}/deleteTimeEntry`).then(() => {
|
2019-11-05 07:59:48 +00:00
|
|
|
this.fetchHours();
|
2019-11-05 10:57:05 +00:00
|
|
|
this.vnApp.showSuccess(this.$t('Entry removed'));
|
2019-11-05 07:59:48 +00:00
|
|
|
});
|
|
|
|
}
|
2021-06-17 13:09:04 +00:00
|
|
|
|
|
|
|
edit($event, hour) {
|
|
|
|
if ($event.defaultPrevented) return;
|
|
|
|
|
|
|
|
this.selectedRow = hour;
|
|
|
|
this.$.editEntry.show($event);
|
|
|
|
}
|
|
|
|
|
|
|
|
save() {
|
2021-06-18 10:32:37 +00:00
|
|
|
try {
|
|
|
|
const entry = this.selectedRow;
|
|
|
|
if (!entry.direction)
|
|
|
|
throw new Error(`The entry type can't be empty`);
|
|
|
|
|
|
|
|
const query = `WorkerTimeControls/${entry.id}/updateTimeEntry`;
|
|
|
|
this.$http.post(query, {direction: entry.direction})
|
|
|
|
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
|
|
|
|
.then(() => this.$.editEntry.hide())
|
|
|
|
.then(() => this.fetchHours());
|
|
|
|
} catch (e) {
|
|
|
|
this.vnApp.showError(this.$t(e.message));
|
|
|
|
}
|
2021-06-17 13:09:04 +00:00
|
|
|
}
|
2019-05-17 11:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-11-05 10:57:05 +00:00
|
|
|
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
2019-05-17 11:27:51 +00:00
|
|
|
|
2020-07-24 12:22:30 +00:00
|
|
|
ngModule.vnComponent('vnWorkerTimeControl', {
|
2019-05-17 11:27:51 +00:00
|
|
|
template: require('./index.html'),
|
2021-06-11 08:58:00 +00:00
|
|
|
controller: Controller,
|
|
|
|
bindings: {
|
|
|
|
worker: '<'
|
|
|
|
}
|
2019-05-17 11:27:51 +00:00
|
|
|
});
|