How to Display Daily Absences in Slack? 

Background information

We are going to use Zapier in order to create a trigger that will call Timmi Absences API every morning at 7 am and that will post the list of daily absences in Slack.

Note : Some of our clients are using a similar code with Google Cloud Engine.

Zapier is an online service allowing to automate actions on the web. The principle is very simple, it can be summarized like this "If action X happens in application A, then do action Y in application B"

zapier-how-to

We are going to create the following formula "If it is 7 am, then ask Timmi Absences for the list of absences for the day and post the message in Slack"

Logging in to Zappier

You will be able to log in here : https://zapier.com.

Please create an account or use an existing account.

Zap configuration

 

You have to configure the first step. The “Choose App” button will display a list of tools available. In the tab “Built-in apps” you will then be able to choose the schedule icon.

You will now have to set your schedule. First, make sure you select how often you want the script to run, for example every day.

You will then choose the time of the day to run the script, as well as whether you want it to be triggered during weekends or not.

Once this first step has been completed, you can test it with the “Test this Step” feature. For the second step (being the action), please choose the "Code" icon.

 Select Javascript

In the next step, please copy this script into the “Code” section and leave the “Input” part blank.

var urlBase = "https://xxxxxxxxxxx.ilucca.net/api/v3/leavesOfDay"
var appToken = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
fetch(urlBase, {
"headers": { "Authorization": "lucca application=" + appToken } }) .then(function (res) {
return res.json();
}).then(function (data) {
  var entries = data.data.items;
var result = [];
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
var res = {
name: entry.user.displayName,
};
if(entry.startsAM && (!entry.endsAM || entry.endsOn != entry.startsOn)) {
res.detail = "all day";
} else if(entry.startsAM && entry.endsAM && entry.endsOn == entry.startsOn) {
res.detail = "this morning";
} else {
res.detail = "this afternoon";
}

if (entry.endsOn !== entry.startsOn) {
var endSp = entry.endsOn.split("T")[0].split("-");
res.detail += " and until " + endSp[2] + "/" + endSp[1] + "/" + endSp[0] + " inclus";
}
result.push(res);
}
if (result.length === 0) {
result.push({
name: "Nobody",
detail: "today"
});
}
callback(null, result);
}).catch(function (error) {
console.log(error);
});

To use this script, you will have to replace xxxxxxxxxxx in the urlBase variable with the name of your Lucca authority, as well as replace the appToken variable xxxxxxxxxxx-xxxxxx-xxxxxxxx with yours.
You can get this token from dedicated interface or by contacting the Lucca Support Team.

You may sometimes need a Zapier pro account to perform this type of connexion, otherwise the test might display an error.

You only have to configure the last action that will send the results to one of your Slack channels.

Choose the "Send Channel Message" option.

For the next step, sign in with your Slack account login details.  and complete the options, starting with the channel name:

Once the channel name has been entered you will have to write the message you want to display.
Feel free to use the text in the following example.

To finish the set up, just save and  run the tests.

Zap launch

You can activate the zap by wwitching the “OFF” button to “ON”.

Every morning at 7 am Slack will give you the list of daily absences.

Advanced zap (for experts)

It is possible to configure a zap in five steps that will notify the team in a dedicated channel a few days before the absence.

 

In step 2

You have to add 4 Data input 

url : https://lucca.ilucca.net/api/v3/leaves?leavePeriod.ownerId=greaterthan,0

appToken:  your token

offsetDays: 2 (= be notified 2 days before)

numberDayMinimum: 0 (= be notified if there is a minimum of 0 consecutive offset days)

In the code part you have to add the following code: 

// Function to process the recovered results with the query to send the results

var getCleanChannelName = function (channelName) {
channelName = channelName.replace(/\s+/g, '');
channelName = 'absence_' + channelName.toLocaleLowerCase();
return channelName;
}

var sendResult = function (results) {
var res = {};

res.list = [];
res.zapierLimitSize = 25;
if (input.validDepartment) {
res.validDepartmentList = input.validDepartment.toLocaleLowerCase().split(',');
for (var i = 0; i < res.validDepartmentList.length; i++) {
res.validDepartmentList[i] = getCleanChannelName(res.validDepartmentList[i]);
}
console.log(res.validDepartmentList);
}

res.channelExist = function (channelName) {
channelName = channelName.toLocaleLowerCase();
for (var index = 0; index < this.list.length; index++) {
if (channelName && this.list[index].channel && channelName === this.list[index].channel) {
return true;
}
}
return false;
}

res.channelAdd = function (channelName) {
channelName = channelName.toLocaleLowerCase();
if (channelName && this.list.length < this.zapierLimitSize && !this.channelExist(channelName)) {
var newElem = {};
newElem.channel = channelName;
newElem.message = '';

this.list.push(newElem);
}
}

res.listAddMessage = function (channelName, message) {
channelName = channelName.toLocaleLowerCase();
if (this.list.length < this.zapierLimitSize) {
this.channelAdd(channelName);

for (var index = 0; index < this.list.length; index++) {
if (channelName && this.list[index].channel === channelName) {
this.list[index].message += message;
break;
}
}
}
}

res.listAddMessageFilter = function (channelName, message) {
channelName = channelName.toLocaleLowerCase();
if (this.validDepartmentList === undefined || this.validDepartmentList === "") {
this.listAddMessage(channelName, message);
}
else {
for (var index = 0; index < this.validDepartmentList.length; index++) {
if (this.validDepartmentList[index] === channelName) {
this.listAddMessage(channelName, message);
}
}
}
}

if (results !== undefined) {
for (var i = 0; i < results.length; i++) {
if (results[i].numberDay >= input.numberDayMinimum) {
if (results[i].numberDay >= 2) {
var messageTmp = results[i].name + ' : from ' + results[i].detail + '\n';
}
else {
var messageTmp = results[i].name + ' : ' + results[i].detail + '\n';
}
var channelName = getCleanChannelName(results[i].departmentName)

res.listAddMessageFilter(channelName, messageTmp);
}
}
}

callback(null, res.list);
}
var dayDiff = function (d1, d2) {
d1 = d1.getTime() / 86400000;
d2 = d2.getTime() / 86400000;
return new Number(d2 - d1).toFixed(0);
};
var checkIsIn = function (result, name) {
for (var i = 0; i < result.length; i++) {
if (result[i] === name) {
return true;
}
}
return false;
};
// Request file

var request = function (thisDay) {

var results = [];
fetch(input.url + '&date=' + thisDay.todayS + '&fields=isAM,leavePeriod[owner.name,owner.department,endsOn,endsAM,startsOn]', {
'headers': {
'Authorization': 'lucca application=' + input.appToken
}
}).then(function (res) {
return res.json();
}).then(function (data) {
console.log(data);
var leaves = data.data.items;
var hash = {};

// List all absentees at J+input.offsetDays

leaves.map(function (leave) {
var username = leave.leavePeriod.owner.name;
var userleave = hash[username];
if (!userleave) {
userleave = {
morning: false,
afternoon: false,
end: leave.leavePeriod.endsOn.split('T')[0]
};
hash[username] = userleave;
console.log(leave.leavePeriod.startsOn.split('T')[0]);
if (leave.leavePeriod.startsOn.split('T')[0] === thisDay.todayS) {
results.push({
name: username,
leave: userleave,
departmentName: leave.leavePeriod.owner.department.name,
departmentId: leave.leavePeriod.owner.department.id
});
}
}
if (leave.isAM) {
userleave.morning = true;
} else {
userleave.afternoon = true;
}
});

// Create the outgoing messages for each absentee

results.map(function (curRes) {
var endSp = curRes.leave.end.split('-');
var endSpDate = new Date(endSp[0], endSp[1] - 1, endSp[2]);
var numberDay = parseInt(dayDiff(thisDay.date, endSpDate)) + 1;

if (curRes.leave.morning && curRes.leave.afternoon) {
curRes.detail = thisDay.formatString;
} else if (curRes.leave.morning) {
curRes.detail = thisDay.formatString + ' morning';
} else {
curRes.detail = thisDay.formatString + ' afternoon ';
}

if (curRes.leave.end !== curRes.todayS && numberDay >= 2) {
if (numberDay < 7) {
curRes.detail += ' during ' + numberDay;
curRes.detail += numberDay > 1 ? ' days' : ' day';
}
else {
var nbrWeek = (numberDay / 7) >> 0;
if ((numberDay / 7 - nbrWeek) > 0.5) {
nbrWeek += 1;
}

curRes.detail += ' during ' + nbrWeek;
curRes.detail += nbrWeek > 1 ? ' weeks' : ' week';
}
curRes.numberDay = numberDay;
}
else {
curRes.numberDay = 0;
}
});

sendResult(results);
}).catch(function (error) {
console.log(error);
});
}
// Date variables initiation file.

var getNextWorkingDate = function (offsetDays) {

// Creation of all the variables for the date.

if (!offsetDays) {
return null;
}

var day = new Date();
var nextDay = {};

for (var i = 0; i < offsetDays; i++) {
day.setDate(day.getDate() + 1);
if (day.toDateString().split(' ')[0] === 'Sat' || day.toDateString().split(' ')[0] === 'Sun') {
day.setDate(day.getDate() + 2);
}
}

var weekDays = {
'Mon': 'monday',
'Tue': 'tuesday',
'Wed': 'wednesday',
'Thu': 'thursday',
'Fri': 'friday',
'Sat': 'saturday',
'Sun': 'sunday'
};

nextDay.date = day;
nextDay.yearS = '' + day.getFullYear();
nextDay.month = day.getMonth() + 1;
nextDay.monthS = nextDay.month > 9 ? '' + nextDay.month : '0' + nextDay.month;
nextDay.dayS = day.getDate() > 9 ? '' + day.getDate() : '0' + day.getDate();
nextDay.todayS = nextDay.yearS + '-' + nextDay.monthS + '-' + nextDay.dayS;
nextDay.formatString = weekDays[day.toDateString().split(' ')[0]];
return nextDay;
};

//If the input variable exists check the value of offsetDays and the value of numberDayMinimum

if (input) {
if (input.offsetDays === undefined || input.offsetDays < 0) {
input.offsetDays = 0;
}

if (input.numberDayMinimum === undefined || input.numberDayMinimum < 0) {
input.numberDayMinimum = 0;
}

// Then initialise the variable nextDay with the next date taken into account
var nextDay = getNextWorkingDate(input.offsetDays);

// Finally launch the query
request(nextDay);
}

The third step involves the creation of a Slack channel

Add a filter for step 4

Step 5 allows to add a message into the channel.

Page content

Was this article helpful?
0 out of 1 found this helpful