mirror of
https://github.com/st-tu-dresden-praktikum/swt23w23
synced 2024-07-19 21:04:36 +02:00
parent
a46d2ad169
commit
0119b1cfa0
|
@ -300,6 +300,7 @@ image:models/design/staff.svg[class design diagram - Staff]
|
||||||
|StaffController |A Spring MVC Controller for handling staff-related operations such as adding, removing, and updating staff data. It interacts with StaffManagement.
|
|StaffController |A Spring MVC Controller for handling staff-related operations such as adding, removing, and updating staff data. It interacts with StaffManagement.
|
||||||
|StaffManagement |A class that manages interactions and logic with StaffRepository. It provides methods to find, save/add, list, and delete staff members.
|
|StaffManagement |A class that manages interactions and logic with StaffRepository. It provides methods to find, save/add, list, and delete staff members.
|
||||||
|StaffRepository |An extension of 'CrudRepository' that provides standard methods to perform CRUD operations on staff objects.
|
|StaffRepository |An extension of 'CrudRepository' that provides standard methods to perform CRUD operations on staff objects.
|
||||||
|
|StaffForm |A Form to cache a user input that was made during registration or updating an Employee.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
=== Link between analysis and design
|
=== Link between analysis and design
|
||||||
|
|
|
@ -6,6 +6,8 @@ skinparam groupInheritance 2
|
||||||
package Spring {
|
package Spring {
|
||||||
class CrudRepository
|
class CrudRepository
|
||||||
class Streamable
|
class Streamable
|
||||||
|
class Errors
|
||||||
|
class Model
|
||||||
}
|
}
|
||||||
|
|
||||||
package catering.staff {
|
package catering.staff {
|
||||||
|
@ -32,13 +34,18 @@ package catering.staff {
|
||||||
class StaffController {
|
class StaffController {
|
||||||
+ StaffController(staffRepository: StaffRepository)
|
+ StaffController(staffRepository: StaffRepository)
|
||||||
+ getStaff(model: Model): String
|
+ getStaff(model: Model): String
|
||||||
|
+ getStaff(model: Model, form: StaffForm): String
|
||||||
+ removeEmployee(employee: Employee, model: Model): String
|
+ removeEmployee(employee: Employee, model: Model): String
|
||||||
+ addEmployee(name: String, job: JobType): String
|
+ addEmployee(form:StaffForm, result:Errors, model: Model): String
|
||||||
+ editEmployee(employee: Employee, model Model): String
|
+ editEmployee(employee: Employee, model Model): String
|
||||||
+ updateEmployee(employee: Employee, name: String, job: JobType): String
|
+ editEmployee(model Model, form:StaffForm): String
|
||||||
|
+ updateEmployee(employee: Employee, form:StaffForm): String
|
||||||
}
|
}
|
||||||
StaffController --> StaffManagement : -staffManagement
|
StaffController --> StaffManagement : -staffManagement
|
||||||
StaffController ..> Employee
|
StaffController ..> Employee
|
||||||
|
StaffController ..> StaffForm
|
||||||
|
StaffController ..> Model
|
||||||
|
StaffController ..> Errors
|
||||||
|
|
||||||
class StaffManagement {
|
class StaffManagement {
|
||||||
+ StaffManagement(staffRepository: StaffRepository)
|
+ StaffManagement(staffRepository: StaffRepository)
|
||||||
|
@ -56,6 +63,16 @@ package catering.staff {
|
||||||
StaffRepository ..|> Streamable
|
StaffRepository ..|> Streamable
|
||||||
StaffRepository o-- Employee
|
StaffRepository o-- Employee
|
||||||
|
|
||||||
|
class StaffForm {
|
||||||
|
- name: String
|
||||||
|
+ StaffForm(): void
|
||||||
|
+ getName(): String
|
||||||
|
+ getJob(): JobType
|
||||||
|
+ setName(name:String): void
|
||||||
|
+ setJob(job:JobType): void
|
||||||
|
+ validate(e:Errors): void
|
||||||
|
}
|
||||||
|
StaffForm ..> JobType : -job
|
||||||
}
|
}
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
BIN
src/main/asciidoc/models/design/staff.svg
(Stored with Git LFS)
BIN
src/main/asciidoc/models/design/staff.svg
(Stored with Git LFS)
Binary file not shown.
|
@ -3,11 +3,15 @@ package catering.staff;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class StaffController {
|
public class StaffController {
|
||||||
|
@ -21,10 +25,26 @@ public class StaffController {
|
||||||
@GetMapping("/staff")
|
@GetMapping("/staff")
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public String getStaff(Model model) {
|
public String getStaff(Model model) {
|
||||||
|
return getStaff(model, new StaffForm());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStaff(Model model, @Valid StaffForm form) {
|
||||||
model.addAttribute("staff", staffManagement.findAll());
|
model.addAttribute("staff", staffManagement.findAll());
|
||||||
|
model.addAttribute("form", form);
|
||||||
return "staff";
|
return "staff";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/staff/add")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public String addEmployee(@Valid @ModelAttribute("form") StaffForm form, Errors result, Model model) {
|
||||||
|
form.validate(result);
|
||||||
|
if (result.hasErrors()) {
|
||||||
|
return getStaff(model, form);
|
||||||
|
}
|
||||||
|
staffManagement.save(new Employee(form.getName(), form.getJob()));
|
||||||
|
return "redirect:/staff";
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/staff/remove")
|
@PostMapping("/staff/remove")
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public String removeEmployee(@RequestParam("id") Employee employee, Model model) {
|
public String removeEmployee(@RequestParam("id") Employee employee, Model model) {
|
||||||
|
@ -32,25 +52,30 @@ public class StaffController {
|
||||||
return "redirect:/staff";
|
return "redirect:/staff";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/staff/add")
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
|
||||||
public String addEmployee(@RequestParam String name, @RequestParam JobType job) {
|
|
||||||
staffManagement.save(new Employee(name, job));
|
|
||||||
return "redirect:/staff";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/staff/edit/{id}")
|
@GetMapping("/staff/edit/{id}")
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public String editEmployee(@PathVariable("id") Employee employee, Model model) {
|
public String editEmployee(@PathVariable("id") Employee employee, Model model) {
|
||||||
model.addAttribute("employee", employee);
|
StaffForm form = new StaffForm();
|
||||||
|
form.setJob(employee.getJob());
|
||||||
|
form.setName(employee.getName());
|
||||||
|
return editEmployee(model, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String editEmployee(Model model, @Valid StaffForm form) {
|
||||||
|
model.addAttribute("form", form);
|
||||||
return "edit-staff";
|
return "edit-staff";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/staff/edit/{id}")
|
@PostMapping("/staff/edit/{id}")
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public String updateEmployee(@PathVariable("id") Employee employee, @RequestParam String name, @RequestParam JobType job) {
|
public String updateEmployee(@PathVariable("id") Employee employee, @Valid @ModelAttribute("form") StaffForm form,
|
||||||
employee.setJob(job);
|
Errors result, Model model) {
|
||||||
employee.setName(name);
|
form.validate(result);
|
||||||
|
if (result.hasErrors()) {
|
||||||
|
return editEmployee(model, form);
|
||||||
|
}
|
||||||
|
employee.setJob(form.getJob());
|
||||||
|
employee.setName(form.getName());
|
||||||
staffManagement.save(employee);
|
staffManagement.save(employee);
|
||||||
return "redirect:/staff";
|
return "redirect:/staff";
|
||||||
}
|
}
|
||||||
|
|
38
src/main/java/catering/staff/StaffForm.java
Normal file
38
src/main/java/catering/staff/StaffForm.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package catering.staff;
|
||||||
|
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class StaffForm {
|
||||||
|
|
||||||
|
private @NotEmpty String name;
|
||||||
|
private @NotNull JobType job;
|
||||||
|
|
||||||
|
public StaffForm() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobType getJob() {
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJob(JobType job) {
|
||||||
|
this.job = job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(Errors e) {
|
||||||
|
if (job == null) {
|
||||||
|
e.rejectValue("job", "job is not a job type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,17 +7,18 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
<form th:object="${employee}" method="post">
|
<form th:object="${form}" method="post">
|
||||||
<input type="hidden" th:field="*{id}" />
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="name">Name:</label>
|
<label class="form-label" for="name">Name:</label>
|
||||||
<input class="form-control" type="text" th:field="*{name}" required />
|
<input class="form-control" type="text" th:field="*{name}" th:errorclass="is-invalid" required/>
|
||||||
|
<div th:if="${#fields.hasErrors('name')}" class="invalid-feedback">Ungültiger Name</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="job">Beruf:</label>
|
<label class="form-label" for="job">Beruf:</label>
|
||||||
<select name="job" class="form-select">
|
<select th:field="*{job}" class="form-select" th:errorclass="is-invalid">
|
||||||
<option th:each="type : ${T(catering.staff.JobType).values()}" th:value="${type}" th:selected="${type.name() == employee.job.name()}" th:text="${type}" required></option>
|
<option th:each="type : ${T(catering.staff.JobType).values()}" th:value="${type}" th:text="${type}" required></option>
|
||||||
</select>
|
</select>
|
||||||
|
<div th:if="${#fields.hasErrors('job')}" class="invalid-feedback">Ungültiger Job</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" type="submit">Speichern</button>
|
<button class="btn btn-primary" type="submit">Speichern</button>
|
||||||
<a th:href="@{/staff}"><button type="button" class="btn btn-danger">Abbrechen</button></a>
|
<a th:href="@{/staff}"><button type="button" class="btn btn-danger">Abbrechen</button></a>
|
||||||
|
|
|
@ -37,16 +37,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2>Personal Hinzufügen</h2>
|
<h2>Personal Hinzufügen</h2>
|
||||||
<form action="/staff/add" method="post">
|
<form th:object="${form}" th:action="@{/staff/add}" method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="name">Name</label>
|
<label class="form-label" for="name">Name</label>
|
||||||
<input class="form-control" type="text" name="name" required />
|
<input class="form-control" type="text" th:field="*{name}" th:errorclass="is-invalid" required>
|
||||||
|
<div th:if="${#fields.hasErrors('name')}" class="invalid-feedback">Ungültiger Name</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="job">Beruf:</label>
|
<label class="form-label" for="job">Beruf:</label>
|
||||||
<select name="job" class="form-select">
|
<select th:field="*{job}" class="form-select" th:errorclass="is-invalid">
|
||||||
<option th:each="type : ${T(catering.staff.JobType).values()}" th:value="${type}" th:text="${type}" required></option>
|
<option th:each="type : ${T(catering.staff.JobType).values()}" th:value="${type}" th:text="${type}" required></option>
|
||||||
</select>
|
</select>
|
||||||
|
<div th:if="${#fields.hasErrors('job')}" class="invalid-feedback">Ungültiger Job</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" type="submit">Hinzufügen</button>
|
<button class="btn btn-primary" type="submit">Hinzufügen</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -29,8 +29,8 @@ class StaffControllerIntegrationTests {
|
||||||
MockMvc mvc;
|
MockMvc mvc;
|
||||||
|
|
||||||
MockHttpServletRequestBuilder createStaff = post("/staff/add")
|
MockHttpServletRequestBuilder createStaff = post("/staff/add")
|
||||||
.param("name", "Karl Baum")
|
.param("name", "Karl Baum")
|
||||||
.param("job", "COOK");
|
.param("job", "COOK");
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StaffManagement staffManagement;
|
private StaffManagement staffManagement;
|
||||||
|
@ -55,16 +55,16 @@ class StaffControllerIntegrationTests {
|
||||||
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
void viewStaff() throws Exception {
|
void viewStaff() throws Exception {
|
||||||
mvc.perform(get("/staff"))
|
mvc.perform(get("/staff"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(content().string(containsString(defaultEmployee.getName())));
|
.andExpect(content().string(containsString(defaultEmployee.getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
void viewStaffEditPage() throws Exception {
|
void viewStaffEditPage() throws Exception {
|
||||||
mvc.perform(get("/staff/edit/" + defaultEmployeeId.toString()))
|
mvc.perform(get("/staff/edit/" + defaultEmployeeId.toString()))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(content().string(containsString(defaultEmployee.getName())));
|
.andExpect(content().string(containsString(defaultEmployee.getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -83,12 +83,12 @@ class StaffControllerIntegrationTests {
|
||||||
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
void modifyStaff() throws Exception {
|
void modifyStaff() throws Exception {
|
||||||
mvc.perform(post("/staff/edit/" + defaultEmployeeId.toString())
|
mvc.perform(post("/staff/edit/" + defaultEmployeeId.toString())
|
||||||
.param("name", "Dieter Bäume")
|
.param("name", "Dieter Bäume")
|
||||||
.param("job", "SERVICE")).andExpect(redirectedUrl("/staff"))
|
.param("job", "SERVICE")).andExpect(redirectedUrl("/staff"))
|
||||||
.andExpect(redirectedUrl("/staff"));
|
.andExpect(redirectedUrl("/staff"));
|
||||||
assertThat(staffManagement.findById(defaultEmployeeId).get())
|
assertThat(staffManagement.findById(defaultEmployeeId).get())
|
||||||
.extracting("name", "job")
|
.extracting("name", "job")
|
||||||
.containsExactly("Dieter Bäume", JobType.SERVICE);
|
.containsExactly("Dieter Bäume", JobType.SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -103,6 +103,53 @@ class StaffControllerIntegrationTests {
|
||||||
.doesNotContain("Dieter Baum");
|
.doesNotContain("Dieter Baum");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
|
void addStaffWrong() throws Exception {
|
||||||
|
mvc.perform(post("/staff/add"))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Name")))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Job")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
|
void editStaffWrong() throws Exception {
|
||||||
|
mvc.perform(post("/staff/edit/" + defaultEmployeeId.toString()))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Name")))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Job")));
|
||||||
|
assertThat(staffManagement.findById(defaultEmployeeId).get())
|
||||||
|
.extracting("name", "job")
|
||||||
|
.containsExactly("Dieter Baum", JobType.COOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
|
void addStaffWithWrongJobType() throws Exception {
|
||||||
|
assertThat(staffManagement.findAll().stream())
|
||||||
|
.extracting("name")
|
||||||
|
.doesNotContain("Paul Kunst");
|
||||||
|
mvc.perform(post("/staff/add")
|
||||||
|
.param("name", "Paul Kunst")
|
||||||
|
.param("job", "notAJob"))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Job")));
|
||||||
|
assertThat(staffManagement.findAll().stream())
|
||||||
|
.extracting("name")
|
||||||
|
.doesNotContain("Paul Kunst");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||||
|
void editStaffWithWrongJobType() throws Exception {
|
||||||
|
mvc.perform(
|
||||||
|
post("/staff/edit/" + defaultEmployeeId.toString())
|
||||||
|
.param("name", defaultEmployee.getName())
|
||||||
|
.param("job", "notAJob"))
|
||||||
|
.andExpect(content().string(containsString("Ungültiger Job")));
|
||||||
|
assertThat(staffManagement.findById(defaultEmployeeId).get())
|
||||||
|
.extracting("name", "job")
|
||||||
|
.containsExactly("Dieter Baum", JobType.COOK);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "dieter", password = "123", roles = "CUSTOMER")
|
@WithMockUser(username = "dieter", password = "123", roles = "CUSTOMER")
|
||||||
void refuseCustomer() throws Exception {
|
void refuseCustomer() throws Exception {
|
||||||
|
@ -114,10 +161,10 @@ class StaffControllerIntegrationTests {
|
||||||
@WithAnonymousUser
|
@WithAnonymousUser
|
||||||
void refuseAnonymous() throws Exception {
|
void refuseAnonymous() throws Exception {
|
||||||
mvc.perform(get("/staff"))
|
mvc.perform(get("/staff"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
|
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
|
||||||
mvc.perform(get("/staff/edit/" + defaultEmployeeId))
|
mvc.perform(get("/staff/edit/" + defaultEmployeeId))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
|
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue