Assign supervisor to student ideas no matter if target (goal) is reached #96

Merged
ansv7779 merged 12 commits from 67-supervisor-target-non-blocking into develop 2025-02-18 09:59:24 +01:00
4 changed files with 92 additions and 18 deletions
core/src/main/java/se/su/dsv/scipro
view/src/main
java/se/su/dsv/scipro/match
webapp/css
war/src/main/resources

@ -13,6 +13,7 @@ import java.util.*;
import java.util.function.Function;
import se.su.dsv.scipro.checklist.ChecklistCategory;
import se.su.dsv.scipro.file.FileUpload;
import se.su.dsv.scipro.match.*;
import se.su.dsv.scipro.match.ApplicationPeriod;
import se.su.dsv.scipro.match.Idea;
import se.su.dsv.scipro.match.IdeaService;
@ -85,16 +86,19 @@ public class DataInitializer implements Lifecycle {
private User stina_student;
private User sid_student;
private User simon_student;
private ProjectType bachelorClass;
private User sofia_student;
private Set<ResearchArea> researchAreas;
private Long researchAreaId = RESEARCH_AREA_ID;
private Set<Language> languages;
private ApplicationPeriod applicationPeriod;
private Keyword keyword1;
private Set<Language> languages = Set.of(Language.SWEDISH, Language.ENGLISH);
private Program program;
private ResearchArea researchArea1;
private ResearchArea researchArea2;
private Keyword keyword1;
private Keyword keyword2;
private ProjectType bachelorClass;
private ProjectType masterClass;
private ProjectType magisterClass;
private ApplicationPeriod applicationPeriod;
private Project project2;
@Transactional
@ -103,6 +107,7 @@ public class DataInitializer implements Lifecycle {
if (profile.getCurrentProfile() == Profiles.DEV && noUsers()) {
createDefaultProjectTypesIfNotDone();
createDefaultChecklistCategoriesIfNotDone();
createProgram();
createApplicationPeriodIfNotDone();
createGradingCriterionTemplateIfNotDone();
createResearchAreasForDemo();
@ -111,6 +116,8 @@ public class DataInitializer implements Lifecycle {
createUsers();
createMatchedIdea();
createProjects();
createTarget();
createStudentIdea();
createRoughDraftApproval();
}
if (profile.getCurrentProfile() == Profiles.DEV && noAdminUser()) {
@ -135,6 +142,15 @@ public class DataInitializer implements Lifecycle {
return userService.findByUsername(ADMIN + MAIL) == null;
}
private void createProgram() {
program = new Program();
program.setCode("AppCompSci");
program.setName("Tillämpad Datavetenskap");
program.setExternalId(123);
program.setNameEn("Applied Computer Science");
program = save(program);
}
private void createApplicationPeriodIfNotDone() {
applicationPeriod = new ApplicationPeriod("HT 2014");
applicationPeriod.setStartDate(LocalDate.now().minusDays(APPLICATION_PERIOD_START_MINUS_DAYS));
@ -150,12 +166,12 @@ public class DataInitializer implements Lifecycle {
keyword1 = new Keyword("IT");
keyword1.addResearchArea(researchArea1);
keyword1.addResearchArea(researchArea2);
save(keyword1);
keyword1 = save(keyword1);
Keyword keyword2 = new Keyword("Computers");
keyword2 = new Keyword("Computers");
keyword2.addResearchArea(researchArea1);
keyword2.addResearchArea(researchArea2);
save(keyword2);
keyword2 = save(keyword2);
}
private void createResearchAreasForDemo() {
@ -211,6 +227,11 @@ public class DataInitializer implements Lifecycle {
// can not be used as author on any idea
// can not be used as author on any project
createStudent("Stig");
// Used to test assign supervisor to student idea
// this student has a submitted idea, which has not assigned supervisor
// don't use this student for anything else
sofia_student = createStudent("Sofia");
}
private User createStudent(String firstName) {
@ -229,8 +250,11 @@ public class DataInitializer implements Lifecycle {
user.setUnit(u);
user.setResearchAreas(researchAreas);
user.setLanguages(languages);
user.setActiveAsSupervisor(true);
createBeta(user);
return user;
return save(user);
}
private User createUser(String firstName, String lastName) {
@ -304,6 +328,32 @@ public class DataInitializer implements Lifecycle {
save(getMagisterTemplate());
}
private void createTarget() {
Target target = new Target(eric_employee, applicationPeriod, bachelorClass);
target.setTarget(10);
save(target);
}
private void createStudentIdea() {
Idea idea = new Idea();
idea.setTitle("Fundamental Math Concepts of AI");
idea.setType(Idea.Type.STUDENT);
TholanderBox box = new TholanderBox();
box.setLiterature("Math AI Literature");
box.setBackground("Math AI Background");
box.setProblem("Math AI Problem");
box.setMethod("Math AI Method");
box.setInterests("Math AI Interests");
idea.setTholanderBox(box);
idea.setProjectType(bachelorClass);
idea.setApplicationPeriod(applicationPeriod);
List<Keyword> keywords = List.of(keyword1, keyword2);
ideaService.saveStudentIdea(idea, sofia_student, program, new HashSet<User>(), keywords, true);
}
private GradingReportTemplate getBachelorTemplate() {
GradingReportTemplate gradingReportTemplate = new GradingReportTemplate(
bachelorClass,

@ -205,17 +205,34 @@ public abstract class AbstractAdminIdeaPanel extends Panel {
ideaService.adminUnmatchIdea(idea, SciProSession.get().getUser());
info("Unmatched idea: " + idea.getTitle());
} else {
if (
targetService.hasTargetsLeft(
idea.getApplicationPeriod(),
newSelection,
idea.getProjectType()
)
) {
ideaService.changeSupervisor(idea, newSelection, SciProSession.get().getUser());
info("Supervisor changed");
ideaService.changeSupervisor(idea, newSelection, SciProSession.get().getUser());
Target currentTarget = targetService.findOne(
idea.getApplicationPeriod(),
newSelection,
idea.getProjectType()
);
Long countMatched = ideaService.countMatched(
idea.getApplicationPeriod(),
newSelection,
idea.getProjectType()
);
int targetCounter = (currentTarget == null) ? 0 : currentTarget.getTarget();
ansv7779 marked this conversation as resolved
Review

This seems weird, a count method should return 0 not null.

This seems weird, a count method should return 0 not `null`.
Review

Fine point, the unnecessary null check has been removed.

The rationale for null check is that ideaService.countMatched returning Long. It would be better that a @NotNull annotation is applied to such method which is guaranteed to return non null object.

Fine point, the unnecessary null check has been removed. The rationale for null check is that ideaService.countMatched returning Long. It would be better that a @NotNull annotation is applied to such method which is guaranteed to return non null object.
String msg =
"Supervisor changed: matched/target -> " +
countMatched +
" / " +
targetCounter +
" (" +
idea.getProjectType().getName() +
")";
if (countMatched > targetCounter) {
warn(msg);
} else {
error("The supervisor have reached current target numbers");
info(msg);
}
}
target.addListener(new AjaxFeedbackPanelUpdater());

@ -129,6 +129,12 @@ footer a:hover { color: #d95e00;}
border-color: #EBCCD1;
}
.feedbackPanelWARNING {
color: #000000;
background-color: #FFD105;
border-color: #EBCCD1;
}
.feedbackPanelINFO {
color: #3C763D;
background-color: #DFF0D8;

@ -9,6 +9,7 @@ spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.Ph
# We also need to set the implicit strategy to be JPA compliant, as we rely on this naming strategy for certain
# join tables (idea_Keyword vs idea_keyword)
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
spring.jpa.show-sql=false
spring.mvc.servlet.path=/api