/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FenixEdu Academic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.ui.spring.controller.student;
import com.google.gson.JsonArray;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import org.fenixedu.academic.domain.Attends;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.ExportGrouping;
import org.fenixedu.academic.domain.Grouping;
import org.fenixedu.academic.domain.Person;
import org.fenixedu.academic.domain.Shift;
import org.fenixedu.academic.domain.StudentGroup;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.student.Registration;
import org.fenixedu.academic.predicate.AccessControl;
import org.fenixedu.bennu.core.rest.JsonAwareResource;
import org.fenixedu.bennu.spring.portal.SpringApplication;
import org.fenixedu.bennu.spring.portal.SpringFunctionality;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.FenixFramework;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@SpringApplication(description = "link.student.group", path = "enroll-spring", group = "anyone", hint = "Student",
title = "label.enroll")
@SpringFunctionality(app = StudentGroupingController.class, title = "label.groupEnrolment")
@RequestMapping("/student/groups")
public class StudentGroupingController extends JsonAwareResource {
@Autowired
StudentGroupingService studentGroupingService;
@RequestMapping(method = RequestMethod.GET)
public String home() {
return "student/groupings/showGroupings";
}
@RequestMapping(value = "/groupings", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> getOpenEnrollmentGroupings() {
return new ResponseEntity<>(view(AccessControl
.getPerson()
.getStudent()
.getRegistrationsSet()
.stream()
.flatMap(registration -> registration.getAssociatedAttendsSet().stream())
.map(Attends::getExecutionCourse)
.filter(executionCourse -> executionCourse.getExecutionPeriod() == ExecutionSemester
.readActualExecutionSemester())
.flatMap(executionCourse -> executionCourse.getGroupings().stream())
.filter(grouping -> grouping.getAttendsSet().stream()
.anyMatch(attends -> attends.getRegistration().getPerson() == AccessControl.getPerson()))
.filter(grouping -> checkEnrolmentDate(grouping)).collect(Collectors.toList()))
.toString(), HttpStatus.OK);
}
@RequestMapping(value = "/grouping/{grouping}", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> getGrouping(Grouping grouping) {
if (!groupingIsOpenForEnrollment(grouping)) {
throw new DomainException("error.grouping.notOpenToEnrollment");
}
if (!personInGroupingAttends(grouping, AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()).toString(),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(grouping).toString(), HttpStatus.OK);
}
@RequestMapping(value = "/shift/{shift}", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> getShift(Shift shift) {
if (shift.getAssociatedStudentGroupsSet().stream().map(StudentGroup::getGrouping)
.noneMatch(grouping -> personInGroupingAttends(grouping, AccessControl.getPerson()))) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(shift).toString(), HttpStatus.OK);
}
@RequestMapping(value = "/studentGroup/{studentGroup}", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> getStudentGroup(StudentGroup studentGroup) {
if (!personInGroupingAttends(studentGroup.getGrouping(), AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (!groupingIsOpenForEnrollment(studentGroup.getGrouping())) {
throw new DomainException("error.grouping.notOpenToEnrollment");
}
return new ResponseEntity<>(view(studentGroup).toString(), HttpStatus.OK);
}
@RequestMapping(value = "{grouping}/shifts", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> getShitsForGrouping(@PathVariable Grouping grouping) {
if (!groupingIsOpenForEnrollment(grouping)) {
// throw new DomainException("error.grouping.notOpenToEnrollment");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notOpenToEnrollment")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (grouping.getShiftType() == null) {
return new ResponseEntity<>(new JsonArray().toString(), HttpStatus.OK);
}
//because the existing domain might still be in use, otherwise we could just got grouping.getShiftGroupingProperties
return new ResponseEntity<>(view(grouping.getExportGroupingsSet().stream().map(ExportGrouping::getExecutionCourse)
.flatMap(executionCourse -> executionCourse.getAssociatedShifts().stream())
.filter(shift -> shift.getTypes().contains(grouping.getShiftType())).collect(Collectors.toList())).toString(), HttpStatus.OK);
}
@RequestMapping(value = "{grouping}/studentGroupsEnrolledByStudent")
public @ResponseBody ResponseEntity<String> getStudentGroupsEnrolledByStudent(@PathVariable Grouping grouping) {
if (!groupingIsOpenForEnrollment(grouping)) {
// throw new DomainException("error.grouping.notOpenToEnrollment");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notOpenToEnrollment")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (!personInGroupingAttends(grouping, AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(grouping
.getStudentGroupsSet()
.stream()
.filter(studentGroup -> studentGroup.getAttendsSet().stream()
.anyMatch(attends -> attends.getRegistration().getPerson() == AccessControl.getPerson()))).toString(), HttpStatus.OK);
}
@RequestMapping(value = "{grouping}/studentGroups")
public @ResponseBody ResponseEntity<String> getStudentGroups(@PathVariable Grouping grouping) {
if (!personInGroupingAttends(grouping, AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (!groupingIsOpenForEnrollment(grouping)) {
// throw new DomainException("error.grouping.notOpenToEnrollment");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notOpenToEnrollment")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(grouping.getStudentGroupsSet()).toString(), HttpStatus.OK);
}
@RequestMapping(value = "{grouping}/studentsToEnroll")
public @ResponseBody ResponseEntity<String> getStudentsToEnroll(@PathVariable Grouping grouping) {
if (!personInGroupingAttends(grouping, AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (!groupingIsOpenForEnrollment(grouping)) {
// throw new DomainException("error.grouping.notOpenToEnrollment");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.studentGroupShift.notOpen")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(grouping
.getAttendsSet()
.stream()
.filter(attends -> grouping.getStudentGroupsSet().stream()
.noneMatch(sg -> sg.getAttendsSet().stream().anyMatch(at -> at.equals(attends))))
.map(Attends::getRegistration).map(Registration::getPerson).collect(Collectors.toList())).toString(), HttpStatus.OK);
}
@RequestMapping(value = "/studentGroup/{studentGroup}/enrolled")
public @ResponseBody ResponseEntity<String> getStudentsEnrolled(@PathVariable StudentGroup studentGroup) {
if (!personInGroupingAttends(studentGroup.getGrouping(), AccessControl.getPerson())) {
// throw new DomainException("error.grouping.notEnroled");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notEnroled")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
if (!groupingIsOpenForEnrollment(studentGroup.getGrouping())) {
// throw new DomainException("error.grouping.notOpenToEnrollment");
return new ResponseEntity<>(
createErrorJson((new DomainException("error.grouping.notOpenToEnrollment")).getLocalizedMessage()),
HttpStatus.FORBIDDEN);
}
return new ResponseEntity<>(view(studentGroup.getAttendsSet().stream().map(Attends::getRegistration)
.map(Registration::getPerson).collect(Collectors.toList())).toString(), HttpStatus.OK);
}
@RequestMapping(value = "/studentGroup/{studentGroup}/enroll", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> enroll(@PathVariable StudentGroup studentGroup) {
try {
studentGroupingService.enroll(studentGroup, AccessControl.getPerson());
return new ResponseEntity<>(HttpStatus.OK);
} catch (DomainException dme) {
return new ResponseEntity<>(createErrorJson(dme.getLocalizedMessage()), HttpStatus.FORBIDDEN);
}
}
@RequestMapping(value = "/studentGroup/{studentGroup}/unenroll", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> unenroll(@PathVariable StudentGroup studentGroup) {
try {
studentGroupingService.unenroll(studentGroup, AccessControl.getPerson());
return new ResponseEntity<>(HttpStatus.OK);
} catch (DomainException dme) {
return new ResponseEntity<>(createErrorJson(dme.getLocalizedMessage()), HttpStatus.FORBIDDEN);
}
}
@RequestMapping(value = "/studentGroup/{studentGroup}/changeShift", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> changeShift(@PathVariable StudentGroup studentGroup,
@RequestBody String shiftJson) {
try {
Shift newShift =
FenixFramework.getDomainObject(new JsonParser().parse(shiftJson).getAsJsonObject().get("id").getAsString());
studentGroupingService.changeShift(studentGroup, newShift);
return new ResponseEntity<>(HttpStatus.OK);
} catch (DomainException dme) {
return new ResponseEntity<>(createErrorJson(dme.getLocalizedMessage()), HttpStatus.FORBIDDEN);
}
}
@RequestMapping(value = "/createStudentGroup/{grouping}/", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> createStudentGroup(@PathVariable Grouping grouping,
@RequestBody String studentsToEnrollJson) {
return createStudentGroup(grouping, null, studentsToEnrollJson);
}
@RequestMapping(value = "/createStudentGroup/{grouping}/{shift}", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> createStudentGroup(@PathVariable Grouping grouping,
@PathVariable Shift shift,
@RequestBody String studentsToEnrollJson) {
try {
List<Person> studentsToEnroll = new ArrayList<Person>();
for (JsonElement elem : new JsonParser().parse(studentsToEnrollJson).getAsJsonArray()) {
JsonObject object = elem.getAsJsonObject();
studentsToEnroll.add((Person) FenixFramework.getDomainObject(object.get("id").getAsString()));
}
studentGroupingService.createStudentGroup(grouping, shift, studentsToEnroll);
return new ResponseEntity<>(HttpStatus.OK);
} catch (DomainException dme) {
return new ResponseEntity<>(createErrorJson(dme.getLocalizedMessage()), HttpStatus.FORBIDDEN);
}
}
private String createErrorJson(String message) {
JsonObject object = new JsonObject();
object.addProperty("message", message);
return object.toString();
}
public Boolean groupingIsOpenForEnrollment(Grouping grouping) {
return grouping.getEnrolmentBeginDayDateDateTime().isBeforeNow()
&& grouping.getEnrolmentEndDayDateDateTime().isAfterNow();
}
public Boolean personInGroupingAttends(Grouping grouping, Person person) {
return grouping.getAttendsSet().stream().map(Attends::getRegistration).map(Registration::getPerson)
.anyMatch(p -> p.equals(AccessControl.getPerson()));
}
public static boolean checkEnrolmentDate(Grouping grouping) {
if (grouping.getEnrolmentBeginDay() == null || grouping.getEnrolmentBeginDay().before(Calendar.getInstance())) {
if (grouping.getEnrolmentEndDay() == null || grouping.getEnrolmentEndDay().after(Calendar.getInstance())) {
return true;
}
return false;
}
return false;
}
}