diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java index 4ff5a389..c9a11bbd 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java @@ -2,6 +2,7 @@ import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.Group; +import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.service.FileService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -16,17 +17,21 @@ public class GroupAdapter { private FileService fileService; - public Group toModel(final GroupDto dto) { + public Group toModel(GroupDto dto, User user) { return Group.builder() .id(dto.getId()) .name(dto.getName()) .description(dto.getDescription()) .createdAt(dto.getCreatedAt()) + .valid(dto.isValid()) + .user(user) .build(); } public GroupDto toDto(Group model) { final String imageUrl = model.getImage() != null ? fileService.buildFileUri(model.getImage().getObjectKey()) : DEFAULT_GROUP_IMAGE_URI; + final String username = model.getUser() != null ? model.getUser().getUsername() : ""; + final Long userId = model.getUser() != null ? model.getUser().getId() : null; return GroupDto.builder() .id(model.getId()) .name(model.getName()) @@ -34,6 +39,9 @@ public GroupDto toDto(Group model) { .description(model.getDescription()) .createdAt(model.getCreatedAt()) .imageUrl(imageUrl) + .valid(model.isValid()) + .username(username) + .userId(userId) .build(); } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java index f6a3e1a1..96dd51e9 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java @@ -30,6 +30,7 @@ public JobPostingDto toDto(JobPosting model) { .createdAt(model.getCreatedAt()) .archive(model.isArchive()) .businessSector(model.getBusinessSector()) + .valid(model.isValid()) .build(); } @@ -50,6 +51,7 @@ public JobPosting toModel(JobPostingDto dto) { .businessSector(dto.getBusinessSector()) .createdAt(dto.getCreatedAt()) .archive(dto.isArchive()) + .valid(dto.isValid()) .build(); } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java index 6ff5f1c0..2fd86bcb 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java @@ -1,6 +1,7 @@ package com.dynonuggets.refonteimplicaction.controller; import com.dynonuggets.refonteimplicaction.dto.GroupDto; +import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.service.GroupService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -40,15 +41,15 @@ public ResponseEntity createSubreddit(@RequestBody GroupDto group) { return ResponseEntity.status(CREATED).body(saveDto); } - @GetMapping - public ResponseEntity> getAll( + @GetMapping(GET_VALIDATED_GROUPS_URI) + public ResponseEntity> getAllValidGroups( @RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "rows", defaultValue = "10") int rows, @RequestParam(value = "sortBy", defaultValue = "id") String sortBy, @RequestParam(value = "sortOrder", defaultValue = "ASC") String sortOrder ) { Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); - Page subredditDtos = groupService.getAll(pageable); + Page subredditDtos = groupService.getAllValidGroups(pageable); return ResponseEntity.ok(subredditDtos); } @@ -63,4 +64,22 @@ public ResponseEntity> subscribeGroup(@PathVariable final String final List groupDtos = groupService.addGroup(groupName); return ResponseEntity.ok(groupDtos); } + + @GetMapping(GET_PENDING_GROUP_URI) + public ResponseEntity> getAllPendingGroups( + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "rows", defaultValue = "10") int rows, + @RequestParam(value = "sortBy", defaultValue = "id") String sortBy, + @RequestParam(value = "sortOrder", defaultValue = "ASC") String sortOrder + ) { + Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); + Page pendingGroups = groupService.getAllPendingGroups(pageable); + return ResponseEntity.ok(pendingGroups); + } + + @PatchMapping(VALIDATE_GROUP_URI) + public ResponseEntity validateGroup(@RequestBody final Group group) { + groupService.validateGroup(group); + return ResponseEntity.ok().build(); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java index 9d9c522c..8ec0708d 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java @@ -2,6 +2,7 @@ import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; import com.dynonuggets.refonteimplicaction.exception.ImplicactionException; +import com.dynonuggets.refonteimplicaction.model.JobPosting; import com.dynonuggets.refonteimplicaction.service.JobPostingService; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -43,7 +44,23 @@ public ResponseEntity> getAllByCriteria( Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); final boolean applyCheck = Boolean.parseBoolean(checkApplyAsString); final Boolean isArchive = StringUtils.isNotBlank(archiveAsString) ? Boolean.parseBoolean(archiveAsString) : null; - Page jobPostingDtos = jobPostingService.getAllWithCriteria(pageable, search, contractType, isArchive, applyCheck); + Page jobPostingDtos = jobPostingService.getAllWithCriteria(pageable, search, contractType, isArchive, applyCheck, null); + return ResponseEntity.ok(jobPostingDtos); + } + + @GetMapping(VALIDATED_JOBS) + public ResponseEntity> getAllActiveByCriteria( + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "rows", defaultValue = "10") int rows, + @RequestParam(value = "sortBy", defaultValue = "id") String sortBy, + @RequestParam(value = "sortOrder", defaultValue = "ASC") String sortOrder, + @RequestParam(value = "search", defaultValue = "") String search, + @RequestParam(value = "contractType", required = false) String contractType, + @RequestParam(value = "archive", required = false) String archiveAsString + ) { + Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); + final Boolean isArchive = StringUtils.isNotBlank(archiveAsString) ? Boolean.parseBoolean(archiveAsString) : null; + Page jobPostingDtos = jobPostingService.getAllActiveWithCriteria(pageable, search, contractType, isArchive); return ResponseEntity.ok(jobPostingDtos); } @@ -76,4 +93,20 @@ public ResponseEntity> toggleArchiveJobs(@RequestBody final List updated = jobPostingService.toggleArchiveAll(jobsId); return ResponseEntity.ok(updated); } + + @GetMapping(GET_PENDING_JOB_URI) + public ResponseEntity> getAllPendingJobs( + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "rows", defaultValue = "10") int rows + ) { + Pageable pageable = PageRequest.of(page, rows); + Page pendingJobs = jobPostingService.getAllPendingJobs(pageable); + return ResponseEntity.ok(pendingJobs); + } + + @PatchMapping(VALIDATE_JOB_URI) + public ResponseEntity validateJob(@RequestBody final JobPosting job) { + jobPostingService.validateJob(job); + return ResponseEntity.ok().build(); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java index 355de990..9b8172b9 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java @@ -18,5 +18,8 @@ public class GroupDto { private Integer numberOfPosts; private String imageUrl; private Instant createdAt; + private boolean valid; private List users; + private String username; + private Long userId; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java index 3c2270e2..c0fa0bb3 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java @@ -28,5 +28,6 @@ public class JobPostingDto { private Instant createdAt; private boolean archive; private boolean apply; + private boolean valid; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java index 0ce3cd84..1cbc4671 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java @@ -42,4 +42,7 @@ public class Group { @ManyToMany(fetch = FetchType.LAZY, cascade = ALL, mappedBy = "groups") private List users; + + @Column(name = "valid") + private boolean valid; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java index 648d6181..982d526e 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java @@ -54,4 +54,7 @@ public class JobPosting { @Column(columnDefinition = "boolean default false") private boolean archive; + + @Column(name = "valid") + private boolean valid; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java index 682f5e41..c1020f3a 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java @@ -1,6 +1,7 @@ package com.dynonuggets.refonteimplicaction.repository; import com.dynonuggets.refonteimplicaction.model.Group; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -13,4 +14,8 @@ public interface GroupRepository extends JpaRepository { List findAllByTopPosting(Pageable pageable); Optional findByName(String name); + + Page findAllByValidIsFalse(Pageable pageable); + + Page findAllByValidIsTrue(Pageable pageable); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java index 9c3b5c03..c4d84042 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java @@ -1,10 +1,12 @@ package com.dynonuggets.refonteimplicaction.repository; import com.dynonuggets.refonteimplicaction.model.JobPosting; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface JobPostingRepository extends JpaRepository, JobPostingRepositoryCustom { - + Page findAllByValidIsFalse(Pageable pageable); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepositoryCustom.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepositoryCustom.java index 7c6a7b18..5f8e9046 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepositoryCustom.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepositoryCustom.java @@ -10,8 +10,9 @@ public interface JobPostingRepositoryCustom { * @param pageable l'objet de pagination * @param search la chaîne de caratères à rechercher dans les champs title, description, keywords * @param contractType le type de contrat à rechercher (CDD, CDI) + * @param valid la validation de l'offre par l'administrateur * @return la liste de résultats paginée des JobPostings correspondant aux critères */ - Page findAllWithCriteria(final Pageable pageable, final String search, final String contractType, final Boolean archive); + Page findAllWithCriteria(final Pageable pageable, final String search, final String contractType, final Boolean archive, Boolean valid); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/impl/JobPostingRepositoryImpl.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/impl/JobPostingRepositoryImpl.java index b6e0e9cf..99286712 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/impl/JobPostingRepositoryImpl.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/impl/JobPostingRepositoryImpl.java @@ -24,7 +24,7 @@ public class JobPostingRepositoryImpl implements JobPostingRepositoryCustom { private final EntityManager entityManager; @Override - public Page findAllWithCriteria(Pageable pageable, String search, String contractType, Boolean archive) { + public Page findAllWithCriteria(Pageable pageable, String search, String contractType, Boolean archive, Boolean valid) { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery query = criteriaBuilder.createQuery(JobPosting.class); Root queryRoot = query.from(JobPosting.class); @@ -52,6 +52,11 @@ public Page findAllWithCriteria(Pageable pageable, String search, St if (archive != null) { predicates.add(criteriaBuilder.equal(queryRoot.get("archive"), archive)); } + + if (valid != null) { + predicates.add(criteriaBuilder.equal(queryRoot.get("valid"), valid)); + } + // combinaison des différents prédicats Predicate finalPredicate = criteriaBuilder.and(predicates.toArray(new Predicate[0])); diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java index 0b510512..dab25ec9 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java @@ -3,6 +3,7 @@ import com.dynonuggets.refonteimplicaction.adapter.GroupAdapter; import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.exception.NotFoundException; +import com.dynonuggets.refonteimplicaction.exception.UserNotFoundException; import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.User; @@ -20,6 +21,7 @@ import java.util.List; import static com.dynonuggets.refonteimplicaction.utils.Message.GROUP_NOT_FOUND_MESSAGE; +import static com.dynonuggets.refonteimplicaction.utils.Message.USER_NOT_FOUND_MESSAGE; import static java.util.stream.Collectors.toList; @Service @@ -37,8 +39,9 @@ public class GroupService { public GroupDto save(MultipartFile image, GroupDto groupDto) { final FileModel fileModel = cloudService.uploadImage(image); final FileModel fileSave = fileRepository.save(fileModel); - - Group group = groupAdapter.toModel(groupDto); + User user = userRepository.findById(groupDto.getUserId()) + .orElseThrow(() -> new UserNotFoundException(String.format(USER_NOT_FOUND_MESSAGE, groupDto.getUserId()))); + Group group = groupAdapter.toModel(groupDto, user); group.setImage(fileSave); group.setCreatedAt(Instant.now()); group.setUser(authService.getCurrentUser()); @@ -50,7 +53,9 @@ public GroupDto save(MultipartFile image, GroupDto groupDto) { @Transactional public GroupDto save(GroupDto groupDto) { - Group group = groupAdapter.toModel(groupDto); + User user = userRepository.findById(groupDto.getUserId()) + .orElseThrow(() -> new UserNotFoundException(String.format(USER_NOT_FOUND_MESSAGE, groupDto.getUserId()))); + Group group = groupAdapter.toModel(groupDto, user); group.setCreatedAt(Instant.now()); group.setUser(authService.getCurrentUser()); final Group save = groupRepository.save(group); @@ -58,8 +63,8 @@ public GroupDto save(GroupDto groupDto) { } @Transactional(readOnly = true) - public Page getAll(Pageable pageable) { - final Page subreddits = groupRepository.findAll(pageable); + public Page getAllValidGroups(Pageable pageable) { + final Page subreddits = groupRepository.findAllByValidIsTrue(pageable); return subreddits.map(groupAdapter::toDto); } @@ -82,4 +87,16 @@ public List addGroup(String groupName) { .map(groupAdapter::toDto) .collect(toList()); } + + @Transactional + public Page getAllPendingGroups(Pageable pageable) { + return groupRepository.findAllByValidIsFalse(pageable) + .map(groupAdapter::toDto); + } + + @Transactional + public void validateGroup(Group group) { + group.setValid(true); + groupRepository.save(group); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java index 9d4e75b0..feaada3f 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java @@ -49,9 +49,9 @@ public JobPostingDto getJobById(Long jobId) { return jobDto; } - public Page getAllWithCriteria(Pageable pageable, String search, String contractType, Boolean archive, boolean applyCheck) { + public Page getAllWithCriteria(Pageable pageable, String search, String contractType, Boolean archive, boolean applyCheck, Boolean valid) { // récupération des jobs - final Page jobs = jobPostingRepository.findAllWithCriteria(pageable, search, contractType, archive); + final Page jobs = jobPostingRepository.findAllWithCriteria(pageable, search, contractType, archive, valid); if (applyCheck) { final List jobIds = jobs.stream().map(JobPosting::getId).collect(toList()); final List jobAppliesIds = getAllAppliesWithJobIdsIn(jobIds, authService.getCurrentUser().getId()); @@ -103,4 +103,20 @@ public List toggleArchiveAll(List jobsId) { .map(jobPostingAdapter::toDto) .collect(Collectors.toList()); } + + @Transactional + public Page getAllPendingJobs(Pageable pageable) { + return jobPostingRepository.findAllByValidIsFalse(pageable) + .map(jobPostingAdapter::toDto); + } + + @Transactional + public void validateJob(JobPosting job) { + job.setValid(true); + jobPostingRepository.save(job); + } + + public Page getAllActiveWithCriteria(Pageable pageable, String search, String contractType, Boolean isArchive) { + return this.getAllWithCriteria(pageable, search, contractType, isArchive, true, true); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java index 722b7aee..b316d142 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java @@ -19,6 +19,9 @@ public class ApiUrls { public static final String DELETE_JOB_URI = "/{jobId}"; public static final String ARCHIVE_JOB_URI = "/{jobId}/archive"; public static final String ARCHIVE_JOBS_URI = "/archive"; + public static final String GET_PENDING_JOB_URI = "/pending"; + public static final String VALIDATE_JOB_URI = "/validate"; + public static final String VALIDATED_JOBS = "/validated"; // POSTS public static final String POSTS_BASE_URI = "/api/posts"; @@ -29,6 +32,9 @@ public class ApiUrls { public static final String GROUPS_BASE_URI = "/api/groups"; public static final String GET_ALL_BY_TOP_POSTING_URI = "/top-posting"; public static final String CREATE_NO_IMAGE = "/no-image"; + public static final String GET_PENDING_GROUP_URI = "/pending"; + public static final String VALIDATE_GROUP_URI = "/validate"; + public static final String GET_VALIDATED_GROUPS_URI = "/validated"; public static final String SUBSCRIBE_GROUP = "/{groupName}/subscribe"; // COMMENTS diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java index e816091f..09c48ff8 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java @@ -4,6 +4,8 @@ import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.Post; +import com.dynonuggets.refonteimplicaction.model.User; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.FileService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,6 +29,9 @@ class GroupAdapterTest { @InjectMocks GroupAdapter groupAdapter; + @Mock + UserRepository userRepository; + @Test void should_map_to_model() { // given @@ -34,10 +39,17 @@ void should_map_to_model() { .id(123L) .description("blablabla") .name("blabla") + .userId(1L) + .username("test") + .build(); + + User user = User.builder() + .id(1L) + .username("test") .build(); // when - final Group actual = groupAdapter.toModel(expected); + final Group actual = groupAdapter.toModel(expected, user); // then assertThat(actual.getId()).isEqualTo(expected.getId()); @@ -49,12 +61,18 @@ void should_map_to_model() { @Test void should_map_to_dto_with_count_when_model_has_posts() { // given + User user = User.builder() + .id(1L) + .username("test") + .build(); + Group expectedModel = Group.builder() .id(123L) .description("blablabla") .name("blabla") .posts(Arrays.asList(new Post(), new Post(), new Post(), new Post())) .createdAt(Instant.now()) + .user(user) .build(); // when @@ -62,22 +80,30 @@ void should_map_to_dto_with_count_when_model_has_posts() { // then assertThat(actualDto).usingRecursiveComparison() - .ignoringFields("user", "posts", "numberOfPosts", "imageUrl") + .ignoringFields("user", "posts", "numberOfPosts", "imageUrl", "username", "userId") .isEqualTo(expectedModel); assertThat(actualDto.getNumberOfPosts()).isEqualTo(expectedModel.getPosts().size()); assertThat(actualDto.getImageUrl()).isEqualTo(GroupAdapter.DEFAULT_GROUP_IMAGE_URI); + assertThat(actualDto.getUsername()).isEqualTo(expectedModel.getUser().getUsername()); + assertThat(actualDto.getUserId()).isEqualTo(expectedModel.getUser().getId()); } @Test void should_map_to_dto_with_image_url_when_model_has_image() { // given + User user = User.builder() + .id(1L) + .username("test") + .build(); + Group expectedModel = Group.builder() .id(123L) .description("blablabla") .name("blabla") .image(FileModel.builder().url("http://url.com").objectKey("blablabla").build()) .createdAt(Instant.now()) + .user(user) .build(); String expectedUrl = "http://url/objectKey"; @@ -89,10 +115,12 @@ void should_map_to_dto_with_image_url_when_model_has_image() { // then assertThat(actualDto).usingRecursiveComparison() - .ignoringFields("user", "posts", "numberOfPosts", "imageUrl") + .ignoringFields("user", "posts", "numberOfPosts", "imageUrl", "username", "userId") .isEqualTo(expectedModel); assertThat(actualDto.getNumberOfPosts()).isZero(); assertThat(actualDto.getImageUrl()).contains(expectedUrl); + assertThat(actualDto.getUsername()).isEqualTo(expectedModel.getUser().getUsername()); + assertThat(actualDto.getUserId()).isEqualTo(expectedModel.getUser().getId()); } } diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java index 00d4b7e2..87e2c8db 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java @@ -19,7 +19,7 @@ class JobApplicationAdapterTest extends ControllerIntegrationTestBase { void given_company_should_return_dto() { // given Company company = new Company(1234L, "World Company", "http://logo.com", "La World Company est une multinationale imaginaire basée aux États-Unis", "http://word-company.com"); - JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User user = User.builder().id(87L).build(); JobApplication model = new JobApplication(123L, job, user, PENDING, Instant.now(), false); @@ -40,7 +40,7 @@ void given_company_should_return_dto() { void given_no_company_should_return_dto() { // given Company company = null; - JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User user = User.builder().id(87L).build(); JobApplication model = new JobApplication(123L, job, user, PENDING, Instant.now(), false); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java index d37ecadc..510c81de 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java @@ -32,7 +32,7 @@ class PostAdapterTest { void toPost() { // given User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 0, currentUser, now(), group); PostRequest postRequest = new PostRequest(123L, null, "Super Post", "http://url.site", "Test"); @@ -62,7 +62,7 @@ void should_return_post_with_no_subreddit_and_poster_has_no_image() { @Test void should_return_post_with_subreddit_image_null() { User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 12, currentUser, now(), group); final int expectedCommentCount = 10; @@ -77,7 +77,7 @@ void should_return_post_with_subreddit_image_null() { void toPostResponse() { // given User currentUser = User.builder().id(123L).username("test user").image(FileModel.builder().url("http://url.com").build()).build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, FileModel.builder().url("http://img.com").build(), emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, FileModel.builder().url("http://img.com").build(), emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 12, currentUser, now(), group); final int expectedCommentCount = 10; diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java index 9124eb9a..43bf370c 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java @@ -1,17 +1,22 @@ package com.dynonuggets.refonteimplicaction.controller; import com.dynonuggets.refonteimplicaction.dto.GroupDto; +import com.dynonuggets.refonteimplicaction.model.User; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.GroupService; import com.google.common.collect.Ordering; import com.google.gson.reflect.TypeToken; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.*; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.ResultActions; +import java.util.Arrays; import java.util.List; +import java.util.Optional; import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.*; import static java.util.Arrays.asList; @@ -33,6 +38,9 @@ class GroupControllerIntegrationTest extends ControllerIntegrationTestBase { @MockBean GroupService groupService; + @Mock + UserRepository userRepository; + @Test void should_response_forbidden_when_create_subreddit_with_no_authentication() throws Exception { // given @@ -55,7 +63,7 @@ void should_response_forbidden_when_create_subreddit_with_no_authentication() th @Test @WithMockUser - void should_list_all_subreddit_whith_no_authentication() throws Exception { + void should_list_all_subreddit_with_no_authentication() throws Exception { // given final Pageable DEFAULT_PAGEABLE = PageRequest.of(0, 10, Sort.DEFAULT_DIRECTION, "id"); final Page subreddits = new PageImpl<>(asList( @@ -70,10 +78,16 @@ void should_list_all_subreddit_whith_no_authentication() throws Exception { GroupDto.builder().id(14L).build(), GroupDto.builder().id(15L).build() )); - given(groupService.getAll(DEFAULT_PAGEABLE)).willReturn(subreddits); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + + given(groupService.getAllValidGroups(DEFAULT_PAGEABLE)).willReturn(subreddits); + given(userRepository.findById(any())).willReturn(Optional.of(user)); // when - final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI).contentType(APPLICATION_JSON)); + final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI + GET_VALIDATED_GROUPS_URI).contentType(APPLICATION_JSON)); // then resultActions.andDo(print()) @@ -91,7 +105,7 @@ void should_list_all_subreddit_whith_no_authentication() throws Exception { } resultActions.andReturn(); - verify(groupService, times(1)).getAll(any()); + verify(groupService, times(1)).getAllValidGroups(any()); } @Test @@ -102,7 +116,7 @@ void should_response_forbidden_when_listing_all_subreddit_whith_no_authenticatio // then resultActions.andDo(print()).andExpect(status().isForbidden()); - verify(groupService, never()).getAll(any()); + verify(groupService, never()).getAllValidGroups(any()); } @Test @@ -157,4 +171,45 @@ void should_response_forbidden_when_top_posting_and_not_authenticated() throws E verify(groupService, never()).getAllByTopPosting(anyInt()); } + + @Test + @WithMockUser + void should_get_all_pending_groups_when_authenticated() throws Exception { + //given + List groupDtos = Arrays.asList( + GroupDto.builder().id(1L).valid(false).build(), + GroupDto.builder().id(2L).valid(false).build(), + GroupDto.builder().id(3L).valid(false).build() + ); + Page groupPageMockResponse = new PageImpl<>(groupDtos); + given(groupService.getAllPendingGroups(any())).willReturn(groupPageMockResponse); + + // when + ResultActions resultActions = mvc.perform( + get(GROUPS_BASE_URI + GET_PENDING_GROUP_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isOk()); + + for (int i = 0; i < groupDtos.size(); i++) { + final String contentPath = String.format("$.content[%d]", i); + resultActions.andExpect(jsonPath(contentPath + ".id", is(Math.toIntExact(groupDtos.get(i).getId())))); + resultActions.andExpect(jsonPath(contentPath + ".valid", is(groupDtos.get(i).isValid()))); + } + + verify(groupService, times(1)).getAllPendingGroups(any()); + } + + @Test + void should_response_forbidden_when_pending_groups_and_not_authenticated() throws Exception { + + // when + final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI + GET_PENDING_GROUP_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()).andExpect(status().isForbidden()); + + verify(groupService, never()).getAllPendingGroups(any()); + } } diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java index 99afb790..88ee9c47 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java @@ -1,5 +1,6 @@ package com.dynonuggets.refonteimplicaction.controller; +import com.dynonuggets.refonteimplicaction.adapter.JobPostingAdapter; import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; import com.dynonuggets.refonteimplicaction.exception.NotFoundException; import com.dynonuggets.refonteimplicaction.service.JobPostingService; @@ -36,6 +37,9 @@ class JobsPostingControllerTest extends ControllerIntegrationTestBase { @MockBean JobPostingService jobPostingService; + @MockBean + JobPostingAdapter jobPostingAdapter; + List jobPostings; @BeforeEach @@ -51,7 +55,7 @@ void getJobPostingsListShouldListAllJobs() throws Exception { // given Page jobPostingPageMockResponse = new PageImpl<>(jobPostings); - given(jobPostingService.getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean())).willReturn(jobPostingPageMockResponse); + given(jobPostingService.getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean(), any())).willReturn(jobPostingPageMockResponse); // when ResultActions resultActions = mvc.perform( @@ -74,7 +78,7 @@ void getJobPostingsListShouldListAllJobs() throws Exception { .andExpect(jsonPath(contentPath + ".salary", is(jobPostings.get(i).getSalary()))); } - verify(jobPostingService, times(1)).getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean()); + verify(jobPostingService, times(1)).getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean(), any()); } @Test @@ -82,7 +86,7 @@ void getAllWithoutJwtShouldBeForbidden() throws Exception { mvc.perform(get(JOBS_BASE_URI)).andDo(print()) .andExpect(status().isForbidden()); - verify(jobPostingService, times(0)).getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean()); + verify(jobPostingService, times(0)).getAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean(), anyBoolean()); } @Test @@ -246,4 +250,46 @@ void archiveJobListWithoutJwtShouldBeForbidden() throws Exception { .andExpect(status().isForbidden()); verify(jobPostingService, never()).toggleArchiveAll(Collections.singletonList(anyLong())); } + + @Test + @WithMockUser + void should_get_all_pending_jobs_when_authenticated() throws Exception { + //given + List jobPostingDtos = Arrays.asList( + JobPostingDto.builder().id(1L).valid(false).build(), + JobPostingDto.builder().id(2L).valid(false).build(), + JobPostingDto.builder().id(3L).valid(false).build() + ); + Page jobPageMockResponse = new PageImpl<>(jobPostingDtos); + given(jobPostingService.getAllPendingJobs(any())).willReturn(jobPageMockResponse); + + // when + ResultActions resultActions = mvc.perform( + get(JOBS_BASE_URI + GET_PENDING_JOB_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isOk()); + + for (int i = 0; i < jobPostingDtos.size(); i++) { + final String contentPath = String.format("$.content[%d]", i); + resultActions.andExpect(jsonPath(contentPath + ".id", is(Math.toIntExact(jobPostingDtos.get(i).getId())))); + resultActions.andExpect(jsonPath(contentPath + ".valid", is(jobPostingDtos.get(i).isValid()))); + } + + verify(jobPostingService, times(1)).getAllPendingJobs(any()); + } + + @Test + void should_response_forbidden_when_pending_jobs_and_not_authenticated() throws Exception { + + // when + final ResultActions resultActions = mvc.perform(get(JOBS_BASE_URI + GET_PENDING_JOB_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()).andExpect(status().isForbidden()); + + verify(jobPostingService, never()).getAllPendingJobs(any()); + } + } diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java index 5c8e7cfa..b9d07870 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java @@ -144,7 +144,7 @@ void should_throw_exception_when_not_exists() { void should_get_comments_for_post_when_exists() { // given User currentUser = User.builder().id(123L).username("Sankukai").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post post = new Post(12L, "Super Post", "http://url.site", "Test", 88000, currentUser, Instant.now(), group); List comments = asList( new Comment(3L, "comment1", post, Instant.now(), currentUser), diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java index 56d3c0cb..68503195 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java @@ -1,12 +1,14 @@ package com.dynonuggets.refonteimplicaction.service; import com.dynonuggets.refonteimplicaction.adapter.GroupAdapter; +import com.dynonuggets.refonteimplicaction.adapter.UserAdapter; import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.repository.FileRepository; import com.dynonuggets.refonteimplicaction.repository.GroupRepository; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.impl.S3CloudServiceImpl; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,6 +25,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -46,6 +49,12 @@ class GroupServiceTest { @Mock FileRepository fileRepository; + @Mock + UserRepository userRepository; + + @Mock + UserAdapter userAdapter; + @InjectMocks GroupService groupService; @@ -93,9 +102,15 @@ void should_save_subreddit_with_image() { "test data".getBytes() ); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + given(userRepository.findById(any())).willReturn(Optional.of(user)); + when(cloudService.uploadImage(any())).thenReturn(fileModel); when(fileRepository.save(fileModel)).thenReturn(fileModel); - when(groupAdapter.toModel(any())).thenReturn(sentModel); + when(groupAdapter.toModel(any(), any())).thenReturn(sentModel); when(authService.getCurrentUser()).thenReturn(currentUser); when(groupRepository.save(any())).thenReturn(saveModel); when(groupAdapter.toDto(any())).thenReturn(expectedDto); @@ -136,9 +151,15 @@ void should_save_when_no_image() { .description("Elle est super bien ma description") .build(); - given(groupAdapter.toModel(any())).willReturn(sentModel); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + + given(groupAdapter.toModel(any(), any())).willReturn(sentModel); given(authService.getCurrentUser()).willReturn(currentUser); given(groupRepository.save(any())).willReturn(saveModel); + given(userRepository.findById(any())).willReturn(Optional.of(user)); // when groupService.save(sentDto); @@ -173,10 +194,9 @@ void should_list_all_subreddits() { Pageable pageable = PageRequest.of(first, first * size); Page subredditsPage = new PageImpl<>(groups.subList(0, size - 1)); - given(groupRepository.findAll(any(Pageable.class))).willReturn(subredditsPage); - + given(groupRepository.findAllByValidIsTrue(any(Pageable.class))).willReturn(subredditsPage); // when - Page actuals = groupService.getAll(pageable); + Page actuals = groupService.getAllValidGroups(pageable); // then assertThat(actuals.getTotalElements()).isEqualTo(subredditsPage.getTotalElements()); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java index 11e14cd3..7beeeeaa 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java @@ -58,7 +58,7 @@ class JobApplicationServiceTest extends ControllerIntegrationTestBase { void should_create_apply() { // given JobApplicationRequest request = new JobApplicationRequest(123L, PENDING, null); - JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); final User currentUser = User.builder().id(45L).build(); JobApplication jobApplication = new JobApplication(67L, job, currentUser, request.getStatus(), Instant.now(), false); JobApplicationDto expectedDto = new JobApplicationDto(jobApplication.getId(), jobApplication.getJob().getId(), jobApplication.getJob().getTitle(), jobApplication.getJob().getCompany().getName(), jobApplication.getJob().getCompany().getLogo(), jobApplication.getStatus().name(), "Paris (75)", CDI, false); @@ -103,7 +103,7 @@ void should_throw_exception_when_creating_with_already_applied_job() { JobApplicationRequest request = new JobApplicationRequest(jobId, PENDING, null); IllegalArgumentException expectedException = new IllegalArgumentException(String.format(APPLY_ALREADY_EXISTS_FOR_JOB, jobId)); final JobApplication apply = JobApplication.builder().id(123L).build(); - JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User currentUser = User.builder().id(123L).build(); given(jobRepository.findById(anyLong())).willReturn(Optional.of(job)); given(authService.getCurrentUser()).willReturn(currentUser); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobPostingServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobPostingServiceTest.java index 61436945..de58a203 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobPostingServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobPostingServiceTest.java @@ -49,13 +49,13 @@ void should_get_all_jobs_with_criteria_and_check_apply() { Page jobPage = new PageImpl<>(jobs); Pageable pageable = PageRequest.of(0, 10); User currentUser = User.builder().id(123L).build(); - given(jobPostingRepository.findAllWithCriteria(any(), anyString(), anyString(), anyBoolean())).willReturn(jobPage); + given(jobPostingRepository.findAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean())).willReturn(jobPage); given(jobApplicationRepository.findAllByJob_IdInAndUser_Id(anyList(), anyLong())).willReturn(Collections.emptyList()); given(authService.getCurrentUser()).willReturn(currentUser); given(jobPostingAdapter.toDto(any())).willReturn(JobPostingDto.builder().build()); // when - final Page actual = JobPostingService.getAllWithCriteria(pageable, "", CDD.name(), false, true); + final Page actual = JobPostingService.getAllWithCriteria(pageable, "", CDD.name(), false, true, true); // then assertThat(actual.getTotalElements()).isEqualTo(jobPage.getTotalElements()); @@ -67,10 +67,10 @@ void should_get_all_jobs_with_criteria_and_check_apply_false() { List jobs = Collections.singletonList(JobPosting.builder().id(123L).contractType(CDD).build()); Page jobPage = new PageImpl<>(jobs); Pageable pageable = PageRequest.of(0, 10); - given(jobPostingRepository.findAllWithCriteria(any(), anyString(), anyString(), anyBoolean())).willReturn(jobPage); + given(jobPostingRepository.findAllWithCriteria(any(), anyString(), anyString(), anyBoolean(), anyBoolean())).willReturn(jobPage); // when - final Page actual = JobPostingService.getAllWithCriteria(pageable, "", CDD.name(), false, false); + final Page actual = JobPostingService.getAllWithCriteria(pageable, "", CDD.name(), false, false, true); // then assertThat(actual.getTotalElements()).isEqualTo(jobPage.getTotalElements()); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java index c065725a..f810f517 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java @@ -63,7 +63,7 @@ class PostServiceTest { void should_save_post_if_subreddit_exists() { // given User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 0, null, Instant.now(), null); PostRequest postRequest = new PostRequest(123L, 123L, "First Subreddit", "http://url.site", "Test"); @@ -128,7 +128,7 @@ void should_throw_exception_when_save_post_and_subreddit_not_found() { void should_get_post_when_exists() { // given User currentUser = User.builder().id(123L).username("Sankukai").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post post = new Post(12L, "Super Post", "http://url.site", "Test", 88000, currentUser, Instant.now(), group); PostResponse expectedResponse = new PostResponse(123L, "Super post", "http://url.site", "Test", "Sankukai", currentUser.getId(), null, "Super Subreddit", 88000, 12, null, true, false, null); given(postRepository.findById(anyLong())).willReturn(Optional.of(post)); @@ -158,7 +158,7 @@ void should_throw_exception_when_post_not_exists() { void should_list_all_posts() { // given User currentUser = User.builder().id(1345L).username("gustave").build(); - Group group = new Group(123L, "Sub 1", "Description Sub 1", null, Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Sub 1", "Description Sub 1", null, Instant.now(), currentUser, null, emptyList(), true); Pageable pageable = PageRequest.of(0, 10, Sort.DEFAULT_DIRECTION, "id"); Page expectedPages = new PageImpl<>(asList( new Post(1L, "Post 1", null, "Description 1", 0, currentUser, Instant.now(), group), diff --git a/frontend-implicaction/src/app/admin/admin.module.ts b/frontend-implicaction/src/app/admin/admin.module.ts index 19926ba9..97210239 100644 --- a/frontend-implicaction/src/app/admin/admin.module.ts +++ b/frontend-implicaction/src/app/admin/admin.module.ts @@ -8,12 +8,14 @@ import {CompaniesComponent} from './companies/companies.component'; import {TableModule} from 'primeng/table'; import {CompaniesModule} from './companies/companies.module'; import {FeatherModule} from 'angular-feather'; +import {PendingGroupTableComponent} from './groups/pending-group-table/pending-group-table.component'; @NgModule({ declarations: [ AdminComponent, CompaniesComponent, + PendingGroupTableComponent, ], imports: [ CommonModule, @@ -24,6 +26,9 @@ import {FeatherModule} from 'angular-feather'; FeatherModule ], providers: [{provide: LOCALE_ID, useValue: 'fr'}], + exports: [ + PendingGroupTableComponent + ] }) export class AdminModule { constructor() { diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html index 6e3e3c41..7280055b 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html @@ -7,3 +7,16 @@
Nouveaux utilisateurs
+
+
+
Nouvelles offres
+
+ +
+
+
+
Nouveaux groupes
+
+ +
+ diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts index 57868219..68e0a150 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts @@ -4,6 +4,8 @@ import {DashboardComponent} from './dashboard.component'; import {AdminOverviewComponent} from './components/admin-overview/admin-overview.component'; import {DashboardRoutingModule} from './dashboard-routing.module'; import {UsersModule} from '../users/users.module'; +import {AdminJobsModule} from '../jobs/admin-jobs.module'; +import {AdminModule} from '../admin.module'; @NgModule({ @@ -14,7 +16,9 @@ import {UsersModule} from '../users/users.module'; imports: [ CommonModule, DashboardRoutingModule, - UsersModule + UsersModule, + AdminJobsModule, + AdminModule, ] }) export class DashboardModule { diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html new file mode 100644 index 00000000..77541784 --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html @@ -0,0 +1,41 @@ + + + + Nom + Description + Administrateur + Crée le + + + + + {{group.name}} + {{group.description}} + {{group.username}} + {{group.createdAt}} + + + + + + + Aucun groupe est en attente de validation. + + diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.scss b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts new file mode 100644 index 00000000..0add9b8d --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PendingGroupTableComponent } from './pending-group-table.component'; + +describe('PendingGroupTableComponent', () => { + let component: PendingGroupTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PendingGroupTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PendingGroupTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts new file mode 100644 index 00000000..46a8d601 --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts @@ -0,0 +1,56 @@ +import {Component} from '@angular/core'; +import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination/base-with-pagination.component'; +import {Group} from '../../../discussion/model/group'; +import {ActivatedRoute} from '@angular/router'; +import {ToasterService} from '../../../core/services/toaster.service'; +import {GroupService} from '../../../discussion/services/group.service'; +import {finalize, take} from 'rxjs/operators'; +import {Criteria} from '../../../shared/models/Criteria'; + +@Component({ + selector: 'app-pending-group-table', + templateUrl: './pending-group-table.component.html', + styleUrls: ['./pending-group-table.component.scss'] +}) +export class PendingGroupTableComponent extends BaseWithPaginationComponent { + + isLoading = true; + selectedOrderCode: string; + rowsPerPage = this.pageable.rowsPerPages[0]; + + constructor( + private toastService: ToasterService, + private groupService: GroupService, + protected route: ActivatedRoute + ) { + super(route); + } + + validateGroup(group: Group): void { + this.groupService + .validateGroup(group) + .subscribe( + () => this.paginate(this.pageable), + () => this.toastService.error('Oops', `Une erreur est survenue lors de la validation du groupe.`), + () => this.toastService.success('Succès', `Le groupe ${group.name} est désormais validé.`), + ); + } + + protected innerPaginate(): void { + this.groupService + .getAllPendingGroup(this.pageable) + .pipe( + take(1), + finalize(() => this.isLoading = false) + ) + .subscribe( + data => { + this.pageable.totalPages = data.totalPages; + this.pageable.rows = data.size; + this.pageable.totalElements = data.totalElements; + this.pageable.content = data.content; + }, + () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), + ); + } +} diff --git a/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts b/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts index 2f31963f..3d943005 100644 --- a/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts +++ b/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts @@ -4,17 +4,22 @@ import {AdminJobsComponent} from './admin-jobs.component'; import {AdminJobsRoutingModule} from './admin-jobs-routing.module'; import {TableModule} from 'primeng/table'; import {EditorModule} from 'primeng/editor'; -import {JobPostingFormComponent} from './components/job-posting-form/job-posting-form.component'; import {ReactiveFormsModule} from '@angular/forms'; import {FeatherModule} from 'angular-feather'; import {DropdownModule} from 'primeng/dropdown'; import {CheckboxModule} from 'primeng/checkbox'; +import {PendingJobTableComponent} from './components/pending-job-table/pending-job-table.component'; +import {JobPostingFormComponent} from './components/job-posting-form/job-posting-form.component'; @NgModule({ declarations: [ AdminJobsComponent, - JobPostingFormComponent + JobPostingFormComponent, + PendingJobTableComponent + ], + exports: [ + PendingJobTableComponent ], imports: [ CommonModule, diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.html b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.html new file mode 100644 index 00000000..a1a7ceee --- /dev/null +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.html @@ -0,0 +1,39 @@ + + + + Title + Description + Localisation + + + + + {{job.title}} + {{job.description}} + {{job.location}} + + + + + + + Aucune offre est en attente de validation. + + diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.scss b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts new file mode 100644 index 00000000..fec40b42 --- /dev/null +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PendingJobTableComponent } from './pending-job-table.component'; + +describe('PendingJobTableComponent', () => { + let component: PendingJobTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PendingJobTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PendingJobTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts new file mode 100644 index 00000000..381986fc --- /dev/null +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts @@ -0,0 +1,57 @@ +import {Component} from '@angular/core'; +import {BaseWithPaginationComponent} from '../../../../shared/components/base-with-pagination/base-with-pagination.component'; +import {JobPosting} from '../../../../shared/models/job-posting'; +import {ToasterService} from '../../../../core/services/toaster.service'; +import {JobService} from '../../../../job/services/job.service'; +import {ActivatedRoute} from '@angular/router'; +import {finalize, take} from 'rxjs/operators'; +import {Criteria} from '../../../../shared/models/Criteria'; + +@Component({ + selector: 'app-pending-job-table', + templateUrl: './pending-job-table.component.html', + styleUrls: ['./pending-job-table.component.scss'] +}) +export class PendingJobTableComponent extends BaseWithPaginationComponent { + + isLoading = true; + // Pagination et filtres + rowsPerPage = this.pageable.rowsPerPages[0]; + + constructor( + private toastService: ToasterService, + private jobsService: JobService, + protected route: ActivatedRoute + ) { + super(route); + } + + validateJob(job: JobPosting): void { + this.jobsService + .validateJob(job) + .subscribe( + () => this.paginate(this.pageable), + () => this.toastService.error('Oops', `Une erreur est survenue lors de la validation de l'offre.`), + () => this.toastService.success('Succès', `L'offre ${job.title} est désormais validée.`), + ); + } + + protected innerPaginate(): void { + this.jobsService + .getAllPendingActivationJobs(this.pageable) + .pipe( + take(1), + finalize(() => this.isLoading = false) + ) + .subscribe( + data => { + this.pageable.totalPages = data.totalPages; + this.pageable.rows = data.size; + this.pageable.totalElements = data.totalElements; + this.pageable.content = data.content; + }, + () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), + ); + } + +} diff --git a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html index 2671b4eb..1514c6cd 100644 --- a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html +++ b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html @@ -1,5 +1,5 @@ {{roleCodesToString(user.roles)}}