diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/AppConfig.java b/buisnesslogic/src/main/java/com/plannaplan/entities/AppConfig.java index 6487691..52db7a1 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/AppConfig.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/AppConfig.java @@ -2,6 +2,8 @@ package com.plannaplan.entities; import java.sql.Date; import java.sql.Timestamp; +import java.time.LocalDate; +import java.util.TimeZone; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -11,6 +13,8 @@ import javax.persistence.Id; import com.plannaplan.models.TourData; import com.plannaplan.types.AppState; +import org.springframework.scheduling.support.CronTrigger; + /** * entity that keeps app configurations */ @@ -115,4 +119,53 @@ public class AppConfig { return AppState.NO_TOUR; } + /** + * get cron expression of first tour end + * + * @return spring cron expression + */ + public CronTrigger getFirstTourEndCron() { + return getCron(this.firstTourEnd); + } + + /** + * get cron expression of second tour end + * + * @return spring cron expression + */ + public CronTrigger getSecondTourEndCron() { + return getCron(this.secondTourEnd); + } + + /** + * get cron expression of first tour start + * + * @return spring cron expression + */ + public CronTrigger getFirstTourStartCron() { + return getCron(this.firstTourStart); + } + + /** + * get cron expression of second tour start + * + * @return spring cron expression + */ + public CronTrigger getSecondTourStartCron() { + return getCron(this.secondTourStart); + } + + /** + * create spring cron expression + * + * @param date date to create cron exp from + * @return spring cron expression. Remember that spring's cron deosn't contain + * year in it. + */ + private CronTrigger getCron(Date date) { + final LocalDate tourEnd = date.toLocalDate(); + return new CronTrigger("0 0 0 " + tourEnd.getDayOfMonth() + " " + tourEnd.getMonthValue() + " ?", + TimeZone.getTimeZone(TimeZone.getDefault().getID())); + } + } diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/Assignment.java b/buisnesslogic/src/main/java/com/plannaplan/entities/Assignment.java index 81642a6..2f0722b 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/Assignment.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/Assignment.java @@ -38,6 +38,15 @@ public class Assignment { this.group = group; } + /** + * If it returns trues it mesans u are assigned to group accepted by algorythm + * + * @return boolean isAccepted + */ + public boolean isAccepted() { + return this.group.getRegisteredStudents().contains(this.commision.getCommisionOwner()); + } + /** * Assignment * diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/Groups.java b/buisnesslogic/src/main/java/com/plannaplan/entities/Groups.java index eccbdc5..95521c6 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/Groups.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/Groups.java @@ -1,10 +1,15 @@ package com.plannaplan.entities; +import java.util.HashSet; +import java.util.Set; + import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import com.plannaplan.types.GroupType; @@ -36,23 +41,36 @@ public class Groups { private Lecturer lecturer; private Integer zajCykId; private Integer grNr; + @ManyToMany(mappedBy = "studentRegisteredGrups", fetch = FetchType.EAGER) + private Set registeredStudents; + + public Set getRegisteredStudents() { + return this.registeredStudents; + } + + public void assignUser(User user) { + if (this.registeredStudents == null) { + this.registeredStudents = new HashSet<>(); + } + this.registeredStudents.add(user); + } public Groups() { } - public Integer getGr_nr() { + public Integer getGrNr() { return grNr; } - public void setGr_nr(Integer grNr) { + public void setGrNr(Integer grNr) { this.grNr = grNr; } - public Integer getZaj_cyk_id() { + public Integer getZajCykId() { return zajCykId; } - public void setZaj_cyk_id(Integer zajCykId) { + public void setZajCykId(Integer zajCykId) { this.zajCykId = zajCykId; } diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java index 24e45bc..149880d 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java @@ -1,13 +1,19 @@ package com.plannaplan.entities; import java.sql.Timestamp; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; import com.plannaplan.models.UserApiResponse; import com.plannaplan.types.UserRoles; @@ -32,6 +38,21 @@ public class User { private String token; private String refreshToken; private Timestamp tokenUsageDate; + private Integer ranking; + @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinTable + private Set studentRegisteredGrups; + + public Set getStudentRegisteredGrups() { + return this.studentRegisteredGrups; + } + + public void claimGroup(Groups group) { + if (this.studentRegisteredGrups == null) { + this.studentRegisteredGrups = new HashSet<>(); + } + this.studentRegisteredGrups.add(group); + } public User() { } @@ -63,6 +84,21 @@ public class User { this.usosId = usosId; } + /** + * + * @param name name given to the user + * @param surname surname given to the user + * @param mail mail given to the user + * @param usosId id in the USOS system + * @param role user's role + * @param ranking ranking points [100;500]. It's calculated by + * gradesAvg*100*studiesYear + */ + public User(String name, String surname, String mail, String usosId, UserRoles role, Integer ranking) { + this(name, surname, mail, usosId, role); + this.ranking = ranking; + } + /** * usos id getter * @@ -189,6 +225,25 @@ public class User { return this.id; } + /** + * Ranking points are [100;500]. It's calculated by gradesAvg*100*studiesYear + * + * @return ranking points [100;500] + */ + public Integer getRanking() { + return ranking; + } + + /** + * Ranking points setter. Ranking points are [100;500]. It's calculated by + * gradesAvg*100*studiesYear + * + * @param ranking ranking points [100;500] + */ + public void setRanking(Integer ranking) { + this.ranking = ranking; + } + /** * updates user entity with data got by UsosApiService::getUserData * diff --git a/buisnesslogic/src/main/java/com/plannaplan/models/EmailAcceptedData.java b/buisnesslogic/src/main/java/com/plannaplan/models/EmailAcceptedData.java new file mode 100755 index 0000000..341b32b --- /dev/null +++ b/buisnesslogic/src/main/java/com/plannaplan/models/EmailAcceptedData.java @@ -0,0 +1,97 @@ +package com.plannaplan.models; + +import java.util.Iterator; +import java.util.List; + +import com.plannaplan.entities.Groups; + +/** + * Instance to keep data to send in mail about accepted courses results + */ +public class EmailAcceptedData { + private List accepted; + private List removed; + + public EmailAcceptedData() { + + } + + /** + * creates instance of class + * + * @param accepted list of groups that user joined to + * @param removed lsit of groups that user failed to join + */ + public EmailAcceptedData(List accepted, List removed) { + this.accepted = accepted; + this.removed = removed; + } + + /** + * get list of removed assignments + * + * @return removed assingments + */ + public List getRemoved() { + return removed; + } + + /** + * set list of removed assignments + * + * @param removed list of removed assignments + */ + public void setRemoved(List removed) { + this.removed = removed; + } + + /** + * get list of accepted assignments + * + * @return accepted assingments + */ + public List getAccepted() { + return accepted; + } + + /** + * set list of accepted assignments + * + * @param accepted list of accepted assignments + */ + public void setAccepted(List accepted) { + this.accepted = accepted; + } + + /** + * it creates and return email message body + * + * @return string with emiale massage + */ + public String getEmailMessage() { + String response = "Akceptacja Twoich przedmiotów właśnie dobiegła końca.\n\n"; + if (this.accepted != null && this.accepted.size() > 0) { + response += "Zatwierdzone grupy: \n"; + Iterator iterator = accepted.iterator(); + while (iterator.hasNext()) { + final Groups gorup = iterator.next(); + final String courseName = gorup.getCourseId() != null ? gorup.getCourseId().getName() + : "Nieznana grupa"; + response += (" - " + courseName + " - " + gorup.getType() + "\n"); + } + + } + if (this.removed != null && this.removed.size() > 0) { + response += "Usunięte grupy: \n"; + Iterator iterator = removed.iterator(); + while (iterator.hasNext()) { + final Groups gorup = iterator.next(); + final String courseName = gorup.getCourseId() != null ? gorup.getCourseId().getName() + : "Nieznana grupa"; + response += (" - " + courseName + " - " + gorup.getType() + "\n"); + } + + } + return response; + } +} diff --git a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java index 4c0b0ab..aea1bee 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java +++ b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java @@ -35,13 +35,13 @@ import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository { - @Query("FROM User WHERE email = ?1 OR usosId = ?1") /** * return user by given authority * * @param authority user usosId or email * @return optional with user if found */ + @Query("FROM User WHERE email = ?1 OR usosId = ?1") Optional getByAuthority(@Param("authority") String authority); @Query("FROM User WHERE email = ?1") @@ -56,7 +56,6 @@ public interface UserRepository extends JpaRepository { @Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%)") List searchForUsers(@Param("query") String query); - @Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%) AND role=?2") /** * search for user with given query * @@ -64,6 +63,7 @@ public interface UserRepository extends JpaRepository { * @param role limits results by role * @return list opf results */ + @Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%) AND role=?2") List searchForUsers(@Param("query") String query, @Param("role") UserRoles role); @Query("FROM User WHERE role=?1") diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/AssignmentService.java b/buisnesslogic/src/main/java/com/plannaplan/services/AssignmentService.java index ce21a8f..e5a8ccf 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/AssignmentService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/AssignmentService.java @@ -1,17 +1,22 @@ package com.plannaplan.services; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import com.plannaplan.entities.Assignment; import com.plannaplan.entities.Commision; +import com.plannaplan.entities.Groups; +import com.plannaplan.entities.User; +import com.plannaplan.models.EmailAcceptedData; import com.plannaplan.repositories.AssignmentRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** - * Service of Assignment which can save assignments, diplay assignments, get ammount of assigments. + * Service of Assignment which can save assignments, diplay assignments, get + * ammount of assigments. */ @Service @@ -19,11 +24,21 @@ public class AssignmentService { @Autowired private AssignmentRepository repo; + @Autowired + private CommisionService service; + + @Autowired + private UserService userService; + + @Autowired + private EmailService emailService; + public AssignmentService() { } /** * Save given assignment + * * @param assignment assignment to save * @return assignment saved assignment with database id */ @@ -31,17 +46,20 @@ public class AssignmentService { return this.repo.save(assignment); } - /* - * getCommisionAssignments - * Return id of the commision + /** + * gets list of assignments of given commision + * + * @param com Commision to get assinments from + * @return list of assignments */ public List getCommisionAssignments(Commision com) { return this.repo.getByCommision(com.getId()); } - /* - * getAssignmentsAmmount - * Return count assignments ammount + /** + * get ammount of all assignments (not only for selected commision) + * + * @return long - ammount of assingments */ public long getAssignmentsAmmount() { return this.repo.count(); @@ -49,10 +67,41 @@ public class AssignmentService { /** * Get assigmnent by id + * * @param id id of assigmnent * @return Optional of assignment */ public Optional getById(Long id) { return this.repo.findById(id); } + + /** + * this method will activate accept algorythm for all students. Algorythm is + * takeing each student in order defined by ranking and accept for him groups + * that are joinable for him + */ + public void callAcceptAlgorythm() { + final List students = this.userService.getStudentsSortedByRanking(); + + students.forEach(e -> { + final Optional com = this.service.getNewestCommision(e); + final List accepted = new ArrayList<>(); + final List removed = new ArrayList<>(); + + if (com.isPresent()) { + final List assignments = this.getCommisionAssignments(com.get()); + assignments.forEach(a -> { + final Groups group = a.getGroup(); + if (group.getCapacity() > group.getRegisteredStudents().size()) { + e.claimGroup(group); + accepted.add(group); + } else { + removed.add(group); + } + }); + } + this.userService.save(e); + this.emailService.sendAcceptationResult(e, new EmailAcceptedData(accepted, removed)); + }); + } } diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/CommisionService.java b/buisnesslogic/src/main/java/com/plannaplan/services/CommisionService.java index 63d4c4f..109dfd4 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/CommisionService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/CommisionService.java @@ -12,7 +12,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** - * Service of CommisionService which can save commision, get user's commisions, get newest user's commision, get ammount of commisions. + * Service of CommisionService which can save commision, get user's commisions, + * get newest user's commision, get ammount of commisions. */ @Service @@ -25,12 +26,6 @@ public class CommisionService { public CommisionService() { } - /* - * save - * - * @param commision which assignment should be save in service - * @return commision - */ public Commision save(Commision commision) { Optional lastCommision = this.getNewestCommision(commision.getCommisionOwner()); if (lastCommision.isPresent()) { @@ -45,25 +40,31 @@ public class CommisionService { } - /* - * getUsersCommisions - * Return given users id + /** + * gets user commisions + * + * @param user owner of commisions + * @return list of user commisions */ public List getUsersCommisions(User user) { return this.repo.getUsers(user.getId()); } - /* - * getNewestCommision - * Return the newest commision of the user + /** + * get newest commision ov given user + * + * @param user owener of commision we attemp to get + * @return optional if commition was found */ public Optional getNewestCommision(User user) { return this.repo.getNewestCommision(user.getId()).stream().findFirst(); } - /* - * getCommisionsAmmount - * Return ammount of commisions + /** + * get ammpounts of commisions + * + * @return long - ammounts of commisions (all even from history, not only + * cutrrent one) */ public long getCommisionsAmmount() { return this.repo.count(); diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/ConfiguratorService.java b/buisnesslogic/src/main/java/com/plannaplan/services/ConfiguratorService.java index baa7510..6d045c8 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/ConfiguratorService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/ConfiguratorService.java @@ -9,6 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.InputStream; +import java.sql.Date; +import java.time.LocalDate; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -26,29 +28,40 @@ public class ConfiguratorService { private FileToDatabaseMigrator migrator; @Autowired private AppConfigRepository configRepo; + @Autowired + private EventService eventService; + @Autowired + private AssignmentService assignmentService; public ConfiguratorService() { } /** - * methoid to config system + * methoid to config system. it shedules PerformAcceptAlgorythmTask as a side + * effect * * @param data ConfigData containng system configs */ public void config(ConfigData data) { FileReader reader = new FileReader(data.getFilestream()); FileData coursesData = reader.read(); - this.configRepo.save(new AppConfig(data.getFirstTour(), data.getSecondTour())); + final AppConfig config = new AppConfig(data.getFirstTour(), data.getSecondTour()); + this.configRepo.save(config); migrator.migrate(coursesData); + this.shceduleTaskAfterToursDateChange(config); } /** - * Save tours to DataBase - * @param firstTour First tour period. + * Save tours to DataBase and shedule PerformAcceptAlgorythmTask as a side + * effect + * + * @param firstTour First tour period. * @param secondTour Second tour period. */ public void saveTours(TourData firstTour, TourData secondTour) { - this.configRepo.save(new AppConfig(firstTour, secondTour)); + final AppConfig config = new AppConfig(firstTour, secondTour); + this.configRepo.save(config); + this.shceduleTaskAfterToursDateChange(config); } /** @@ -78,9 +91,46 @@ public class ConfiguratorService { * * @param inputStream This input stream contains new courses to import. */ - public void importCoursesStream(InputStream inputStream) { + public void importCoursesStream(InputStream inputStream) { FileReader reader = new FileReader(inputStream); FileData coursesData = reader.read(); migrator.migrate(coursesData); } + + private void shceduleTaskAfterToursDateChange(AppConfig config) { + + this.eventService.scheduleTask(EventService.FIRST_TOUR_SCHEDULE, + new AlgorythmAcceptTask(config.getFirstTourEnd()), config.getFirstTourEndCron()); + + this.eventService.scheduleTask(EventService.SECOND_TOUR_SCHEDULE, + new AlgorythmAcceptTask(config.getSecondTourEnd()), config.getSecondTourEndCron()); + } + + /** + * It's local class to perform accept Task. It's needed to be here due to have + * acces to AssignmentService. + */ + private class AlgorythmAcceptTask implements Runnable { + + private LocalDate localDate; + + /** + * create instance of AlgorythmAcceptTask + * + * @param date date of algorythm perform. Needed to check if ti's being called + * in correct year + */ + public AlgorythmAcceptTask(Date date) { + this.localDate = date.toLocalDate(); + } + + @Override + public void run() { + if (localDate.getYear() == LocalDate.now().getYear()) { + assignmentService.callAcceptAlgorythm(); + } + + } + + } } \ No newline at end of file diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/EmailService.java b/buisnesslogic/src/main/java/com/plannaplan/services/EmailService.java index a26495e..cfa0bee 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/EmailService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/EmailService.java @@ -1,5 +1,8 @@ package com.plannaplan.services; +import com.plannaplan.entities.User; +import com.plannaplan.models.EmailAcceptedData; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.SimpleMailMessage; @@ -35,4 +38,20 @@ public class EmailService { mailMessage.setText(message); emailSender.send(mailMessage); } + + /** + * sends email with infromation about accepted groups + * + * @param user user to send a mail + * @param data EmailAcceptedData instance containing informations about accepted + * and removed groups + */ + public void sendAcceptationResult(User user, EmailAcceptedData data) { + SimpleMailMessage mailMessage = new SimpleMailMessage(); + mailMessage.setFrom(appEmail); + mailMessage.setTo(user.getEmail()); + mailMessage.setSubject("[PlanNaPlan] Akceptacja przedmiotów"); + mailMessage.setText(data.getEmailMessage()); + emailSender.send(mailMessage); + } } diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java b/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java index 7569bd0..b70af1b 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java @@ -1,17 +1,51 @@ package com.plannaplan.services; -// import org.springframework.beans.factory.annotation.Autowired; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; + +import javax.annotation.PostConstruct; + import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Service; @Service public class EventService { - // @Autowired - // private EmailService emailService; + public static final int FIRST_TOUR_SCHEDULE = 0; + public static final int SECOND_TOUR_SCHEDULE = 1; - @Scheduled(cron = "0 2 17 * * *") + private ThreadPoolTaskScheduler scheduler; + private Map> jobsMap = new HashMap<>(); + + @Scheduled(cron = "0 24 17 * * *") public void collectGroupLosses() { System.out.println("Checking for groups"); } + + /** + * Schedule provided task to perform + * + * @param taskId static filed of this class that represents to what event + * we want to assign task + * @param task runnable class that perform task in implemented run method + * @param cronTrigger CronTrigger instance with date to perform + */ + public void scheduleTask(int taskId, Runnable task, CronTrigger cronTrigger) { + ScheduledFuture scheduledTask = jobsMap.get(taskId); + if (scheduledTask != null) { + scheduledTask.cancel(true); + jobsMap.put(taskId, null); + } + scheduledTask = this.scheduler.schedule(task, cronTrigger); + jobsMap.put(taskId, scheduledTask); + } + + @PostConstruct + public void initialize() { + this.scheduler = new ThreadPoolTaskScheduler(); + this.scheduler.initialize(); + } } diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java index 16de2d8..64cbe9d 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java @@ -3,6 +3,7 @@ package com.plannaplan.services; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; import com.plannaplan.entities.User; import com.plannaplan.exceptions.UserNotFoundException; @@ -153,4 +154,19 @@ public class UserService { return this.repo.getAllByRole(UserRoles.ADMIN).size() > 0; } + public void saveAll(List users) { + this.repo.saveAll(users); + } + + /** + * get students sorted by their ranking + * + * @return list of students + */ + public List getStudentsSortedByRanking() { + return this.repo.getAllByRole(UserRoles.STUDENT).stream().sorted((u1, u2) -> { + return -1 * u1.getRanking().compareTo(u2.getRanking()); + }).collect(Collectors.toList()); + } + } \ No newline at end of file diff --git a/buisnesslogic/src/test/java/com/plannaplan/entities/AppConfigTest.java b/buisnesslogic/src/test/java/com/plannaplan/entities/AppConfigTest.java index a280c22..2d8f64f 100755 --- a/buisnesslogic/src/test/java/com/plannaplan/entities/AppConfigTest.java +++ b/buisnesslogic/src/test/java/com/plannaplan/entities/AppConfigTest.java @@ -138,4 +138,52 @@ public class AppConfigTest { assertTrue(config.getCurrentState() == AppState.SECOND_TOUR); } + @Test + public void shouldReturnFirstStartDatesCorns() { + final Date firtstTourStart = Date.valueOf("2020-11-12"); + final Date firtstTourEnd = Date.valueOf("2020-11-13"); + final Date secondTourStart = Date.valueOf("2020-11-14"); + final Date secondTourEnd = Date.valueOf("2020-11-15"); + + final AppConfig config = new AppConfig(new TourData(firtstTourStart, firtstTourEnd), + new TourData(secondTourStart, secondTourEnd)); + assertTrue(config.getFirstTourStartCron().getExpression().equals("0 0 0 12 11 ?")); + } + + @Test + public void shouldReturnSecondStartDatesCorns() { + final Date firtstTourStart = Date.valueOf("2020-11-12"); + final Date firtstTourEnd = Date.valueOf("2020-11-13"); + final Date secondTourStart = Date.valueOf("2020-11-14"); + final Date secondTourEnd = Date.valueOf("2020-11-15"); + + final AppConfig config = new AppConfig(new TourData(firtstTourStart, firtstTourEnd), + new TourData(secondTourStart, secondTourEnd)); + assertTrue(config.getSecondTourStartCron().getExpression().equals("0 0 0 14 11 ?")); + } + + @Test + public void shouldReturnFirstEndDatesCorns() { + final Date firtstTourStart = Date.valueOf("2020-11-12"); + final Date firtstTourEnd = Date.valueOf("2020-11-13"); + final Date secondTourStart = Date.valueOf("2020-11-14"); + final Date secondTourEnd = Date.valueOf("2020-11-15"); + + final AppConfig config = new AppConfig(new TourData(firtstTourStart, firtstTourEnd), + new TourData(secondTourStart, secondTourEnd)); + assertTrue(config.getFirstTourEndCron().getExpression().equals("0 0 0 13 11 ?")); + } + + @Test + public void shouldReturnSecondEndDatesCorns() { + final Date firtstTourStart = Date.valueOf("2020-11-12"); + final Date firtstTourEnd = Date.valueOf("2020-11-13"); + final Date secondTourStart = Date.valueOf("2020-11-14"); + final Date secondTourEnd = Date.valueOf("2020-11-15"); + + final AppConfig config = new AppConfig(new TourData(firtstTourStart, firtstTourEnd), + new TourData(secondTourStart, secondTourEnd)); + assertTrue(config.getSecondTourEndCron().getExpression().equals("0 0 0 15 11 ?")); + } + } diff --git a/buisnesslogic/src/test/java/com/plannaplan/services/AssignmentServiceTest.java b/buisnesslogic/src/test/java/com/plannaplan/services/AssignmentServiceTest.java index 1f4bb31..efe00fa 100755 --- a/buisnesslogic/src/test/java/com/plannaplan/services/AssignmentServiceTest.java +++ b/buisnesslogic/src/test/java/com/plannaplan/services/AssignmentServiceTest.java @@ -2,18 +2,27 @@ package com.plannaplan.services; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.MethodMode; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.stream.IntStream; import com.plannaplan.entities.Assignment; import com.plannaplan.entities.Commision; +import com.plannaplan.entities.Groups; import com.plannaplan.entities.User; import com.plannaplan.types.UserRoles; +import com.plannaplan.types.WeekDay; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,6 +38,8 @@ public class AssignmentServiceTest { private CommisionService comServie; @Autowired private UserService userService; + @Autowired + private GroupService groupService; @Test public void shouldSaveAssignment() { @@ -56,6 +67,70 @@ public class AssignmentServiceTest { assertTrue("Returned list size should be 1", response.size() == 1); } + @Test + @Ignore + @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) + public void shouldPerformAcceptAlgorythm() { + final Random generator = new Random(); + + final List groups = new ArrayList<>(); + + IntStream.range(0, 418).forEach(i -> { + groups.add(this.groupService.save(new Groups(generator.nextInt(80) + 20, null, null, + generator.nextInt(9) * 30 + 9 * 30, WeekDay.getDay(generator.nextInt(5)), null))); + }); + + IntStream.range(0, 1700).forEach(i -> { + final User user = this.userService.save(new User(null, null, + "shouldPerformAcceptAlgorythm-" + UUID.randomUUID().toString() + "@AssignmentService.test", null, + UserRoles.STUDENT, generator.nextInt(400) + 100)); + final Commision com = this.comServie.save(new Commision(user)); + IntStream.range(0, 5).forEach(j -> { + this.service.save(new Assignment(groups.get(generator.nextInt(groups.size())), com)); + }); + }); + this.service.callAcceptAlgorythm(); + } + + /** + * This test will also sand a mail to users as a side effect. U can check them + * in mailcater + */ + @Test + @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) + public void shouldNotAcceptForOnePerson() { + final Random generator = new Random(); + final Groups group = this.groupService.save(new Groups(5, null, null, 840, WeekDay.MONDAY, null)); + + IntStream.range(0, 6).forEach(i -> { + final User user = this.userService.save(new User(null, null, + "shouldNotAcceptForOnePerson-" + UUID.randomUUID().toString() + "@AssignmentService.test", null, + UserRoles.STUDENT, generator.nextInt(400) + 100)); + + final Commision com = this.comServie.save(new Commision(user)); + + this.service.save(new Assignment(group, com)); + }); + + this.service.callAcceptAlgorythm(); + + final List users = this.userService.getStudentsSortedByRanking(); + final User loser = users.get(users.size() - 1); + + assertTrue(loser.getStudentRegisteredGrups().size() == 0); + + users.forEach(u -> { + final Commision com = this.comServie.getNewestCommision(u).get(); + final List assignments = com.getAssignments(); + if (u.getId() == loser.getId()) { + assertTrue(!assignments.get(0).isAccepted()); + } else { + assertTrue(assignments.get(0).isAccepted()); + } + }); + + } + private void addAssignmentToCommision(Commision com) { Assignment a = new Assignment(null, com); this.service.save(a); diff --git a/buisnesslogic/src/test/java/com/plannaplan/services/ConfiguratorServiceTest.java b/buisnesslogic/src/test/java/com/plannaplan/services/ConfiguratorServiceTest.java index d69754d..4e299d1 100755 --- a/buisnesslogic/src/test/java/com/plannaplan/services/ConfiguratorServiceTest.java +++ b/buisnesslogic/src/test/java/com/plannaplan/services/ConfiguratorServiceTest.java @@ -10,8 +10,11 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertTrue; import java.io.InputStream; +import java.lang.reflect.Field; import java.sql.Date; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ScheduledFuture; import com.plannaplan.TestApplication; import com.plannaplan.entities.AppConfig; @@ -46,6 +49,9 @@ public class ConfiguratorServiceTest { @Autowired private AppConfigRepository appConfigRepo; + @Autowired + private EventService eventService; + @Test public void shouldImportDataToDataBase() { final InputStream inputStream = getClass().getClassLoader() @@ -66,20 +72,20 @@ public class ConfiguratorServiceTest { @Test @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) - public void shouldUpdatePreviousImport(){ + public void shouldUpdatePreviousImport() { final InputStream inputStream = getClass().getClassLoader() - .getResourceAsStream(ConfiguratorServiceTest.BEFORE_UPDATE_FILE); + .getResourceAsStream(ConfiguratorServiceTest.BEFORE_UPDATE_FILE); this.configuratorService.importCoursesStream(inputStream); int groups_ammount = this.groupService.getGroupsAmmount(); - + assertTrue(groups_ammount == 2); final InputStream inputStream2 = getClass().getClassLoader() - .getResourceAsStream(ConfiguratorServiceTest.AFTER_UPDATE_FILE); + .getResourceAsStream(ConfiguratorServiceTest.AFTER_UPDATE_FILE); this.configuratorService.importCoursesStream(inputStream2); int groups_ammount2 = this.groupService.getGroupsAmmount(); - Optional newGroup = this.groupService.find(456458, 3); + Optional newGroup = this.groupService.find(456458, 3); Optional updateGroup = this.groupService.find(456457, 2); assertTrue(groups_ammount2 == 3); @@ -101,4 +107,28 @@ public class ConfiguratorServiceTest { } + @Test + @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) + public void shlouldScheduleTaskWhenSetTourDate() + throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + final InputStream inputStream = getClass().getClassLoader() + .getResourceAsStream(TestApplication.TEST_CONFIG_FILE); + final ConfigData data = new ConfigData( + new TourData(new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + 86400000)), + new TourData(new Date(System.currentTimeMillis() + 86400000), + new Date(System.currentTimeMillis() + 2 * 86400000)), + inputStream); + this.configuratorService.config(data); + + final Field reader = EventService.class.getDeclaredField("jobsMap"); + reader.setAccessible(true); + + @SuppressWarnings("unchecked") + final Map> map = (Map>) reader.get(this.eventService); + + assertTrue(map.size() == 2); + assertTrue(map.get(EventService.FIRST_TOUR_SCHEDULE).isDone() == false); + assertTrue(map.get(EventService.SECOND_TOUR_SCHEDULE).isDone() == false); + } + } diff --git a/restservice/src/main/java/com/plannaplan/App.java b/restservice/src/main/java/com/plannaplan/App.java index d77366b..5369a49 100755 --- a/restservice/src/main/java/com/plannaplan/App.java +++ b/restservice/src/main/java/com/plannaplan/App.java @@ -2,6 +2,7 @@ package com.plannaplan; import java.io.InputStream; import java.sql.Date; +import java.util.Random; import com.plannaplan.models.ConfigData; import com.plannaplan.models.TourData; @@ -30,7 +31,7 @@ public class App { private ConfiguratorService contrl; @Autowired - UserService userService; + private UserService userService; @Value("${plannaplan.dev}") private boolean isDev; @@ -52,10 +53,11 @@ public class App { System.out.println(Logo.getInitInfo(isDev)); if (this.isDev) { - InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Zajecia.xlsx"); - ConfigData data = new ConfigData( - new TourData(new Date(System.currentTimeMillis()), - new Date(System.currentTimeMillis() + 86400000)), + final Random generator = new Random(); + final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Zajecia.xlsx"); + final ConfigData data = new ConfigData( + new TourData(new Date(System.currentTimeMillis() - 86400000), + new Date(System.currentTimeMillis())), new TourData(new Date(System.currentTimeMillis() + 86400000), new Date(System.currentTimeMillis() + 2 * 86400000)), inputStream); @@ -65,6 +67,7 @@ public class App { newuser.setEmail("tommy@st.amu.edu.pl"); newuser.setName("Tomek"); newuser.setSurname("Atomek"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -72,6 +75,7 @@ public class App { newuser.setEmail("robercik@st.amu.edu.pl"); newuser.setName("Robert"); newuser.setSurname("Głowacki"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -79,6 +83,7 @@ public class App { newuser.setEmail("mewa@st.amu.edu.pl"); newuser.setName("Poznanska"); newuser.setSurname("Mewa"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -86,6 +91,7 @@ public class App { newuser.setEmail("tkul2@st.amu.edu.pl"); newuser.setName("Tomasz"); newuser.setSurname("Kula"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -93,6 +99,7 @@ public class App { newuser.setEmail("annana@st.amu.edu.pl"); newuser.setName("Anna"); newuser.setSurname("Na"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -100,6 +107,7 @@ public class App { newuser.setEmail("mnart@st.amu.edu.pl"); newuser.setName("Marta"); newuser.setSurname("Narta"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -107,6 +115,7 @@ public class App { newuser.setEmail("zmineniane@st.amu.edu.pl"); newuser.setName("Tutaj"); newuser.setSurname("Koncza"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -114,6 +123,7 @@ public class App { newuser.setEmail("mi@st.amu.edu.pl"); newuser.setName("Mi"); newuser.setSurname("Sie"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); @@ -121,11 +131,13 @@ public class App { newuser.setEmail("pms@st.amu.edu.pl"); newuser.setName("Pomysly"); newuser.setSurname("Sad"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); newuser = new User(); newuser.setEmail("iamnull@st.amu.edu.pl"); + newuser.setRanking(generator.nextInt(400) + 100); newuser.setRole(UserRoles.STUDENT); this.userService.save(newuser); }