Skip to content

Commit

Permalink
RI-191: [marketplace] ajoute une apply en base lors du click sur le b…
Browse files Browse the repository at this point in the history
…outon ajouter au jobBoard (#194)
  • Loading branch information
matthieuaudemard committed Nov 22, 2021
1 parent 7880a03 commit 252dcdd
Show file tree
Hide file tree
Showing 19 changed files with 224 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package com.dynonuggets.refonteimplicaction.controller;

import com.dynonuggets.refonteimplicaction.dto.ApplicationRequest;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationDto;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationRequest;
import com.dynonuggets.refonteimplicaction.exception.ImplicactionException;
import com.dynonuggets.refonteimplicaction.service.JobApplicationService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.List;

import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.APPLY_BASE_URI;
import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.GET_APPLY_URI;
Expand All @@ -25,12 +23,18 @@ public class JobApplicationController {
private final JobApplicationService applyService;

@PostMapping
public ResponseEntity<JobApplicationDto> createApply(@RequestBody ApplicationRequest requestDto) throws ImplicactionException {
public ResponseEntity<JobApplicationDto> createApply(@RequestBody JobApplicationRequest requestDto) throws ImplicactionException {
final JobApplicationDto saveDto = applyService.createApplyIfNotExists(requestDto);
URI location = UriComponentsBuilder.fromPath(APPLY_BASE_URI + GET_APPLY_URI)
.buildAndExpand(saveDto.getId())
.toUri();

return ResponseEntity.created(location).body(saveDto);
}

@GetMapping()
public ResponseEntity<List<JobApplicationDto>> getAllAppliesByUserId() {
List<JobApplicationDto> applies = applyService.getAllAppliesForCurrentUser();
return ResponseEntity.ok(applies);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Data
@Getter
@AllArgsConstructor
public class ApplicationRequest {
public class JobApplicationRequest {
private Long jobId;
private ApplyStatusEnum status;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import com.dynonuggets.refonteimplicaction.model.JobApplication;
import com.dynonuggets.refonteimplicaction.model.JobPosting;
import com.dynonuggets.refonteimplicaction.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface JobApplicationRepository extends JpaRepository<JobApplication, Long> {
Optional<JobApplication> findByJob(JobPosting job);

List<JobApplication> findAllByUserAndArchiveIsFalse(User user);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package com.dynonuggets.refonteimplicaction.service;

import com.dynonuggets.refonteimplicaction.adapter.JobApplicationAdapter;
import com.dynonuggets.refonteimplicaction.dto.ApplicationRequest;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationDto;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationRequest;
import com.dynonuggets.refonteimplicaction.exception.NotFoundException;
import com.dynonuggets.refonteimplicaction.model.JobApplication;
import com.dynonuggets.refonteimplicaction.model.JobPosting;
import com.dynonuggets.refonteimplicaction.model.User;
import com.dynonuggets.refonteimplicaction.repository.JobApplicationRepository;
import com.dynonuggets.refonteimplicaction.repository.JobPostingRepository;
import com.dynonuggets.refonteimplicaction.utils.Message;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.List;

import static com.dynonuggets.refonteimplicaction.utils.Message.APPLY_ALREADY_EXISTS_FOR_JOB;
import static com.dynonuggets.refonteimplicaction.utils.Message.JOB_NOT_FOUND_MESSAGE;
import static java.util.stream.Collectors.toList;

@Service
@AllArgsConstructor
Expand All @@ -25,12 +28,12 @@ public class JobApplicationService {
private final JobApplicationAdapter applyAdapter;
private final AuthService authService;

public JobApplicationDto createApplyIfNotExists(ApplicationRequest applyRequest) {
public JobApplicationDto createApplyIfNotExists(JobApplicationRequest applyRequest) {
final JobPosting job = jobRepository.findById(applyRequest.getJobId())
.orElseThrow(() -> new NotFoundException(String.format(JOB_NOT_FOUND_MESSAGE, applyRequest.getJobId())));

if (applyRepository.findByJob(job).isPresent()) {
throw new IllegalArgumentException(String.format(Message.APPLY_ALREADY_EXISTS_FOR_JOB, job.getId()));
throw new IllegalArgumentException(String.format(APPLY_ALREADY_EXISTS_FOR_JOB, job.getId()));
}

final JobApplication apply = JobApplication.builder()
Expand All @@ -45,4 +48,13 @@ public JobApplicationDto createApplyIfNotExists(ApplicationRequest applyRequest)

return applyAdapter.toDto(applySave);
}

public List<JobApplicationDto> getAllAppliesForCurrentUser() {
final User currentUser = authService.getCurrentUser();

return applyRepository.findAllByUserAndArchiveIsFalse(currentUser)
.stream()
.map(applyAdapter::toDto)
.collect(toList());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.dynonuggets.refonteimplicaction.controller;

import com.dynonuggets.refonteimplicaction.dto.ApplicationRequest;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationDto;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationRequest;
import com.dynonuggets.refonteimplicaction.exception.NotFoundException;
import com.dynonuggets.refonteimplicaction.service.JobApplicationService;
import org.junit.jupiter.api.Test;
Expand All @@ -10,17 +10,21 @@
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.ResultActions;

import static com.dynonuggets.refonteimplicaction.model.ApplyStatusEnum.PENDING;
import static com.dynonuggets.refonteimplicaction.model.ContractTypeEnum.CDI;
import java.util.List;

import static com.dynonuggets.refonteimplicaction.model.ApplyStatusEnum.*;
import static com.dynonuggets.refonteimplicaction.model.ContractTypeEnum.*;
import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.APPLY_BASE_URI;
import static com.dynonuggets.refonteimplicaction.utils.Message.APPLY_ALREADY_EXISTS_FOR_JOB;
import static com.dynonuggets.refonteimplicaction.utils.Message.JOB_NOT_FOUND_MESSAGE;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

Expand All @@ -34,7 +38,7 @@ class JobApplicationControllerTest extends ControllerIntegrationTestBase {
@WithMockUser
void should_create_apply() throws Exception {
// given
ApplicationRequest request = new ApplicationRequest(123L, PENDING);
JobApplicationRequest request = new JobApplicationRequest(123L, PENDING);
JobApplicationDto response = new JobApplicationDto(243L, 123L, "Mon super Job", "Google", "http://uri.com", PENDING, CDI);
given(applicationService.createApplyIfNotExists(any())).willReturn(response);
String json = gson.toJson(request);
Expand Down Expand Up @@ -62,7 +66,7 @@ void should_create_apply() throws Exception {
@WithMockUser
void should_return_notfound_when_creating_apply_and_job_notfound() throws Exception {
// given
ApplicationRequest request = new ApplicationRequest(123L, PENDING);
JobApplicationRequest request = new JobApplicationRequest(123L, PENDING);
String json = gson.toJson(request);
final NotFoundException exception = new NotFoundException(String.format(JOB_NOT_FOUND_MESSAGE, request.getJobId()));
given(applicationService.createApplyIfNotExists(any())).willThrow(exception);
Expand All @@ -84,7 +88,7 @@ void should_return_notfound_when_creating_apply_and_job_notfound() throws Except
@WithMockUser
void should_return_bad_request_when_creating_apply_with_already_applied_job() throws Exception {
// given
ApplicationRequest request = new ApplicationRequest(123L, PENDING);
JobApplicationRequest request = new JobApplicationRequest(123L, PENDING);
String json = gson.toJson(request);
final IllegalArgumentException exception = new IllegalArgumentException(String.format(APPLY_ALREADY_EXISTS_FOR_JOB, request.getJobId()));
given(applicationService.createApplyIfNotExists(any())).willThrow(exception);
Expand All @@ -105,7 +109,7 @@ void should_return_bad_request_when_creating_apply_with_already_applied_job() th
@Test
void should_return_forbidden_when_creating_apply_and_no_auth() throws Exception {
// given
ApplicationRequest request = new ApplicationRequest(123L, PENDING);
JobApplicationRequest request = new JobApplicationRequest(123L, PENDING);
String json = gson.toJson(request);

// when
Expand All @@ -118,4 +122,46 @@ void should_return_forbidden_when_creating_apply_and_no_auth() throws Exception

verify(applicationService, never()).createApplyIfNotExists(any());
}

@Test
@WithMockUser
void should_list_all_users_application() throws Exception {
// given
List<JobApplicationDto> expecteds = asList(
new JobApplicationDto(1L, 12L, "super job", "google", "http://url.com", PENDING, CDD),
new JobApplicationDto(2L, 13L, "super job 2", "microsof", "http://url2.com", CHASED, CDD),
new JobApplicationDto(3L, 14L, "super job 3", "amazon", "http://url3.com", INTERVIEW, INTERIM)
);
int expectedSize = expecteds.size();
given(applicationService.getAllAppliesForCurrentUser()).willReturn(expecteds);

// when
final ResultActions resultActions = mvc.perform(get(APPLY_BASE_URI));

// then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.size()", is(expectedSize)));

for (int i = 0; i < expectedSize; i++) {
String contentPath = String.format("$[%d].", i);
resultActions.andExpect(jsonPath(contentPath + "id", is(expecteds.get(i).getId().intValue())))
.andExpect(jsonPath(contentPath + "jobId", is(expecteds.get(i).getJobId().intValue())))
.andExpect(jsonPath(contentPath + "companyName", is(expecteds.get(i).getCompanyName())))
.andExpect(jsonPath(contentPath + "companyImageUri", is(expecteds.get(i).getCompanyImageUri())))
.andExpect(jsonPath(contentPath + "status", is(expecteds.get(i).getStatus().name())))
.andExpect(jsonPath(contentPath + "contractType", is(expecteds.get(i).getContractType().name())));
}

verify(applicationService, times(1)).getAllAppliesForCurrentUser();
}

@Test
void should_response_forbidden_when_listing_and_no_auth() throws Exception {
// when
final ResultActions resultActions = mvc.perform(get(APPLY_BASE_URI));

// then
resultActions.andExpect(status().isForbidden());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void getJobPostingsListShouldListAllJobs() throws Exception {

for (int i = 0; i < jobPostings.size(); i++) {
final String contentPath = String.format("$.content[%d]", i);
actions.andExpect(jsonPath(contentPath + ".id", is(Math.toIntExact(jobPostings.get(i).getId()))))
actions.andExpect(jsonPath(contentPath + ".id", is(jobPostings.get(i).getId().intValue())))
.andExpect(jsonPath(contentPath + ".createdAt", is(jobPostings.get(i).getCreatedAt().toString())))
.andExpect(jsonPath(contentPath + ".description", is(jobPostings.get(i).getDescription())))
.andExpect(jsonPath(contentPath + ".location", is(jobPostings.get(i).getLocation())))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.dynonuggets.refonteimplicaction.adapter.JobApplicationAdapter;
import com.dynonuggets.refonteimplicaction.controller.ControllerIntegrationTestBase;
import com.dynonuggets.refonteimplicaction.dto.ApplicationRequest;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationDto;
import com.dynonuggets.refonteimplicaction.dto.JobApplicationRequest;
import com.dynonuggets.refonteimplicaction.exception.NotFoundException;
import com.dynonuggets.refonteimplicaction.model.Company;
import com.dynonuggets.refonteimplicaction.model.JobApplication;
Expand All @@ -18,11 +18,14 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.Instant;
import java.util.List;
import java.util.Optional;

import static com.dynonuggets.refonteimplicaction.model.ApplyStatusEnum.PENDING;
import static com.dynonuggets.refonteimplicaction.model.ApplyStatusEnum.*;
import static com.dynonuggets.refonteimplicaction.model.ContractTypeEnum.CDI;
import static com.dynonuggets.refonteimplicaction.utils.Message.APPLY_ALREADY_EXISTS_FOR_JOB;
import static com.dynonuggets.refonteimplicaction.utils.Message.JOB_NOT_FOUND_MESSAGE;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -50,12 +53,12 @@ class JobApplicationServiceTest extends ControllerIntegrationTestBase {
@Test
void should_create_apply() {
// given
ApplicationRequest request = new ApplicationRequest(123L, PENDING);
JobApplicationRequest request = new JobApplicationRequest(123L, PENDING);
JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, Instant.now(), false);
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(), CDI);
given(jobRepository.findById(anyLong())).willReturn(java.util.Optional.of(job));
given(jobRepository.findById(anyLong())).willReturn(Optional.of(job));
given(authService.getCurrentUser()).willReturn(currentUser);
given(applyRepostitory.save(any())).willReturn(jobApplication);
given(applyAdapter.toDto(any())).willReturn(expectedDto);
Expand All @@ -78,7 +81,7 @@ void should_create_apply() {
void should_throw_notfound_when_creating_with_no_found_job() {
// given
long jobId = 123L;
ApplicationRequest request = new ApplicationRequest(jobId, PENDING);
JobApplicationRequest request = new JobApplicationRequest(jobId, PENDING);
NotFoundException expectedException = new NotFoundException(String.format(JOB_NOT_FOUND_MESSAGE, jobId));
given(jobRepository.findById(anyLong())).willThrow(expectedException);

Expand All @@ -93,14 +96,36 @@ void should_throw_notfound_when_creating_with_no_found_job() {
void should_throw_exception_when_creating_with_already_applied_job() {
// given
long jobId = 123L;
ApplicationRequest request = new ApplicationRequest(jobId, PENDING);
JobApplicationRequest request = new JobApplicationRequest(jobId, PENDING);
IllegalArgumentException expectedException = new IllegalArgumentException(String.format(APPLY_ALREADY_EXISTS_FOR_JOB, jobId));
given(jobRepository.findById(anyLong())).willThrow(expectedException);
final JobApplication apply = JobApplication.builder().build();
JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, Instant.now(), false);
given(jobRepository.findById(anyLong())).willReturn(Optional.of(job));
given(applyRepostitory.findByJob(any())).willReturn(Optional.of(apply));

// when
final IllegalArgumentException actualException = assertThrows(IllegalArgumentException.class, () -> jobApplicationService.createApplyIfNotExists(request));

// then
assertThat(actualException.getMessage()).isEqualTo(expectedException.getMessage());
}

@Test
void should_return_all_users_apply() {
// given
User currentUser = User.builder().id(123L).build();
List<JobApplication> expecteds = asList(
new JobApplication(1L, JobPosting.builder().id(12L).build(), currentUser, PENDING, Instant.now(), false),
new JobApplication(2L, JobPosting.builder().id(13L).build(), currentUser, CHASED, Instant.now(), false),
new JobApplication(3L, JobPosting.builder().id(14L).build(), currentUser, INTERVIEW, Instant.now(), false)
);
given(authService.getCurrentUser()).willReturn(currentUser);
given(applyRepostitory.findAllByUserAndArchiveIsFalse(any())).willReturn(expecteds);

// when
final List<JobApplicationDto> allAppliesForCurrentUser = jobApplicationService.getAllAppliesForCurrentUser();

// then
assertThat(allAppliesForCurrentUser.size()).isEqualTo(expecteds.size());
}
}
14 changes: 6 additions & 8 deletions data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,12 @@ VALUES (50);
DROP TABLE IF EXISTS `job_application`;
CREATE TABLE `job_application`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`last_update` datetime DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`job_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`archive` tinyint(1) DEFAULT '0',
`submitted_at` datetime DEFAULT NULL,
`status_id` bigint NOT NULL,
`id` bigint NOT NULL AUTO_INCREMENT,
`last_update` datetime DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`job_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`archive` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `FKobel3nnbi451ftywx9q9m2qax` (`job_id`),
KEY `FKcbu1yb4kyxowejebm87crxtr8` (`user_id`),
Expand Down
6 changes: 3 additions & 3 deletions frontend-implicaction/src/app/board/board.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {Component, OnInit} from '@angular/core';
import {ApplyStatusCode, ApplyStatusEnum} from './enums/apply-status-enum';
import {JobApply} from './models/job-apply';
import {JobApplication} from './models/job-application';
import {CdkDragDrop, moveItemInArray, transferArrayItem} from '@angular/cdk/drag-drop';

export class BoardColumn {
status: ApplyStatusEnum;
applies: JobApply[] = [];
applies: JobApplication[] = [];
}


Expand Down Expand Up @@ -61,7 +61,7 @@ export class BoardComponent implements OnInit {
});
}

drop(event: CdkDragDrop<JobApply[], any>, statusCode: ApplyStatusCode): void {
drop(event: CdkDragDrop<JobApplication[], any>, statusCode: ApplyStatusCode): void {
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, Input} from '@angular/core';
import {JobApply} from '../../models/job-apply';
import {JobApplication} from '../../models/job-application';
import {Constants} from '../../../config/constants';
import {Univers} from '../../../shared/enums/univers';

Expand All @@ -13,7 +13,7 @@ export class ApplyCardComponent {
readonly COMPANY_IMAGE_DEFAULT_URI = Constants.COMPANY_IMAGE_DEFAULT_URI;

@Input()
apply: JobApply;
apply: JobApplication;

univers = Univers;

Expand Down
Loading

0 comments on commit 252dcdd

Please sign in to comment.