feat: Implement create project route (SCRUM-7) #11

Merged
ptran merged 5 commits from feature/create-project into main 2024-09-25 11:03:47 +00:00
10 changed files with 344 additions and 344 deletions
Showing only changes of commit a93d569783 - Show all commits

@ -1,50 +1,50 @@
name: "Quality Check" name: "Quality Check"
on: on:
- pull_request - pull_request
jobs: jobs:
test: test:
name: "Tests" name: "Tests"
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
container: container:
image: "cimg/openjdk:21.0.2-node" image: "cimg/openjdk:21.0.2-node"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v3
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.gradle/caches ~/.gradle/caches
~/.gradle/wrapper ~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: "Prepare Gradle" - name: "Prepare Gradle"
run: gradle clean run: gradle clean
- name: "Check" - name: "Check"
run: gradle testClasses run: gradle testClasses
- name: "Stop Gradle" - name: "Stop Gradle"
run: gradle --stop run: gradle --stop
checkstyle: checkstyle:
name: "Checkstyle Main" name: "Checkstyle Main"
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
container: container:
image: "cimg/openjdk:21.0.2-node" image: "cimg/openjdk:21.0.2-node"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v3
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.gradle/caches ~/.gradle/caches
~/.gradle/wrapper ~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: "Prepare Gradle" - name: "Prepare Gradle"
run: gradle clean run: gradle clean
- name: "Check" - name: "Check"
run: gradle check run: gradle check
- name: "Stop Gradle" - name: "Stop Gradle"
run: gradle --stop run: gradle --stop

@ -1,6 +1,6 @@
POST https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token POST https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded
grant_type=password&client_id=employee-management-service&username=user&password=test grant_type=password&client_id=employee-management-service&username=user&password=test
> {% client.global.set("auth_token", response.body.access_token); %} > {% client.global.set("auth_token", response.body.access_token); %}

@ -1,15 +1,15 @@
### GET request to example server ### GET request to example server
POST http://localhost:8080/projects POST http://localhost:8080/projects
Authorization: Bearer {{auth_token}} Authorization: Bearer {{auth_token}}
Content-Type: application/json Content-Type: application/json
{ {
"name": "name", "name": "name",
"leading_employee": 1, "leading_employee": 1,
"employees": [2, 3], "employees": [2, 3],
"contractor": 4, "contractor": 4,
"contractorName": "Peter File", "contractorName": "Peter File",
"comment": "goal of project", "comment": "goal of project",
"startDate": "01.01.2000", "startDate": "01.01.2000",
"plannedEndDate": "01.01.2001" "plannedEndDate": "01.01.2001"
} }

@ -1,51 +1,51 @@
package de.szut.lf8_starter.exceptionHandling; package de.szut.lf8_starter.exceptionHandling;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.ConstraintViolationException; import jakarta.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequest;
import java.util.Date; import java.util.Date;
@ControllerAdvice @ControllerAdvice
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "500", description = "invalid JSON posted", @ApiResponse(responseCode = "500", description = "invalid JSON posted",
content = @Content) content = @Content)
}) })
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class) @ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleHelloEntityNotFoundException(ResourceNotFoundException ex, WebRequest request) { public ResponseEntity<?> handleHelloEntityNotFoundException(ResourceNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
} }
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public ResponseEntity<ErrorDetails> handleAllOtherExceptions(Exception ex, WebRequest request) { public ResponseEntity<ErrorDetails> handleAllOtherExceptions(Exception ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getClass() + " " + ex.getMessage(), request.getDescription(false)); ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getClass() + " " + ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR); return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
} }
@ExceptionHandler(MethodArgumentNotValidException.class) @ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorDetails> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) { public ResponseEntity<ErrorDetails> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
} }
@ExceptionHandler(ConstraintViolationException.class) @ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<ErrorDetails> handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) { public ResponseEntity<ErrorDetails> handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) {
String errorMessage = ex.getConstraintViolations().stream().findFirst().get().getMessage(); String errorMessage = ex.getConstraintViolations().stream().findFirst().get().getMessage();
ErrorDetails errorDetails = new ErrorDetails(new Date(), errorMessage, request.getDescription(false)); ErrorDetails errorDetails = new ErrorDetails(new Date(), errorMessage, request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
} }
} }

@ -1,43 +1,43 @@
package de.szut.lf8_starter.project; package de.szut.lf8_starter.project;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@Getter @Getter
@Setter @Setter
public class GetProjectDto { public class GetProjectDto {
@NotBlank @NotBlank
private String name; private String name;
@NotNull @NotNull
private long leadingEmployee; private long leadingEmployee;
private List<Long> employees; private List<Long> employees;
@NotNull @NotNull
private long contractor; private long contractor;
@NotBlank @NotBlank
private String contractorName; private String contractorName;
@NotBlank @NotBlank
private String comment; private String comment;
@NotNull @NotNull
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate startDate; private LocalDate startDate;
@NotNull @NotNull
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate plannedEndDate; private LocalDate plannedEndDate;
@NotNull @NotNull
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate endDate; private LocalDate endDate;
} }

@ -1,43 +1,43 @@
package de.szut.lf8_starter.project; package de.szut.lf8_starter.project;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.CreatedDate;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
@Setter @Setter
@Entity @Entity
@Table(name = "projects") @Table(name = "projects")
public class ProjectEntity { public class ProjectEntity {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id; private long id;
private String name; private String name;
private long leadingEmployee; private long leadingEmployee;
@ElementCollection @ElementCollection
private List<Long> employees; private List<Long> employees;
private long contractor; private long contractor;
private String contractorName; private String contractorName;
private String comment; private String comment;
@CreatedDate @CreatedDate
private LocalDate startDate; private LocalDate startDate;
private LocalDate plannedEndDate; private LocalDate plannedEndDate;
private LocalDate endDate; private LocalDate endDate;
} }

@ -1,39 +1,39 @@
package de.szut.lf8_starter.project; package de.szut.lf8_starter.project;
import de.szut.lf8_starter.project.dto.CreateProjectDto; import de.szut.lf8_starter.project.dto.CreateProjectDto;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class ProjectMapper { public class ProjectMapper {
public ProjectEntity mapCreateDtoToEntity(CreateProjectDto createProjectDto) { public ProjectEntity mapCreateDtoToEntity(CreateProjectDto createProjectDto) {
ProjectEntity projectEntity = new ProjectEntity(); ProjectEntity projectEntity = new ProjectEntity();
projectEntity.setName(createProjectDto.getName()); projectEntity.setName(createProjectDto.getName());
projectEntity.setComment(createProjectDto.getComment()); projectEntity.setComment(createProjectDto.getComment());
projectEntity.setLeadingEmployee(createProjectDto.getLeadingEmployee()); projectEntity.setLeadingEmployee(createProjectDto.getLeadingEmployee());
projectEntity.setEmployees(createProjectDto.getEmployees()); projectEntity.setEmployees(createProjectDto.getEmployees());
projectEntity.setContractor(createProjectDto.getContractor()); projectEntity.setContractor(createProjectDto.getContractor());
projectEntity.setContractorName(createProjectDto.getContractorName()); projectEntity.setContractorName(createProjectDto.getContractorName());
projectEntity.setStartDate(createProjectDto.getStartDate()); projectEntity.setStartDate(createProjectDto.getStartDate());
projectEntity.setPlannedEndDate(createProjectDto.getPlannedEndDate()); projectEntity.setPlannedEndDate(createProjectDto.getPlannedEndDate());
projectEntity.setEndDate(createProjectDto.getEndDate()); projectEntity.setEndDate(createProjectDto.getEndDate());
return projectEntity; return projectEntity;
} }
public GetProjectDto mapToGetDto(ProjectEntity projectEntity) { public GetProjectDto mapToGetDto(ProjectEntity projectEntity) {
GetProjectDto getProjectDto = new GetProjectDto(); GetProjectDto getProjectDto = new GetProjectDto();
getProjectDto.setName(projectEntity.getName()); getProjectDto.setName(projectEntity.getName());
getProjectDto.setComment(projectEntity.getComment()); getProjectDto.setComment(projectEntity.getComment());
getProjectDto.setLeadingEmployee(projectEntity.getLeadingEmployee()); getProjectDto.setLeadingEmployee(projectEntity.getLeadingEmployee());
getProjectDto.setEmployees(projectEntity.getEmployees()); getProjectDto.setEmployees(projectEntity.getEmployees());
getProjectDto.setContractor(projectEntity.getContractor()); getProjectDto.setContractor(projectEntity.getContractor());
getProjectDto.setContractorName(projectEntity.getContractorName()); getProjectDto.setContractorName(projectEntity.getContractorName());
getProjectDto.setStartDate(projectEntity.getStartDate()); getProjectDto.setStartDate(projectEntity.getStartDate());
getProjectDto.setPlannedEndDate(projectEntity.getPlannedEndDate()); getProjectDto.setPlannedEndDate(projectEntity.getPlannedEndDate());
getProjectDto.setEndDate(projectEntity.getEndDate()); getProjectDto.setEndDate(projectEntity.getEndDate());
return getProjectDto; return getProjectDto;
} }
} }

@ -1,16 +1,16 @@
package de.szut.lf8_starter.project; package de.szut.lf8_starter.project;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class ProjectService { public class ProjectService {
private final ProjectRepository projectRepository; private final ProjectRepository projectRepository;
public ProjectService(ProjectRepository projectRepository) { public ProjectService(ProjectRepository projectRepository) {
this.projectRepository = projectRepository; this.projectRepository = projectRepository;
} }
public ProjectEntity create(ProjectEntity projectEntity) { public ProjectEntity create(ProjectEntity projectEntity) {
return this.projectRepository.save(projectEntity); return this.projectRepository.save(projectEntity);
} }
} }

@ -1,42 +1,42 @@
package de.szut.lf8_starter.project.dto; package de.szut.lf8_starter.project.dto;
import de.szut.lf8_starter.project.GetProjectDto; import de.szut.lf8_starter.project.GetProjectDto;
import de.szut.lf8_starter.project.ProjectEntity; import de.szut.lf8_starter.project.ProjectEntity;
import de.szut.lf8_starter.project.ProjectMapper; import de.szut.lf8_starter.project.ProjectMapper;
import de.szut.lf8_starter.project.ProjectService; import de.szut.lf8_starter.project.ProjectService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@RequestMapping(value = "/projects") @RequestMapping(value = "/projects")
public class CreateProjectAction { public class CreateProjectAction {
private final ProjectService projectService; private final ProjectService projectService;
private final ProjectMapper projectMapper; private final ProjectMapper projectMapper;
public CreateProjectAction(ProjectService projectService, ProjectMapper mappingService) { public CreateProjectAction(ProjectService projectService, ProjectMapper mappingService) {
this.projectService = projectService; this.projectService = projectService;
this.projectMapper = mappingService; this.projectMapper = mappingService;
} }
@Operation(summary = "Creates a new Project") @Operation(summary = "Creates a new Project")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "created project", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))}), @ApiResponse(responseCode = "201", description = "created project", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))}),
@ApiResponse(responseCode = "400", description = "invalid JSON posted", content = @Content), @ApiResponse(responseCode = "400", description = "invalid JSON posted", content = @Content),
@ApiResponse(responseCode = "401", description = "not authorized", content = @Content)}) @ApiResponse(responseCode = "401", description = "not authorized", content = @Content)})
@PostMapping @PostMapping
public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) { public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) {
ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto); ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto);
projectEntity = this.projectService.create(projectEntity); projectEntity = this.projectService.create(projectEntity);
return this.projectMapper.mapToGetDto(projectEntity); return this.projectMapper.mapToGetDto(projectEntity);
} }
} }

@ -1,42 +1,42 @@
package de.szut.lf8_starter.project.dto; package de.szut.lf8_starter.project.dto;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@Getter @Getter
@Setter @Setter
public class CreateProjectDto { public class CreateProjectDto {
@NotBlank @NotBlank
private String name; private String name;
@NotNull @NotNull
private long leadingEmployee; private long leadingEmployee;
private List<Long> employees; private List<Long> employees;
@NotNull @NotNull
private long contractor; private long contractor;
@NotBlank @NotBlank
private String contractorName; private String contractorName;
@NotBlank @NotBlank
private String comment; private String comment;
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
@NotNull @NotNull
private LocalDate startDate; private LocalDate startDate;
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
@NotNull @NotNull
private LocalDate plannedEndDate; private LocalDate plannedEndDate;
@JsonFormat(pattern = "dd.MM.yyyy") @JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate endDate; private LocalDate endDate;
} }