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 eb78deca..4aacce09 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 @@ -3,11 +3,9 @@ import com.dynonuggets.refonteimplicaction.dto.CompanyDto; import com.dynonuggets.refonteimplicaction.dto.ContractTypeDto; import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; -import com.dynonuggets.refonteimplicaction.dto.StatusDto; import com.dynonuggets.refonteimplicaction.model.Company; import com.dynonuggets.refonteimplicaction.model.ContractType; import com.dynonuggets.refonteimplicaction.model.JobPosting; -import com.dynonuggets.refonteimplicaction.model.Status; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -17,13 +15,11 @@ public class JobPostingAdapter { private final CompanyAdapter companyAdapter; private final ContractTypeAdapter contractAdapter; - private final StatusAdapter statusAdapter; public JobPostingDto toDto(JobPosting model) { CompanyDto companyDto = companyAdapter.toDto(model.getCompany()); ContractTypeDto contractTypeDto = contractAdapter.toDto(model.getContractType()); - StatusDto statusDto = statusAdapter.toDto(model.getStatus()); return JobPostingDto.builder() .id(model.getId()) @@ -35,7 +31,6 @@ public JobPostingDto toDto(JobPosting model) { .salary(model.getSalary()) .keywords(model.getKeywords()) .contractType(contractTypeDto) - .status(statusDto) .createdAt(model.getCreatedAt()) .build(); } @@ -44,7 +39,6 @@ public JobPosting toModel(JobPostingDto dto) { Company company = companyAdapter.toModel(dto.getCompany()); ContractType contractType = contractAdapter.toModel(dto.getContractType()); - Status status = statusAdapter.toModel(dto.getStatus()); return JobPosting.builder() .id(dto.getId()) @@ -56,7 +50,6 @@ public JobPosting toModel(JobPostingDto dto) { .salary(dto.getSalary()) .keywords(dto.getKeywords()) .contractType(contractType) - .status(status) .createdAt(dto.getCreatedAt()) .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 a3fee3c6..0802d105 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 @@ -57,4 +57,10 @@ public ResponseEntity delete(@PathVariable Long jobId) { jobPostingService.deleteJobPosting(jobId); return ResponseEntity.noContent().build(); } + + @PatchMapping(path = ARCHIVE_JOB_URI) + public ResponseEntity toggleArchive(@PathVariable Long jobId) { + JobPostingDto updated = jobPostingService.toggleArchiveJobPosting(jobId); + return ResponseEntity.ok(updated); + } } 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 f881d15a..4db47975 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 @@ -22,7 +22,7 @@ public class JobPostingDto { private String salary; private String keywords; private ContractTypeDto contractType; - private StatusDto status; private Instant createdAt; + private boolean archive; } 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 4519a03a..3d1acea6 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 @@ -47,10 +47,9 @@ public class JobPosting { @JoinColumn(name = "contract_type_id", nullable = false) private ContractType contractType; - @ManyToOne - @JoinColumn(name = "status_id", nullable = false) - private Status status; - @Column(name = "created_at") private Instant createdAt; + + @Column(name = "archive") + private boolean archive; } 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 f76c210d..9a8a912c 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 @@ -53,4 +53,14 @@ public void deleteJobPosting(Long jobPostingId) { .orElseThrow(() -> new NotFoundException("Impossible de supprimer l'offre, " + jobPostingId + " n'existe pas.")); jobPostingRepository.delete(jobPosting); } + + @Transactional + public JobPostingDto toggleArchiveJobPosting(Long jobPostingId) { + JobPosting jobPosting = jobPostingRepository.findById(jobPostingId) + .orElseThrow(() -> new NotFoundException(String.format(Message.JOB_NOT_FOUND_MESSAGE, jobPostingId))); + jobPosting.setArchive(jobPosting.isArchive()); + final JobPosting save = jobPostingRepository.save(jobPosting); + return jobPostingAdapter.toDto(save); + } + } 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 4930353c..b18ecb6a 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 @@ -6,6 +6,7 @@ public class ApiUrls { public static final String JOBS_BASE_URI = "/api/job-postings"; public static final String GET_JOB_URI = "/{jobId}"; public static final String DELETE_JOB_URI = "/{jobId}"; + public static final String ARCHIVE_JOB_URI = "/{jobId}/archive"; // POSTS public static final String POSTS_BASE_URI = "/api/posts"; diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapterTest.java index 887ada17..72aae199 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapterTest.java @@ -3,11 +3,9 @@ import com.dynonuggets.refonteimplicaction.dto.CompanyDto; import com.dynonuggets.refonteimplicaction.dto.ContractTypeDto; import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; -import com.dynonuggets.refonteimplicaction.dto.StatusDto; import com.dynonuggets.refonteimplicaction.model.Company; import com.dynonuggets.refonteimplicaction.model.ContractType; import com.dynonuggets.refonteimplicaction.model.JobPosting; -import com.dynonuggets.refonteimplicaction.model.Status; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -17,28 +15,22 @@ class JobPostingAdapterTest { CompanyDto companyDto; - StatusDto statusDto; ContractTypeDto contractTypeDto; Company company; - Status status; ContractType contractType; JobPosting jobPosting; JobPostingAdapter jobPostingAdapter; CompanyAdapter companyAdapter; - StatusAdapter statusAdapter; ContractTypeAdapter contractTypeAdapter; @BeforeEach public void setUp() { companyAdapter = new CompanyAdapter(); - statusAdapter = new StatusAdapter(); contractTypeAdapter = new ContractTypeAdapter(); - jobPostingAdapter = new JobPostingAdapter(companyAdapter, contractTypeAdapter, statusAdapter); + jobPostingAdapter = new JobPostingAdapter(companyAdapter, contractTypeAdapter); company = new Company(1L, "urlModel", "logo", "name", "description"); - status = new Status(2L, "label", "type"); contractType = new ContractType(3L, "label", "code"); companyDto = new CompanyDto(1L, "urlModel", "logo", "name", "description"); - statusDto = new StatusDto(2L, "label", "type"); contractTypeDto = new ContractTypeDto(3L, "label", "code"); jobPosting = JobPosting.builder() @@ -51,7 +43,6 @@ public void setUp() { .salary("salary") .keywords("keywords") .contractType(contractType) - .status(status) .createdAt(Instant.now()) .build(); } @@ -68,7 +59,6 @@ void toDtoTest() { assertThat(jobPostingDto.getLocation()).isEqualTo(jobPosting.getLocation()); assertThat(jobPostingDto.getSalary()).isEqualTo(jobPosting.getSalary()); assertThat(jobPostingDto.getKeywords()).isEqualTo(jobPosting.getKeywords()); - assertThat(jobPostingDto.getStatus()).isEqualTo(statusDto); assertThat(jobPostingDto.getContractType()).isEqualTo(contractTypeDto); assertThat(jobPostingDto.getCreatedAt()).isEqualTo(jobPosting.getCreatedAt()); } 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 6c1df6a2..3c9d51d6 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 @@ -16,14 +16,14 @@ import java.util.Arrays; import java.util.List; -import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.GET_JOB_URI; -import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.JOBS_BASE_URI; +import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.*; import static com.dynonuggets.refonteimplicaction.utils.Message.JOB_NOT_FOUND_MESSAGE; import static org.hamcrest.Matchers.is; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.*; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -126,4 +126,61 @@ void getJobByIdWithoutJwtShouldBeForbidden() throws Exception { verify(jobPostingService, times(0)).getJobById(anyLong()); } + + @Test + @WithMockUser + void archiveJobShouldChangeStatus() throws Exception { + // given + JobPostingDto givenDto = JobPostingDto.builder() + .id(1L) + .archive(false) + .build(); + + JobPostingDto expectedDto = JobPostingDto.builder() + .id(1L) + .archive(true) + .build(); + + given(jobPostingService.toggleArchiveJobPosting(anyLong())).willReturn(expectedDto); + + // when + final ResultActions resultActions = mvc.perform(patch(JOBS_BASE_URI + ARCHIVE_JOB_URI, givenDto.getId()).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is((givenDto.getId().intValue())))) + .andExpect(jsonPath("$.archive", is(!givenDto.isArchive()))); + verify(jobPostingService, times(1)).toggleArchiveJobPosting(anyLong()); + } + + @Test + @WithMockUser + void archiveJobPostingWhithUnexistingIdShouldThrowException() throws Exception { + // given + final long jobId = 123L; + final NotFoundException exception = new NotFoundException(String.format(JOB_NOT_FOUND_MESSAGE, jobId)); + given(jobPostingService.toggleArchiveJobPosting(anyLong())).willThrow(exception); + + // when + ResultActions resultActions = mvc.perform(patch(JOBS_BASE_URI + ARCHIVE_JOB_URI, jobId)); + + // then + resultActions.andExpect(status().isNotFound()); + verify(jobPostingService, times(1)).toggleArchiveJobPosting(anyLong()); + } + + @Test + void archiveJobByIdWithoutJwtShouldBeForbidden() throws Exception { + // given + final long jobId = 123L; + + // when + ResultActions resultActions = mvc.perform(patch(JOBS_BASE_URI + ARCHIVE_JOB_URI, jobId).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isForbidden()); + verify(jobPostingService, never()).toggleArchiveJobPosting(anyLong()); + } } diff --git a/data.sql b/data.sql index a51f3f02..4d4225f7 100644 --- a/data.sql +++ b/data.sql @@ -255,4 +255,4 @@ CREATE TABLE `work_experience` ALTER TABLE `job_posting` ADD `short_description` longtext NULL AFTER `description`; --- 2021-09-25 14:15:20 +-- 2021-09-25 14:15:20 \ No newline at end of file diff --git a/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.html b/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.html index 12965818..fb8997ca 100644 --- a/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.html +++ b/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.html @@ -59,7 +59,7 @@ type="button" >