Calendar changes
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
parent
dd8e03dd0f
commit
01b32d2b89
|
@ -0,0 +1,5 @@
|
||||||
|
ALTER TABLE `postgresql`.`calendar_employee`
|
||||||
|
ADD COLUMN `id` INT NULL AUTO_INCREMENT FIRST,
|
||||||
|
ADD UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
|
||||||
|
ADD INDEX `id_index` (`id` ASC) VISIBLE;
|
||||||
|
;
|
|
@ -5,6 +5,7 @@ CREATE
|
||||||
SQL SECURITY DEFINER
|
SQL SECURITY DEFINER
|
||||||
VIEW `workerCalendar2` AS
|
VIEW `workerCalendar2` AS
|
||||||
SELECT
|
SELECT
|
||||||
|
`ce`.`id` AS `id`,
|
||||||
`ce`.`business_id` AS `businessFk`,
|
`ce`.`business_id` AS `businessFk`,
|
||||||
`ce`.`calendar_state_id` AS `absenceTypeFk`,
|
`ce`.`calendar_state_id` AS `absenceTypeFk`,
|
||||||
`ce`.`date` AS `dated`
|
`ce`.`date` AS `dated`
|
|
@ -135,7 +135,7 @@ export default class Calendar extends FormInput {
|
||||||
$days: [day],
|
$days: [day],
|
||||||
$type: 'day'
|
$type: 'day'
|
||||||
});
|
});
|
||||||
this.repaint();
|
// this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('createAbsence', {
|
||||||
|
description: 'Returns an array of absences from an specified worker',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'absenceTypeId',
|
||||||
|
type: 'Number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dated',
|
||||||
|
type: 'Date',
|
||||||
|
required: false
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/createAbsence`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.createAbsence = async(ctx, id, absenceTypeId, dated) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
||||||
|
|
||||||
|
if (!isSubordinate)
|
||||||
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
const labour = await models.WorkerLabour.findOne({
|
||||||
|
where: {
|
||||||
|
and: [
|
||||||
|
{workerFk: id},
|
||||||
|
{or: [{
|
||||||
|
ended: {gte: [dated]}
|
||||||
|
}, {ended: null}]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return models.WorkerCalendar.create({
|
||||||
|
businessFk: labour.businessFk,
|
||||||
|
absenceTypeFk: absenceTypeId,
|
||||||
|
dated: dated
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,101 +0,0 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethodCtx('createAbsences', {
|
|
||||||
description: 'Returns an array of absences from an specified worker',
|
|
||||||
accepts: [{
|
|
||||||
arg: 'id',
|
|
||||||
type: 'Number',
|
|
||||||
description: 'The worker id',
|
|
||||||
http: {source: 'path'}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'absenceTypeId',
|
|
||||||
type: 'Number',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'dated',
|
|
||||||
type: 'Date',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'started',
|
|
||||||
type: 'Date',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'ended',
|
|
||||||
type: 'Date',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'type',
|
|
||||||
type: 'String',
|
|
||||||
required: true
|
|
||||||
}],
|
|
||||||
returns: 'Object',
|
|
||||||
http: {
|
|
||||||
path: `/:id/createAbsences`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.createAbsences = async(ctx, id, absenceTypeId, dated, started, ended, type) => {
|
|
||||||
const models = Self.app.models;
|
|
||||||
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
|
||||||
|
|
||||||
if (!isSubordinate)
|
|
||||||
throw new UserError(`You don't have enough privileges`);
|
|
||||||
|
|
||||||
const absences = [];
|
|
||||||
|
|
||||||
if (type == 'day') {
|
|
||||||
const contracts = await models.WorkerLabour.find({
|
|
||||||
where: {
|
|
||||||
and: [
|
|
||||||
{workerFk: id},
|
|
||||||
{or: [{
|
|
||||||
ended: {gte: [yearStarted]}
|
|
||||||
}, {ended: null}]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
absences.push({
|
|
||||||
businessFk: 106,
|
|
||||||
absenceTypeFk: absenceTypeId,
|
|
||||||
dated: dated
|
|
||||||
});
|
|
||||||
} else if (type == 'range')
|
|
||||||
console.log(true);
|
|
||||||
|
|
||||||
return models.WorkerCalendar.create(absences);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/* include: [{
|
|
||||||
relation: 'holidays',
|
|
||||||
scope: {
|
|
||||||
where: {year}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'workCenter',
|
|
||||||
scope: {
|
|
||||||
include: {
|
|
||||||
relation: 'holidays',
|
|
||||||
scope: {
|
|
||||||
include: [{
|
|
||||||
relation: 'detail'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'type'
|
|
||||||
}],
|
|
||||||
where: {
|
|
||||||
dated: {between: [yearStarted, yearEnded]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}], */
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('deleteAbsence', {
|
||||||
|
description: 'Returns an array of absences from an specified worker',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'absenceId',
|
||||||
|
type: 'Number',
|
||||||
|
required: true
|
||||||
|
}],
|
||||||
|
returns: 'Object',
|
||||||
|
http: {
|
||||||
|
path: `/:id/deleteAbsence`,
|
||||||
|
verb: 'DELETE'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.deleteAbsence = async(ctx, id, absenceId) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
||||||
|
|
||||||
|
if (!isSubordinate)
|
||||||
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
const absence = await models.WorkerCalendar.findById(absenceId);
|
||||||
|
|
||||||
|
return absence.destroy();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,40 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('updateAbsence', {
|
||||||
|
description: 'Returns an array of absences from an specified worker',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The worker id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'absenceId',
|
||||||
|
type: 'Number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'absenceTypeId',
|
||||||
|
type: 'Number',
|
||||||
|
required: true
|
||||||
|
}],
|
||||||
|
returns: 'Object',
|
||||||
|
http: {
|
||||||
|
path: `/:id/updateAbsence`,
|
||||||
|
verb: 'PATCH'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.updateAbsence = async(ctx, id, absenceId, absenceTypeId) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
||||||
|
|
||||||
|
if (!isSubordinate)
|
||||||
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
const absence = await models.WorkerCalendar.findById(absenceId);
|
||||||
|
|
||||||
|
return absence.updateAttribute('absenceTypeFk', absenceTypeId);
|
||||||
|
};
|
||||||
|
};
|
|
@ -7,12 +7,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"id": true,
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
"businessFk": {
|
"businessFk": {
|
||||||
"id": 1,
|
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
||||||
"dated": {
|
"dated": {
|
||||||
"id": 3,
|
|
||||||
"type": "Date"
|
"type": "Date"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,5 +4,7 @@ module.exports = Self => {
|
||||||
require('../methods/worker/isSubordinate')(Self);
|
require('../methods/worker/isSubordinate')(Self);
|
||||||
require('../methods/worker/getWorkedHours')(Self);
|
require('../methods/worker/getWorkedHours')(Self);
|
||||||
require('../methods/worker/uploadFile')(Self);
|
require('../methods/worker/uploadFile')(Self);
|
||||||
require('../methods/worker/createAbsences')(Self);
|
require('../methods/worker/createAbsence')(Self);
|
||||||
|
require('../methods/worker/deleteAbsence')(Self);
|
||||||
|
require('../methods/worker/updateAbsence')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
display-controls="false"
|
display-controls="false"
|
||||||
hide-contiguous="true"
|
hide-contiguous="true"
|
||||||
hide-year="true"
|
hide-year="true"
|
||||||
on-selection="$ctrl.onSelection($days, $type, $weekday)">
|
on-selection="$ctrl.onSelection($days)">
|
||||||
</vn-calendar>
|
</vn-calendar>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,61 +38,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</vn-side-menu>
|
</vn-side-menu>
|
||||||
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="dialog"
|
|
||||||
on-response="$ctrl.onAbsenceResponse($response)"
|
|
||||||
message="{{$ctrl.isNew ? 'Add absence' : 'Edit absence'}}">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-vertical class="vn-pb-md">
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.selected.type"
|
|
||||||
label="One day"
|
|
||||||
val="day">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.selected.type"
|
|
||||||
label="Range of dates"
|
|
||||||
val="range">
|
|
||||||
</vn-radio>
|
|
||||||
</vn-vertical>
|
|
||||||
<vn-date-picker
|
|
||||||
ng-if="$ctrl.selected.type == 'day'"
|
|
||||||
label="Day"
|
|
||||||
ng-model="$ctrl.selected.dated">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-horizontal
|
|
||||||
ng-if="$ctrl.selected.type == 'range'">
|
|
||||||
<vn-date-picker
|
|
||||||
label="From"
|
|
||||||
ng-model="$ctrl.selected.started">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
label="To"
|
|
||||||
ng-model="$ctrl.selected.ended">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
response="cancel"
|
|
||||||
translate-attr="{value: 'Cancel'}">
|
|
||||||
</input>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
ng-if="!$ctrl.isNew"
|
|
||||||
response="delete"
|
|
||||||
translate-attr="{value: 'Delete'}">
|
|
||||||
</input>
|
|
||||||
<button response="accept">
|
|
||||||
<span ng-if="$ctrl.isNew" translate>Add</span>
|
|
||||||
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
|
||||||
</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
<vn-confirm
|
||||||
vn-id="confirm"
|
vn-id="confirm"
|
||||||
message="This item will be deleted"
|
message="This item will be deleted"
|
||||||
|
|
|
@ -72,7 +72,9 @@ class Controller extends Section {
|
||||||
let type = absence.absenceType;
|
let type = absence.absenceType;
|
||||||
addEvent(absence.dated, {
|
addEvent(absence.dated, {
|
||||||
name: type.name,
|
name: type.name,
|
||||||
color: type.rgb
|
color: type.rgb,
|
||||||
|
type: type.code,
|
||||||
|
absenceId: absence.id
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -103,67 +105,81 @@ class Controller extends Section {
|
||||||
this.absenceType = absenceType;
|
this.absenceType = absenceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelection($days, $type, $weekday) {
|
onSelection($days) {
|
||||||
if (!this.absenceType)
|
if (!this.absenceType)
|
||||||
return this.vnApp.showMessage(this.$t('Choose an absence type'));
|
return this.vnApp.showMessage(this.$t('Choose an absence type'));
|
||||||
|
|
||||||
let $events = [];
|
const day = $days[0];
|
||||||
for (let day of $days) {
|
const stamp = day.getTime();
|
||||||
const stamp = day.getTime();
|
const event = this.events[stamp];
|
||||||
$events = $events.concat(this.events[stamp] || []);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($events.length)
|
if (event) {
|
||||||
this.edit($events[0]);
|
if (event.type == this.absenceType.code)
|
||||||
else
|
this.delete(day, event);
|
||||||
this.create($type, $days, $weekday);
|
else
|
||||||
|
this.edit(event);
|
||||||
|
} else
|
||||||
|
this.create(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(type, days, weekday) {
|
create(dated) {
|
||||||
this.isNew = true;
|
const absenceType = this.absenceType;
|
||||||
this.selected = {
|
const params = {
|
||||||
type: 'day',
|
dated: dated,
|
||||||
dated: days[0]
|
absenceTypeId: absenceType.id
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$.dialog.show();
|
const path = `Workers/${this.$params.id}/createAbsence`;
|
||||||
}
|
this.$http.post(path, params).then(res => {
|
||||||
|
this.responseHandler(() => {
|
||||||
edit() {
|
const newEvent = res.data;
|
||||||
this.isNew = false;
|
this.events[dated.getTime()] = {
|
||||||
}
|
name: absenceType.name,
|
||||||
|
color: absenceType.rgb,
|
||||||
onAbsenceResponse(response) {
|
type: absenceType.code,
|
||||||
switch (response) {
|
absenceId: newEvent.id
|
||||||
case 'accept': {
|
};
|
||||||
const selected = this.selected;
|
|
||||||
const params = Object.assign(selected, {
|
|
||||||
absenceTypeId: this.absenceType.id
|
|
||||||
});
|
|
||||||
|
|
||||||
/* const selected = {
|
|
||||||
businessFk: 106,
|
|
||||||
absenceTypeFk: this.absenceType.id,
|
|
||||||
dated: $days[0]
|
|
||||||
}; */
|
|
||||||
|
|
||||||
let req;
|
|
||||||
if (this.isNew) {
|
|
||||||
const path = `Workers/${this.$params.id}/createAbsences`;
|
|
||||||
req = this.$http.post(path, params);
|
|
||||||
} else
|
|
||||||
req = this.$http.put(`${this.path}/${selected.id}`, selected);
|
|
||||||
|
|
||||||
return req.then(() => {
|
|
||||||
this.selected = null;
|
|
||||||
this.isNew = null;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(event) {
|
||||||
|
const absenceType = this.absenceType;
|
||||||
|
const params = {
|
||||||
|
absenceId: event.absenceId,
|
||||||
|
absenceTypeId: absenceType.id
|
||||||
|
};
|
||||||
|
const path = `Workers/${this.$params.id}/updateAbsence`;
|
||||||
|
this.$http.patch(path, params).then(
|
||||||
|
this.responseHandler(() => {
|
||||||
|
event.color = absenceType.rgb;
|
||||||
|
event.name = absenceType.name;
|
||||||
|
event.code = absenceType.code;
|
||||||
|
this.refresh();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(day, event) {
|
||||||
|
const params = {absenceId: event.absenceId};
|
||||||
|
const path = `Workers/${this.$params.id}/deleteAbsence`;
|
||||||
|
this.$http.delete(path, {params}).then(
|
||||||
|
this.responseHandler(() => {
|
||||||
|
delete this.events[day.getTime()];
|
||||||
|
this.refresh();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
responseHandler(cb) {
|
||||||
|
if (this.repaintCanceller) {
|
||||||
|
clearTimeout(this.repaintCanceller);
|
||||||
|
this.repaintCanceller = null;
|
||||||
}
|
}
|
||||||
case 'delete':
|
|
||||||
return this.onDelete(this.selected.id)
|
this.repaintCanceller = setTimeout(
|
||||||
.then(response => response == 'accept');
|
() => cb(), 650);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
|
|
Loading…
Reference in New Issue