diff --git a/CHANGELOG.md b/CHANGELOG.md
index c28e2b784..cb869bc1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.5.3] - 2022-08-16
+
+### Added
+ - Aggiunta email di warning per assenze per missione non inserite a causa di assenze preesistenti
+ - Aggiunta possibilità per il responsabile di sede di vedere i flussi di richiesta ferie anche
+ di personale non del proprio istituto ma di cui si è responsabile di sede (utile per le Aree di Ricerca)
+ - Aggiunte alcune label per gli screenreader per migliorare l'accessibilità
+ - Aggiunta possibilità di vedere nel menù la gestione dei telework se questi sono abilitati per
+ l'utente
+ - Aggiunta possibilità di vedere il menu con i flussi di lavoro al personale che è responsabile di
+ sede, anche sulle sedi diversa dalla propria di assegnazione
+### Changed
+ - Corretto controllo dei buoni pasto inviati ad Attestati (funzionalità solo per CNR)
+ - La cancellazione dei servizi di reperibilità adesso è possibile anche se il servizio
+ ha associato delle persone ma non ha nessun giorno di reperibilità assegnato
+ - Modificato il comportamento del codice 39LA per l'assegnazione del buono pasto (non lo assegna)
+ - Rimosso codice 40LA dalla lista dei codici prendibili
+ - Modificata lista dei flussi attivi evitando di mostrare quelli relativi alla propria sede se non
+ si hanno gli opportuni permessi
+ - Rimossa scritta SSO nella form di login tramite OAuth
+ - Modificato messaggio di errore in caso di richiesta riposo compensativo senza ore sufficienti
+
## [2.5.2] - 2022-07-06
### Added
@@ -15,7 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Aggiunta possibilità di cedere un giorno di reperibilità
- Aggiunto controllo sulla visibilità della presenza giornaliera dei dipendenti appartenenti ad un
gruppo da parte del responsabile di gruppo
-
### Changed
- Corretto messaggio di errore in caso di attestato di fine mese non calcolato correttamente
- Modificato il conteggio dei giorni di presenza in sede quando un dipendente è in telelavoro e
@@ -223,4 +244,4 @@ e tipologia di orario di lavoro e aggiornamento del corrispondente externalId
## [2.0.0] - 2021-02-25
### Added
-- Prima relaase pubblica open source
\ No newline at end of file
+- Prima relaase pubblica open source
diff --git a/VERSION b/VERSION
index 21b159dc8..a4db534a2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.5.2
\ No newline at end of file
+2.5.3
\ No newline at end of file
diff --git a/app/controllers/AbsenceRequests.java b/app/controllers/AbsenceRequests.java
index 4f9745229..0db0407da 100644
--- a/app/controllers/AbsenceRequests.java
+++ b/app/controllers/AbsenceRequests.java
@@ -35,6 +35,7 @@
import helpers.TemplateExtensions;
import helpers.Web;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
@@ -59,6 +60,7 @@
import models.UsersRolesOffices;
import models.absences.AbsenceType;
import models.absences.GroupAbsenceType;
+import models.absences.GroupAbsenceType.GroupAbsenceTypePattern;
import models.absences.JustifiedType;
import models.absences.definitions.DefaultAbsenceType;
import models.absences.definitions.DefaultGroup;
@@ -248,17 +250,18 @@ public static void listToApprove(AbsenceRequestType type) {
fromDate);
List groups =
groupDao.groupsByOffice(person.office, Optional.absent(), Optional.of(false));
- List roleList = uroDao.getUsersRolesOfficesByUser(person.user);
+ List roleList =
+ uroDao.getAdministrativeUsersRolesOfficesByUser(person.user);
List results =
absenceRequestDao.allResults(roleList, fromDate, Optional.absent(), type, groups, person);
- List myResults = absenceRequestDao.toApproveResults(roleList, Optional.absent(),
+ Set myResults = absenceRequestDao.toApproveResults(roleList, Optional.absent(),
Optional.absent(), type, groups, person);
List approvedResults = absenceRequestDao.totallyApproved(roleList, fromDate,
Optional.absent(), type, groups, person);
val config = absenceRequestManager.getConfiguration(type, person);
val onlyOwn = false;
- log.debug("Preparate richieste da approvare per {} in {} ms. Da approvare = {}",
- person.getFullname(), System.currentTimeMillis() - start, myResults.size());
+ log.debug("Preparate richieste da approvare per {} in {} ms. Da approvare = {}. Flussi attivi = {}",
+ person.getFullname(), System.currentTimeMillis() - start, myResults.size(), results.size());
render(config, results, type, onlyOwn, approvedResults, myResults);
}
@@ -302,8 +305,13 @@ public static void blank(Optional personId, LocalDate from, AbsenceRequest
val absenceRequest = new AbsenceRequest();
absenceRequest.type = type;
absenceRequest.person = person;
+
+ PeriodChain periodChain = null;
+ GroupAbsenceType groupAbsenceType = null;
if (type.equals(AbsenceRequestType.COMPENSATORY_REST) && person.isTopQualification()) {
+ groupAbsenceType = absenceComponentDao
+ .groupAbsenceTypeByName(DefaultGroup.RIPOSI_CNR.name()).get();
PersonStampingRecap psDto = stampingsRecapFactory.create(person, LocalDate.now().getYear(),
LocalDate.now().getMonthOfYear(), true);
int maxDays = (Integer) configurationManager.configValue(person.office,
@@ -312,26 +320,32 @@ public static void blank(Optional personId, LocalDate from, AbsenceRequest
handleCompensatoryRestSituation = true;
}
if (type.equals(AbsenceRequestType.VACATION_REQUEST)) {
- GroupAbsenceType vacationGroup =
+ groupAbsenceType =
absenceComponentDao.groupAbsenceTypeByName(DefaultGroup.FERIE_CNR.name()).get();
IWrapperPerson wperson = wrapperFactory.create(person);
for (Contract contract : wperson.orderedYearContracts(LocalDate.now().getYear())) {
VacationSituation vacationSituation = absenceService.buildVacationSituation(contract,
- LocalDate.now().getYear(), vacationGroup, Optional.absent(), false);
+ LocalDate.now().getYear(), groupAbsenceType, Optional.absent(), false);
vacationSituations.add(vacationSituation);
}
+ periodChain = absenceService
+ .residual(person, groupAbsenceType, LocalDate.now());
+ }
+ if (type.equals(AbsenceRequestType.PERSONAL_PERMISSION)) {
+ groupAbsenceType = absenceComponentDao
+ .groupAbsenceTypeByName(DefaultGroup.G_661.name()).get();
+ periodChain = absenceService
+ .residual(person, groupAbsenceType, LocalDate.now());
}
- GroupAbsenceType permissionGroup = absenceComponentDao
- .groupAbsenceTypeByName(DefaultGroup.G_661.name()).get();
- PeriodChain periodChain = absenceService
- .residual(person, permissionGroup, LocalDate.now());
+
boolean showVacationPeriods = false;
boolean retroactiveAbsence = false;
absenceRequest.startAt = absenceRequest.endTo = LocalDateTime.now().plusDays(1);
boolean insertable = true;
- GroupAbsenceType groupAbsenceType = absenceRequestManager.getGroupAbsenceType(absenceRequest);
+ groupAbsenceType = absenceRequestManager.getGroupAbsenceType(absenceRequest);
+
AbsenceType absenceType = null;
AbsenceForm absenceForm = absenceService.buildAbsenceForm(absenceRequest.person,
absenceRequest.startAtAsDate(), null, absenceRequest.endToAsDate(), null, groupAbsenceType,
@@ -340,6 +354,7 @@ public static void blank(Optional personId, LocalDate from, AbsenceRequest
absenceService.insert(absenceRequest.person, absenceForm.groupSelected, absenceForm.from,
absenceForm.to, absenceForm.absenceTypeSelected, absenceForm.justifiedTypeSelected,
null, null, false, absenceManager);
+
render("@edit", absenceRequest, insertable, insertReport, vacationSituations,
compensatoryRestAvailable, handleCompensatoryRestSituation, showVacationPeriods,
@@ -358,10 +373,12 @@ public static void edit(final AbsenceRequest absenceRequest, boolean retroactive
rules.checkIfPermitted(absenceRequest);
boolean insertable = true;
- GroupAbsenceType permissionGroup = absenceComponentDao
- .groupAbsenceTypeByName(DefaultGroup.G_661.name()).get();
- PeriodChain periodChain = absenceService
- .residual(absenceRequest.person, permissionGroup, LocalDate.now());
+ GroupAbsenceType permissionGroup = groupAbsenceType;
+ PeriodChain periodChain = null;
+ if (!groupAbsenceType.name.equals(DefaultGroup.RIPOSI_CNR.name())) {
+ periodChain = absenceService
+ .residual(absenceRequest.person, permissionGroup, LocalDate.now());
+ }
if (absenceRequest.startAt == null || absenceRequest.endTo == null) {
Validation.addError("absenceRequest.startAt",
diff --git a/app/controllers/Competences.java b/app/controllers/Competences.java
index 07ae806e7..790ff930a 100755
--- a/app/controllers/Competences.java
+++ b/app/controllers/Competences.java
@@ -986,14 +986,24 @@ public static void evaluateReperibility(Long reperibilityTypeId, boolean confirm
flash.success("Riabilitato servizio %s", type.description);
activateServices(type.office.id);
}
- if (!type.personReperibilities.isEmpty()) {
+
+ log.debug("Reperibility type = {}, personReperibilities.size = {}, "
+ + "personReperibilitiesDays.size = {}",
+ type, type.personReperibilities.size(),
+ type.personReperibilities.stream().flatMap(pr -> pr.personReperibilityDays.stream()).collect(Collectors.toList()).size());
+
+ if (!type.personReperibilities.isEmpty() &&
+ !type.personReperibilities.stream().flatMap(pr -> pr.personReperibilityDays.stream()).collect(Collectors.toList()).isEmpty()) {
type.disabled = true;
type.save();
+ log.info("Disabilitato servizio {}", type);
flash.success("Il servizio è stato disabilitato e non rimosso perchè legato con informazioni "
+ "importanti presenti in altre tabelle");
} else {
+ type.personReperibilities.stream().forEach(pr -> pr.delete());
type.delete();
+ log.info("Rimosso servizio {}", type);
flash.success("Servizio rimosso con successo");
}
activateServices(type.office.id);
diff --git a/app/controllers/InformationRequests.java b/app/controllers/InformationRequests.java
index c7ca5c564..3863547db 100644
--- a/app/controllers/InformationRequests.java
+++ b/app/controllers/InformationRequests.java
@@ -46,6 +46,7 @@
import manager.flows.InformationRequestManager;
import manager.recaps.personstamping.PersonStampingRecap;
import manager.recaps.personstamping.PersonStampingRecapFactory;
+import models.Contract;
import models.Person;
import models.Role;
import models.TeleworkValidation;
@@ -73,7 +74,7 @@
@Slf4j
@With(Resecure.class)
public class InformationRequests extends Controller {
-
+
@Inject
static InformationRequestManager informationRequestManager;
@Inject
@@ -100,23 +101,23 @@ public class InformationRequests extends Controller {
public static void teleworks() {
list(InformationType.TELEWORK_INFORMATION);
}
-
+
public static void illness() {
list(InformationType.ILLNESS_INFORMATION);
}
-
+
public static void serviceExit() {
list(InformationType.SERVICE_INFORMATION);
}
-
+
public static void teleworksToApprove() {
listToApprove(InformationType.TELEWORK_INFORMATION);
}
-
+
public static void illnessToApprove() {
listToApprove(InformationType.ILLNESS_INFORMATION);
}
-
+
public static void serviceExitToApprove() {
listToApprove(InformationType.SERVICE_INFORMATION);
}
@@ -149,34 +150,33 @@ public static void list(InformationType type) {
List illnessClosed = Lists.newArrayList();
switch (type) {
case TELEWORK_INFORMATION:
- teleworks = informationRequestDao.teleworksByPersonAndDate(person, fromDate,
+ teleworks = informationRequestDao.teleworksByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.TELEWORK_INFORMATION, true);
- teleworksClosed = informationRequestDao.teleworksByPersonAndDate(person, fromDate,
+ teleworksClosed = informationRequestDao.teleworksByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.TELEWORK_INFORMATION, false);
break;
case ILLNESS_INFORMATION:
- illness = informationRequestDao.illnessByPersonAndDate(person, fromDate,
+ illness = informationRequestDao.illnessByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.ILLNESS_INFORMATION, true);
- illnessClosed = informationRequestDao.illnessByPersonAndDate(person, fromDate,
+ illnessClosed = informationRequestDao.illnessByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.ILLNESS_INFORMATION, false);
break;
case SERVICE_INFORMATION:
- services = informationRequestDao.servicesByPersonAndDate(person, fromDate,
+ services = informationRequestDao.servicesByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.SERVICE_INFORMATION, true);
- servicesClosed = informationRequestDao.servicesByPersonAndDate(person, fromDate,
+ servicesClosed = informationRequestDao.servicesByPersonAndDate(person, fromDate,
Optional.absent(), InformationType.SERVICE_INFORMATION, false);
break;
default:
log.info("Passato argomento non conosciuto");
break;
}
- render(teleworks, services, illness, teleworksClosed,
+ render(teleworks, services, illness, teleworksClosed,
illnessClosed, servicesClosed, config, type);
}
-
+
/**
- * Genera la pagina con tutte le richieste di flusso informativo del tipo passato
- * come parametro.
+ * Genera la pagina con tutte le richieste di flusso informativo del tipo passato come parametro.
*
* @param type la tipologia di flusso informativo.
*/
@@ -187,15 +187,15 @@ public static void listToApprove(InformationType type) {
val fromDate = LocalDateTime.now().withDayOfYear(1).withMonth(1).minusMonths(1);
log.debug("Prelevo le richieste da approvare di assenze di tipo {} a partire da {}", type,
fromDate);
-
+
List roleList = uroDao.getUsersRolesOfficesByUser(person.user);
- List myResults =
+ List myResults =
informationRequestDao.toApproveResults(roleList, Optional.absent(),
- Optional.absent(), type, person);
- List approvedResults =
+ Optional.absent(), type, person);
+ List approvedResults =
informationRequestDao.totallyApproved(roleList, fromDate,
- Optional.absent(), type, person);
-
+ Optional.absent(), type, person);
+
List idMyResults = myResults.stream().map(ir -> ir.id).collect(Collectors.toList());
List idApprovedResults = approvedResults.stream().map(ir -> ir.id)
.collect(Collectors.toList());
@@ -224,20 +224,20 @@ public static void listToApprove(InformationType type) {
val config = informationRequestManager.getConfiguration(type, person);
val onlyOwn = false;
- render(config, type, onlyOwn, approvedResults, myResults,
+ render(config, type, onlyOwn, approvedResults, myResults,
myIllnessResult, illnessApprovedResult, myServiceResult, serviceApprovedResult,
myTeleworkResult, teleworkApprovedResult);
}
-
+
/**
* Crea la pagina di inserimento di una nuova richiesta di flusso informativo.
*
* @param personId l'identificativo della persona
- * @param type la tipologia di flusso informativo da generare
+ * @param type la tipologia di flusso informativo da generare
*/
public static void blank(Optional personId, InformationType type) {
Verify.verifyNotNull(type);
-
+
Person person;
if (personId.isPresent()) {
rules.check("AbsenceRequests.blank4OtherPerson");
@@ -252,7 +252,7 @@ public static void blank(Optional personId, InformationType type) {
}
}
notFoundIfNull(person);
-
+
val configurationProblems = informationRequestManager.checkconfiguration(type, person);
if (!configurationProblems.isEmpty()) {
flash.error(Joiner.on(" ").join(configurationProblems));
@@ -272,33 +272,32 @@ public static void blank(Optional personId, InformationType type) {
illnessRequest.informationType = type;
render("@editIllnessRequest", illnessRequest, type, person);
break;
- default:
+ default:
break;
}
}
-
+
public static void editServiceRequest(ServiceRequest serviceRequest, InformationType type,
@CheckWith(StringIsTime.class) String begin, @CheckWith(StringIsTime.class) String finish) {
-
-
+
}
-
+
public static void editIllnessRequest(IllnessRequest illnessRequest, boolean retroactiveAbsence) {
-
+
}
-
+
/**
* Persiste la richiesta di uscita di servizio e avvia il flusso approvativo.
*
* @param serviceRequest la richiesta di uscita di servizio
- * @param begin l'orario di inizio
- * @param finish l'orario di fine
+ * @param begin l'orario di inizio
+ * @param finish l'orario di fine
*/
public static void saveServiceRequest(ServiceRequest serviceRequest,
@CheckWith(StringIsTime.class) String begin, @CheckWith(StringIsTime.class) String finish) {
InformationType type = serviceRequest.informationType;
boolean insertable = true;
- if (Validation.hasErrors()) {
+ if (Validation.hasErrors()) {
response.status = 400;
insertable = false;
render("@editServiceRequest", serviceRequest, insertable, begin, finish, type);
@@ -315,25 +314,25 @@ public static void saveServiceRequest(ServiceRequest serviceRequest,
render("@editServiceRequest", serviceRequest, insertable, begin, finish, type);
}
if (serviceRequest.beginAt.isAfter(serviceRequest.finishTo)) {
- Validation.addError("serviceRequest.beginAt",
+ Validation.addError("serviceRequest.beginAt",
"L'orario di inizio non può essere successivo all'orario di fine");
response.status = 400;
insertable = false;
render("@editServiceRequest", serviceRequest, insertable, begin, finish, type);
}
- informationRequestManager.configure(Optional.absent(),
+ informationRequestManager.configure(Optional.absent(),
Optional.of(serviceRequest), Optional.absent());
serviceRequest.startAt = LocalDateTime.now();
serviceRequest.save();
-
+
boolean isNewRequest = !serviceRequest.isPersistent();
if (isNewRequest || !serviceRequest.flowStarted) {
- informationRequestManager.executeEvent(Optional.fromNullable(serviceRequest),
+ informationRequestManager.executeEvent(Optional.fromNullable(serviceRequest),
Optional.absent(), Optional.absent(), serviceRequest.person,
InformationRequestEventType.STARTING_APPROVAL_FLOW, Optional.absent());
if (serviceRequest.autoApproved()) {
- informationRequestManager.executeEvent(Optional.fromNullable(serviceRequest),
- Optional.absent(), Optional.absent(), serviceRequest.person,
+ informationRequestManager.executeEvent(Optional.fromNullable(serviceRequest),
+ Optional.absent(), Optional.absent(), serviceRequest.person,
InformationRequestEventType.COMPLETE, Optional.absent());
}
if (serviceRequest.person.isSeatSupervisor()) {
@@ -350,9 +349,9 @@ public static void saveServiceRequest(ServiceRequest serviceRequest,
}
flash.success("Operazione effettuata correttamente");
InformationRequests.list(serviceRequest.informationType);
-
+
}
-
+
/**
* Persiste la richiesta e avvia il flusso informativo.
*
@@ -366,22 +365,22 @@ public static void saveIllnessRequest(IllnessRequest illnessRequest) {
Validation.addError("illnessRequest.endDate",
"Entrambi i campi data devono essere valorizzati");
response.status = 400;
-
+
render("@editIllnessRequest", illnessRequest, type);
}
if (illnessRequest.beginDate.isAfter(illnessRequest.endDate)) {
- Validation.addError("illnessRequest.beginDate",
+ Validation.addError("illnessRequest.beginDate",
"La data di inizio non può essere successiva alla data di fine");
response.status = 400;
render("@editIllnessRequest", illnessRequest, type);
}
- informationRequestManager.configure(Optional.of(illnessRequest),
+ informationRequestManager.configure(Optional.of(illnessRequest),
Optional.absent(), Optional.absent());
illnessRequest.startAt = LocalDateTime.now();
illnessRequest.save();
boolean isNewRequest = !illnessRequest.isPersistent();
if (isNewRequest || !illnessRequest.flowStarted) {
- informationRequestManager.executeEvent(Optional.absent(),
+ informationRequestManager.executeEvent(Optional.absent(),
Optional.fromNullable(illnessRequest), Optional.absent(), illnessRequest.person,
InformationRequestEventType.STARTING_APPROVAL_FLOW, Optional.absent());
if (illnessRequest.person.isSeatSupervisor()) {
@@ -399,27 +398,36 @@ public static void saveIllnessRequest(IllnessRequest illnessRequest) {
flash.success("Operazione effettuata correttamente");
InformationRequests.list(illnessRequest.informationType);
}
-
+
/**
* Persiste la richiesta di telelavoro e avvia il flusso informativo.
*
* @param personId l'identificativo della persona
- * @param year l'anno di riferimento
- * @param month il mese di riferimento
+ * @param year l'anno di riferimento
+ * @param month il mese di riferimento
*/
public static void saveTeleworkRequest(Long personId, int year, int month) {
Person person = personDao.getPersonById(personId);
notFoundIfNull(person);
- TeleworkRequest teleworkRequest = new TeleworkRequest();
- teleworkRequest.year = year;
- teleworkRequest.month = month;
- teleworkRequest.person = person;
- teleworkRequest.startAt = LocalDateTime.now();
- teleworkRequest.informationType = InformationType.TELEWORK_INFORMATION;
- teleworkRequest.save();
- informationRequestManager.configure(Optional.absent(),
- Optional.absent(), Optional.of(teleworkRequest));
+
+ TeleworkRequest teleworkRequest;
+
+ val teleworkRequestInPeriod = informationRequestDao.personTeleworkInPeriod(person, month, year);
+ if (!teleworkRequestInPeriod.isPresent()) {
+ teleworkRequest = new TeleworkRequest();
+ teleworkRequest.year = year;
+ teleworkRequest.month = month;
+ teleworkRequest.person = person;
+ teleworkRequest.startAt = LocalDateTime.now();
+ teleworkRequest.informationType = InformationType.TELEWORK_INFORMATION;
+ teleworkRequest.save();
+ informationRequestManager.configure(Optional.absent(), Optional.absent(),
+ Optional.of(teleworkRequest));
+ } else {
+ teleworkRequest = teleworkRequestInPeriod.get();
+ }
boolean isNewRequest = !teleworkRequest.isPersistent();
+
if (isNewRequest || !teleworkRequest.flowStarted) {
informationRequestManager.executeEvent(Optional.absent(), Optional.absent(),
Optional.fromNullable(teleworkRequest), teleworkRequest.person,
@@ -438,10 +446,10 @@ public static void saveTeleworkRequest(Long personId, int year, int month) {
}
flash.success("Operazione effettuata correttamente");
InformationRequests.list(teleworkRequest.informationType);
-
+
}
-
-
+
+
/**
* Metodo dispatcher che chiama il corretto metodo per approvare la richiesta.
*
@@ -468,11 +476,11 @@ public static void approval(long id) {
notFoundIfNull(request);
User user = Security.getUser().get();
- boolean approved = informationRequestManager.approval(serviceRequest,
+ boolean approved = informationRequestManager.approval(serviceRequest,
illnessRequest, teleworkRequest, user);
if (approved) {
- notificationManager.sendEmailToUser(Optional.absent(), Optional.absent(),
+ notificationManager.sendEmailToUser(Optional.absent(), Optional.absent(),
Optional.fromNullable(request), true);
log.debug("Inviata mail con approvazione");
flash.success("Operazione conclusa correttamente");
@@ -483,10 +491,10 @@ public static void approval(long id) {
InformationRequests.listToApprove(request.informationType);
} else {
InformationRequests.list(request.informationType);
- }
+ }
}
-
+
/**
* Dispatcher che instrada al corretto metodo l'operazione da fare sulla richiesta a seconda dei
* parametri.
@@ -524,25 +532,25 @@ public static void disapproval(long id, boolean disapproval, String reason) {
break;
default:
break;
- }
-
- if (informationRequest.officeHeadApprovalRequired
+ }
+
+ if (informationRequest.officeHeadApprovalRequired
&& informationRequest.officeHeadApproved == null
&& user.hasRoles(Role.SEAT_SUPERVISOR)) {
// caso di approvazione da parte del responsabile di sede
informationRequestManager.officeHeadDisapproval(id, reason);
flash.error("Richiesta respinta");
InformationType type = informationRequest.informationType;
- render("@show", informationRequest, type, serviceRequest,
+ render("@show", informationRequest, type, serviceRequest,
illnessRequest, teleworkRequest, user);
}
render("@show", informationRequest, user);
}
-
+
/**
* Mostra al template la richiesta.
*
- * @param id l'id della richiesta da visualizzare
+ * @param id l'id della richiesta da visualizzare
* @param type la tipologia di richiesta
*/
public static void show(long id, InformationType type) {
@@ -555,23 +563,23 @@ public static void show(long id, InformationType type) {
TeleworkRequest teleworkRequest = null;
switch (type) {
case SERVICE_INFORMATION:
- serviceRequest = informationRequestDao.getServiceById(id).get();
+ serviceRequest = informationRequestDao.getServiceById(id).get();
break;
case ILLNESS_INFORMATION:
- illnessRequest = informationRequestDao.getIllnessById(id).get();
+ illnessRequest = informationRequestDao.getIllnessById(id).get();
break;
case TELEWORK_INFORMATION:
- teleworkRequest = informationRequestDao.getTeleworkById(id).get();
+ teleworkRequest = informationRequestDao.getTeleworkById(id).get();
break;
default:
log.info("Passato argomento non conosciuto");
break;
}
boolean disapproval = false;
- render(informationRequest, teleworkRequest, illnessRequest, serviceRequest,
+ render(informationRequest, teleworkRequest, illnessRequest, serviceRequest,
type, user, disapproval);
}
-
+
/**
* Form di cancellazione di un flusso informativo.
*
@@ -594,34 +602,34 @@ public static void delete(long id) {
case TELEWORK_INFORMATION:
teleworkRequest = Optional.fromNullable(informationRequestDao.getTeleworkById(id).get());
break;
- default:
+ default:
break;
}
- informationRequestManager.executeEvent(serviceRequest, illnessRequest,
+ informationRequestManager.executeEvent(serviceRequest, illnessRequest,
teleworkRequest, Security.getUser().get().person,
InformationRequestEventType.DELETE, Optional.absent());
flash.success(Web.msgDeleted(InformationRequest.class));
list(informationRequest.informationType);
}
-
+
/**
* Ritorna il riepilogo del telelavoro dell'anno/mese della persona in oggetto.
*
* @param personId l'identificativo della persona
- * @param year l'anno di riferimento
- * @param month il mese di riferimento
+ * @param year l'anno di riferimento
+ * @param month il mese di riferimento
* @throws NoSuchFieldException eccezione di mancanza di campo
- * @throws ExecutionException eccezione in esecuzione
+ * @throws ExecutionException eccezione in esecuzione
*/
- public static void generateTeleworkReport(Long personId, int year, int month)
+ public static void generateTeleworkReport(Long personId, int year, int month)
throws NoSuchFieldException, ExecutionException {
-
+
Person person = personDao.getPersonById(personId);
notFoundIfNull(person);
IWrapperPerson wrperson = wrapperFactory.create(person);
-
+
List list = Lists.newArrayList();
-
+
if (!wrperson.isActiveInMonth(new YearMonth(year, month))) {
flash.error("Non esiste situazione mensile per il mese di %s %s",
DateUtility.fromIntToStringMonth(month), year);
@@ -631,38 +639,38 @@ public static void generateTeleworkReport(Long personId, int year, int month)
}
PersonStampingRecap psDto = stampingsRecapFactory
.create(wrperson.getValue(), year, month, true);
-
+
log.debug("Chiedo la lista delle timbrature in telelavoro ad applicazione esterna.");
-
+
list = manager.stampingsForReport(psDto);
render(list, person);
}
-
+
/**
* Ritorna la form di gestione approvazioni di telelavoro.
*
- * @param personId l'identificativo della persona di cui gestire le richieste/approvazioni
- * di telelavoro
+ * @param personId l'identificativo della persona di cui gestire le richieste/approvazioni di
+ * telelavoro
*/
public static void handleTeleworkApproval(Long personId) {
PersonLite p = null;
Person person = personDao.getPersonById(personId);
- if (person.personConfigurations.stream().noneMatch(pc ->
+ if (person.personConfigurations.stream().noneMatch(pc ->
pc.epasParam.equals(EpasParam.TELEWORK_STAMPINGS) && pc.fieldValue.equals("true"))) {
@SuppressWarnings("unchecked")
List persons = (List) renderArgs.get("navPersons");
if (persons.isEmpty()) {
flash.error("Non ci sono persone abilitate al telelavoro!!");
- Stampings.personStamping(personId, Integer.parseInt(session.get("yearSelected")),
+ Stampings.personStamping(personId, Integer.parseInt(session.get("yearSelected")),
Integer.parseInt(session.get("monthSelected")));
}
p = persons.get(0);
-
+
}
if (p != null) {
- person = personDao.getPersonById(p.id);
+ person = personDao.getPersonById(p.id);
}
-
+
Preconditions.checkNotNull(person);
rules.checkIfPermitted(person.office);
List dtoList = Lists.newArrayList();
@@ -684,7 +692,7 @@ public static void handleTeleworkApproval(Long personId) {
}
render(dtoList);
}
-
+
/**
* Revoca la validazione ad un telelavoro.
*
@@ -694,12 +702,12 @@ public static void revokeValidation(Long validationId) {
Optional validation = validationDao.getValidationById(validationId);
if (validation.isPresent()) {
validation.get().delete();
- flash.success("Validazione rimossa. Effettuare nuova richiesta di approvazione");
+ flash.success("Validazione rimossa. Effettuare nuova richiesta di approvazione");
} else {
flash.error("Validazione sconosciuta! Verificare l'identificativo.");
}
- Stampings.personStamping(Security.getUser().get().person.id,
- Integer.parseInt(session.get("yearSelected")),
- Integer.parseInt(session.get("monthSelected")));
+ Stampings.personStamping(Security.getUser().get().person.id,
+ Integer.parseInt(session.get("yearSelected")),
+ Integer.parseInt(session.get("monthSelected")));
}
}
diff --git a/app/controllers/rest/Missions.java b/app/controllers/rest/Missions.java
index f120b7db9..f8d95cca3 100644
--- a/app/controllers/rest/Missions.java
+++ b/app/controllers/rest/Missions.java
@@ -26,10 +26,12 @@
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import manager.MissionManager;
+import manager.NotificationManager;
import manager.configurations.ConfigurationManager;
import manager.configurations.EpasParam;
import models.Office;
import models.exports.MissionFromClient;
+import play.cache.Cache;
import play.data.binding.As;
import play.mvc.Controller;
import play.mvc.With;
@@ -48,6 +50,8 @@ public class Missions extends Controller {
private static ConfigurationManager configurationManager;
@Inject
private static OfficeDao officeDao;
+ @Inject
+ private static NotificationManager notificationManager;
private static void logInfo(String description, MissionFromClient body) {
log.info(MissionManager.LOG_PREFIX + "{}. Messaggio: {}", description, body);
@@ -73,12 +77,12 @@ public static void amqpreceiver(@As(binder = JsonMissionBinder.class)MissionFrom
JsonResponse.badRequest();
return;
}
-
+
if (body.dataInizio.isAfter(body.dataFine)) {
logWarn("Data di inizio successiva alla data di fine, messaggio scartato", body);
JsonResponse.badRequest();
}
-
+
// person not present (404)
if (!missionManager.linkToPerson(body).isPresent()) {
logWarn("Dipendente riferito nel messaggio non trovato, messaggio scartato", body);
@@ -89,7 +93,7 @@ public static void amqpreceiver(@As(binder = JsonMissionBinder.class)MissionFrom
Optional officeByMessage = officeDao.byCodeId(body.codiceSede);
//Ufficio associato alla persona prelevata tramite la matricola passata nel JSON
Office office = body.person.office;
-
+
if (!officeByMessage.isPresent()) {
logWarn(
String.format("Attenzione il codice sede %s non è presente su ePAS ed il dipendente %s "
@@ -103,7 +107,7 @@ public static void amqpreceiver(@As(binder = JsonMissionBinder.class)MissionFrom
body.codiceSede, office.name, office.codeId, body.person.getFullname()),
body);
}
-
+
// Check if integration ePAS-Missions is enabled
if (!(Boolean) configurationManager
.configValue(office, EpasParam.ENABLE_MISSIONS_INTEGRATION)) {
@@ -112,7 +116,7 @@ public static void amqpreceiver(@As(binder = JsonMissionBinder.class)MissionFrom
office.name, body.person.fullName()), body);
JsonResponse.ok();
}
-
+
boolean success = false;
switch (body.tipoMissione) {
case "ORDINE":
@@ -131,7 +135,17 @@ public static void amqpreceiver(@As(binder = JsonMissionBinder.class)MissionFrom
if (success) {
logInfo("Messaggio inserito con successo", body);
} else {
- logWarn("Non è stato possibile inserire il messaggio", body);
+ logWarn("Problemi durante l'inserimento del messaggio", body);
+ String problematicMissionCacheKey =
+ String.format("mission.problematic.%s.%s.%s.%s",
+ body.tipoMissione, body.id, body.anno, body.numero);
+ if (Cache.get(problematicMissionCacheKey) == null) {
+ log.debug("Imposto la cache di missione problematica con valore true per {}", body);
+ notificationManager.sendEmailMissionFromClientProblems(body);
+ Cache.set(problematicMissionCacheKey, true, "1d");
+ } else {
+ logInfo("Missione problematica già segnalata all'utente. Email non inviata.", body);
+ }
JsonResponse.conflict();
}
diff --git a/app/dao/AbsenceRequestDao.java b/app/dao/AbsenceRequestDao.java
index 377f49f69..1388e44f6 100644
--- a/app/dao/AbsenceRequestDao.java
+++ b/app/dao/AbsenceRequestDao.java
@@ -20,6 +20,7 @@
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.inject.Provider;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.JPQLQuery;
@@ -27,6 +28,7 @@
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.persistence.EntityManager;
@@ -120,7 +122,7 @@ public List findByPersonAndDate(Person person,
* @param absenceRequestType il tipo di richiesta da cercare
* @return la lista di tutti i flussi attivi da approvare.
*/
- public List toApproveResults(List uros,
+ public Set toApproveResults(List uros,
Optional fromDate, Optional toDate,
AbsenceRequestType absenceRequestType, List groups, Person signer) {
Preconditions.checkNotNull(fromDate);
@@ -134,7 +136,7 @@ public List toApproveResults(List uros,
if (uros.stream().noneMatch(uro -> uro.role.name.equals(Role.GROUP_MANAGER)
|| uro.role.name.equals(Role.PERSONNEL_ADMIN)
|| uro.role.name.equals(Role.SEAT_SUPERVISOR))) {
- return Lists.newArrayList();
+ return Sets.newHashSet();
}
if (fromDate.isPresent()) {
conditions.and(absenceRequest.startAt.after(fromDate.get()));
@@ -146,7 +148,7 @@ public List toApproveResults(List uros,
.and(absenceRequest.flowStarted.isTrue())
.and(absenceRequest.flowEnded.isFalse()));
- List results = new ArrayList<>();
+ Set results = Sets.newHashSet();
if (uros.stream().anyMatch(uro -> uro.role.name.equals(Role.SEAT_SUPERVISOR))) {
results.addAll(
toApproveResultsAsSeatSuperVisor(
@@ -253,7 +255,7 @@ public List allResults(List uros,
conditions.and(absenceRequest.managerApprovalRequired.isTrue())
.and(absenceRequest.managerApproved.isNotNull())
.and(person.office.eq(signer.office));
- final QAffiliation affiliation = QAffiliation.affiliation;
+ final QAffiliation affiliation = QAffiliation.affiliation;
query = getQueryFactory().selectFrom(absenceRequest)
.join(absenceRequest.person, person).fetchJoin()
.join(person.affiliations, affiliation)
diff --git a/app/dao/InformationRequestDao.java b/app/dao/InformationRequestDao.java
index da01ecec2..3e0c28096 100644
--- a/app/dao/InformationRequestDao.java
+++ b/app/dao/InformationRequestDao.java
@@ -50,7 +50,6 @@
* Dao per i flussi informativi.
*
* @author dario
- *
*/
public class InformationRequestDao extends DaoBase {
@@ -60,17 +59,16 @@ public class InformationRequestDao extends DaoBase {
}
/**
- * Metodo che ritorna la lista delle richieste di flusso corrispondenti ai
- * parametri passati.
+ * Metodo che ritorna la lista delle richieste di flusso corrispondenti ai parametri passati.
*
- * @param uroList la lista dei ruoli sulle sedi
- * @param fromDate da quale data cercare le richieste (opzionale)
- * @param toDate a quale data cercare le richieste (opzionale)
+ * @param uroList la lista dei ruoli sulle sedi
+ * @param fromDate da quale data cercare le richieste (opzionale)
+ * @param toDate a quale data cercare le richieste (opzionale)
* @param informationType il tipo di richiesta
- * @param signer chi deve firmare la richiesta
+ * @param signer chi deve firmare la richiesta
* @return la lista delle richieste di flusso corrispondenti ai parametri passati.
*/
- public List toApproveResults(List uroList,
+ public List toApproveResults(List uroList,
Optional fromDate, Optional toDate,
InformationType informationType, Person signer) {
final QInformationRequest informationRequest = QInformationRequest.informationRequest;
@@ -86,7 +84,7 @@ public List toApproveResults(List uroList
}
if (toDate.isPresent()) {
conditions.and(informationRequest.endTo.before(toDate.get()));
- }
+ }
conditions.and(informationRequest.informationType.eq(informationType)
.and(informationRequest.flowStarted.isTrue())
.and(informationRequest.flowEnded.isFalse()));
@@ -94,10 +92,10 @@ public List toApproveResults(List uroList
List results = new ArrayList<>();
if (informationType.equals(InformationType.ILLNESS_INFORMATION)
&& uroList.stream().anyMatch(uro -> uro.role.name.equals(Role.PERSONNEL_ADMIN))) {
- results.addAll(toApproveResultsAsPersonnelAdmin(uroList,
+ results.addAll(toApproveResultsAsPersonnelAdmin(uroList,
informationType, signer, conditions));
} else {
- results.addAll(toApproveResultsAsSeatSuperVisor(uroList,
+ results.addAll(toApproveResultsAsSeatSuperVisor(uroList,
informationType, signer, conditions));
}
@@ -107,9 +105,9 @@ public List toApproveResults(List uroList
/**
* Lista delle richiesta di assenza per persona e data.
*
- * @param person La persona della quale recuperare le richieste di assenza
- * @param fromDate La data iniziale dell'intervallo temporale da considerare
- * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
+ * @param person La persona della quale recuperare le richieste di assenza
+ * @param fromDate La data iniziale dell'intervallo temporale da considerare
+ * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
* @param informationType Il tipo di richiesta di assenza specifico
* @return La lista delle richieste di assenze sull'intervallo e la persona specificati.
*/
@@ -140,9 +138,9 @@ public List teleworksByPersonAndDate(Person person,
/**
* Lista delle richiesta di assenza per persona e data.
*
- * @param person La persona della quale recuperare le richieste di assenza
- * @param fromDate La data iniziale dell'intervallo temporale da considerare
- * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
+ * @param person La persona della quale recuperare le richieste di assenza
+ * @param fromDate La data iniziale dell'intervallo temporale da considerare
+ * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
* @param informationType Il tipo di richiesta di assenza specifico
* @return La lista delle richieste di assenze sull'intervallo e la persona specificati.
*/
@@ -173,9 +171,9 @@ public List illnessByPersonAndDate(Person person,
/**
* Lista delle richiesta di assenza per persona e data.
*
- * @param person La persona della quale recuperare le richieste di assenza
- * @param fromDate La data iniziale dell'intervallo temporale da considerare
- * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
+ * @param person La persona della quale recuperare le richieste di assenza
+ * @param fromDate La data iniziale dell'intervallo temporale da considerare
+ * @param toDate La data finale dell'intervallo temporale da considerare (opzionale)
* @param informationType Il tipo di richiesta di assenza specifico
* @return La lista delle richieste di assenze sull'intervallo e la persona specificati.
*/
@@ -206,7 +204,7 @@ public List servicesByPersonAndDate(Person person,
/**
* Ritorna la richiesta informativa con id passato come parametro.
*
- * @param id l'identificativo della richiesta
+ * @param id l'identificativo della richiesta
* @return La richiesta con l'id passato come parametro.
*/
public InformationRequest getById(Long id) {
@@ -262,12 +260,11 @@ public Optional getTeleworkById(Long id) {
}
/**
- * La lista delle richieste di malattia appartenenti alla lista di id passati
- * come parametro.
+ * La lista delle richieste di malattia appartenenti alla lista di id passati come parametro.
*
* @param ids la lista di id di richieste di malattia
- * @return la lista delle richieste di malattia appartenenti alla lista di id
- * passati come parametro.
+ * @return la lista delle richieste di malattia appartenenti alla lista di id passati come
+ * parametro.
*/
public List illnessByIds(List ids) {
final QIllnessRequest illnessRequest = QIllnessRequest.illnessRequest;
@@ -276,12 +273,12 @@ public List illnessByIds(List ids) {
}
/**
- * La lista delle richieste di uscita di servizio appartenenti alla lista
- * di id passati come parametro.
+ * La lista delle richieste di uscita di servizio appartenenti alla lista di id passati come
+ * parametro.
*
* @param ids la lista di id di richieste di uscita di servizio
- * @return la lista delle richieste di uscita di servizio appartenenti
- * alla lista di id passati come parametro.
+ * @return la lista delle richieste di uscita di servizio appartenenti alla lista di id passati
+ * come parametro.
*/
public List servicesByIds(List ids) {
final QServiceRequest serviceRequest = QServiceRequest.serviceRequest;
@@ -290,12 +287,11 @@ public List servicesByIds(List ids) {
}
/**
- * La lista delle richieste di telelavoro appartenenti alla lista di id passati
- * come parametro.
+ * La lista delle richieste di telelavoro appartenenti alla lista di id passati come parametro.
*
* @param ids la lista di id di richieste di telelavoro
- * @return la lista delle richieste di telelavoro appartenenti alla lista di id
- * passati come parametro.
+ * @return la lista delle richieste di telelavoro appartenenti alla lista di id passati come
+ * parametro.
*/
public List teleworksByIds(List ids) {
final QTeleworkRequest teleworkRequest = QTeleworkRequest.teleworkRequest;
@@ -307,8 +303,8 @@ public List teleworksByIds(List ids) {
* La lista di tutte le richieste di telelavoro effettuate dalla persona passata come parametro.
*
* @param person la persona di cui ricercare le richieste di telelavoro
- * @return la lista di tutte le richieste di telelavoro effettuate dalla persona passata
- * come parametro.
+ * @return la lista di tutte le richieste di telelavoro effettuate dalla persona passata come
+ * parametro.
*/
public List personTeleworkList(Person person) {
final QTeleworkRequest teleworkRequest = QTeleworkRequest.teleworkRequest;
@@ -316,21 +312,43 @@ public List personTeleworkList(Person person) {
.orderBy(teleworkRequest.year.desc(), teleworkRequest.month.desc()).fetch();
}
+ /**
+ * La richiesta di telelavoro effettuate dalla persona del mese ed anno passati come parametro.
+ *
+ * @param person la persona di cui ricercare le richieste di telelavoro
+ * @param month il mese della richiesta di telelavoro
+ * @param year l'anno della richieste di telelavoro
+ * @return la richiesta di telelavoro effettuate dalla persona del mese ed anno passati come
+ * parametro.
+ */
+ public Optional personTeleworkInPeriod(Person person, Integer month,
+ Integer year) {
+ final QTeleworkRequest teleworkRequest = QTeleworkRequest.teleworkRequest;
+
+ final BooleanBuilder conditions = new BooleanBuilder();
+ conditions.and(teleworkRequest.person.eq(person))
+ .and(teleworkRequest.month.eq(month)
+ .and(teleworkRequest.year.eq(year)));
+
+ final TeleworkRequest result = getQueryFactory().selectFrom(teleworkRequest)
+ .where(conditions).fetchFirst();
+ return Optional.fromNullable(result);
+ }
/**
* Ritorna la lista delle informationRequest da approvare come responsabile di sede.
*
- * @param uros la lista degli userRoleOffice
+ * @param uros la lista degli userRoleOffice
* @param informationType il tipo di richiesta
- * @param signer il firmatario della richiesta
- * @param conditions le condizioni da applicare alla ricerca
+ * @param signer il firmatario della richiesta
+ * @param conditions le condizioni da applicare alla ricerca
* @return Lista delle InformationRequest da Approvare come responsabile di sede.
*/
private List toApproveResultsAsSeatSuperVisor(List uros,
InformationType informationType, Person signer, BooleanBuilder conditions) {
final QInformationRequest informationRequest = QInformationRequest.informationRequest;
- if (uros.stream().anyMatch(uro -> uro.role.name.equals(Role.SEAT_SUPERVISOR)
+ if (uros.stream().anyMatch(uro -> uro.role.name.equals(Role.SEAT_SUPERVISOR)
|| uro.role.name.equals(Role.PERSONNEL_ADMIN))) {
List officeList = uros.stream().map(u -> u.office).collect(Collectors.toList());
conditions = seatSupervisorQuery(officeList, conditions, signer);
@@ -361,12 +379,11 @@ private List toApproveResultsAsPersonnelAdmin(List officeList,
+ private BooleanBuilder seatSupervisorQuery(List officeList,
BooleanBuilder condition, Person signer) {
final QInformationRequest informationRequest = QInformationRequest.informationRequest;
@@ -381,12 +398,11 @@ private BooleanBuilder seatSupervisorQuery(List officeList,
* Ritorna le condizioni con l'aggiunta di quelle relative al responsabile di sede.
*
* @param officeList la lista delle sedi
- * @param condition le condizioni pregresse
- * @param signer colui che deve firmare la richiesta
+ * @param condition le condizioni pregresse
+ * @param signer colui che deve firmare la richiesta
* @return le condizioni per determinare se il responsabile di sede è coinvolto nell'approvazione.
- *
*/
- private BooleanBuilder personnelAdminQuery(List officeList,
+ private BooleanBuilder personnelAdminQuery(List officeList,
BooleanBuilder condition, Person signer) {
final QInformationRequest informationRequest = QInformationRequest.informationRequest;
@@ -400,9 +416,9 @@ private BooleanBuilder personnelAdminQuery(List officeList,
/**
* Metodo che ritorna la lista delle richieste già approvate per ruolo data e tipo.
*
- * @param uros la lista degli users_roles_offices
- * @param fromDate la data da cui cercare le richieste
- * @param toDate la data fino a cui cercare le richieste (opzionale)
+ * @param uros la lista degli users_roles_offices
+ * @param fromDate la data da cui cercare le richieste
+ * @param toDate la data fino a cui cercare le richieste (opzionale)
* @param informationType il tipo della richiesta.
* @return la lista delle richieste totalmente approvate.
*/
@@ -420,7 +436,7 @@ public List totallyApproved(List uros,
conditions.and(informationRequest.startAt.after(fromDate))
.and(informationRequest.informationType.eq(informationType)
.and(informationRequest.flowEnded.isTrue())
- .and(informationRequest.person.office.in(officeList)));
+ .and(informationRequest.person.office.in(officeList)));
if (toDate.isPresent()) {
conditions.and(informationRequest.endTo.before(toDate.get()));
@@ -450,27 +466,27 @@ private List totallyApprovedOnRole(List u
conditions.and(informationRequest.startAt.after(fromDate))
.and(informationRequest.informationType.eq(informationType)
.and(informationRequest.flowEnded.isTrue())
- .and(informationRequest.person.office.eq(signer.office)));
+ .and(informationRequest.person.office.eq(signer.office)));
if (toDate.isPresent()) {
conditions.and(informationRequest.endTo.before(toDate.get()));
}
if (uros.stream().anyMatch(uro -> uro.role.name.equals(Role.SEAT_SUPERVISOR))) {
conditions.and(
- informationRequest.officeHeadApprovalRequired.isTrue()
- .and(informationRequest.officeHeadApproved.isNotNull())
- .and(person.office.in(officeList)));
+ informationRequest.officeHeadApprovalRequired.isTrue()
+ .and(informationRequest.officeHeadApproved.isNotNull())
+ .and(person.office.in(officeList)));
} else {
conditions.and(
- informationRequest.administrativeApprovalRequired.isTrue()
- .and(informationRequest.administrativeApproved.isNotNull())
- .and(person.office.in(officeList)));
+ informationRequest.administrativeApprovalRequired.isTrue()
+ .and(informationRequest.administrativeApproved.isNotNull())
+ .and(person.office.in(officeList)));
}
return getQueryFactory().selectFrom(informationRequest)
.join(informationRequest.person, person)
.join(person.office, office)
.where(office.in(uros.stream().map(
- userRoleOffices -> userRoleOffices.office)
+ userRoleOffices -> userRoleOffices.office)
.collect(Collectors.toSet())).and(conditions))
.orderBy(informationRequest.startAt.desc())
.fetch();
diff --git a/app/dao/UsersRolesOfficesDao.java b/app/dao/UsersRolesOfficesDao.java
index 7819f15e4..da5ddefd9 100755
--- a/app/dao/UsersRolesOfficesDao.java
+++ b/app/dao/UsersRolesOfficesDao.java
@@ -101,6 +101,22 @@ public List getUsersRolesOfficesByUser(User user) {
return getQueryFactory().selectFrom(uro).where(uro.user.eq(user)).fetch();
}
+ /**
+ * La lista di tutti gli userRoleOffice legati all'utente passato.
+ *
+ * @param user l'utente
+ * @return la lista di tutti gli usersRolesOffices associati al parametro passato.
+ */
+ public List getAdministrativeUsersRolesOfficesByUser(User user) {
+ final QUsersRolesOffices uro = QUsersRolesOffices.usersRolesOffices;
+ return getQueryFactory().selectFrom(uro).where(uro.user.eq(user), uro.role.name.eq(Role.ABSENCE_MANAGER)
+ .or(uro.role.name.eq(Role.GROUP_MANAGER))
+ .or(uro.role.name.eq(Role.PERSONNEL_ADMIN))
+ .or(uro.role.name.eq(Role.PERSONNEL_ADMIN_MINI))
+ .or(uro.role.name.eq(Role.SEAT_SUPERVISOR))).fetch();
+ }
+
+
/**
* Metodo per effettuare check dello stato ruoli epas <-> perseo.
*/
diff --git a/app/helpers/TemplateUtility.java b/app/helpers/TemplateUtility.java
index 9a56f23c1..37d7d42ce 100644
--- a/app/helpers/TemplateUtility.java
+++ b/app/helpers/TemplateUtility.java
@@ -241,7 +241,7 @@ public final int compensatoryRestRequests() {
List roleList = uroDao.getUsersRolesOfficesByUser(user);
List groups =
groupDao.groupsByOffice(user.person.office, Optional.absent(), Optional.of(false));
- List results = absenceRequestDao
+ Set results = absenceRequestDao
.toApproveResults(roleList, Optional.absent(), Optional.absent(),
AbsenceRequestType.COMPENSATORY_REST, groups, user.person);
return results.size();
@@ -261,7 +261,7 @@ public final int vacationRequests() {
List roleList = uroDao.getUsersRolesOfficesByUser(user);
List groups =
groupDao.groupsByOffice(user.person.office, Optional.absent(), Optional.of(false));
- List results = absenceRequestDao
+ Set results = absenceRequestDao
.toApproveResults(roleList, Optional.absent(), Optional.absent(),
AbsenceRequestType.VACATION_REQUEST, groups, user.person);
@@ -282,7 +282,7 @@ public final int personalPermissionRequests() {
List roleList = uroDao.getUsersRolesOfficesByUser(user);
List groups =
groupDao.groupsByOffice(user.person.office, Optional.absent(), Optional.of(false));
- List results = absenceRequestDao
+ Set results = absenceRequestDao
.toApproveResults(roleList, Optional.absent(), Optional.absent(),
AbsenceRequestType.PERSONAL_PERMISSION, groups, user.person);
@@ -303,7 +303,7 @@ public final int vacationPastYearAfterDeadlineRequests() {
List roleList = uroDao.getUsersRolesOfficesByUser(user);
List groups =
groupDao.groupsByOffice(user.person.office, Optional.absent(), Optional.of(false));
- List results = absenceRequestDao
+ Set results = absenceRequestDao
.toApproveResults(roleList, Optional.absent(), Optional.absent(),
AbsenceRequestType.VACATION_PAST_YEAR_AFTER_DEADLINE_REQUEST, groups, user.person);
diff --git a/app/manager/MissionManager.java b/app/manager/MissionManager.java
index ffc4d0efa..a0d9636b9 100644
--- a/app/manager/MissionManager.java
+++ b/app/manager/MissionManager.java
@@ -143,7 +143,8 @@ public Optional linkToPerson(MissionFromClient mission) {
public boolean createMissionFromClient(MissionFromClient body, boolean recompute) {
String missionCacheKey = "createMission." + body.id;
-
+ boolean managedMissionOk = true;
+
if (Cache.get(missionCacheKey) == null) {
log.debug(LOG_PREFIX + "Imposto la cache {} con valore true", missionCacheKey);
Cache.set(missionCacheKey, true, "1mn");
@@ -220,13 +221,15 @@ public boolean createMissionFromClient(MissionFromClient body, boolean recompute
while (!actualDate.toLocalDate().isAfter(body.dataFine.toLocalDate())) {
situation = getSituation(actualDate, body, workInterval);
- atomicInsert(situation, body, actualDate);
+ if (!atomicInsert(situation, body, actualDate)) {
+ managedMissionOk = false;
+ };
actualDate = actualDate.plusDays(1);
}
recalculate(body, Optional.>absent());
Cache.delete(missionCacheKey);
- return true;
+ return managedMissionOk;
}
/**
@@ -318,6 +321,7 @@ private WorkingTimeTypeDay getFromDayOfMission(Person person, LocalDate actualDa
* @return true se la gestione della missione è andata a buon fine, false altrimenti.
*/
public boolean manageMissionFromClient(MissionFromClient body, boolean recompute) {
+ boolean managedMissionOk = true;
if (body.idOrdine == null) {
return false;
}
@@ -369,7 +373,9 @@ public boolean manageMissionFromClient(MissionFromClient body, boolean recompute
return false;
}
situation = getSituation(dateToConsider, body, workInterval);
- atomicInsert(situation, body, dateToConsider);
+ if (!atomicInsert(situation, body, dateToConsider)) {
+ managedMissionOk = false;
+ };
}
/*
@@ -402,8 +408,8 @@ public boolean manageMissionFromClient(MissionFromClient body, boolean recompute
//consistencyManager.updatePersonSituation(body.person.id, body.dataInizio.toLocalDate());
recalculate(body, Optional.fromNullable(missions));
- log.debug("Lanciati i ricalcoli");
- return true;
+ log.debug("Lanciati i ricalcoli per {} dal {}", body.person, body.dataInizio);
+ return managedMissionOk;
}
/**
@@ -512,10 +518,10 @@ private boolean insertMission(String destination, Person person,
person.getFullname(), numero, from, to, hours, minutes);
return false;
}
-
+
log.debug(LOG_PREFIX + "Sto per inserire una missione per {}. Codice {}, {} - {}, "
+ "tempo {}:{}", person, mission.code, from, to, hours, minutes);
-
+
Integer localHours = hours;
Integer localMinutes = minutes;
@@ -523,7 +529,9 @@ private boolean insertMission(String destination, Person person,
absenceService.insert(person, group, from.toLocalDate(),
to.toLocalDate(), mission, type,
localHours, localMinutes, false, absenceManager);
- if (insertReport.criticalErrors.isEmpty() || insertReport.warningsPreviousVersion.isEmpty()) {
+ log.debug("Insert Report = {}", insertReport);
+ if (insertReport.criticalErrors.isEmpty() && insertReport.warningsPreviousVersion.isEmpty()
+ && !insertReport.absencesToPersist.isEmpty()) {
for (Absence absence : insertReport.absencesToPersist) {
PersonDay personDay = personDayManager
.getOrCreateAndPersistPersonDay(person, absence.getAbsenceDate());
@@ -537,9 +545,9 @@ private boolean insertMission(String destination, Person person,
absence.note = "Missione: " + numero + '\n'
+ "Anno: " + anno + '\n'
+ "(Identificativo: " + absence.externalIdentifier + ")";
-
+
absence.save();
-
+
final Optional currentUser = Security.getUser();
if (currentUser.isPresent()) {
notificationManager.notificationAbsencePolicy(currentUser.get(),
@@ -559,6 +567,10 @@ private boolean insertMission(String destination, Person person,
}
JPA.em().flush();
return true;
+ } else {
+ log.info("Missione id={} di {}, insert Report con problemi di inserimento o "
+ + "nessuna assenza da inserire = {}",
+ id, person.getFullname(), insertReport);
}
return false;
@@ -662,7 +674,7 @@ private LocalDateTime rightDate(LocalDate date, MissionFromClient body) {
* @param body l'oggetto dto proveniente dal mission manager
* @param actualDate la data attuale su cui lavorare
*/
- private void atomicInsert(Situation situation, MissionFromClient body, LocalDateTime actualDate) {
+ private boolean atomicInsert(Situation situation, MissionFromClient body, LocalDateTime actualDate) {
boolean missionInserted = false;
if (situation.isFirstOrLastDay) {
@@ -701,6 +713,7 @@ > getFromDayOfMission(body.person, actualDate.toLocalDate()).workingTime) {
+ "idOrdine = {}, anno = {}, numero = {}", body.destinazioneMissione,
actualDate, body.id, body.idOrdine, body.anno, body.numero);
}
+ return missionInserted;
}
/**
diff --git a/app/manager/NotificationManager.java b/app/manager/NotificationManager.java
index 5bf11bb98..651b879c5 100644
--- a/app/manager/NotificationManager.java
+++ b/app/manager/NotificationManager.java
@@ -31,8 +31,8 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
-import lombok.extern.slf4j.Slf4j;
import lombok.val;
+import lombok.extern.slf4j.Slf4j;
import manager.configurations.ConfigurationManager;
import manager.configurations.EpasParam;
import models.Competence;
@@ -55,6 +55,7 @@
import models.enumerate.AccountRole;
import models.enumerate.InformationType;
import models.enumerate.NotificationSubject;
+import models.exports.MissionFromClient;
import models.flows.AbsenceRequest;
import models.flows.CompetenceRequest;
import models.flows.Group;
@@ -1762,4 +1763,51 @@ private void sendEmailInformationRequestConfirmation(InformationRequest informat
informationRequest, person.email, simpleEmail.getSubject(), mailBody);
}
+
+ /**
+ * Nel caso ci siano stati problemi nella gestione dei giorni
+ * @param mission
+ */
+ public void sendEmailMissionFromClientProblems(MissionFromClient mission) {
+ Verify.verifyNotNull(mission.person);
+ final Person person = mission.person;
+ SimpleEmail simpleEmail = new SimpleEmail();
+ String replayTo = (String) configurationManager
+ .configValue(person.office, EpasParam.EMAIL_TO_CONTACT);
+ try {
+ simpleEmail.addTo(person.email);
+ simpleEmail.addReplyTo(replayTo);
+ simpleEmail.addCc(replayTo);
+ } catch (EmailException e) {
+ log.error("Errore nell'invio dell'email per missione con problemi", e);
+ e.printStackTrace();
+ }
+
+ simpleEmail.setSubject(
+ String.format("ePas: verificare missione n. %s del %s di %s",
+ mission.numero, mission.anno, mission.person.getFullname()));
+
+ final StringBuilder message = new StringBuilder()
+ .append(String.format("Gentile %s,\r\n", person.getName()));
+ message.append("ePAS ha ricevuto un messaggio dall'applicativo Missioni di tipo ")
+ .append(mission.tipoMissione).append(" missione.\r\n");
+ message.append( String.format("La missione è la numero %s del %s dal %s al %s.\r\n\r\n",
+ mission.numero, mission.anno, TemplateExtensions.format(mission.dataInizio),
+ TemplateExtensions.format(mission.dataFine)));
+ message.append("Non è stato possibile inserire, modificare o cancellare tutti ")
+ .append("i giorni di missione previsti.\r\n\r\n");
+ message.append("Si prega di verificare i dati della missione su ePAS con il proprio")
+ .append(" ufficio del personale.");
+ val mailBody = message.toString();
+ try {
+ simpleEmail.setMsg(mailBody);
+ } catch (EmailException e) {
+ e.printStackTrace();
+ }
+ Mail.send(simpleEmail);
+ log.info("Inviata email per problemi sulla missione n. {} del {} di {} dal {} al {}",
+ mission.numero, mission.anno, mission.person.getFullname(),
+ TemplateExtensions.format(mission.dataInizio),
+ TemplateExtensions.format(mission.dataFine));
+ }
}
diff --git a/app/manager/ReperibilityManager2.java b/app/manager/ReperibilityManager2.java
index 59240fc6e..ef6543fb6 100644
--- a/app/manager/ReperibilityManager2.java
+++ b/app/manager/ReperibilityManager2.java
@@ -35,6 +35,8 @@
import java.util.stream.Collectors;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
+import manager.configurations.ConfigurationManager;
+import manager.configurations.EpasParam;
import models.Competence;
import models.CompetenceCode;
import models.Person;
@@ -66,6 +68,7 @@ public class ReperibilityManager2 {
private final PersonDayManager personDayManager;
private final CompetenceDao competenceDao;
private final PersonReperibilityDayDao reperibilityDao;
+ private final ConfigurationManager configurationManager;
/**
* Injection.
@@ -80,12 +83,13 @@ public class ReperibilityManager2 {
public ReperibilityManager2(PersonReperibilityDayDao reperibilityDayDao,
PersonDayDao personDayDao, PersonDayManager personDayManager,
CompetenceDao competenceDao,
- PersonReperibilityDayDao reperibilityDao) {
+ PersonReperibilityDayDao reperibilityDao, ConfigurationManager configurationManager) {
this.reperibilityDayDao = reperibilityDayDao;
this.personDayDao = personDayDao;
this.personDayManager = personDayManager;
this.competenceDao = competenceDao;
this.reperibilityDao = reperibilityDao;
+ this.configurationManager = configurationManager;
}
/**
@@ -310,10 +314,15 @@ public Map calculateReperibilityWorkDaysCompetences(
final LocalDate lastDay;
- if (to.isAfter(today)) {
- lastDay = today;
- } else {
+ if ((Boolean) configurationManager.configValue(reperibility.office,
+ EpasParam.ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH)) {
lastDay = to;
+ } else {
+ if (to.isAfter(today)) {
+ lastDay = today;
+ } else {
+ lastDay = to;
+ }
}
CompetenceCode code = reperibility.monthlyCompetenceType.workdaysCode;
involvedReperibilityWorkers(reperibility, from, to).forEach(person -> {
@@ -390,10 +399,15 @@ public Map calculateReperibilityHolidaysCompetences(
final LocalDate lastDay;
- if (end.isAfter(today)) {
- lastDay = today;
- } else {
+ if ((Boolean) configurationManager.configValue(reperibility.office,
+ EpasParam.ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH)) {
lastDay = end;
+ } else {
+ if (end.isAfter(today)) {
+ lastDay = today;
+ } else {
+ lastDay = end;
+ }
}
CompetenceCode code = reperibility.monthlyCompetenceType.holidaysCode;
involvedReperibilityWorkers(reperibility, start, end).forEach(person -> {
@@ -426,12 +440,19 @@ public void assignReperibilityCompetences(ReperibilityTypeMonth reperibilityType
final LocalDate today = LocalDate.now();
final LocalDate lastDay;
-
- if (monthEnd.isAfter(today)) {
- lastDay = today;
- } else {
+
+ if ((Boolean) configurationManager.configValue(reperibilityTypeMonth
+ .personReperibilityType.office,
+ EpasParam.ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH)) {
lastDay = monthEnd;
+ } else {
+ if (monthEnd.isAfter(today)) {
+ lastDay = today;
+ } else {
+ lastDay = monthEnd;
+ }
}
+
//cerco le persone reperibili nel periodo di interesse
final List involvedReperibilityPeople = involvedReperibilityWorkers(
reperibilityTypeMonth.personReperibilityType, monthBegin, monthEnd);
diff --git a/app/manager/ShiftManager2.java b/app/manager/ShiftManager2.java
index 4be04311f..c6e1586e8 100644
--- a/app/manager/ShiftManager2.java
+++ b/app/manager/ShiftManager2.java
@@ -767,8 +767,14 @@ public int calculatePersonShiftCompetencesInPeriod(ShiftType activity, Person pe
break;
case holiday:
- timeInterval = Optional.fromNullable(daily);
- timeInterval2 = Optional.absent();
+ if (setting.holidayShiftInNightToo) {
+ timeInterval = Optional.of(new TimeInterval(new LocalTime(0, 0), new LocalTime(23, 59)));
+ timeInterval2 = Optional.absent();
+ } else {
+ timeInterval = Optional.fromNullable(daily);
+ timeInterval2 = Optional.absent();
+ }
+
list = shifts.stream().filter(day -> {
return personDayManager.isHoliday(day.personShift.person, day.date,
setting.saturdayHolidayShift);
diff --git a/app/manager/attestati/dto/show/SeatCertification.java b/app/manager/attestati/dto/show/SeatCertification.java
index 8edfed0eb..8229d7164 100644
--- a/app/manager/attestati/dto/show/SeatCertification.java
+++ b/app/manager/attestati/dto/show/SeatCertification.java
@@ -50,6 +50,7 @@ public static class PersonCertification {
public String matricola;
public boolean validato;
public int numBuoniPasto;
+ public int numBuoniPastoElettronici;
public List righeAssenza = Lists.newArrayList();
public List righeCompetenza = Lists.newArrayList(); //??
public List righeFormazione = Lists.newArrayList();
@@ -60,6 +61,7 @@ public String toString() {
.add("matricola", matricola)
.add("validato", validato)
.add("numBuoniPasto", numBuoniPasto)
+ .add("numBuoniPastoElettronici", numBuoniPastoElettronici)
.add("righeAssenza", righeAssenza)
.toString();
}
diff --git a/app/manager/attestati/service/CertificationService.java b/app/manager/attestati/service/CertificationService.java
index b57f9859e..904233a1b 100644
--- a/app/manager/attestati/service/CertificationService.java
+++ b/app/manager/attestati/service/CertificationService.java
@@ -151,8 +151,8 @@ private Map personAttestatiCertifications(Person person,
certification.year = year;
certification.month = month;
certification.certificationType = CertificationType.MEAL;
- certification.content = personCertification.numBuoniPasto + "";
-
+ certification.content = String.format("%s;%s",
+ personCertification.numBuoniPasto, personCertification.numBuoniPastoElettronici);
certifications.put(certification.aMapKey(), certification);
return certifications;
diff --git a/app/manager/configurations/ConfigurationManager.java b/app/manager/configurations/ConfigurationManager.java
index 7c749d94c..97cabe046 100644
--- a/app/manager/configurations/ConfigurationManager.java
+++ b/app/manager/configurations/ConfigurationManager.java
@@ -48,11 +48,9 @@
import models.base.IPropertyInPeriod;
import models.enumerate.BlockType;
import models.query.QConfiguration;
-import models.query.QPersonConfiguration;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.joda.time.MonthDay;
-import play.db.jpa.JPAPlugin;
import play.jobs.Job;
@@ -88,25 +86,8 @@ public class ConfigurationManager {
public List configurationWithType(EpasParam epasParam) {
final QConfiguration configuration = QConfiguration.configuration;
- final JPQLQuery> query = queryFactory.from(configuration)
+ final JPQLQuery query = queryFactory.selectFrom(configuration)
.where(configuration.epasParam.eq(epasParam));
- return (List) query.fetch();
- }
-
- /**
- * La lista delle configurazioni delle persone con parametro epasParam e valore value.
- *
- * @param epasParam il parametro da cercare
- * @param value il valore da cercare
- * @return la lista di configurazioni della persona.
- */
- public List configurationWithTypeAndValue(
- EpasParam epasParam, String value) {
- final QPersonConfiguration configuration = QPersonConfiguration.personConfiguration;
-
- final JPQLQuery query = queryFactory.selectFrom(configuration)
- .where(configuration.epasParam.eq(epasParam)
- .and(configuration.fieldValue.eq(value)));
return query.fetch();
}
diff --git a/app/manager/configurations/EpasParam.java b/app/manager/configurations/EpasParam.java
index e5e0d4b6f..ac9fd1e99 100644
--- a/app/manager/configurations/EpasParam.java
+++ b/app/manager/configurations/EpasParam.java
@@ -68,6 +68,14 @@ public enum EpasParam {
EpasParamValueType.formatValue(true),
Lists.newArrayList(),
Office.class),
+
+ ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH("enable_reperibility_approval_before_end_month",
+ EpasParamCategory.GENERAL,
+ EpasParamTimeType.GENERAL,
+ EpasParamValueType.BOOLEAN,
+ EpasParamValueType.formatValue(false),
+ Lists.newArrayList(),
+ Office.class),
ENABLE_MISSIONS_INTEGRATION("enable_mission_integration",
EpasParamCategory.GENERAL,
diff --git a/app/manager/services/absences/AbsenceService.java b/app/manager/services/absences/AbsenceService.java
index 0c1b78bc3..e8e1f1635 100644
--- a/app/manager/services/absences/AbsenceService.java
+++ b/app/manager/services/absences/AbsenceService.java
@@ -772,7 +772,13 @@ private InsertReport insertReportFromOldReport(AbsenceInsertReport absenceInsert
templateRow.absenceErrors
.add(AbsenceError.builder().absence(absenceResponse.getAbsenceAdded())
.absenceProblem(AbsenceProblem.NotOnHoliday).build());
- } else {
+ }
+ if (!absenceResponse.getWarning().isEmpty()) {
+ templateRow.absenceErrors.add(AbsenceError.builder().absence(absenceResponse.getAbsenceAdded())
+ .absenceProblem(AbsenceProblem.MinimumTimeViolated).build());
+ }
+
+ else {
templateRow.absenceErrors
.add(AbsenceError.builder().absence(absenceResponse.getAbsenceAdded())
.absenceProblem(AbsenceProblem.LimitExceeded).build());
diff --git a/app/manager/services/absences/model/AbsencePeriod.java b/app/manager/services/absences/model/AbsencePeriod.java
index d36e83b70..d91674a52 100644
--- a/app/manager/services/absences/model/AbsencePeriod.java
+++ b/app/manager/services/absences/model/AbsencePeriod.java
@@ -43,6 +43,7 @@
import models.absences.TakableAbsenceBehaviour.TakeCountBehaviour;
import models.absences.definitions.DefaultAbsenceType;
import models.enumerate.VacationCode;
+import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.testng.collections.Lists;
@@ -213,6 +214,15 @@ public int computePeriodTakableAmount(TakeCountBehaviour countBehaviour, LocalDa
if (countBehaviour.equals(TakeCountBehaviour.period)) {
if (this.takableCodes.contains(absenceTypeDao
.getAbsenceTypeByCode(DefaultAbsenceType.A_LAGILE.getCode()).get())) {
+ /* Caso di febbraio: secondo la nota del DG i giorni di lavoro agile a febbraio
+ * non possono essere più di 8. Quindi sottraggo 2 giorni nella modalità
+ * prevista dall'algoritmo (2 * 100) al quantitativo di giorni previsto per il
+ * gruppo del codice LAGILE (this.fixexPeriodTakableAmount).
+ */
+
+ if (from.monthOfYear().get() == DateTimeConstants.FEBRUARY) {
+ return this.fixedPeriodTakableAmount - 2 * 100;
+ }
List workingDays = personDayManager.workingDaysInMonth(person, from, to);
int count = (workingDays.size() * 100 / 2);
if (count % 100 != 0) {
diff --git a/app/models/GeneralSetting.java b/app/models/GeneralSetting.java
index edc85e42c..a269a12ca 100644
--- a/app/models/GeneralSetting.java
+++ b/app/models/GeneralSetting.java
@@ -79,6 +79,8 @@ public class GeneralSetting extends BaseModel {
public boolean roundingShiftQuantity = false;
public boolean enableUniqueDailyShift = true;
+
+ public boolean holidayShiftInNightToo = false;
// Fine parametri gestione giorni di turno
diff --git a/app/models/absences/definitions/DefaultAbsenceType.java b/app/models/absences/definitions/DefaultAbsenceType.java
index 41e7b31d5..4c3f64d1f 100644
--- a/app/models/absences/definitions/DefaultAbsenceType.java
+++ b/app/models/absences/definitions/DefaultAbsenceType.java
@@ -51,7 +51,7 @@ public enum DefaultAbsenceType {
A_LAGILE("L-AGILE",
"Lavoro agile", false,
- ImmutableSet.of(JustifiedTypeName.assign_all_day), 0, false,
+ ImmutableSet.of(JustifiedTypeName.complete_day_and_add_overtime), 0, false,
MealTicketBehaviour.notAllowMealTicket, 0, null, Sets.newHashSet(),
new LocalDate(2022, 3, 29), null, true, false, true),
@@ -59,7 +59,7 @@ public enum DefaultAbsenceType {
"Lavoro agile con maturazione buono pasto", false,
ImmutableSet.of(JustifiedTypeName.assign_all_day), 0, false,
MealTicketBehaviour.allowMealTicket, 0, null, Sets.newHashSet(),
- new LocalDate(2022, 3, 29), null, true, false, true),
+ new LocalDate(2022, 3, 29), new LocalDate(2022, 6, 28), true, false, true),
A_COVID19("COVID19",
"Emergenza coronavirus, attività lavorativa presso il domicilio dei dipendenti", false,
@@ -83,7 +83,7 @@ public enum DefaultAbsenceType {
A_39LA("39LA",
"Lavoro agile per dipendenti fragili o per assistenza a disabile/immunodepresso", false,
ImmutableSet.of(JustifiedTypeName.assign_all_day), 0, false,
- MealTicketBehaviour.allowMealTicket, 0, null, Sets.newHashSet(),
+ MealTicketBehaviour.notAllowMealTicket, 0, null, Sets.newHashSet(),
null, null, true, false, true),
A_39LANOBP("39LA",
@@ -91,13 +91,13 @@ public enum DefaultAbsenceType {
+ "senza buono pasto", false,
ImmutableSet.of(JustifiedTypeName.assign_all_day), 0, false,
MealTicketBehaviour.notAllowMealTicket, 0, null, Sets.newHashSet(), null,
- null, true, false, true),
+ new LocalDate(2022, 7, 1), true, false, true),
A_40LA("40LA",
"Lavoro agile per quarantena/isolamento fiduciario", false,
ImmutableSet.of(JustifiedTypeName.assign_all_day), 0, false,
MealTicketBehaviour.allowMealTicket, 0, null, Sets.newHashSet(), null,
- null, true, false, true),
+ new LocalDate(2022, 7, 1), true, false, true),
A_18M("18M", "Permesso assistenza parenti/affini disabili L. 104/92 in ore e minuti", true,
ImmutableSet.of(JustifiedTypeName.specified_minutes), 0, false,
diff --git a/app/models/absences/definitions/DefaultTakable.java b/app/models/absences/definitions/DefaultTakable.java
index e8429da9a..d3e64fb56 100644
--- a/app/models/absences/definitions/DefaultTakable.java
+++ b/app/models/absences/definitions/DefaultTakable.java
@@ -122,13 +122,13 @@ public enum DefaultTakable {
-1, null),
T_LAGILE(AmountType.units,
- ImmutableSet.of(DefaultAbsenceType.A_LAGILE, DefaultAbsenceType.A_LAGILEBP),
- ImmutableSet.of(DefaultAbsenceType.A_LAGILE, DefaultAbsenceType.A_LAGILEBP),
+ ImmutableSet.of(DefaultAbsenceType.A_LAGILE),
+ ImmutableSet.of(DefaultAbsenceType.A_LAGILE),
10, null),
T_39LA(AmountType.units,
- ImmutableSet.of(DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_39LANOBP),
- ImmutableSet.of(DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_39LANOBP),
+ ImmutableSet.of(DefaultAbsenceType.A_39LA),
+ ImmutableSet.of(DefaultAbsenceType.A_39LA),
-1, null),
T_SMART(AmountType.units,
@@ -494,7 +494,7 @@ public enum DefaultTakable {
DefaultAbsenceType.A_401, DefaultAbsenceType.A_412,
DefaultAbsenceType.A_402, DefaultAbsenceType.A_62,
DefaultAbsenceType.A_62A, DefaultAbsenceType.A_62D, DefaultAbsenceType.A_98CV,
- DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_40LA, DefaultAbsenceType.A_46,
+ DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_46,
DefaultAbsenceType.A_46RA, DefaultAbsenceType.A_VAC19),
ImmutableSet.of(DefaultAbsenceType.A_102,
DefaultAbsenceType.A_103, DefaultAbsenceType.A_103BP,
@@ -539,7 +539,7 @@ public enum DefaultTakable {
DefaultAbsenceType.A_401, DefaultAbsenceType.A_412,
DefaultAbsenceType.A_402, DefaultAbsenceType.A_62,
DefaultAbsenceType.A_62A, DefaultAbsenceType.A_62D, DefaultAbsenceType.A_98CV,
- DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_40LA, DefaultAbsenceType.A_46,
+ DefaultAbsenceType.A_39LA, DefaultAbsenceType.A_46,
DefaultAbsenceType.A_46RA, DefaultAbsenceType.A_VAC19),
-1, null),
diff --git a/app/views/AbsenceGroups/_configureSelectedGroup.html b/app/views/AbsenceGroups/_configureSelectedGroup.html
index 73116f971..19d7f33f7 100644
--- a/app/views/AbsenceGroups/_configureSelectedGroup.html
+++ b/app/views/AbsenceGroups/_configureSelectedGroup.html
@@ -52,7 +52,7 @@
#{f.selectEnum 'minutes', items:absenceForm.selectableMinutes(), value:absenceForm.minutes, byEquals:'true' /}
#{/if}
- #{if absenceForm.absenceTypeSelected || !absenceForm.hasAbsenceTypeChoice() }
+ #{if absenceForm.absenceTypeSelected || !absenceForm.hasAbsenceTypeChoice()}
#{secure.check 'Certifications.certifications'}
#{f.checkbox 'forceInsert', value:forceInsert /}
#{if forceInsert}
diff --git a/app/views/AbsenceRequests/_form.html b/app/views/AbsenceRequests/_form.html
index adf9609b5..6cd814fe7 100644
--- a/app/views/AbsenceRequests/_form.html
+++ b/app/views/AbsenceRequests/_form.html
@@ -21,12 +21,13 @@
#{f.hidden 'absenceRequest.person.id' /}
#{f.hidden 'absenceRequest.type' /}
#{f.hidden 'persist', value:persist /}
+ #{f.hidden 'groupAbsenceType.id', value:absenceForm.groupSelected.id /}
#{f.date 'absenceRequest.startAt', required:true, class:'auto-submit-parent',
value:absenceRequest.startAt?.format("dd/MM/yyyy") /}
#{f.date 'absenceRequest.endTo', class:'auto-submit-parent',
value:absenceRequest.endTo?.format("dd/MM/yyyy") /}
-
+
#{if absenceRequest.type.equals(models.flows.enumerate.AbsenceRequestType.PERSONAL_PERMISSION)}
#{if absenceForm != null}
diff --git a/app/views/AbsenceRequests/_report.html b/app/views/AbsenceRequests/_report.html
index a4b572fa1..b4781eaa0 100644
--- a/app/views/AbsenceRequests/_report.html
+++ b/app/views/AbsenceRequests/_report.html
@@ -24,6 +24,7 @@
#{alert color:'danger'}
Elenco degli errori riscontrati
Si sta inserendo un'assenza in un giorno che già contiene un'assenza a giustificazione giornaliera
+ oppure non ci sono sufficienti ore a disposizione per fruire di un riposo compensativo
#{/alert}
#{/if}
diff --git a/app/views/Administration/_generalSetting.html b/app/views/Administration/_generalSetting.html
index 1a6fe58f6..f90ed3d70 100644
--- a/app/views/Administration/_generalSetting.html
+++ b/app/views/Administration/_generalSetting.html
@@ -144,7 +144,7 @@ &{actionSelected+'.table'}
#{/b.buttons}
#{/form}
#{/accordionItem}
- #{accordionItem 'enableDailyPresenceForManagerParam', parent:'generalSetting', title:'Abilita visualizzazione presenza giornaliera gruppi', open:false}
+ #{accordionItem 'enableDailyPresenceForManagerParam', parent:'generalSetting', title:'Abilita visualizzazione presenza giornaliera gruppi', open:false}
#{form action:@saveGeneralSetting(), method:'POST', class:'form form-horizontal'}
#{f.hidden 'generalSetting.id' /}
#{alert color:'info'}Abilita la visualizzazione della presenza giornaliera dei dipendenti appartenenti a un gruppo#{/alert}
@@ -154,4 +154,14 @@ &{actionSelected+'.table'}
#{/b.buttons}
#{/form}
#{/accordionItem}
+ #{accordionItem 'holidayShiftInNightToo', parent:'generalSetting', title:'Abilita conteggio festivo per tutti gli orari in giorno festivo', open:false}
+ #{form action:@saveGeneralSetting(), method:'POST', class:'form form-horizontal'}
+ #{f.hidden 'generalSetting.id' /}
+ #{alert color:'info'}Abilita al conteggio di turno festivo qualsiasi turno svolto nelle 24 ore di un giorno festivo (anche se dovrebbe essere notturno)#{/alert}
+ #{f.booleanRadio 'generalSetting.holidayShiftInNightToo' /}
+ #{b.buttons}
+ #{b.save /}
+ #{/b.buttons}
+ #{/form}
+ #{/accordionItem}
#{/accordionGroup}
diff --git a/app/views/Configurations/_tutorial.html b/app/views/Configurations/_tutorial.html
index a0b8a1714..53215b6bd 100644
--- a/app/views/Configurations/_tutorial.html
+++ b/app/views/Configurations/_tutorial.html
@@ -22,6 +22,14 @@
#{/if}
+ #{if configuration.epasParam.equals(manager.configurations.EpasParam.ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH) }
+ Impostando a sì questo parametro sarà possibile, per i responsabili dei servizi di reperibilità, procedere all'approvazione del calendario dell'intero
+ mese di reperibilità anche se il mese non è ancora terminato. Ad esempio, se il calendario fosse già completamente schedulato per l'intero mese
+ e si tentasse l'approvazione prima della fine del mese (es.: giorno 25 del mese), con questo parametro a SI verrebbero conteggiati tutti i giorni del mese
+ nell'approvazione e non solo quelli fino al giorno in cui si sta approvando il calendario del servizio.
+
+ #{/if}
+
#{if configuration.epasParam.equals(manager.configurations.EpasParam.ENABLE_MISSIONS_INTEGRATION) }
Abilitando questa funzionalità, ePAS comunicherà con la piattaforma Missioni ricevendo in automatico i giorni di missione dei dipendenti
e inserendoli automaticamente nel loro cartellino.
diff --git a/app/views/Secure/_login_idp.html b/app/views/Secure/_login_idp.html
index 54154af92..f5abb704d 100644
--- a/app/views/Secure/_login_idp.html
+++ b/app/views/Secure/_login_idp.html
@@ -43,7 +43,7 @@
- Utilizza il bottone sottostante per accedere con le credenziali ${companyCode} (SSO)
+ Utilizza il bottone sottostante per accedere con le credenziali ${companyCode}
diff --git a/app/views/Stampings/personStamping.html b/app/views/Stampings/personStamping.html
index 90b59a570..621fbaf51 100755
--- a/app/views/Stampings/personStamping.html
+++ b/app/views/Stampings/personStamping.html
@@ -11,7 +11,7 @@
-
+ Riepilogo mensile &{'Month.'+ psDto.month} ${psDto.year}
Giorno |
Buono pasto |
diff --git a/app/views/Stampings/personStampingComponents/_mealTicketsTemplate.html b/app/views/Stampings/personStampingComponents/_mealTicketsTemplate.html
index 27a796359..572291123 100644
--- a/app/views/Stampings/personStampingComponents/_mealTicketsTemplate.html
+++ b/app/views/Stampings/personStampingComponents/_mealTicketsTemplate.html
@@ -13,16 +13,16 @@
#{if dayRecap.mealTicket}
webui-popover-hover
#{if dayRecap.mealTicket.equals("NO")}
-data-content="&{'mealTicket.notAquired'}">
+data-content="&{'mealTicket.notAquired'}">no
#{/if}
#{if dayRecap.mealTicket.equals("NOT_YET")}
-data-content="&{'mealTicket.notYetAquired'}">
+data-content="&{'mealTicket.notYetAquired'}">da maturare
#{/if}
#{if dayRecap.mealTicket.equals("YES")}
-data-content="&{'mealTicket.aquired'}">
+data-content="&{'mealTicket.aquired'}">si
#{/if}
#{if dayRecap.mealTicket.equals("YES_IF_EXIT_NOW")}
-data-content="&{'mealTicket.aquiredExitingNow'}">
+data-content="&{'mealTicket.aquiredExitingNow'}">si uscendo adesso
#{/if}
#{/if}
#{else}
diff --git a/app/views/_employeeMenu.html b/app/views/_employeeMenu.html
index 526d80da8..d00e905e4 100644
--- a/app/views/_employeeMenu.html
+++ b/app/views/_employeeMenu.html
@@ -58,6 +58,11 @@
#{secure.li @TeleworkStampings.teleworkStampings(session.get("yearSelected"), session.get("monthSelected")) }
#{/secure.li}
+
+ #{secure.li @InformationRequests.teleworks()}
+
+ #{/secure.li}
+
#{/if}
#{navbar.li @Absences.absences(session.get("yearSelected"), session.get("monthSelected")) }
diff --git a/app/views/tags/absences/absence-popover.html b/app/views/tags/absences/absence-popover.html
index daf3562a7..c4096db90 100755
--- a/app/views/tags/absences/absence-popover.html
+++ b/app/views/tags/absences/absence-popover.html
@@ -26,6 +26,7 @@
#{else}
${_absence.absenceType.code}
#{/else}
+ ${_absence.absenceType.description}
#{/if}
diff --git a/conf/messages.it b/conf/messages.it
index a5d11b34e..e0f0d036d 100755
--- a/conf/messages.it
+++ b/conf/messages.it
@@ -448,6 +448,7 @@ generalSetting.maxDaysInPastForRestStampings =Numero massimo di giorni nel passa
generalSetting.enableAutoconfigCovid19=Abilita visione auto inserimento covid19 in configurazione
generalSetting.enableAutoconfigSmartworking=Abilita visione auto inserimento smartworking in configurazione
generalSetting.enableDailyPresenceForManager=Abilita visualizzazione presenza giornaliera dipendenti appartenenti a gruppo
+generalSetting.holidayShiftInNightToo=Considera come festivi i turni notturni effettuati nei festivi
group.label =Nome gruppo
group.limitType =Periodo di utililzzo limite
@@ -1179,6 +1180,7 @@ TR_VACATIONS= Inserimento ferie e permessi per Tecnologi e Ricercatori
TR_COMPENSATORY= Inserimento riposi compensativi per Tecnologi e Ricercatori
ENABLE_CALENDARSHIFT= Abilitazione gestione calendario turni
ENABLE_CALENDAR_REPERIBILITY= Abilitazione gestione calendario reperibilità
+ENABLE_REPERIBILITY_APPROVAL_BEFORE_END_MONTH=Abilta approvazione reperibilità prima della fine del mese
ENABLE_MISSIONS_INTEGRATION= Abilitazione integrazione con piattaforma Missioni
SEND_FLOWS_NOTIFICATION=Invio notifica per terminazione flusso di approvazione
SEND_MANAGER_NOTIFICATION_FOR_661=Invio notifica terminazione flusso permesso personale a responsabile di gruppo
diff --git a/conf/permissions.drl b/conf/permissions.drl
index 2f1f6c02c..c2f8c20a3 100755
--- a/conf/permissions.drl
+++ b/conf/permissions.drl
@@ -887,17 +887,17 @@ end
rule showAbsenceRequest
when
- UsersRolesOffices(role.name == Role.SEAT_SUPERVISOR || role.name == Role.PERSONNEL_ADMIN)
- $ar: AbsenceRequest(person != currentOperator.person, person.getInstitute() == currentOperator.person.getInstitute())
+ $ar: AbsenceRequest(person != currentOperator.person)
+ UsersRolesOffices(role.name == Role.SEAT_SUPERVISOR || role.name == Role.PERSONNEL_ADMIN, office == $ar.person.office)
$c: PermissionCheck(action == "AbsenceRequests.show", target==$ar, granted == false)
then
$c.grant();
end
rule showInformationRequest
-when
- UsersRolesOffices(role.name == Role.SEAT_SUPERVISOR || role.name == Role.PERSONNEL_ADMIN)
- $ir: InformationRequest(person != currentOperator.person)
+when
+ $ir: InformationRequest(person != currentOperator.person)
+ UsersRolesOffices(role.name == Role.SEAT_SUPERVISOR || role.name == Role.PERSONNEL_ADMIN, office == $ir.person.office)
$c: PermissionCheck(action == "InformationRequests.show", target==$ir, granted == false)
then
$c.grant();
@@ -3667,6 +3667,20 @@ then
$c.grant();
end
+/*
+ * Permesso per l'abilitazione alla visualizzazione dei flussi delle assenze per
+ * i responsabili di sede
+ */
+rule isFlowsVisibleForSeatSupervisor
+when
+ $uro: UsersRolesOffices(role.name == Role.SEAT_SUPERVISOR)
+ $o: Office() from $uro.office
+ Configuration(epasParam == EpasParam.ENABLE_FLOWS, fieldValue == true) from $o.configurations
+ $c: PermissionCheck(action == "AbsenceRequests.enabled", granted == false, target == null)
+then
+ $c.grant();
+end
+
/*
* Permesso per l'abilitazione alla visualizzazione delle richieste di ferie anno passato dopo il 31/8
*/
diff --git a/db/evolutions/191.sql b/db/evolutions/191.sql
new file mode 100644
index 000000000..64513615a
--- /dev/null
+++ b/db/evolutions/191.sql
@@ -0,0 +1,9 @@
+# ---!Ups
+
+ALTER TABLE general_setting ADD COLUMN holiday_shift_in_night_too BOOLEAN DEFAULT FALSE;
+ALTER TABLE general_setting_history ADD COLUMN holiday_shift_in_night_too BOOLEAN DEFAULT FALSE;
+
+# ---!Downs
+
+ALTER TABLE general_setting DROP COLUMN holiday_shift_in_night_too;
+ALTER TABLE general_setting_history DROP COLUMN holiday_shift_in_night_too;
\ No newline at end of file