3122 Stöd för manuell hantering av slutsem för handledare

This commit is contained in:
Wayne Westmoreland 2023-12-01 17:21:13 +01:00
parent 9100e593a8
commit 5905308085
13 changed files with 64 additions and 44 deletions

@ -274,9 +274,7 @@ public class FinalSeminarServiceImpl extends AbstractServiceImpl<FinalSeminar, L
@Override
@Transactional
public Either<OpposeError, FinalSeminarOpposition> attemptAddOppositionAsSupervisor(User student, FinalSeminar finalSeminar, Project project) {
if (!project.isParticipant(student)) {
return Either.left(OpposeError.NotAuthorOfSameProjectType);
} else if (finalSeminar.getActiveParticipants().contains(student)) {
if (finalSeminar.getActiveParticipants().contains(student)) {
return Either.left(OpposeError.AlreadyParticipant);
} else if (finalSeminar.getOpponents().contains(student)) {
return Either.left(OpposeError.AlreadyOpponent);
@ -305,9 +303,7 @@ public class FinalSeminarServiceImpl extends AbstractServiceImpl<FinalSeminar, L
@Override
@Transactional
public Either<ParticipateError, FinalSeminarActiveParticipation> attemptAddActiveParticipationAsSupervisor(User student, FinalSeminar finalSeminar, Project project) {
if (!project.isParticipant(student)) {
return Either.left(ParticipateError.NotAuthorOfSameProjectType);
} else if (finalSeminar.getActiveParticipants().contains(student)) {
if (finalSeminar.getActiveParticipants().contains(student)) {
return Either.left(ParticipateError.AlreadyParticipant);
} else if (finalSeminar.getOpponents().contains(student)) {
return Either.left(ParticipateError.AlreadyOpponent);

@ -1,5 +1,5 @@
package se.su.dsv.scipro.finalseminar;
public enum OpposeError {
AlreadyOpponent, AlreadyParticipant, NotAuthorOfSameProjectType
AlreadyOpponent, AlreadyParticipant
}

@ -1,5 +1,5 @@
package se.su.dsv.scipro.finalseminar;
public enum ParticipateError {
AlreadyOpponent, AlreadyParticipant, NotAuthorOfSameProjectType
AlreadyOpponent, AlreadyParticipant
}

@ -192,7 +192,7 @@ public class IdeaServiceImpl extends AbstractServiceImpl<Idea, Long> implements
if (idea.getProjectType().getProjectTypeSettings().getMinAuthors() > 1 && coAuthor == null && !applicationPeriodService.hasIdeaSizeExemption(creator, ap)) {
return new Pair<>(Boolean.FALSE, BACHELOR_NEED_PARTNER_ERROR);
}
if (!projectService.getActiveProjects(creator, idea.getProjectType()).isEmpty()) {
if (!projectService.getActiveProjectsByUserAndProjectType(creator, idea.getProjectType()).isEmpty()) {
return new Pair<>(Boolean.FALSE, MessageFormat.format(ALREADY_HAVE_AN_ACTIVE_PROJECT, generalSystemSettingsInstance.getActiveProjectIdeaSupportMail()));
}
if (coAuthor != null) {
@ -205,7 +205,7 @@ public class IdeaServiceImpl extends AbstractServiceImpl<Idea, Long> implements
if (coAuthor.getDegreeType() != ProjectType.UNKNOWN && coAuthor.getDegreeType() != idea.getProjectType().getDegreeType()) {
return new Pair<>(Boolean.FALSE, WRONG_LEVEL_FOR_YOUR_PARTNER);
}
if (!projectService.getActiveProjects(coAuthor, idea.getProjectType()).isEmpty()) {
if (!projectService.getActiveProjectsByUserAndProjectType(coAuthor, idea.getProjectType()).isEmpty()) {
return new Pair<>(Boolean.FALSE, MessageFormat.format(PARTNER_ALREADY_HAS_ACTIVE_PROJECT, generalSystemSettingsInstance.getActiveProjectIdeaSupportMail()));
}
}

@ -22,7 +22,9 @@ public interface ProjectService extends GenericService<Project, Long>, FilteredS
Member.Type getMemberType(Project project, User user);
List<Project> getActiveProjects(User author, ProjectType pc);
List<Project> getActiveProjectsByUserAndProjectType(User author, ProjectType pc);
List<Project> getActiveProjectsByUser(User author);
List<Project> findAll(Filter params);

@ -126,10 +126,15 @@ public class ProjectServiceImpl extends AbstractServiceImpl<Project, Long> imple
}
@Override
public List<Project> getActiveProjects(User author, ProjectType pc) {
public List<Project> getActiveProjectsByUserAndProjectType(User author, ProjectType pc) {
return findAll(hasStatus(ProjectStatus.ACTIVE).and(hasProjectType(pc)).and(isAuthor(author)));
}
@Override
public List<Project> getActiveProjectsByUser(User author) {
return findAll(hasStatus(ProjectStatus.ACTIVE).and(isAuthor(author)));
}
@Override
public List<Project> findAll(Filter params) {
return findAll(toPredicate(params));

@ -137,7 +137,7 @@ public class ProjectServiceImplIntegrationTest extends IntegrationTest {
project = save(project);
List<Project> expectedList = Collections.singletonList(project);
assertEquals(expectedList, projectService.getActiveProjects(user, projectType));
assertEquals(expectedList, projectService.getActiveProjectsByUserAndProjectType(user, projectType));
}
@Test

@ -187,9 +187,8 @@ public class SeminarCRUDPanel extends GenericPanel<FinalSeminar> {
}
}
private Optional<Project> getPotentialParticipantProject(User participant, ProjectType projectType) {
List<Project> projects = projectService.getActiveProjects(participant, projectType);
private Optional<Project> getPotentialParticipantProjectForUserAndType(User participant, ProjectType projectType) {
List<Project> projects = projectService.getActiveProjectsByUserAndProjectType(participant, projectType);
if (projects.size() == 1) {
return Optional.of(projects.get(0));
} else {
@ -197,11 +196,28 @@ public class SeminarCRUDPanel extends GenericPanel<FinalSeminar> {
}
}
private Optional<Project> getPotentialParticipantProjectForUser(User participant) {
List<Project> projects = projectService.getActiveProjectsByUser(participant);
projects.sort(Comparator.comparing(Project::getStartDate).reversed());
if (!projects.isEmpty()) {
return Optional.of(projects.get(0));
} else {
return Optional.empty();
}
}
private void addActiveParticipants(FinalSeminar finalSeminar) {
for (User potentialParticipant : activeParticipants.getModelObject()) {
Optional<Project> maybeProject = getPotentialParticipantProject(potentialParticipant, finalSeminar.getProjectType());
boolean authorHasActiveProject;
Optional<Project> maybeProject = getPotentialParticipantProjectForUserAndType(potentialParticipant, finalSeminar.getProjectType());
if (maybeProject.isEmpty()) {
error(getString("opponent.no.project", Model.of(potentialParticipant)));
maybeProject = getPotentialParticipantProjectForUser(potentialParticipant);
authorHasActiveProject = false;
} else {
authorHasActiveProject = true;
}
if (maybeProject.isEmpty()) {
error(getString("UserHasNoActiveProject", Model.of(potentialParticipant)));
} else {
final Project project = maybeProject.get();
Either<ParticipateError, FinalSeminarActiveParticipation> result = seminarService.attemptAddActiveParticipationAsSupervisor(potentialParticipant, finalSeminar, project);
@ -212,17 +228,16 @@ public class SeminarCRUDPanel extends GenericPanel<FinalSeminar> {
error(potentialParticipant.getFullName() + " that you selected as an active participant is already an opponent");
case AlreadyParticipant ->
error(potentialParticipant.getFullName() + " that you selected as an active participant is already an active participant");
case NotAuthorOfSameProjectType ->
error("Failed to add " + potentialParticipant.getFullName() + " as an active participant: Not an author of a project of the same type");
}
return false;
},
success -> {
success("Added " + potentialParticipant.getFullName() + " as an opponent");
success("Added " + potentialParticipant.getFullName() + " as a participant." +
(authorHasActiveProject ? "" : " Note! " + potentialParticipant.getFullName() + " doesn't have a project of the same type"));
events.add(SeminarEvent.Event.PARTICIPATION_CHANGED);
return true;
});
}
}String test = authorHasActiveProject ? "test" : "test2";
}
activeParticipants.clearInput();
activeParticipants.getModel().setObject(Collections.emptyList());
@ -230,10 +245,16 @@ public class SeminarCRUDPanel extends GenericPanel<FinalSeminar> {
private void addOpponents(FinalSeminar finalSeminar) {
for (User potentialOpponent : opponents.getModelObject()) {
Optional<Project> maybeProject = getPotentialParticipantProject(potentialOpponent, finalSeminar.getProjectType());
boolean authorHasActiveProject;
Optional<Project> maybeProject = getPotentialParticipantProjectForUserAndType(potentialOpponent, finalSeminar.getProjectType());
if (maybeProject.isEmpty()) {
error(getString("opponent.no.project", Model.of(potentialOpponent)));
maybeProject = getPotentialParticipantProjectForUser(potentialOpponent);
authorHasActiveProject = false;
} else {
authorHasActiveProject = true;
}
if (maybeProject.isEmpty()) {
error(getString("UserHasNoActiveProject", Model.of(potentialOpponent)));
} else {
final Project project = maybeProject.get();
Either<OpposeError, FinalSeminarOpposition> result = seminarService.attemptAddOppositionAsSupervisor(potentialOpponent, finalSeminar, project);
@ -244,20 +265,19 @@ public class SeminarCRUDPanel extends GenericPanel<FinalSeminar> {
error(potentialOpponent.getFullName() + " that you selected as an opponent is already an opponent");
case AlreadyParticipant ->
error(potentialOpponent.getFullName() + " that you selected as an opponent is already an active participant");
case NotAuthorOfSameProjectType ->
error("Failed to add " + potentialOpponent.getFullName() + ": Not an author of a project of the same type");
}
return false;
},
success -> {
success("Added " + potentialOpponent.getFullName() + " as an opponent");
success("Added " + potentialOpponent.getFullName() + " as an opponent." +
(authorHasActiveProject ? "" : " Note! " + potentialOpponent.getFullName() + " doesn't have a project of the same type"));
events.add(SeminarEvent.Event.OPPOSITION_CHANGED);
return true;
});
}
opponents.clearInput();
opponents.getModel().setObject(Collections.emptyList());
}
opponents.clearInput();
opponents.getModel().setObject(Collections.emptyList());
}
private void saveSeminar(FinalSeminarDetails finalSeminarDetails) {

@ -4,7 +4,7 @@ maxOpponents.RangeValidator.minimum=The selected number of max oppositions may n
FinalSeminarLanguage.SWEDISH=Swedish
# suppress inspection "UnusedProperty"
FinalSeminarLanguage.ENGLISH=English
opponent.no.project=${fullName} does not have an active project of this project type.
UserHasNoActiveProject=${fullName} does not have an active project.
final.seminar.updated=Final seminar saved
create= Create
update= Update

@ -101,7 +101,7 @@ public class CompleteIdeaDialogPanel extends GenericPanel<Idea> {
final ProjectType selectedProjectType = getModelObject().getProjectType();
final boolean partnerHasActiveProject = coAuthorChoice.getModelObject()
.stream()
.map(partner -> projectService.getActiveProjects(partner, selectedProjectType))
.map(partner -> projectService.getActiveProjectsByUserAndProjectType(partner, selectedProjectType))
.flatMap(Collection::stream)
.findAny()
.isPresent();
@ -163,7 +163,7 @@ public class CompleteIdeaDialogPanel extends GenericPanel<Idea> {
}
final ProjectType projectType = getModelObject().getProjectType();
for (User partner : partners) {
if (!projectService.getActiveProjects(partner, projectType).isEmpty()) {
if (!projectService.getActiveProjectsByUserAndProjectType(partner, projectType).isEmpty()) {
error(getString("partner.already.has.an.active.project.on.this.level", Model.of(partner)));
}
}

@ -158,7 +158,7 @@ public class ProjectIdeaSubmissionPanel extends GenericPanel<Idea> {
final ProjectType selectedProjectType = getModelObject().getProjectType();
if (selectedProjectType != null) {
final boolean hasActiveProject = !projectService
.getActiveProjects(SciProSession.get().getUser(), selectedProjectType)
.getActiveProjectsByUserAndProjectType(SciProSession.get().getUser(), selectedProjectType)
.isEmpty();
setVisible(hasActiveProject);
}
@ -202,7 +202,7 @@ public class ProjectIdeaSubmissionPanel extends GenericPanel<Idea> {
if (selectedProjectType != null) {
final boolean partnerHasActiveProject = coAuthorChoice.getModelObject()
.stream()
.map(partner -> projectService.getActiveProjects(partner, selectedProjectType))
.map(partner -> projectService.getActiveProjectsByUserAndProjectType(partner, selectedProjectType))
.flatMap(Collection::stream)
.findAny()
.isPresent();
@ -354,11 +354,11 @@ public class ProjectIdeaSubmissionPanel extends GenericPanel<Idea> {
}
final ProjectType projectType = projectTypeChoice.getConvertedInput();
if (projectType != null) {
if (!projectService.getActiveProjects(SciProSession.get().getUser(), projectType).isEmpty()) {
if (!projectService.getActiveProjectsByUserAndProjectType(SciProSession.get().getUser(), projectType).isEmpty()) {
error(getString("you.already.have.an.active.project.on.this.level"));
}
for (User partner : partners) {
if (!projectService.getActiveProjects(partner, projectType).isEmpty()) {
if (!projectService.getActiveProjectsByUserAndProjectType(partner, projectType).isEmpty()) {
error(getString("partner.already.has.an.active.project.on.this.level", Model.of(partner)));
}
}

@ -121,8 +121,7 @@ footer a:hover { color: #d95e00;}
border: 1px solid #fbeed5;
}
.feedbackPanel li { padding: 2px;}
.feedbackPanel span { padding-left: 10px;}
.feedbackPanel li { padding: 2px 10px;}
.feedbackPanelERROR {
color: #A94442;
@ -134,14 +133,12 @@ footer a:hover { color: #d95e00;}
color: #3C763D;
background-color: #DFF0D8;
border-color: #D6E9C6;
padding-left: 0;
}
.feedbackPanelSUCCESS {
color: #3C763D;
background-color: #DFF0D8;
border-color: #D6E9C6;
padding-left: 0;
}
/************************************************** MENUS ***********************************************************/

@ -104,7 +104,7 @@ public class ProjectIdeaSubmissionPanelTest extends SciProTest {
@Test
public void can_not_submit_idea_if_already_has_active_project() {
when(projectService.getActiveProjects(eq(user), any(ProjectType.class))).thenReturn(Collections.singletonList(new Project()));
when(projectService.getActiveProjectsByUserAndProjectType(eq(user), any(ProjectType.class))).thenReturn(Collections.singletonList(new Project()));
startPanel(idea);
fillInFormAndSubmit();
tester.assertFeedback(path(panel, "feedback"), panel.getString("you.already.have.an.active.project.on.this.level"));
@ -113,8 +113,8 @@ public class ProjectIdeaSubmissionPanelTest extends SciProTest {
@Test
public void can_not_submit_idea_if_co_author_has_active_project() {
final User coAuthor = mockCoAuthor();
when(projectService.getActiveProjects(eq(user), any(ProjectType.class))).thenReturn(List.of());
when(projectService.getActiveProjects(eq(coAuthor), any(ProjectType.class))).thenReturn(Collections.singletonList(new Project()));
when(projectService.getActiveProjectsByUserAndProjectType(eq(user), any(ProjectType.class))).thenReturn(List.of());
when(projectService.getActiveProjectsByUserAndProjectType(eq(coAuthor), any(ProjectType.class))).thenReturn(Collections.singletonList(new Project()));
startPanel(idea);
fillInFormAndSubmit(coAuthor.getId(), true);
tester.assertFeedback(path(panel, "feedback"), panel.getString("partner.already.has.an.active.project.on.this.level", Model.of(coAuthor)));