Gestire la richiesta e approvazione delle ferie con Moduli, Fogli e Calendario di Google

Nell’articolo spieghiamo come implementare un sistema di gestione ferie completo.

Le richieste di ferie saranno raccolte tramite un Modulo e memorizzate su un Foglio. L’utente che autorizza o respinge le ferie accederà al Foglio e avrà a disposizione una funzionalità per selezionare la richiesta ed accettarla o respingerla.

In caso di accettazione, il periodo temporale specificato nella richiesta di ferie, sarà aggiunto come evento su un calendario ferie.
Sia in caso di accettazione che di rifiuto, all’utente che ne ha fatto richiesta verrà notificato l’esito via email.

Cominciamo!

Per prima cosa creiamo un nuovo Modulo di Google, diamogli il nome “Domanda di Ferie” e aggiungiamo i seguenti campi:

  • “Nome e Cognome” (di tipo “Testo risposta breve”)
  • “Matricola” (di tipo “Testo risposta breve”)
  • “Dal giorno” (di tipo “Data”)
  • “Al giorno” (di tipo “Data”)

Aggiungiamo un Foglio per le risposte e apriamolo

A questo punto apriamo il menu “Estensioni” > “Apps script” e incolliamo il codice che segue

const CALENDAR_ID = "<CALENDAR_ID>"
const AUTORIZED = true
const REJECTED = false

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Verifica')
      .addItem('Autorizza', 'authorize')
      .addItem('Respingi', 'reject')
      .addToUi();
}

function onSelectionChange(e) {
  const range = e.range;
  PropertiesService.getScriptProperties().setProperty("selectedRow",range.getRow());
  const sheet = range.getSheet();
  const maxRows = sheet.getDataRange().getLastRow();
  const maxColumns = sheet.getMaxColumns();

  sheet.getRange(2, 1, maxRows - 1, maxColumns).setBackground(null);
  
  if (range.getRow() > 1 && range.getRow() <= maxRows) {
    sheet.getRange(range.getRow(), 1, 1, maxColumns).setBackground("#FFcc00");
  }
}

function getUi() {
  return SpreadsheetApp.getUi();
}

function authorize(){
  const request = getRequest()
  if (request){
    sendMail(request, AUTORIZED)
    addCalendarEvent(request.name, request.dateFrom, request.dateTo)
  }
}

function reject(){
  const request = getRequest()
  if (request){
    sendMail(request, REJECTED)
  }
}

function getRequest(){
  const sheet = SpreadsheetApp.getActiveSheet()
  const maxColumns = sheet.getMaxColumns();
  const maxRows = sheet.getDataRange().getLastRow();

  var row = null;
  if (PropertiesService.getScriptProperties().getProperty("selectedRow") != null){
    row = parseInt(PropertiesService.getScriptProperties().getProperty("selectedRow"))
    if (row == 1 || row > maxRows ){
      getUi().alert("Selezionare una richiesta!")
      return null;
    }
  } else {
    getUi().alert("Selezionare una richiesta!")
    return null;
  }
  
  const sel = sheet.getRange(row, 1, 1, maxColumns);
  const values = sel.getValues()

  const request = {}
  request.requestDate = values[0][0]
  request.email = values[0][1]
  request.name = values[0][2]
  request.idNumber = values[0][3]
  request.dateFrom = values[0][4]
  request.dateTo = values[0][5]

  return request;
}

function addCalendarEvent(title, startDate, endDate) {
  endDate.setHours(endDate.getHours() + 24);
  var event = CalendarApp.getCalendarById(CALENDAR_ID).createEvent(
    title,
    startDate,
    endDate
  );
}

function formatDate(date){
 return Utilities.formatDate(date, "GMT+1", "dd/MM/yyyy")
}

function sendMail(request, result){
  var subject = null
  var body = "Buongiorno " + request.name + " (matricola: " + request.idNumber + "),\n"
  body += "La tua richiesta di ferie per il periodo " + formatDate(request.dateFrom) + " - " + formatDate(request.dateTo)+ "\n"
  
  if (result){
    subject = "Richiesta di ferie accettata"
    body += "è stata approvata"
  } else {
    subject = "Richiesta di ferie respinta"
    body += "è stata respinta"
  }
  MailApp.sendEmail(request.email, subject, body);
}

Nella funzione onOpen, creiamo un menu personalizzato nel nostro foglio e gli aggiungiamo due voci; la prima richiamerà la funzione per autorizzare la specifica richiesta di ferie selezionata, l’altra per respingerla.

Attraverso la funzione onSelectionChange che viene eseguita dal nostro foglio ogni volta che effettuiamo una selezione di celle, implementiamo un meccanismo che evidenzia tutta la riga selezionata in giallo.
Inoltre memorizziamo il numero della riga selezionata, in una proprietà del foglio (che chiamiamo selectedRow), attraverso l’istruzione:
PropertiesService.getScriptProperties().setProperty(“selectedRow”,range.getRow())

La funzione getRequest ci consente di recuperare le informazioni della richiesta selezionata dall’utente che autorizza le richieste, recuperando l’indice di riga appena salvato.

Il metodo authorize, recupera la richiesta e la autorizza, inviando una mail di richiesta autorizzata (sendMail) e inserendo l’evento (addCalendarEvent) nel calendario ferie il cui id è specificato nella variabile a inizio script “CALENDAR_ID”

Il metodo reject, notifica attraverso mail la richiesta rigettata.