feat: Implement create project route (SCRUM-7) (!11)
Co-authored-by: Phan Huy Tran <p.tran@neusta.de> Reviewed-on: #11 Reviewed-by: Jan Gleytenhoover <krisellp9@gmail.com>
This commit is contained in:
parent
5e9d4a1d0a
commit
8c275ab443
@ -1,4 +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); %}
|
@ -44,6 +44,7 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-validation")
|
||||||
compileOnly("org.projectlombok:lombok")
|
compileOnly("org.projectlombok:lombok")
|
||||||
annotationProcessor("org.projectlombok:lombok")
|
annotationProcessor("org.projectlombok:lombok")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
188
gradlew.bat
vendored
188
gradlew.bat
vendored
@ -1,94 +1,94 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem Copyright 2015 the original author or authors.
|
@rem Copyright 2015 the original author or authors.
|
||||||
@rem
|
@rem
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@rem you may not use this file except in compliance with the License.
|
@rem you may not use this file except in compliance with the License.
|
||||||
@rem You may obtain a copy of the License at
|
@rem You may obtain a copy of the License at
|
||||||
@rem
|
@rem
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@rem
|
@rem
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
@rem SPDX-License-Identifier: Apache-2.0
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
@rem This is normally unused
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo. 1>&2
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
exit /b %EXIT_CODE%
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
15
requests/createProject.http
Normal file
15
requests/createProject.http
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
### GET request to example server
|
||||||
|
POST http://localhost:8080/projects
|
||||||
|
Authorization: Bearer {{auth_token}}
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"leading_employee": 1,
|
||||||
|
"employees": [2, 3],
|
||||||
|
"contractor": 4,
|
||||||
|
"contractorName": "Peter File",
|
||||||
|
"comment": "goal of project",
|
||||||
|
"startDate": "01.01.2000",
|
||||||
|
"plannedEndDate": "01.01.2001"
|
||||||
|
}
|
@ -3,8 +3,10 @@ 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 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.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;
|
||||||
@ -24,5 +26,26 @@ public class GlobalExceptionHandler {
|
|||||||
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<ErrorDetails> handleAllOtherExceptions(Exception ex, WebRequest request) {
|
||||||
|
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getClass() + " " + ex.getMessage(), request.getDescription(false));
|
||||||
|
|
||||||
|
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<ErrorDetails> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) {
|
||||||
|
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
|
||||||
|
|
||||||
|
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConstraintViolationException.class)
|
||||||
|
public ResponseEntity<ErrorDetails> handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) {
|
||||||
|
String errorMessage = ex.getConstraintViolations().stream().findFirst().get().getMessage();
|
||||||
|
|
||||||
|
ErrorDetails errorDetails = new ErrorDetails(new Date(), errorMessage, request.getDescription(false));
|
||||||
|
|
||||||
|
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package de.szut.lf8_starter.project;
|
||||||
|
|
||||||
|
import de.szut.lf8_starter.project.dto.CreateProjectDto;
|
||||||
|
import de.szut.lf8_starter.project.dto.GetProjectDto;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/projects")
|
||||||
|
public class CreateProjectAction {
|
||||||
|
private final ProjectService projectService;
|
||||||
|
private final ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
public CreateProjectAction(ProjectService projectService, ProjectMapper mappingService) {
|
||||||
|
this.projectService = projectService;
|
||||||
|
this.projectMapper = mappingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "Creates a new Project")
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@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 = "401", description = "not authorized", content = @Content)})
|
||||||
|
@PostMapping
|
||||||
|
public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) {
|
||||||
|
ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto);
|
||||||
|
|
||||||
|
projectEntity = this.projectService.create(projectEntity);
|
||||||
|
|
||||||
|
return this.projectMapper.mapToGetDto(projectEntity);
|
||||||
|
}
|
||||||
|
}
|
@ -37,5 +37,7 @@ public class ProjectEntity {
|
|||||||
@CreatedDate
|
@CreatedDate
|
||||||
private LocalDate startDate;
|
private LocalDate startDate;
|
||||||
|
|
||||||
|
private LocalDate plannedEndDate;
|
||||||
|
|
||||||
private LocalDate endDate;
|
private LocalDate endDate;
|
||||||
}
|
}
|
||||||
|
40
src/main/java/de/szut/lf8_starter/project/ProjectMapper.java
Normal file
40
src/main/java/de/szut/lf8_starter/project/ProjectMapper.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package de.szut.lf8_starter.project;
|
||||||
|
|
||||||
|
import de.szut.lf8_starter.project.dto.CreateProjectDto;
|
||||||
|
import de.szut.lf8_starter.project.dto.GetProjectDto;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ProjectMapper {
|
||||||
|
public ProjectEntity mapCreateDtoToEntity(CreateProjectDto createProjectDto) {
|
||||||
|
ProjectEntity projectEntity = new ProjectEntity();
|
||||||
|
|
||||||
|
projectEntity.setName(createProjectDto.getName());
|
||||||
|
projectEntity.setComment(createProjectDto.getComment());
|
||||||
|
projectEntity.setLeadingEmployee(createProjectDto.getLeadingEmployee());
|
||||||
|
projectEntity.setEmployees(createProjectDto.getEmployees());
|
||||||
|
projectEntity.setContractor(createProjectDto.getContractor());
|
||||||
|
projectEntity.setContractorName(createProjectDto.getContractorName());
|
||||||
|
projectEntity.setStartDate(createProjectDto.getStartDate());
|
||||||
|
projectEntity.setPlannedEndDate(createProjectDto.getPlannedEndDate());
|
||||||
|
projectEntity.setEndDate(createProjectDto.getEndDate());
|
||||||
|
|
||||||
|
return projectEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetProjectDto mapToGetDto(ProjectEntity projectEntity) {
|
||||||
|
GetProjectDto getProjectDto = new GetProjectDto();
|
||||||
|
|
||||||
|
getProjectDto.setName(projectEntity.getName());
|
||||||
|
getProjectDto.setComment(projectEntity.getComment());
|
||||||
|
getProjectDto.setLeadingEmployee(projectEntity.getLeadingEmployee());
|
||||||
|
getProjectDto.setEmployees(projectEntity.getEmployees());
|
||||||
|
getProjectDto.setContractor(projectEntity.getContractor());
|
||||||
|
getProjectDto.setContractorName(projectEntity.getContractorName());
|
||||||
|
getProjectDto.setStartDate(projectEntity.getStartDate());
|
||||||
|
getProjectDto.setPlannedEndDate(projectEntity.getPlannedEndDate());
|
||||||
|
getProjectDto.setEndDate(projectEntity.getEndDate());
|
||||||
|
|
||||||
|
return getProjectDto;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package de.szut.lf8_starter.project;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ProjectService {
|
||||||
|
private final ProjectRepository projectRepository;
|
||||||
|
|
||||||
|
public ProjectService(ProjectRepository projectRepository) {
|
||||||
|
this.projectRepository = projectRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectEntity create(ProjectEntity projectEntity) {
|
||||||
|
return this.projectRepository.save(projectEntity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package de.szut.lf8_starter.project.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CreateProjectDto {
|
||||||
|
@NotBlank
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private long leadingEmployee;
|
||||||
|
|
||||||
|
private List<Long> employees;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private long contractor;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String contractorName;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
@NotNull
|
||||||
|
private LocalDate startDate;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
@NotNull
|
||||||
|
private LocalDate plannedEndDate;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
private LocalDate endDate;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package de.szut.lf8_starter.project.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GetProjectDto {
|
||||||
|
@NotBlank
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private long leadingEmployee;
|
||||||
|
|
||||||
|
private List<Long> employees;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private long contractor;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String contractorName;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
private LocalDate startDate;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
private LocalDate plannedEndDate;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||||
|
private LocalDate endDate;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user