diff --git a/src/main/java/org/olat/modules/co/ContactFormController.java b/src/main/java/org/olat/modules/co/ContactFormController.java index 711cb9fc9abf2539f7ef38044da5f38b8c3edab7..67845d18861d3cc28aad1a708c3e3418abb347e0 100644 --- a/src/main/java/org/olat/modules/co/ContactFormController.java +++ b/src/main/java/org/olat/modules/co/ContactFormController.java @@ -153,6 +153,20 @@ public class ContactFormController extends BasicController { } return hasAtLeastOneAddress; } + + public String getSubject() { + if(cntctForm != null) { + return cntctForm.getSubject(); + } + return null; + } + + public String getBody() { + if(cntctForm != null) { + return cntctForm.getBody(); + } + return null; + } /** * @param useDefaultTitle diff --git a/src/main/java/org/olat/modules/lecture/LectureBlockAuditLog.java b/src/main/java/org/olat/modules/lecture/LectureBlockAuditLog.java index 26621e9898f2f97932d70202045e481e9a0e4d8e..3d102f81ae3677a41882e88413bf49c774c41689 100644 --- a/src/main/java/org/olat/modules/lecture/LectureBlockAuditLog.java +++ b/src/main/java/org/olat/modules/lecture/LectureBlockAuditLog.java @@ -65,6 +65,7 @@ public interface LectureBlockAuditLog { updateRollCall, adaptRollCall, + sendAppeal } } diff --git a/src/main/java/org/olat/modules/lecture/LectureBlockRollCall.java b/src/main/java/org/olat/modules/lecture/LectureBlockRollCall.java index 54a55b487879a4ec7639a881516e918454ca0111..9a3f03f9451c6cef5cbd41d952baafb97ea84adb 100644 --- a/src/main/java/org/olat/modules/lecture/LectureBlockRollCall.java +++ b/src/main/java/org/olat/modules/lecture/LectureBlockRollCall.java @@ -32,9 +32,7 @@ import org.olat.core.id.ModifiedInfo; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public interface LectureBlockRollCall extends ModifiedInfo, CreateInfo { - - public Long getKey(); +public interface LectureBlockRollCall extends LectureBlockRollCallRef, ModifiedInfo, CreateInfo { public Identity getIdentity(); diff --git a/src/main/java/org/olat/modules/lecture/LectureBlockRollCallRef.java b/src/main/java/org/olat/modules/lecture/LectureBlockRollCallRef.java new file mode 100644 index 0000000000000000000000000000000000000000..2aa3e0f5f64593033bf183859723f6e18a73506c --- /dev/null +++ b/src/main/java/org/olat/modules/lecture/LectureBlockRollCallRef.java @@ -0,0 +1,32 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.lecture; + +/** + * + * Initial date: 27 oct. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface LectureBlockRollCallRef { + + public Long getKey(); + +} diff --git a/src/main/java/org/olat/modules/lecture/LectureService.java b/src/main/java/org/olat/modules/lecture/LectureService.java index 4097ff0a76ae8e9b1381e7558b94e3d8c1aaceec..cdf7d17df82f98eb09ff8543b942d31145bc3931 100644 --- a/src/main/java/org/olat/modules/lecture/LectureService.java +++ b/src/main/java/org/olat/modules/lecture/LectureService.java @@ -138,12 +138,28 @@ public interface LectureService { /** * The audit log of a specific user. * - * @param assessedIdentity + * @param assessedIdentity The assessed identity (Mandatory) * @return A list of roll call changes. */ public List<LectureBlockAuditLog> getAuditLog(IdentityRef assessedIdentity); - + /** + * The audit log of a specific user with a specific action in the + * specified course. + * + * @param entry The course (mandatory) + * @param assessedIdentity The assessed identity (mandatory) + * @param action The action (mandatory) + * @return A list of roll call changes. + */ + public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry, IdentityRef assessedIdentity, LectureBlockAuditLog.Action action); + + /** + * Returns the audit log of the specified course. + * + * @param entry The course + * @return A list of roll call changes. + */ public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry); /** @@ -283,6 +299,8 @@ public interface LectureService { public LectureBlockRollCall getOrCreateRollCall(Identity identity, LectureBlock lectureBlock, Boolean authorizedAbsence, String absenceReason); + public LectureBlockRollCall getRollCall(LectureBlockRollCallRef rollCall); + /** * Standard merge * diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureBlockAuditLogDAO.java b/src/main/java/org/olat/modules/lecture/manager/LectureBlockAuditLogDAO.java index 8b18b6a1297e5bee9affae47b2c6cf1245f76e49..1148dbe33b4d7d5bf1b1643cd0691dae78b91d04 100644 --- a/src/main/java/org/olat/modules/lecture/manager/LectureBlockAuditLogDAO.java +++ b/src/main/java/org/olat/modules/lecture/manager/LectureBlockAuditLogDAO.java @@ -109,7 +109,7 @@ public class LectureBlockAuditLogDAO { } public List<LectureBlockAuditLog> getAuditLog(LectureBlockRef lectureBlock) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(128); sb.append("select log from lectureblockauditlog log where log.lectureBlockKey=:lectureBlockKey"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), LectureBlockAuditLog.class) @@ -118,7 +118,7 @@ public class LectureBlockAuditLogDAO { } public List<LectureBlockAuditLog> getAuditLog(IdentityRef identity) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(128); sb.append("select log from lectureblockauditlog log where log.identityKey=:identityKey"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), LectureBlockAuditLog.class) @@ -126,8 +126,19 @@ public class LectureBlockAuditLogDAO { .getResultList(); } + public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry, IdentityRef identity, LectureBlockAuditLog.Action action) { + StringBuilder sb = new StringBuilder(256); + sb.append("select log from lectureblockauditlog log where log.entryKey=:repoEntryKey and log.identityKey=:identityKey and log.action=:action"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), LectureBlockAuditLog.class) + .setParameter("repoEntryKey", entry.getKey()) + .setParameter("identityKey", identity.getKey()) + .setParameter("action", action.name()) + .getResultList(); + } + public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(128); sb.append("select log from lectureblockauditlog log where log.entryKey=:repoEntryKey"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), LectureBlockAuditLog.class) diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java index c3dc269b05420f49dbf94cb935206bf4b505a8aa..98a8daf5b714dc0e0db3c86f921da722ab8edb0f 100644 --- a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java +++ b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java @@ -62,8 +62,10 @@ import org.olat.group.BusinessGroup; import org.olat.group.DeletableGroupData; import org.olat.modules.lecture.LectureBlock; import org.olat.modules.lecture.LectureBlockAuditLog; +import org.olat.modules.lecture.LectureBlockAuditLog.Action; import org.olat.modules.lecture.LectureBlockRef; import org.olat.modules.lecture.LectureBlockRollCall; +import org.olat.modules.lecture.LectureBlockRollCallRef; import org.olat.modules.lecture.LectureBlockRollCallSearchParameters; import org.olat.modules.lecture.LectureBlockStatus; import org.olat.modules.lecture.LectureBlockToGroup; @@ -279,6 +281,10 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De public List<LectureBlockAuditLog> getAuditLog(IdentityRef assessedIdentity) { return auditLogDao.getAuditLog(assessedIdentity); } + @Override + public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry, IdentityRef assessedIdentity, Action action) { + return auditLogDao.getAuditLog(entry, assessedIdentity, action); + } @Override public List<LectureBlockAuditLog> getAuditLog(RepositoryEntryRef entry) { @@ -458,6 +464,12 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De } return rollCall; } + + @Override + public LectureBlockRollCall getRollCall(LectureBlockRollCallRef rollCall) { + if(rollCall == null) return null; + return lectureBlockRollCallDao.loadByKey(rollCall.getKey()); + } @Override public LectureBlockRollCall updateRollCall(LectureBlockRollCall rollCall) { diff --git a/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java b/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java index f17d10bff71b2d368c3946c331ecde5d78ca794b..b21e6801d5b1bfbd21edf0dc964510d2bb387690 100644 --- a/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java +++ b/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java @@ -24,6 +24,7 @@ import java.util.Date; import org.olat.modules.lecture.LectureBlock; import org.olat.modules.lecture.LectureBlockRef; import org.olat.modules.lecture.LectureBlockRollCall; +import org.olat.modules.lecture.LectureBlockRollCallRef; import org.olat.modules.lecture.LectureBlockStatus; import org.olat.modules.lecture.LectureRollCallStatus; @@ -106,6 +107,10 @@ public class LectureBlockAndRollCall { return rollCallKey != null; } + public LectureBlockRollCallRef getRollCallRef() { + return rollCallKey == null ? null : new LectureBlockRollCallRefImpl(rollCallKey); + } + public boolean isCompulsory() { return compulsory; } diff --git a/src/main/java/org/olat/modules/lecture/model/LectureBlockRollCallRefImpl.java b/src/main/java/org/olat/modules/lecture/model/LectureBlockRollCallRefImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..bd7552bd8486beeccbb1c92450c7c8204fe7db8f --- /dev/null +++ b/src/main/java/org/olat/modules/lecture/model/LectureBlockRollCallRefImpl.java @@ -0,0 +1,41 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.lecture.model; + +import org.olat.modules.lecture.LectureBlockRollCallRef; + +/** + * + * Initial date: 27 oct. 2017<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class LectureBlockRollCallRefImpl implements LectureBlockRollCallRef { + + private final Long key; + + public LectureBlockRollCallRefImpl(Long key) { + this.key = key; + } + + public Long getKey() { + return key; + } +} diff --git a/src/main/java/org/olat/modules/lecture/ui/ParticipantLectureBlocksController.java b/src/main/java/org/olat/modules/lecture/ui/ParticipantLectureBlocksController.java index f37d5e9ba47adb51c88cba83d9481a9fa61fb9da..886abc2b6c17fd4774df2777895c66ab6fd4dd11 100644 --- a/src/main/java/org/olat/modules/lecture/ui/ParticipantLectureBlocksController.java +++ b/src/main/java/org/olat/modules/lecture/ui/ParticipantLectureBlocksController.java @@ -22,12 +22,15 @@ package org.olat.modules.lecture.ui; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.olat.NewControllerFactory; import org.olat.basesecurity.GroupRoles; import org.olat.commons.calendar.CalendarUtils; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory; +import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -60,6 +63,9 @@ import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactMessage; import org.olat.modules.co.ContactFormController; import org.olat.modules.lecture.LectureBlock; +import org.olat.modules.lecture.LectureBlockAuditLog; +import org.olat.modules.lecture.LectureBlockAuditLog.Action; +import org.olat.modules.lecture.LectureBlockRollCall; import org.olat.modules.lecture.LectureBlockStatus; import org.olat.modules.lecture.LectureModule; import org.olat.modules.lecture.LectureService; @@ -100,6 +106,8 @@ public class ParticipantLectureBlocksController extends FormBasicController { private final boolean authorizedAbsenceEnabled; private final boolean absenceDefaultAuthorized; + @Autowired + private DB dbInstance; @Autowired private UserManager userManager; @Autowired @@ -124,7 +132,7 @@ public class ParticipantLectureBlocksController extends FormBasicController { authorizedAbsenceEnabled = lectureModule.isAuthorizedAbsenceEnabled(); absenceDefaultAuthorized = lectureModule.isAbsenceDefaultAuthorized(); - appealOffset = lectureModule.getRollCallAutoClosePeriod();//TODO absence or is it reminder period + appealOffset = lectureModule.getRollCallAutoClosePeriod(); appealPeriod = lectureModule.getAbsenceAppealPeriod(); initForm(ureq); loadModel(); @@ -196,6 +204,14 @@ public class ParticipantLectureBlocksController extends FormBasicController { Formatter formatter = Formatter.getInstance(getLocale()); List<LectureBlockAndRollCall> rollCalls = lectureService.getParticipantLectureBlocks(entry, assessedIdentity); + List<LectureBlockAuditLog> sendAppealLogs = lectureService.getAuditLog(entry, assessedIdentity, LectureBlockAuditLog.Action.sendAppeal); + Map<Long, Date> appealDates = new HashMap<>(); + for(LectureBlockAuditLog sendAppealLog:sendAppealLogs) { + if(sendAppealLog.getRollCallKey() != null) { + appealDates.put(sendAppealLog.getRollCallKey(), sendAppealLog.getCreationDate()); + } + } + List<LectureBlockAndRollCallRow> rows = new ArrayList<>(rollCalls.size()); for(LectureBlockAndRollCall rollCall:rollCalls) { LectureBlockAndRollCallRow row = new LectureBlockAndRollCallRow(rollCall); @@ -215,9 +231,20 @@ public class ParticipantLectureBlocksController extends FormBasicController { Date beginAppeal = CalendarUtils.removeTime(cal.getTime()); cal.add(Calendar.DATE, appealPeriod); Date endAppeal = CalendarUtils.getEndOfDay(cal).getTime(); + + Date sendAppealDate = null; + if(row.getRow().getRollCallRef() != null ) { + sendAppealDate = appealDates.get(row.getRow().getRollCallRef().getKey()); + } FormLink appealLink = null; - if(now.compareTo(beginAppeal) >= 0 && now.compareTo(endAppeal) <= 0) { + if(sendAppealDate != null) { + String appealFrom = translate("appeal.sent", new String[]{ formatter.formatDate(sendAppealDate) }); + appealLink = uifactory.addFormLink("appeal_" + count++, "appealsend", appealFrom, null, flc, Link.LINK | Link.NONTRANSLATED); + appealLink.setTitle(translate("appeal.sent.tooltip", new String[] { formatter.formatDate(sendAppealDate), formatter.formatDate(beginAppeal), formatter.formatDate(endAppeal) })); + appealLink.setEnabled(false); + appealLink.setDomReplacementWrapperRequired(false); + } else if(now.compareTo(beginAppeal) >= 0 && now.compareTo(endAppeal) <= 0) { appealLink = uifactory.addFormLink("appeal_" + count++, "appeal", translate("appeal"), null, flc, Link.LINK | Link.NONTRANSLATED); appealLink.setTitle(translate("appeal.tooltip", new String[] { formatter.formatDate(beginAppeal), formatter.formatDate(endAppeal) })); appealLink.setUserObject(row); @@ -261,7 +288,8 @@ public class ParticipantLectureBlocksController extends FormBasicController { if(appealCtrl == source) { if(event == Event.DONE_EVENT) { LectureBlockAndRollCall row = (LectureBlockAndRollCall)appealCtrl.getUserObject(); - logAudit("Appeal send for lecture block: " + row.getLectureBlockTitle() + " (" + row.getLectureBlockRef().getKey() + ")", null); + String body = appealCtrl.getBody(); + doAppealAudit(row, body); } cmc.deactivate(); cleanUp(); @@ -344,6 +372,18 @@ public class ParticipantLectureBlocksController extends FormBasicController { cmc.activate(); } + private void doAppealAudit(LectureBlockAndRollCall row, String message) { + logAudit("Appeal send for lecture block: " + row.getLectureBlockTitle() + " (" + row.getLectureBlockRef().getKey() + ")", null); + + LectureBlock lectureBlock = lectureService.getLectureBlock(row.getLectureBlockRef()); + LectureBlockRollCall rollCall = lectureService.getRollCall(row.getRollCallRef()); + lectureService.auditLog(Action.sendAppeal, null, null, message, lectureBlock, rollCall, entry, assessedIdentity, null); + + dbInstance.commit(); + loadModel(); + tableEl.reset(false, false, true); + } + private void doPrint(UserRequest ureq) { ControllerCreator printControllerCreator = new ControllerCreator() { @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 3f6172b40c8b3081119bcedeedcbb5465cddccb1..559b5572de3d4c932b862350e0a59c9ec45a3109 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 @@ -18,6 +18,8 @@ appeal.from=Ab {0} appeal.subject=Rekurs Lektionenblock "{0}" appeal.title=Rekurs f\u00FCr\: "{0}" appeal.tooltip=Rekurs m\u00F6glich von {0} bis {1} +appeal.sent=Am {0} geschickt +appeal.sent.tooltip=Rekurs wurde am {0} geschickt archive.entry=Archivierung attendance.list=Absenzenliste attendance.list.title=Absenzenliste\: {0} 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 124f3bc217ef50d9a49e11bd8e916d6daa209098..d2f70021627fa48f4f94977c6cce9f61ca079101 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 @@ -18,6 +18,8 @@ appeal.from=From {0} appeal.subject=Appeal lecture block "{0}" appeal.title=Appeal for\: "{0}" appeal.tooltip=Appeal possible from {0} until {1} +appeal.sent=Send at {0} +appeal.sent.tooltip=Appeal was sent at {0} archive.entry=Archive attendance.list=Absence list attendance.list.title=Absence list: {0}