From 65b761ff6b96c4b610c2a94cdde61512fd0f6552 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Mon, 19 Aug 2019 16:42:47 +0200
Subject: [PATCH] OO-4150: add some specific participant/teacher... path to
 notice

---
 .../olat/modules/lecture/LectureModule.java   |   7 +-
 .../lecture/manager/LectureBlockDAO.java      |  25 +++-
 .../model/LecturesBlockSearchParameters.java  |  13 +-
 .../lecture/ui/LecturesSecurityCallback.java  |   2 +
 .../ui/LecturesSecurityCallbackFactory.java   |  28 +++-
 .../ui/_i18n/LocalStrings_de.properties       |  31 ++--
 .../ui/_i18n/LocalStrings_en.properties       |  26 ++--
 ...resPermissionsSettingsAdminController.java |   2 +-
 .../coach/AbsenceNoticesListController.java   |   6 +-
 .../lecture/ui/coach/AbsencesController.java  |   2 +-
 .../ui/coach/DailyAbsencesController.java     |   4 +
 .../ui/coach/DispensationsController.java     |   8 +-
 .../EditDatesLecturesEntriesController.java   |  19 ++-
 .../ui/coach/EditNoticeController.java        |   7 +-
 .../ui/coach/EditReasonController.java        |  22 ++-
 .../IdentitiesLecturesRollCallController.java |   2 +-
 .../ui/coach/LecturesCoachingController.java  |  16 ++-
 .../DailyOverviewProfilController.java        |   5 +
 .../ui/profile/IdentityProfileController.java | 135 +++++++++++++++++-
 .../wizard/AbsenceNotice1UserSearchStep.java  |   5 +-
 .../wizard/AbsenceNotice2ConfirmUserStep.java |   5 +-
 .../AbsenceNotice3LecturesEntriesStep.java    |  14 +-
 .../ui/wizard/AbsenceNotice4ReasonStep.java   |   8 +-
 .../DatesLecturesEntriesStepController.java   |  10 +-
 .../ui/wizard/ReasonStepController.java       |   6 +-
 .../lecture/manager/LectureBlockDAOTest.java  |   2 +
 26 files changed, 330 insertions(+), 80 deletions(-)

diff --git a/src/main/java/org/olat/modules/lecture/LectureModule.java b/src/main/java/org/olat/modules/lecture/LectureModule.java
index 4fff4e47b74..2be255f7a2d 100644
--- a/src/main/java/org/olat/modules/lecture/LectureModule.java
+++ b/src/main/java/org/olat/modules/lecture/LectureModule.java
@@ -1,4 +1,5 @@
 /**
+
  * <a href="http://www.openolat.org">
  * OpenOLAT - Online Learning and Training</a><br>
  * <p>
@@ -63,7 +64,7 @@ public class LectureModule extends AbstractSpringModule implements ConfigOnOff {
 	private static final String MASTERCOACH_CAN_SEE_APPEAL = "mastercoach.can.see.appeal";
 	private static final String MASTERCOACH_CAN_AUTHORIZED_APPEAL = "mastercoach.can.authorized.appeal";
 
-	private static final String PARTICIPANT_CAN_NOTICE = "mastercoach.can.notice";
+	private static final String PARTICIPANT_CAN_NOTICE = "participant.can.notice";
 	
 	private static final String DAILY_ROLL_CALL = "daily.rollcall";
 	
@@ -233,7 +234,7 @@ public class LectureModule extends AbstractSpringModule implements ConfigOnOff {
 			teacherCanAuthorizedAbsence = "true".equals(teacherCanAuthorizedAbsenceObj);
 		}
 		
-		String teacherCanSeeAppealObj = getStringPropertyValue(TEACHER_CAN_AUTHORIZED_ABSENCE, true);
+		String teacherCanSeeAppealObj = getStringPropertyValue(TEACHER_CAN_SEE_APPEAL, true);
 		if(StringHelper.containsNonWhitespace(teacherCanSeeAppealObj)) {
 			teacherCanSeeAppeal = "true".equals(teacherCanSeeAppealObj);
 		}
@@ -268,7 +269,7 @@ public class LectureModule extends AbstractSpringModule implements ConfigOnOff {
 			masterCoachCanAuthorizedAppeal = "true".equals(masterCoachCanAuthorizedAppealObj);
 		}
 		
-		String participantCanNoticeObj = getStringPropertyValue(MASTERCOACH_CAN_AUTHORIZED_APPEAL, true);
+		String participantCanNoticeObj = getStringPropertyValue(PARTICIPANT_CAN_NOTICE, true);
 		if(StringHelper.containsNonWhitespace(participantCanNoticeObj)) {
 			participantCanNotice = "true".equals(participantCanNoticeObj);
 		}
diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureBlockDAO.java b/src/main/java/org/olat/modules/lecture/manager/LectureBlockDAO.java
index 55e128dfa8b..adbdae48485 100644
--- a/src/main/java/org/olat/modules/lecture/manager/LectureBlockDAO.java
+++ b/src/main/java/org/olat/modules/lecture/manager/LectureBlockDAO.java
@@ -554,11 +554,24 @@ public class LectureBlockDAO {
 		if(searchParams.getManager() != null) {
 			sb.and()
 			  .append(" exists (select membership.key from repoentrytogroup as rel, bgroupmember as membership")
-	          .append("    where rel.entry.key=entry.key and rel.group.key=membership.group.key and membership.identity.key=:managerKey")
-	          .append("      and membership.role in ('").append(OrganisationRoles.administrator.name()).append("','").append(OrganisationRoles.learnresourcemanager.name()).append("','").append(OrganisationRoles.lecturemanager.name()).append("','").append(GroupRoles.owner.name()).append("')")
+	          .append("   where rel.entry.key=entry.key and rel.group.key=membership.group.key and membership.identity.key=:managerKey")
+	          .append("   and membership.role ").in(OrganisationRoles.administrator, OrganisationRoles.learnresourcemanager, OrganisationRoles.lecturemanager, GroupRoles.owner.name())
+	          .append(" )");
+		}
+		if(searchParams.getMasterCoach() != null) {
+			sb.and()
+			  .append(" exists (select mcMembership.key from lectureblocktogroup as blockToCoachGroup, bgroupmember as mcMembership")
+	          .append("   where block.key=blockToCoachGroup.lectureBlock.key and blockToCoachGroup.group.key=mcMembership.group.key and mcMembership.identity.key=:masterCoachKey")
+	          .append("   and mcMembership.role ").in(CurriculumRoles.mastercoach)
+	          .append(" )");
+		}
+		if(searchParams.getParticipant() != null) {
+			sb.and()
+			  .append(" exists (select participantship.key from lectureblocktogroup as blockToParticipantGroup, bgroupmember as participantship")
+	          .append("   where block.key=blockToParticipantGroup.lectureBlock.key and blockToParticipantGroup.group.key=participantship.group.key and participantship.identity.key=:participantKey")
+	          .append("   and participantship.role ").in(GroupRoles.participant)
 	          .append(" )");
 		}
-		
 		if(searchParams.getTeacher() != null) {
 			sb.and()
 			  .append(" exists (select teachership.key from bgroupmember teachership where")
@@ -607,9 +620,15 @@ public class LectureBlockDAO {
 		if(searchParams.getManager() != null) {
 			query.setParameter("managerKey", searchParams.getManager().getKey());
 		}
+		if(searchParams.getMasterCoach() != null) {
+			query.setParameter("masterCoachKey", searchParams.getMasterCoach().getKey());
+		}
 		if(searchParams.getTeacher() != null) {
 			query.setParameter("teacherKey", searchParams.getTeacher().getKey());
 		}
+		if(searchParams.getParticipant() != null) {
+			query.setParameter("participantKey", searchParams.getParticipant().getKey());
+		}
 	}
 
 	public LectureBlock addGroupToLectureBlock(LectureBlock block, Group group) {
diff --git a/src/main/java/org/olat/modules/lecture/model/LecturesBlockSearchParameters.java b/src/main/java/org/olat/modules/lecture/model/LecturesBlockSearchParameters.java
index c3c581e9598..28bc6cea45c 100644
--- a/src/main/java/org/olat/modules/lecture/model/LecturesBlockSearchParameters.java
+++ b/src/main/java/org/olat/modules/lecture/model/LecturesBlockSearchParameters.java
@@ -44,6 +44,7 @@ public class LecturesBlockSearchParameters {
 	private IdentityRef teacher;
 	private IdentityRef manager;
 	private IdentityRef participant;
+	private IdentityRef masterCoach;
 	private RepositoryEntry entry;
 	private List<LectureRollCallStatus> rollCallStatus;
 	private List<LectureBlockStatus> lectureBlockStatus;
@@ -124,6 +125,14 @@ public class LecturesBlockSearchParameters {
 		this.manager = manager;
 	}
 
+	public IdentityRef getMasterCoach() {
+		return masterCoach;
+	}
+
+	public void setMasterCoach(IdentityRef masterCoach) {
+		this.masterCoach = masterCoach;
+	}
+
 	public IdentityRef getTeacher() {
 		return teacher;
 	}
@@ -142,8 +151,8 @@ public class LecturesBlockSearchParameters {
 	
 	public void setViewAs(IdentityRef identity, LectureRoles role) {
 		switch(role) {
-			case lecturemanager: 
-			case mastercoach: setManager(identity); break;
+			case lecturemanager: setManager(identity); break;
+			case mastercoach: setMasterCoach(identity); break;
 			case teacher: setTeacher(identity); break;
 			case participant:
 			default: setParticipant(identity);
diff --git a/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallback.java b/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallback.java
index f8777688c4a..12a810ea7a0 100644
--- a/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallback.java
+++ b/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallback.java
@@ -33,6 +33,8 @@ public interface LecturesSecurityCallback {
 	
 	public boolean canChangeRates();
 	
+	public boolean canSeeAppeals();
+	
 	public boolean canApproveAppeal();
 	
 	public boolean canEditConfiguration();
diff --git a/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallbackFactory.java b/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallbackFactory.java
index a1c6a810daa..1741b3ba26d 100644
--- a/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallbackFactory.java
+++ b/src/main/java/org/olat/modules/lecture/ui/LecturesSecurityCallbackFactory.java
@@ -75,13 +75,37 @@ public class LecturesSecurityCallbackFactory {
 			return adminRole;
 		}
 
+		@Override
+		public boolean canSeeAppeals() {
+			if(!lectureModule.isAbsenceAppealEnabled()) {
+				return false;
+			}
+			
+			if(viewAs == LectureRoles.teacher) {
+				return teacherRole && lectureModule.isTeacherCanSeeAppeal();
+			}
+			if(viewAs == LectureRoles.mastercoach) {
+				return masterCoachRole && lectureModule.isMasterCoachCanSeeAppeal();
+			}
+			if(viewAs == LectureRoles.lecturemanager) {
+				return adminRole && lectureModule.isAbsenceAppealEnabled();
+			}
+			return false;
+		}
+
 		@Override
 		public boolean canApproveAppeal() {
 			if(adminRole) {
 				return true;
 			}
-			return (masterCoachRole && lectureModule.isMasterCoachCanAuthorizedAppeal())
-					|| (teacherRole && lectureModule.isTeacherCanAuthorizedAppeal());
+			
+			if(viewAs == LectureRoles.teacher) {
+				return teacherRole && lectureModule.isTeacherCanAuthorizedAppeal();
+			}
+			if(viewAs == LectureRoles.mastercoach) {
+				return masterCoachRole && lectureModule.isMasterCoachCanAuthorizedAppeal();
+			}
+			return false;
 		}
 
 		@Override
diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
index 16d4144ede6..0cf06b99f58 100644
--- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
@@ -1,5 +1,4 @@
-#Wed Aug 07 15:31:55 CEST 2019
-
+#Mon Aug 19 16:40:37 CEST 2019
 absence.category=Absenzenbegr\u00FCndung
 absence.category.copied=Absenzenbegr\u00FCndung wurde erfolgreich kopiert.
 absence.category.copy={0} (Kopie)
@@ -56,7 +55,6 @@ attendance.list.title=Absenzenliste\: {0}
 attendance.list.to.sign=Pr\u00E4senzliste
 attendance.list.to.sign.title=Pr\u00E4senzliste\: {0}
 authorized.absence=Entschuldigt
-not.authorized.absence=Unentschuldigt
 authorized.absence.reason=Begr\u00FCndung
 autoclosed=Autoerledigt
 bulk=Benutzername, $org.olat.user.propertyhandlers\:table.name.email oder $org.olat.user.propertyhandlers\:table.name.institutionalUserIdentifier
@@ -64,10 +62,9 @@ bulk.example=test01<br>author02<br>test@openolat.org
 bulk.hint=Im Suchfeld k\u00F6nenn Sie eine Liste von Benutzernamen oder E-Mailadressen der Benutzer eintragen.
 cancel.lecture.blocks=Lektionen absagen
 cancelled=Abgesagt
-contact.teachers.list.name=Dozenten
 close.lecture.blocks=Lektionen abschliessen
-close.lecture.blocks.day=Absenzenerfassung f\u00FCr {0} abschliessen
 close.lecture.blocks.confirmation={0} Lektionen am {1} werden abgeschlossen.
+close.lecture.blocks.day=Absenzenerfassung f\u00FCr {0} abschliessen
 closed=Erledigt
 coach.absence=Absenzen
 coach.appeals=Rekurse
@@ -99,6 +96,7 @@ confirm.delete.assessment.mode.title=Pr\u00FCfungsmodus l\u00F6schen
 confirm.delete.lectures=Wollen Sie wirklich diesen Lektionenblock "{0}" l\u00F6schen?
 confirm.delete.reason=Wollen Sie wirklich diese Begr\u00FCndung "{0}" l\u00F6schen?
 contact.teachers=Dozenten kontaktieren
+contact.teachers.list.name=Dozenten
 copy=Kopieren
 current.lecture=Aktueller Lektionenblock
 date.end=$org.olat.repository\:cif.date.end
@@ -133,12 +131,12 @@ empty.table.participant.list=Es wurde noch keine Anwesenheitskontrolle f\u00FCr
 entry.rate=Kursschwellwert
 error.atleastone.lecture=Bitte w\u00E4hlen Sie mindestens ein Lektionenblock.
 error.collision=Es gibt bereits eine Absenz an diesem Datum.
-error.unauthorized.absence.msg=Es wurde <strong>eine</strong> unentschulidgte Absenz gefunden.
-error.unauthorized.absences.msg=Es wurden <strong>{0}</strong> unentschulidgte Absenzen gefunden.
 error.integer.between=Die Eingabe muss eine Zahl zwischen {0} und {1} sein.
 error.integer.positive=Die Eingabe muss eine positive Zahl sein.
 error.reason.mandatory=Begr\u00FCndung ist erforderlich
 error.search.form.notempty=F\u00FCllen Sie bitte mindestens ein Feld mit zwei Charakter aus.
+error.unauthorized.absence.msg=Es wurde <strong>eine</strong> unentschulidgte Absenz gefunden.
+error.unauthorized.absences.msg=Es wurden <strong>{0}</strong> unentschulidgte Absenzen gefunden.
 evening=Abend
 export.footer.lectures.hint=x \= Lektion abwesend
 export.header.entry=Kurs\: {0}
@@ -248,6 +246,8 @@ log.change.admission.date=Erstzulassungsdatum angepasst\: {0}
 log.change.rate=Schwellwert angepasst\: {0}
 log.remove.admission.date=Erstzulassungsdatum entfernt
 log.remove.rate=Schwellwert entfernt
+mail.body=Nachricht
+mail.subject=Betreff
 managed.flags.lecture.block.all=Vollst\u00E4ndige externe Verwaltung 
 managed.flags.lecture.block.compulsory=Zwingend
 managed.flags.lecture.block.dates=Datum
@@ -261,8 +261,6 @@ managed.flags.lecture.block.preparation=Vorbereitung/Nachbereitung
 managed.flags.lecture.block.settings=Konfiguration
 managed.flags.lecture.block.teachers=Dozenten
 managed.flags.lecture.block.title=Title
-mail.subject=Betreff
-mail.body=Nachricht
 menu.my.lectures=Absenzen
 menu.my.lectures.alt=Lektionen und Absenzen
 morning=Vormittag
@@ -274,6 +272,7 @@ multi.rollcall.title.for=f\u00FCr {0} ({1} Lektionenbl\u00F6cke)
 new.appeal.title=Neue Rekursmeldung
 next.participant=Weiter zum n\u00E4chsten Teilnehmer
 no.teachers=Noch kein Dozent vorhanden
+not.authorized.absence=Unentschuldigt
 notice.dates.lectures.title=Kontext
 notice.end.date=Enddatum
 notice.reason.title=Grund f\u00FCr Abwesenheit
@@ -345,21 +344,22 @@ repo.participants=Teilnehmer
 repo.settings=Konfiguration
 results=Resultate
 rollcall=Anwesenheitskontrolle
+rollcall.absence=Absenz
+rollcall.absence.notice=Abmeldung
 rollcall.coach.hint=Hinweis\: Absenzen werden pro Lektion erfasst. Wird mehr als die H\u00E4lfte einer Lektion vers\u00E4umt, wird diese als Absenz eingetragen.
 rollcall.comment=Bemerkung
+rollcall.dispensation=Dispens
 rollcall.status=Status Lektionenblock
 rollcall.tooltip.absence=Abwesenheit
 rollcall.tooltip.authorized.absence=Entschuldigte Abwesenheit
 rollcall.tooltip.free=Freiwillig
 rollcall.tooltip.ok=Anwesend
 rollcall.tooltip.unauthorized.absence=Unentschuldigte Abwesenheit
-rollcall.absence.notice=Abmeldung
-rollcall.dispensation=Dispens
-rollcall.absence=Absenz
 save.next=Speichern und weiter
 save.temporary=Zwischenspeichern
 search.curriculums=Suche nach Curriculum
 search.date=Datum
+search.entries=Suche nach Kurs
 search.form.category=Grund
 search.form.end=Bis
 search.form.login=Benutzername
@@ -373,7 +373,6 @@ search.form.string=Suche
 search.form.string.hint=In der Suche k\u00F6nnen Sie nach Titeln eines Lektionenblockes oder nach der Externen Referenz suchen. Bei der Suche mit der Externen Referenz werden nur exakte Treffer angezeigt.
 search.form.till=bis
 search.form.type=Art
-search.entries=Suche nach Kurs
 search.participants=Suche nach Teilnehmern
 search.teachers=Suche nach Dozenten
 send=Schicken
@@ -468,14 +467,14 @@ tool.teacher=Als Dozent
 tools=Aktion
 tools.import.table=Lektionbl\u00F6cke aus Excel importieren
 total=Total
+unauthorized.filter=Unentschuldigt
+unauthorized.filter.label=Anzeige
 unoverride.lecture=\u00DCbergehen anhalten
 upto=bis {0}
 user.overview.appeals=Rekurse
 user.overview.dispensation=Dispensen
 user.overview.lectures=Lektionen und Absenzen
 user.profil=Benutzerprofil
-unauthorized.filter=Unentschuldigt
-unauthorized.filter.label=Anzeige
 warning.choose.at.least.one.appeal=Sie m\u00FCssen mindestens einen Rekurs w\u00E4hlen.
 warning.edit.lecture=Absenzenerfassung ist deaktiviert.
 warning.repositoryentry.deleted=$org.olat.repository\:repositoryentry.deleted
@@ -483,4 +482,4 @@ warning.teachers.at.least.one.contact=Es gibt kein Dozent zu kontaktieren
 whole.day=ganzer Tag
 wizard.entries.label.block=<strong>{0}</strong> <small>{1}</small> ({2} Lektionenblock)
 wizard.entries.label.blocks=<strong>{0}</strong> <small>{1}</small> ({2} Lektionenbl\u00F6cke)
-wizard.lectureblock.label=<strong>{0}</strong> <small>{1}</small><br>{2} {3} - {4} {5} Lektionen: "{6}" mit {7}
+wizard.lectureblock.label=<strong>{0}</strong> <small>{1}</small><br>{2} {3} - {4} {5} Lektionen\: "{6}" mit {7}
diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
index f28df5c1e82..f6c53cf59c1 100644
--- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Wed Aug 07 15:32:15 CEST 2019
+#Mon Aug 19 16:40:11 CEST 2019
 absence.category=Reason of absence
 absence.category.copied=Reason of absence was successfully copied.
 absence.category.copy={0} (copie)
@@ -56,7 +56,6 @@ attendance.list.to.sign=Attendance list
 attendance.list.to.sign.title=Attendance list\: {0}
 authorized.absence=Authorized
 authorized.absence.reason=Reason
-not.authorized.absence=Not authorized
 autoclosed=Auto-closed
 bulk=User names, $org.olat.user.propertyhandlers\:table.name.email oder $org.olat.user.propertyhandlers\:table.name.institutionalUserIdentifier
 bulk.example=test01<br>author02<br>test@openolat.org
@@ -64,8 +63,8 @@ bulk.hint=You can give a list of user names or email addresses separated by a re
 cancel.lecture.blocks=Cancel lectures
 cancelled=Cancelled
 close.lecture.blocks=Close lectures
-close.lecture.blocks.day=Close lectures for {0}
 close.lecture.blocks.confirmation={0} lectures at {1} will be closed.
+close.lecture.blocks.day=Close lectures for {0}
 closed=Closed
 coach.absence=Absences
 coach.appeals=Appeals
@@ -129,8 +128,8 @@ empty.table.lectures.blocks=There are no lectures to display.
 empty.table.lectures.blocks.admin=No lecture blocks have been created for this course so far.
 empty.table.participant.list=No roll calls have been made for this course so far.
 entry.rate=Course's rate
-error.collision=There is already an absence at these dates.
 error.atleastone.lecture=Please choose at least one lecture block.
+error.collision=There is already an absence at these dates.
 error.integer.between=The input must be a number between {0} and {1}
 error.integer.positive=The number must be positive.
 error.reason.mandatory=Reason is mandatory
@@ -244,6 +243,8 @@ log.change.admission.date=Update admission date {0}
 log.change.rate=Update attendance rate {0}
 log.remove.admission.date=Remove admission date
 log.remove.rate=Remove attendance rate
+mail.body=Message
+mail.subject=Subject
 managed.flags.lecture.block.all=Fully externally managed
 managed.flags.lecture.block.compulsory=Compulsory
 managed.flags.lecture.block.dates=Dates
@@ -257,8 +258,6 @@ managed.flags.lecture.block.preparation=Preparation
 managed.flags.lecture.block.settings=Configuration
 managed.flags.lecture.block.teachers=Teacher
 managed.flags.lecture.block.title=Title
-mail.subject=Subject
-mail.body=Message
 menu.my.lectures=Absences
 menu.my.lectures.alt=Lectures and absences
 morning=Morning
@@ -267,6 +266,7 @@ multi.rollcall.title.for=for {0} ({1} lecture blocks)
 new.appeal.title=New appeal
 next.participant=To the next participant
 no.teachers=No coaches yet
+not.authorized.absence=Not authorized
 notice.dates.lectures.title=Context
 notice.end.date=End date
 notice.reason.title=Reason of absence
@@ -338,21 +338,22 @@ repo.participants=Participants
 repo.settings=Configuration
 results=Results
 rollcall=Roll call
+rollcall.absence=Absence
+rollcall.absence.notice=Notice of absence
 rollcall.coach.hint=Note\: absences are recorded per lesson. If more than the half a lesson is missed, the lesson is entered as an absence.
 rollcall.comment=Comment
+rollcall.dispensation=Dispensation
 rollcall.status=Roll call status
 rollcall.tooltip.absence=Absent
 rollcall.tooltip.authorized.absence=Authorized absence
 rollcall.tooltip.free=Free
 rollcall.tooltip.ok=Present
 rollcall.tooltip.unauthorized.absence=Not authorized absence
-rollcall.absence.notice=Notice of absence
-rollcall.dispensation=Dispensation
-rollcall.absence=Absence
 save.next=Save and next
 save.temporary=Quick save
 search.curriculums=Search by curriculums
 search.date=Date
+search.entries=Search by courses
 search.form.category=Reason
 search.form.end=Until
 search.form.login=Username
@@ -366,7 +367,6 @@ search.form.string=Search
 search.form.string.hint=You can search title of lecture blocks and title or external reference of courses. External reference is an exact match.
 search.form.till=till
 search.form.type=Type
-search.entries=Search by courses
 search.participants=Search by participants
 search.teachers=Search by teachers
 send=Send
@@ -461,14 +461,14 @@ tool.teacher=As teacher
 tools=Action
 tools.import.table=Import lecture blocks from Excel
 total=Total
+unauthorized.filter=Unauthorized
+unauthorized.filter.label=Display
 unoverride.lecture=Stop override
 upto=till {0}
 user.overview.appeals=Appeals
 user.overview.dispensation=Dispensation
 user.overview.lectures=Lectures and absences
 user.profil=User profil
-unauthorized.filter=Unauthorized
-unauthorized.filter.label=Display
 warning.choose.at.least.one.appeal=You need to choose at least one appeal
 warning.edit.lecture=Roll call ist deactivated.
 warning.repositoryentry.deleted=$org.olat.repository\:repositoryentry.deleted
@@ -476,4 +476,4 @@ warning.teachers.at.least.one.contact=There isn't any teacher to contact
 whole.day=Whole day
 wizard.entries.label.block=<strong>{0}</strong> <small>{1}</small> ({2} lectures block)
 wizard.entries.label.blocks=<strong>{0}</strong> <small>{1}</small> ({2} lectures blocks)
-wizard.lectureblock.label=<strong>{0}</strong> <small>{1}</small><br>{2} {3} - {4} {5} lessons: "{6}" with {7}
+wizard.lectureblock.label=<strong>{0}</strong> <small>{1}</small><br>{2} {3} - {4} {5} lessons\: "{6}" with {7}
diff --git a/src/main/java/org/olat/modules/lecture/ui/admin/LecturesPermissionsSettingsAdminController.java b/src/main/java/org/olat/modules/lecture/ui/admin/LecturesPermissionsSettingsAdminController.java
index 0f92365a93f..6194bc7688b 100644
--- a/src/main/java/org/olat/modules/lecture/ui/admin/LecturesPermissionsSettingsAdminController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/admin/LecturesPermissionsSettingsAdminController.java
@@ -137,6 +137,6 @@ public class LecturesPermissionsSettingsAdminController extends FormBasicControl
 		lectureModule.setMasterCoachCanSeeAppeal(appealEnabled && masterCoachCanSeeAppealEl.isAtLeastSelected(1));
 		lectureModule.setMasterCoachCanAuthorizedAppeal(appealEnabled && masterCoachCanAuthorizeAppealEl.isAtLeastSelected(1));
 
-		lectureModule.setMasterCoachCanAuthorizedAppeal(appealEnabled && participantCanNoticeEl.isAtLeastSelected(1));
+		lectureModule.setParticipantCanNotice(participantCanNoticeEl.isAtLeastSelected(1));
 	}
 }
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java
index d915ee775e1..88e32cc7150 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java
@@ -218,6 +218,10 @@ public class AbsenceNoticesListController extends FormBasicController {
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(NoticeCols.type));
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(NoticeCols.tools));
 	}
+	
+	protected void reloadModel() {
+		loadModel(lastSearchParams);
+	}
 
 	protected void loadModel(AbsenceNoticeSearchParameters searchParams) {
 		lastSearchParams = searchParams;
@@ -485,7 +489,7 @@ public class AbsenceNoticesListController extends FormBasicController {
 	private void doEdit(UserRequest ureq, AbsenceNoticeRow row) {
 		AbsenceNotice notice = lectureService.getAbsenceNotice(row.getAbsenceNotice());
 
-		editNoticeCtrl = new EditNoticeController(ureq, getWindowControl(), notice);
+		editNoticeCtrl = new EditNoticeController(ureq, getWindowControl(), notice, secCallback);
 		listenTo(editNoticeCtrl);
 		
 		String title = translate(AbsenceNoticeHelper.getEditKey(row.getAbsenceNotice()));
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/AbsencesController.java b/src/main/java/org/olat/modules/lecture/ui/coach/AbsencesController.java
index fbab02b9a40..a8529e73f81 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/AbsencesController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/AbsencesController.java
@@ -175,7 +175,7 @@ public class AbsencesController extends BasicController {
 	
 	private void doAddNotice(UserRequest ureq) {
 		final EditAbsenceNoticeWrapper noticeWrapper = new EditAbsenceNoticeWrapper(AbsenceNoticeType.absence);
-		AbsenceNotice1UserSearchStep step = new AbsenceNotice1UserSearchStep(ureq, noticeWrapper);
+		AbsenceNotice1UserSearchStep step = new AbsenceNotice1UserSearchStep(ureq, noticeWrapper, secCallback);
 		StepRunnerCallback stop = (uureq, swControl, runContext) -> {
 			if(noticeWrapper.getAbsenceNotice() == null) {
 				Identity absentIdentity = noticeWrapper.getIdentity();
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/DailyAbsencesController.java b/src/main/java/org/olat/modules/lecture/ui/coach/DailyAbsencesController.java
index 20788080ad0..4c8a4c8d790 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/DailyAbsencesController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/DailyAbsencesController.java
@@ -83,6 +83,10 @@ public class DailyAbsencesController extends BasicController {
 		noticesListCtlr.setCurrentDate(date);
 		noticesListCtlr.loadModel(searchParams);
 	}
+	
+	public void reloadModel() {
+		noticesListCtlr.reloadModel();
+	}
 
 	@Override
 	protected void doDispose() {
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/DispensationsController.java b/src/main/java/org/olat/modules/lecture/ui/coach/DispensationsController.java
index db144bf5d76..60ea054d4f8 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/DispensationsController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/DispensationsController.java
@@ -70,6 +70,7 @@ public class DispensationsController extends BasicController {
 	private final VelocityContainer mainVC;
 
 	private final boolean withAddAbsence;
+	private final LecturesSecurityCallback secCallback;
 	private final AbsenceNoticeSearchParameters searchParams = new AbsenceNoticeSearchParameters();
 	
 	private StepsMainRunController addNoticeCtrl;
@@ -85,6 +86,7 @@ public class DispensationsController extends BasicController {
 			LecturesSecurityCallback secCallback, boolean withSearch, boolean withAddAbsence) {
 		super(ureq, wControl, Util.createPackageTranslator(LectureRepositoryAdminController.class, ureq.getLocale()));
 		
+		this.secCallback = secCallback;
 		this.withAddAbsence = withAddAbsence;
 		
 		searchParams.addTypes(AbsenceNoticeType.notified, AbsenceNoticeType.dispensation);
@@ -153,6 +155,10 @@ public class DispensationsController extends BasicController {
 		}
 	}
 	
+	public void reloadModel() {
+		noticesListCtlr.reloadModel();
+	}
+	
 	private void doSearch(SearchAbsenceNoticeEvent event) {
 		searchParams.setStartDate(event.getStartDate());
 		searchParams.setEndDate(event.getEndDate());
@@ -167,7 +173,7 @@ public class DispensationsController extends BasicController {
 		if(!withAddAbsence) return;
 		
 		final EditAbsenceNoticeWrapper noticeWrapper = new EditAbsenceNoticeWrapper(type);
-		AbsenceNotice1UserSearchStep step = new AbsenceNotice1UserSearchStep(ureq, noticeWrapper);
+		AbsenceNotice1UserSearchStep step = new AbsenceNotice1UserSearchStep(ureq, noticeWrapper, secCallback);
 		StepRunnerCallback stop = (uureq, swControl, runContext) -> {
 			if(noticeWrapper.getAbsenceNotice() == null) {
 				Identity absentIdentity = noticeWrapper.getIdentity();
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java b/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java
index 91d3b939989..0d8dd434d1a 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java
@@ -53,6 +53,7 @@ import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
 import org.olat.modules.lecture.model.LectureBlockWithTeachers;
 import org.olat.modules.lecture.model.LecturesBlockSearchParameters;
 import org.olat.modules.lecture.ui.LectureRepositoryAdminController;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.user.UserManager;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -79,6 +80,7 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 	private final boolean wizard;
 	private final Formatter formatter;
 	private final Identity noticedIdentity;
+	private final LecturesSecurityCallback secCallback;
 	private final EditAbsenceNoticeWrapper noticeWrapper;
 	private List<RepositoryEntry> loadedRepositoryEntries;
 	private List<LectureBlockWithTeachers> loadedLectureBlocks;
@@ -89,10 +91,11 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 	private LectureService lectureService;
 	
 	public EditDatesLecturesEntriesController(UserRequest ureq, WindowControl wControl, Form rootForm,
-			EditAbsenceNoticeWrapper noticeWrapper, boolean wizard) {
+			EditAbsenceNoticeWrapper noticeWrapper, LecturesSecurityCallback secCallback, boolean wizard) {
 		super(ureq, wControl, LAYOUT_DEFAULT, null, rootForm);
 		setTranslator(Util.createPackageTranslator(LectureRepositoryAdminController.class, ureq.getLocale()));
 		this.wizard = wizard;
+		this.secCallback = secCallback;
 		this.noticeWrapper = noticeWrapper;
 		this.noticedIdentity = noticeWrapper.getIdentity();
 		formatter = Formatter.getInstance(getLocale());
@@ -168,6 +171,7 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 		durationEl.setMandatory(true);
 
 		datesEl = uifactory.addDateChooser("noticed.start", null, startDate, formLayout);
+		datesEl.addActionListener(FormEvent.ONCHANGE);
 		datesEl.setDomReplacementWrapperRequired(false);
 		datesEl.setSecondDate(endDate);
 		datesEl.setSeparator("noticed.till");
@@ -266,7 +270,11 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 	private Map<RepositoryEntry,Long> getRepositoryEntries() {
 		LecturesBlockSearchParameters searchParams = new LecturesBlockSearchParameters();
 
-		searchParams.setTeacher(getIdentity());
+		searchParams.setViewAs(getIdentity(), secCallback.viewAs());
+		if(noticedIdentity != null) {
+			searchParams.setParticipant(noticedIdentity);
+		}
+
 		searchParams.setStartDate(datesEl.getDate());
 		if(durationEl.isSelected(0)) {
 			searchParams.setEndDate(CalendarUtils.endOfDay(searchParams.getStartDate()));
@@ -311,7 +319,10 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 		if(noticeWrapper.getPredefinedLectureBlocks() != null && !noticeWrapper.getPredefinedLectureBlocks().isEmpty()) {
 			searchParams.setLectureBlocks(noticeWrapper.getPredefinedLectureBlocks());
 		} else {
-			searchParams.setTeacher(getIdentity());
+			searchParams.setViewAs(getIdentity(), secCallback.viewAs());
+			if(noticedIdentity != null) {
+				searchParams.setParticipant(noticedIdentity);
+			}
 			searchParams.setStartDate(datesEl.getDate());
 			if(durationEl.isSelected(0)) {
 				searchParams.setEndDate(CalendarUtils.endOfDay(searchParams.getStartDate()));
@@ -427,7 +438,7 @@ public class EditDatesLecturesEntriesController extends FormBasicController {
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(durationEl == source) {
 			updateDuration();
-		} else if(targetsEl == source) {
+		} else if(targetsEl == source || datesEl == source) {
 			updateTargets();
 		}
 		super.formInnerEvent(ureq, source, event);
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/EditNoticeController.java b/src/main/java/org/olat/modules/lecture/ui/coach/EditNoticeController.java
index f829a0fdd8e..5cb96ad75a9 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/EditNoticeController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/EditNoticeController.java
@@ -35,6 +35,7 @@ import org.olat.modules.lecture.AbsenceNoticeToRepositoryEntry;
 import org.olat.modules.lecture.LectureBlock;
 import org.olat.modules.lecture.LectureService;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -55,7 +56,7 @@ public class EditNoticeController extends FormBasicController {
 	@Autowired
 	private LectureService lectureService;
 	
-	public EditNoticeController(UserRequest ureq, WindowControl wControl, AbsenceNotice notice) {
+	public EditNoticeController(UserRequest ureq, WindowControl wControl, AbsenceNotice notice, LecturesSecurityCallback secCallback) {
 		super(ureq, wControl, "edit_notice");
 		
 		absenceNotice = notice;
@@ -73,10 +74,10 @@ public class EditNoticeController extends FormBasicController {
 			noticeWrapper.setEntries(entries);
 		}
 		
-		datesAndLecturesCtrl = new EditDatesLecturesEntriesController(ureq, wControl, mainForm, noticeWrapper, false);
+		datesAndLecturesCtrl = new EditDatesLecturesEntriesController(ureq, wControl, mainForm, noticeWrapper, secCallback, false);
 		listenTo(datesAndLecturesCtrl);
 
-		editReasonCtrl = new EditReasonController(ureq, wControl, mainForm, noticeWrapper, false);
+		editReasonCtrl = new EditReasonController(ureq, wControl, mainForm, noticeWrapper, secCallback, false);
 		listenTo(editReasonCtrl);
 		
 		initForm(ureq);
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/EditReasonController.java b/src/main/java/org/olat/modules/lecture/ui/coach/EditReasonController.java
index 159e1091133..f7c094b0dcf 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/EditReasonController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/EditReasonController.java
@@ -41,6 +41,8 @@ import org.olat.modules.lecture.AbsenceNoticeType;
 import org.olat.modules.lecture.LectureService;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
 import org.olat.modules.lecture.ui.LectureRepositoryAdminController;
+import org.olat.modules.lecture.ui.LectureRoles;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.user.UserManager;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -65,6 +67,7 @@ public class EditReasonController extends FormBasicController {
 	private final boolean wizard;
 	private final Identity noticedIdentity;
 	private final EditAbsenceNoticeWrapper noticeWrapper;
+	private final LecturesSecurityCallback secCallback;
 	private List<AbsenceCategory> absenceCategories;
 	
 	@Autowired
@@ -73,10 +76,11 @@ public class EditReasonController extends FormBasicController {
 	private LectureService lectureService;
 	
 	public EditReasonController(UserRequest ureq, WindowControl wControl, Form rootForm,
-			EditAbsenceNoticeWrapper noticeWrapper, boolean wizard) {
+			EditAbsenceNoticeWrapper noticeWrapper, LecturesSecurityCallback secCallback, boolean wizard) {
 		super(ureq, wControl, LAYOUT_DEFAULT, null, rootForm);
 		setTranslator(Util.createPackageTranslator(LectureRepositoryAdminController.class, ureq.getLocale()));
 		this.wizard = wizard;
+		this.secCallback = secCallback;
 		this.noticeWrapper = noticeWrapper;
 		this.noticedIdentity = noticeWrapper.getIdentity();
 		absenceCategories = lectureService.getAllAbsencesCategories();
@@ -97,12 +101,14 @@ public class EditReasonController extends FormBasicController {
 			translate("noticed.type.absence"), translate("noticed.type.notified"), translate("noticed.type.dispensation")
 		};
 		typeEl = uifactory.addRadiosHorizontal("noticed.type", "noticed.type", formLayout, typeKeys, typeValues);
+		typeEl.setVisible(secCallback.viewAs() != LectureRoles.participant);
 		typeEl.addActionListener(FormEvent.ONCHANGE);
 		if(noticeWrapper.getAbsenceNoticeType() != null) {
 			typeEl.select(noticeWrapper.getAbsenceNoticeType().name(), true);
 		}
 		String[] authorizedValues = new String[] { translate("noticed.autorized.yes") };
 		authorizedEl = uifactory.addCheckboxesHorizontal("noticed.autorized", null, formLayout, authorizedKeys, authorizedValues);
+		authorizedEl.setVisible(secCallback.viewAs() != LectureRoles.participant);
 		if(noticeWrapper.getAuthorized() != null && noticeWrapper.getAuthorized().booleanValue()) {
 			authorizedEl.select(authorizedKeys[0], true);
 		}
@@ -160,7 +166,7 @@ public class EditReasonController extends FormBasicController {
 		}
 		
 		typeEl.clearError();
-		if(!typeEl.isOneSelected()) {
+		if(typeEl.isVisible() && !typeEl.isOneSelected()) {
 			typeEl.setErrorKey("form.legende.mandatory", null);
 			allOk &= false;
 		}
@@ -185,7 +191,15 @@ public class EditReasonController extends FormBasicController {
 	protected void formOK(UserRequest ureq) {
 		noticeWrapper.setAbsenceReason(reasonEl.getValue());
 		noticeWrapper.setAbsenceCategory(getAbsenceCategory());
-		noticeWrapper.setAuthorized(authorizedEl.isAtLeastSelected(1));
-		noticeWrapper.setAbsenceNoticeType(AbsenceNoticeType.valueOf(typeEl.getSelectedKey()));
+		if(authorizedEl.isVisible()) {
+			noticeWrapper.setAuthorized(authorizedEl.isAtLeastSelected(1));
+		} else {
+			noticeWrapper.setAuthorized(null);
+		}
+		if(typeEl.isVisible()) {
+			noticeWrapper.setAbsenceNoticeType(AbsenceNoticeType.valueOf(typeEl.getSelectedKey()));
+		} else if(noticeWrapper.getAbsenceNoticeType() != null)  {
+			noticeWrapper.setAbsenceNoticeType(noticeWrapper.getAbsenceNoticeType());
+		}
 	}
 }
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/IdentitiesLecturesRollCallController.java b/src/main/java/org/olat/modules/lecture/ui/coach/IdentitiesLecturesRollCallController.java
index 5d02aecf85b..f225bdc88d1 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/IdentitiesLecturesRollCallController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/IdentitiesLecturesRollCallController.java
@@ -443,7 +443,7 @@ public class IdentitiesLecturesRollCallController extends FormBasicController {
 		noticeWrapper.setPredefinedLectureBlocks(lectureBlocksForIdentity);
 		noticeWrapper.setCurrentDate(currentDate);
 		
-		AbsenceNotice3LecturesEntriesStep step = new AbsenceNotice3LecturesEntriesStep(ureq, noticeWrapper, true);
+		AbsenceNotice3LecturesEntriesStep step = new AbsenceNotice3LecturesEntriesStep(ureq, noticeWrapper, secCallback, true);
 		StepRunnerCallback stop = (uureq, swControl, runContext) -> {
 			if(noticeWrapper.getAbsenceNotice() == null) {
 				Identity absentIdentity = noticeWrapper.getIdentity();
diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCoachingController.java b/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCoachingController.java
index 6391d384dd1..ba544d2ccec 100644
--- a/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCoachingController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCoachingController.java
@@ -58,11 +58,11 @@ import org.olat.repository.RepositoryEntry;
 public class LecturesCoachingController extends BasicController implements Activateable2 {
 	
 	private Link reportLink;
+	private Link appealsLink;
 	private final Link cockpitLink;
 	private final Link lecturesLink;
 	private final Link absenceLink;
 	private final Link dispensationLink;
-	private final Link appealsLink;
 	private final Link lecturesSearchLink;
 	private final VelocityContainer mainVC;
 	private final TooledStackedPanel stackPanel;
@@ -95,8 +95,11 @@ public class LecturesCoachingController extends BasicController implements Activ
 		segmentView.addSegment(absenceLink, false);
 		dispensationLink = LinkFactory.createLink("coach.dispensation", mainVC, this);
 		segmentView.addSegment(dispensationLink, false);
-		appealsLink = LinkFactory.createLink("coach.appeals", mainVC, this);
-		segmentView.addSegment(appealsLink, false);
+		
+		if(secCallback.canSeeAppeals()) {
+			appealsLink = LinkFactory.createLink("coach.appeals", mainVC, this);
+			segmentView.addSegment(appealsLink, false);
+		}
 		
 		lecturesSearchLink = LinkFactory.createLink("coach.lectures.search", mainVC, this);
 		segmentView.addSegment(lecturesSearchLink, false);
@@ -132,14 +135,15 @@ public class LecturesCoachingController extends BasicController implements Activ
 				doOpenLectures(ureq);
 				segmentView.select(lecturesLink);
 			} else if("Absences".equalsIgnoreCase(type)) {
-				doAbsences(ureq);
 				segmentView.select(absenceLink);
 			} else if("Dispenses".equalsIgnoreCase(type)) {
 				doDispenses(ureq);
 				segmentView.select(dispensationLink);
 			} else if("Appeals".equalsIgnoreCase(type)) {
-				doAppeals(ureq);
-				segmentView.select(appealsLink);
+				if(secCallback.canSeeAppeals()) {
+					doAppeals(ureq);
+					segmentView.select(appealsLink);
+				}
 			} else if("Search".equalsIgnoreCase(type)) {
 				List<ContextEntry> subEntries = entries.subList(1, entries.size());
 				doOpenLecturesSearch(ureq).activate(ureq, subEntries, entries.get(0).getTransientState());
diff --git a/src/main/java/org/olat/modules/lecture/ui/profile/DailyOverviewProfilController.java b/src/main/java/org/olat/modules/lecture/ui/profile/DailyOverviewProfilController.java
index fe94c31f2d0..271cae08a26 100644
--- a/src/main/java/org/olat/modules/lecture/ui/profile/DailyOverviewProfilController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/profile/DailyOverviewProfilController.java
@@ -90,6 +90,11 @@ public class DailyOverviewProfilController extends BasicController {
 		lectureBlocksCtrl.setCurrentDate(currentDate);
 		absencesListCtrl.setCurrentDate(currentDate);
 	}
+	
+	
+	public void reloadModel() {
+		absencesListCtrl.reloadModel();
+	}
 
 	@Override
 	protected void event(UserRequest ureq, Component source, Event event) {
diff --git a/src/main/java/org/olat/modules/lecture/ui/profile/IdentityProfileController.java b/src/main/java/org/olat/modules/lecture/ui/profile/IdentityProfileController.java
index 411de14fb46..ce90739574a 100644
--- a/src/main/java/org/olat/modules/lecture/ui/profile/IdentityProfileController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/profile/IdentityProfileController.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.lecture.ui.profile;
 
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.olat.admin.user.UserShortDescription;
@@ -29,20 +31,38 @@ import org.olat.core.gui.components.link.LinkFactory;
 import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel;
 import org.olat.core.gui.components.tabbedpane.TabbedPane;
 import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
+import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
 import org.olat.core.id.Identity;
+import org.olat.core.id.Roles;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Util;
+import org.olat.core.util.mail.ContactList;
+import org.olat.core.util.mail.MailBundle;
+import org.olat.core.util.mail.MailContext;
+import org.olat.core.util.mail.MailContextImpl;
+import org.olat.core.util.mail.MailHelper;
+import org.olat.core.util.mail.MailLoggingAction;
+import org.olat.core.util.mail.MailManager;
+import org.olat.core.util.mail.MailerResult;
+import org.olat.modules.lecture.AbsenceNoticeType;
+import org.olat.modules.lecture.LectureService;
+import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
 import org.olat.modules.lecture.ui.AppealListRepositoryController;
 import org.olat.modules.lecture.ui.LectureRepositoryAdminController;
 import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.modules.lecture.ui.ParticipantLecturesOverviewController;
 import org.olat.modules.lecture.ui.coach.DispensationsController;
+import org.olat.modules.lecture.ui.wizard.AbsenceNotice3LecturesEntriesStep;
 import org.olat.user.DisplayPortraitController;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -52,22 +72,33 @@ import org.olat.user.DisplayPortraitController;
  */
 public class IdentityProfileController extends BasicController implements Activateable2 {
 	
+	private Link backLink;
 	private Link addAbsence;
-	private Link addNoticeOfAbsence;
 	private Link addDispensation;
-	private Link backLink;
+	private Link addNoticeOfAbsence;
 	
 	private TabbedPane tabPane;
 	private final VelocityContainer mainVC;
 	
+	private final Identity profiledIdentity;
+	private final LecturesSecurityCallback secCallback;
+	
+	private StepsMainRunController addNoticeCtrl;
 	private DispensationsController dispensationsCtrl;
 	private AppealListRepositoryController appealsCtrl;
 	private DailyOverviewProfilController dailyOverviewCtrl;
 	private ParticipantLecturesOverviewController lecturesCtrl;
 	
+	@Autowired
+	private MailManager mailService;
+	@Autowired
+	private LectureService lectureService;
+	
 	public IdentityProfileController(UserRequest ureq, WindowControl wControl, Identity profiledIdentity,
 			LecturesSecurityCallback secCallback, boolean withBack) {
 		super(ureq, wControl, Util.createPackageTranslator(LectureRepositoryAdminController.class, ureq.getLocale()));
+		this.profiledIdentity = profiledIdentity;
+		this.secCallback = secCallback;
 		
 		mainVC = createVelocityContainer("profile");
 		if(withBack) {
@@ -148,6 +179,106 @@ public class IdentityProfileController extends BasicController implements Activa
 	protected void event(UserRequest ureq, Component source, Event event) {
 		if(source == backLink) {
 			fireEvent(ureq, Event.BACK_EVENT);
+		} else if(addAbsence == source) {
+			doAddNotice(ureq, AbsenceNoticeType.absence);
+		} else if(addNoticeOfAbsence == source) {
+			doAddNotice(ureq, AbsenceNoticeType.notified);
+		} else if(addDispensation == source) {
+			doAddNotice(ureq, AbsenceNoticeType.dispensation);
+		}
+	}
+	
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(addNoticeCtrl == source) {
+			if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+				getWindowControl().pop();
+				if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+					updateModels();
+				}
+				cleanUp();
+			}
+		}
+		super.event(ureq, source, event);
+	}
+	
+	private void cleanUp() {
+		removeAsListenerAndDispose(addNoticeCtrl);
+		addNoticeCtrl = null;
+	}
+	
+	private void updateModels() {
+		if(dispensationsCtrl != null) {
+			dispensationsCtrl.reloadModel();
+		}
+		if(dailyOverviewCtrl != null) {
+			dailyOverviewCtrl.reloadModel();
+		}
+	}
+	
+	private void doAddNotice(UserRequest ureq, AbsenceNoticeType type) {
+		final EditAbsenceNoticeWrapper noticeWrapper = new EditAbsenceNoticeWrapper(type);
+		noticeWrapper.setIdentity(profiledIdentity);
+		noticeWrapper.setCurrentDate(new Date());
+		
+		AbsenceNotice3LecturesEntriesStep step = new AbsenceNotice3LecturesEntriesStep(ureq, noticeWrapper, secCallback, true);
+		StepRunnerCallback stop = (uureq, swControl, runContext) -> {
+			if(noticeWrapper.getAbsenceNotice() == null) {
+				Identity absentIdentity = noticeWrapper.getIdentity();
+				lectureService.createAbsenceNotice(absentIdentity, noticeWrapper.getAbsenceNoticeType(), noticeWrapper.getAbsenceNoticeTarget(),
+						noticeWrapper.getStartDate(), noticeWrapper.getEndDate(),
+						noticeWrapper.getAbsenceCategory(), noticeWrapper.getAbsenceReason(), noticeWrapper.getAuthorized(),
+						noticeWrapper.getEntries(), noticeWrapper.getLectureBlocks());
+			}
+			
+			if(noticeWrapper.getIdentitiesToContact() != null && !noticeWrapper.getIdentitiesToContact().isEmpty()) {
+				inform(ureq, noticeWrapper);
+			}
+			return StepsMainRunController.DONE_MODIFIED;
+		};
+		
+		String title = translate("add.dispensation.title");
+		if(type == AbsenceNoticeType.notified) {
+			title = translate("add.notice.absence.title");
+		} else if(type == AbsenceNoticeType.absence) {
+			title = translate("add.absence.title");
+		}
+		
+		removeAsListenerAndDispose(addNoticeCtrl);
+		addNoticeCtrl = new StepsMainRunController(ureq, getWindowControl(), step, stop, null, title, "");
+		listenTo(addNoticeCtrl);
+		getWindowControl().pushAsModalDialog(addNoticeCtrl.getInitialComponent());
+	}
+	
+
+	private void inform(UserRequest ureq, EditAbsenceNoticeWrapper noticeWrapper) {
+		boolean success = false;
+		try {
+			List<ContactList> contactList = new ArrayList<>();
+			ContactList memberList = new ContactList(translate("contact.teachers.list.name"));
+			memberList.addAllIdentites(noticeWrapper.getIdentitiesToContact());
+			MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString());
+			MailBundle bundle = new MailBundle();
+			bundle.setContext(context);
+			bundle.setFromId(getIdentity());						
+			bundle.setContactLists(contactList);
+			bundle.setContent(noticeWrapper.getContactSubject(), noticeWrapper.getContactSubject());
+			MailerResult result = mailService.sendMessage(bundle);
+			success = result.isSuccessful();
+			if (success) {
+				showInfo("msg.send.ok");
+				// do logging
+				ThreadLocalUserActivityLogger.log(MailLoggingAction.MAIL_SENT, getClass());
+				fireEvent(ureq, Event.DONE_EVENT);
+			} else {
+				Roles roles = ureq.getUserSession().getRoles();
+				boolean admin = roles.isAdministrator() || roles.isSystemAdmin();
+				MailHelper.printErrorsAndWarnings(result, getWindowControl(), admin, getLocale());
+				fireEvent(ureq, Event.FAILED_EVENT);
+			}
+		} catch (Exception e) {
+			logError("", e);
+			showWarning("error.msg.send.nok");
 		}
 	}
 }
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice1UserSearchStep.java b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice1UserSearchStep.java
index 14daa2442c5..fcdcc184452 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice1UserSearchStep.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice1UserSearchStep.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
 import org.olat.core.gui.control.generic.wizard.StepFormController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 
 /**
  * 
@@ -38,10 +39,10 @@ public class AbsenceNotice1UserSearchStep extends BasicStep {
 	
 	private final EditAbsenceNoticeWrapper noticeWrapper;
 	
-	public AbsenceNotice1UserSearchStep(UserRequest ureq, EditAbsenceNoticeWrapper noticeWrapper) {
+	public AbsenceNotice1UserSearchStep(UserRequest ureq, EditAbsenceNoticeWrapper noticeWrapper, LecturesSecurityCallback secCallback) {
 		super(ureq);
 		this.noticeWrapper = noticeWrapper;
-		setNextStep(new AbsenceNotice2ConfirmUserStep(ureq));
+		setNextStep(new AbsenceNotice2ConfirmUserStep(ureq, secCallback));
 		setI18nTitleAndDescr("user.search.title", "user.search.title");
 	}
 
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice2ConfirmUserStep.java b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice2ConfirmUserStep.java
index 187db70aadd..a7314d3594b 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice2ConfirmUserStep.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice2ConfirmUserStep.java
@@ -26,6 +26,7 @@ import org.olat.core.gui.control.generic.wizard.BasicStep;
 import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
 import org.olat.core.gui.control.generic.wizard.StepFormController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 
 /**
  * 
@@ -35,9 +36,9 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext;
  */
 public class AbsenceNotice2ConfirmUserStep extends BasicStep {
 	
-	public AbsenceNotice2ConfirmUserStep(UserRequest ureq) {
+	public AbsenceNotice2ConfirmUserStep(UserRequest ureq, LecturesSecurityCallback secCallback) {
 		super(ureq);
-		setNextStep(new AbsenceNotice3LecturesEntriesStep(ureq));
+		setNextStep(new AbsenceNotice3LecturesEntriesStep(ureq, secCallback));
 		setI18nTitleAndDescr("user.confirm.title", "user.confirm.title");
 	}
 
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice3LecturesEntriesStep.java b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice3LecturesEntriesStep.java
index 7f98d87a006..a643267199e 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice3LecturesEntriesStep.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice3LecturesEntriesStep.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
 import org.olat.core.gui.control.generic.wizard.StepFormController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 
 /**
  * 
@@ -37,16 +38,19 @@ import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
 public class AbsenceNotice3LecturesEntriesStep extends BasicStep {
 	
 	private final boolean startPoint;
+	private final LecturesSecurityCallback secCallback;
 	private final EditAbsenceNoticeWrapper noticeWrapper;
 	
-	public AbsenceNotice3LecturesEntriesStep(UserRequest ureq) {
-		this(ureq, null, false);
+	public AbsenceNotice3LecturesEntriesStep(UserRequest ureq, LecturesSecurityCallback secCallback) {
+		this(ureq, null, secCallback, false);
 	}
 	
-	public AbsenceNotice3LecturesEntriesStep(UserRequest ureq, EditAbsenceNoticeWrapper noticeWrapper, boolean startPoint) {
+	public AbsenceNotice3LecturesEntriesStep(UserRequest ureq, EditAbsenceNoticeWrapper noticeWrapper,
+			LecturesSecurityCallback secCallback, boolean startPoint) {
 		super(ureq);
 		this.startPoint = startPoint;
-		setNextStep(new AbsenceNotice4ReasonStep(ureq));
+		this.secCallback = secCallback;
+		setNextStep(new AbsenceNotice4ReasonStep(ureq, secCallback));
 		if(startPoint) {
 			this.noticeWrapper = noticeWrapper;
 		} else {
@@ -65,6 +69,6 @@ public class AbsenceNotice3LecturesEntriesStep extends BasicStep {
 		if(noticeWrapper != null) {
 			runContext.put("absence", noticeWrapper);
 		}
-		return new DatesLecturesEntriesStepController(ureq, wControl, form, runContext);
+		return new DatesLecturesEntriesStepController(ureq, wControl, form, runContext, secCallback);
 	}
 }
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice4ReasonStep.java b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice4ReasonStep.java
index 705f81a65b8..12bd855f418 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice4ReasonStep.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/AbsenceNotice4ReasonStep.java
@@ -26,6 +26,7 @@ import org.olat.core.gui.control.generic.wizard.BasicStep;
 import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
 import org.olat.core.gui.control.generic.wizard.StepFormController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 
 /**
  * 
@@ -35,8 +36,11 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext;
  */
 public class AbsenceNotice4ReasonStep extends BasicStep {
 	
-	public AbsenceNotice4ReasonStep(UserRequest ureq) {
+	private final LecturesSecurityCallback secCallback;
+	
+	public AbsenceNotice4ReasonStep(UserRequest ureq, LecturesSecurityCallback secCallback) {
 		super(ureq);
+		this.secCallback = secCallback;
 		setNextStep(new AbsenceNotice5ContactStep(ureq));
 		setI18nTitleAndDescr("wizard.reason.title", "wizard.reason.title");
 	}
@@ -48,6 +52,6 @@ public class AbsenceNotice4ReasonStep extends BasicStep {
 
 	@Override
 	public StepFormController getStepController(UserRequest ureq, WindowControl wControl, StepsRunContext runContext, Form form) {
-		return new ReasonStepController(ureq, wControl, form, runContext);
+		return new ReasonStepController(ureq, wControl, form, runContext, secCallback);
 	}
 }
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/DatesLecturesEntriesStepController.java b/src/main/java/org/olat/modules/lecture/ui/wizard/DatesLecturesEntriesStepController.java
index b38f295d0c0..4f52943d0be 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/DatesLecturesEntriesStepController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/DatesLecturesEntriesStepController.java
@@ -28,6 +28,7 @@ import org.olat.core.gui.control.generic.wizard.StepFormBasicController;
 import org.olat.core.gui.control.generic.wizard.StepsEvent;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.modules.lecture.ui.coach.EditDatesLecturesEntriesController;
 
 /**
@@ -37,14 +38,15 @@ import org.olat.modules.lecture.ui.coach.EditDatesLecturesEntriesController;
  *
  */
 public class DatesLecturesEntriesStepController extends StepFormBasicController {
-	
+
 	private final EditDatesLecturesEntriesController editCtrl;
 	
-	public DatesLecturesEntriesStepController(UserRequest ureq, WindowControl wControl, Form rootForm, StepsRunContext runContext) {
+	public DatesLecturesEntriesStepController(UserRequest ureq, WindowControl wControl, Form rootForm, StepsRunContext runContext,
+			LecturesSecurityCallback secCallback) {
 		super(ureq, wControl, rootForm, runContext, LAYOUT_VERTICAL, null);
-		
+	
 		EditAbsenceNoticeWrapper noticeWrapper = (EditAbsenceNoticeWrapper)getFromRunContext("absence");
-		editCtrl = new EditDatesLecturesEntriesController(ureq, wControl, rootForm, noticeWrapper, true);
+		editCtrl = new EditDatesLecturesEntriesController(ureq, wControl, rootForm, noticeWrapper, secCallback, true);
 		listenTo(editCtrl);
 		initForm(ureq);
 	}
diff --git a/src/main/java/org/olat/modules/lecture/ui/wizard/ReasonStepController.java b/src/main/java/org/olat/modules/lecture/ui/wizard/ReasonStepController.java
index b6ec2566ea4..68aa2b44c7b 100644
--- a/src/main/java/org/olat/modules/lecture/ui/wizard/ReasonStepController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/wizard/ReasonStepController.java
@@ -28,6 +28,7 @@ import org.olat.core.gui.control.generic.wizard.StepFormBasicController;
 import org.olat.core.gui.control.generic.wizard.StepsEvent;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.modules.lecture.model.EditAbsenceNoticeWrapper;
+import org.olat.modules.lecture.ui.LecturesSecurityCallback;
 import org.olat.modules.lecture.ui.coach.EditReasonController;
 
 /**
@@ -40,10 +41,11 @@ public class ReasonStepController extends StepFormBasicController {
 	
 	private final EditReasonController editReasonCtrl;
 	
-	public ReasonStepController(UserRequest ureq, WindowControl wControl, Form rootForm, StepsRunContext runContext) {
+	public ReasonStepController(UserRequest ureq, WindowControl wControl, Form rootForm, StepsRunContext runContext,
+			LecturesSecurityCallback secCallback) {
 		super(ureq, wControl, rootForm, runContext, LAYOUT_VERTICAL, null);
 		EditAbsenceNoticeWrapper noticeWrapper = (EditAbsenceNoticeWrapper)getFromRunContext("absence");
-		editReasonCtrl = new EditReasonController(ureq, wControl, rootForm, noticeWrapper, true);
+		editReasonCtrl = new EditReasonController(ureq, wControl, rootForm, noticeWrapper, secCallback, true);
 		listenTo(editReasonCtrl);
 		initForm(ureq);
 	}
diff --git a/src/test/java/org/olat/modules/lecture/manager/LectureBlockDAOTest.java b/src/test/java/org/olat/modules/lecture/manager/LectureBlockDAOTest.java
index bdbfd2d26a2..d1a28d8cb38 100644
--- a/src/test/java/org/olat/modules/lecture/manager/LectureBlockDAOTest.java
+++ b/src/test/java/org/olat/modules/lecture/manager/LectureBlockDAOTest.java
@@ -197,6 +197,8 @@ public class LectureBlockDAOTest extends OlatTestCase {
 		searchParams.setSearchString("Hello");
 		searchParams.setStartDate(new Date());
 		searchParams.setTeacher(id);
+		searchParams.setMasterCoach(id);
+		searchParams.setManager(id);
 		
 		List<LectureBlock> blocks = lectureBlockDao.searchLectureBlocks(searchParams);
 		Assert.assertNotNull(blocks);
-- 
GitLab