Add wage to employee

This commit is contained in:
Denis Natusch 2023-12-04 11:34:07 +01:00 committed by Simon Bruder
parent 17a0e29dad
commit af09dd4a83
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC
11 changed files with 88 additions and 19 deletions

View file

@ -3,6 +3,12 @@
skinparam linetype ortho skinparam linetype ortho
skinparam groupInheritance 2 skinparam groupInheritance 2
package javax.money {
class MonetaryAmount
class Money
class EURO
}
package Spring { package Spring {
class CrudRepository class CrudRepository
class Streamable class Streamable
@ -21,15 +27,18 @@ package catering.staff {
- name: String - name: String
- id: Long - id: Long
+ Employee() + Employee()
+ Employee(name: String, job: JobType) + Employee(name: String, job: JobType, wage: MonetaryAmount)
+ getId(): Long + getId(): Long
+ getName(): String + getName(): String
+ getJob(): JobType + getJob(): JobType
+ getWage(): Double
+ setName(name: String): void + setName(name: String): void
+ setJob(job: JobType): void + setJob(job: JobType): void
+ setWage(wage: Double): void
} }
Employee --> JobType : -job Employee --> JobType : -job
Employee --> MonetaryAmount : -wage
enum JobType { enum JobType {
COOK COOK
@ -51,6 +60,8 @@ package catering.staff {
StaffController ..> StaffForm StaffController ..> StaffForm
StaffController ..> Model StaffController ..> Model
StaffController ..> Errors StaffController ..> Errors
StaffController ..> Money
StaffController ..> EURO
class StaffManagement { class StaffManagement {
+ StaffManagement(staffRepository: StaffRepository, orderManagement:OrderManagement<CustomOrder>) + StaffManagement(staffRepository: StaffRepository, orderManagement:OrderManagement<CustomOrder>)
@ -76,8 +87,10 @@ package catering.staff {
+ StaffForm(): void + StaffForm(): void
+ getName(): String + getName(): String
+ getJob(): JobType + getJob(): JobType
+ getWage(): Double
+ setName(name:String): void + setName(name:String): void
+ setJob(job:JobType): void + setJob(job:JobType): void
+ setWage( wage:Double): void
+ validate(e:Errors): void + validate(e:Errors): void
} }
StaffForm ..> JobType : -job StaffForm ..> JobType : -job

BIN
src/main/asciidoc/models/design/staff.svg (Stored with Git LFS)

Binary file not shown.

View file

@ -1,5 +1,11 @@
package catering.staff; package catering.staff;
import static org.salespointframework.core.Currencies.EURO;
import javax.money.MonetaryAmount;
import org.javamoney.moneta.Money;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id; import jakarta.persistence.Id;
@ -10,14 +16,16 @@ public class Employee {
private String name; private String name;
private JobType job; private JobType job;
private @Id @GeneratedValue Long id; private @Id @GeneratedValue Long id;
private MonetaryAmount wage;
protected Employee() { protected Employee() {
// No-argument constructor for JPA // No-argument constructor for JPA
} }
public Employee(String name, JobType job) { public Employee(String name, JobType job, MonetaryAmount wage) {
this.name = name; this.name = name;
this.job = job; this.job = job;
this.wage = wage;
} }
public Long getId() { public Long getId() {
@ -32,6 +40,9 @@ public class Employee {
return job; return job;
} }
public Double getWage() {
return wage.getNumber().doubleValue();
}
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
@ -41,6 +52,10 @@ public class Employee {
this.job = job; this.job = job;
} }
public void setWage(Double wage) {
this.wage = Money.of(wage, EURO);
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj instanceof Employee other) { if (obj instanceof Employee other) {

View file

@ -1,5 +1,8 @@
package catering.staff; package catering.staff;
import static org.salespointframework.core.Currencies.EURO;
import org.javamoney.moneta.Money;
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.ui.Model; import org.springframework.ui.Model;
@ -40,7 +43,7 @@ public class StaffController {
if (result.hasErrors()) { if (result.hasErrors()) {
return getStaff(model, form); return getStaff(model, form);
} }
staffManagement.save(new Employee(form.getName(), form.getJob())); staffManagement.save(new Employee(form.getName(), form.getJob(), Money.of(form.getWage(), EURO)));
return "redirect:/staff"; return "redirect:/staff";
} }
@ -57,6 +60,7 @@ public class StaffController {
StaffForm form = new StaffForm(); StaffForm form = new StaffForm();
form.setJob(employee.getJob()); form.setJob(employee.getJob());
form.setName(employee.getName()); form.setName(employee.getName());
form.setWage(employee.getWage());
return editEmployee(model, form); return editEmployee(model, form);
} }
@ -75,6 +79,7 @@ public class StaffController {
} }
employee.setJob(form.getJob()); employee.setJob(form.getJob());
employee.setName(form.getName()); employee.setName(form.getName());
employee.setWage(form.getWage());
staffManagement.save(employee); staffManagement.save(employee);
return "redirect:/staff"; return "redirect:/staff";
} }

View file

@ -4,11 +4,13 @@ import org.springframework.validation.Errors;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
public class StaffForm { public class StaffForm {
private @NotEmpty String name; private @NotEmpty String name;
private @NotNull JobType job; private @NotNull JobType job;
private @PositiveOrZero @NotNull Double wage;
public StaffForm() { public StaffForm() {
} }
@ -21,6 +23,10 @@ public class StaffForm {
return job; return job;
} }
public Double getWage() {
return wage;
}
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@ -29,6 +35,10 @@ public class StaffForm {
this.job = job; this.job = job;
} }
public void setWage(Double wage) {
this.wage = wage;
}
public void validate(Errors e) { public void validate(Errors e) {
if (job == null) { if (job == null) {
e.rejectValue("job", "job is not a job type"); e.rejectValue("job", "job is not a job type");

View file

@ -13,6 +13,11 @@
<input class="form-control" type="text" th:field="*{name}" th:errorclass="is-invalid" 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 th:if="${#fields.hasErrors('name')}" class="invalid-feedback">Ungültiger Name</div>
</div> </div>
<div class="mb-3">
<label class="form-label" for="wage">Lohn:</label>
<input class="form-control" type="text" th:field="*{wage}" th:errorclass="is-invalid" required/>
<div th:if="${#fields.hasErrors('wage')}" class="invalid-feedback">Ungültiger Lohn</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 th:field="*{job}" class="form-select" th:errorclass="is-invalid"> <select th:field="*{job}" class="form-select" th:errorclass="is-invalid">

View file

@ -14,6 +14,7 @@
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Beruf</th> <th>Beruf</th>
<th>Lohn</th>
<th></th> <th></th>
<th></th> <th></th>
</tr> </tr>
@ -21,6 +22,7 @@
<tr th:each="employee : ${staff}"> <tr th:each="employee : ${staff}">
<td th:text="${employee.name}">Max</td> <td th:text="${employee.name}">Max</td>
<td th:text="${employee.job}">Koch</td> <td th:text="${employee.job}">Koch</td>
<td th:text="${employee.wage}"></td>
<td> <td>
<a th:href="@{'/staff/edit/' + ${employee.id}}" <a th:href="@{'/staff/edit/' + ${employee.id}}"
><button class="btn btn-warning">Bearbeiten</button></a ><button class="btn btn-warning">Bearbeiten</button></a
@ -43,6 +45,11 @@
<input class="form-control" type="text" th:field="*{name}" th:errorclass="is-invalid" 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 th:if="${#fields.hasErrors('name')}" class="invalid-feedback">Ungültiger Name</div>
</div> </div>
<div class="mb-3">
<label class="form-label" for="wage">Lohn</label>
<input class="form-control" type="text" th:field="*{wage}" th:errorclass="is-invalid" required>
<div th:if="${#fields.hasErrors('wage')}" class="invalid-feedback">Ungültiger Lohn</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 th:field="*{job}" class="form-select" th:errorclass="is-invalid"> <select th:field="*{job}" class="form-select" th:errorclass="is-invalid">

View file

@ -3,6 +3,8 @@ package catering.order;
import catering.staff.JobType; import catering.staff.JobType;
import catering.staff.Employee; import catering.staff.Employee;
import catering.staff.StaffManagement; import catering.staff.StaffManagement;
import org.javamoney.moneta.Money;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.salespointframework.catalog.Product; import org.salespointframework.catalog.Product;
@ -28,6 +30,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.salespointframework.core.Currencies.EURO;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -63,7 +66,7 @@ public class OrderControllerIntegrationTests {
Password.UnencryptedPassword.of("12345"), Role.of("CUSTOMER")); Password.UnencryptedPassword.of("12345"), Role.of("CUSTOMER"));
} }
myEmployee = new Employee("Sabrina", JobType.SERVICE); myEmployee = new Employee("Sabrina", JobType.SERVICE, Money.of(10, EURO));
staffManagement.save(myEmployee); staffManagement.save(myEmployee);
myUser = userAccountManagement.findByUsername("andi").get(); myUser = userAccountManagement.findByUsername("andi").get();

View file

@ -15,6 +15,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.salespointframework.core.Currencies.EURO;
@SpringBootTest @SpringBootTest
public class OrderUnitTests { public class OrderUnitTests {
@ -26,7 +27,7 @@ public class OrderUnitTests {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
employee = new Employee("Peter Muffin", JobType.COOK); employee = new Employee("Peter Muffin", JobType.COOK, Money.of(10, EURO));
staffManagement.save(employee); staffManagement.save(employee);
order = new CustomOrder(UserAccount.UserAccountIdentifier.of("12345"), order = new CustomOrder(UserAccount.UserAccountIdentifier.of("12345"),

View file

@ -1,26 +1,28 @@
package catering.staff; package catering.staff;
import static org.hamcrest.CoreMatchers.endsWith; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.salespointframework.core.Currencies.EURO;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 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.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.assertj.core.api.Assertions.assertThat;
import org.javamoney.moneta.Money;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.http.HttpHeaders;
@AutoConfigureMockMvc @AutoConfigureMockMvc
@SpringBootTest @SpringBootTest
@ -30,6 +32,7 @@ class StaffControllerIntegrationTests {
MockHttpServletRequestBuilder createStaff = post("/staff/add") MockHttpServletRequestBuilder createStaff = post("/staff/add")
.param("name", "Karl Baum") .param("name", "Karl Baum")
.param("wage", "10")
.param("job", "COOK"); .param("job", "COOK");
@Autowired @Autowired
@ -40,7 +43,7 @@ class StaffControllerIntegrationTests {
@BeforeEach @BeforeEach
void setup() throws Exception { void setup() throws Exception {
defaultEmployee = staffManagement.save(new Employee("Dieter Baum", JobType.COOK)); defaultEmployee = staffManagement.save(new Employee("Dieter Baum", JobType.COOK, Money.of(0, EURO)));
defaultEmployeeId = defaultEmployee.getId(); defaultEmployeeId = defaultEmployee.getId();
} }
@ -84,6 +87,7 @@ class StaffControllerIntegrationTests {
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("wage", "10")
.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())
@ -108,6 +112,7 @@ class StaffControllerIntegrationTests {
void addStaffWrong() throws Exception { void addStaffWrong() throws Exception {
mvc.perform(post("/staff/add")) mvc.perform(post("/staff/add"))
.andExpect(content().string(containsString("Ungültiger Name"))) .andExpect(content().string(containsString("Ungültiger Name")))
.andExpect(content().string(containsString("Ungültiger Lohn")))
.andExpect(content().string(containsString("Ungültiger Job"))); .andExpect(content().string(containsString("Ungültiger Job")));
} }
@ -116,6 +121,7 @@ class StaffControllerIntegrationTests {
void editStaffWrong() throws Exception { void editStaffWrong() throws Exception {
mvc.perform(post("/staff/edit/" + defaultEmployeeId.toString())) mvc.perform(post("/staff/edit/" + defaultEmployeeId.toString()))
.andExpect(content().string(containsString("Ungültiger Name"))) .andExpect(content().string(containsString("Ungültiger Name")))
.andExpect(content().string(containsString("Ungültiger Lohn")))
.andExpect(content().string(containsString("Ungültiger Job"))); .andExpect(content().string(containsString("Ungültiger Job")));
assertThat(staffManagement.findById(defaultEmployeeId).get()) assertThat(staffManagement.findById(defaultEmployeeId).get())
.extracting("name", "job") .extracting("name", "job")
@ -130,6 +136,7 @@ class StaffControllerIntegrationTests {
.doesNotContain("Paul Kunst"); .doesNotContain("Paul Kunst");
mvc.perform(post("/staff/add") mvc.perform(post("/staff/add")
.param("name", "Paul Kunst") .param("name", "Paul Kunst")
.param("wage", "10")
.param("job", "notAJob")) .param("job", "notAJob"))
.andExpect(content().string(containsString("Ungültiger Job"))); .andExpect(content().string(containsString("Ungültiger Job")));
assertThat(staffManagement.findAll().stream()) assertThat(staffManagement.findAll().stream())
@ -143,6 +150,7 @@ class StaffControllerIntegrationTests {
mvc.perform( mvc.perform(
post("/staff/edit/" + defaultEmployeeId.toString()) post("/staff/edit/" + defaultEmployeeId.toString())
.param("name", defaultEmployee.getName()) .param("name", defaultEmployee.getName())
.param("wage", "10")
.param("job", "notAJob")) .param("job", "notAJob"))
.andExpect(content().string(containsString("Ungültiger Job"))); .andExpect(content().string(containsString("Ungültiger Job")));
assertThat(staffManagement.findById(defaultEmployeeId).get()) assertThat(staffManagement.findById(defaultEmployeeId).get())

View file

@ -1,10 +1,12 @@
package catering.staff; package catering.staff;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.salespointframework.core.Currencies.EURO;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Set; import java.util.Set;
import org.javamoney.moneta.Money;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.salespointframework.order.OrderManagement; import org.salespointframework.order.OrderManagement;
@ -57,12 +59,12 @@ class StaffManagmentIntegratonTest {
void addEmployees() { void addEmployees() {
defaultUser = userManagement.createCustomer("sarah", "Baum Weg", "123", "Sarah Klaus"); defaultUser = userManagement.createCustomer("sarah", "Baum Weg", "123", "Sarah Klaus");
e1 = staffManagement.save(new Employee("Alan Turing", JobType.COOK)); e1 = staffManagement.save(new Employee("Alan Turing", JobType.COOK, Money.of(10, EURO)));
e2 = staffManagement.save(new Employee("Ada Lovelace", JobType.COOK)); e2 = staffManagement.save(new Employee("Ada Lovelace", JobType.COOK, Money.of(10, EURO)));
e3 = staffManagement.save(new Employee("Donald Knuth", JobType.COOK)); e3 = staffManagement.save(new Employee("Donald Knuth", JobType.COOK, Money.of(10, EURO)));
e4 = staffManagement.save(new Employee("Grace Hopper", JobType.SERVICE)); e4 = staffManagement.save(new Employee("Grace Hopper", JobType.SERVICE, Money.of(10, EURO)));
e5 = staffManagement.save(new Employee("John von Neumann", JobType.SERVICE)); e5 = staffManagement.save(new Employee("John von Neumann", JobType.SERVICE, Money.of(10, EURO)));
e6 = staffManagement.save(new Employee("Noam Chomsky", JobType.SERVICE)); e6 = staffManagement.save(new Employee("Noam Chomsky", JobType.SERVICE, Money.of(10, EURO)));
c1 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 6, 0), LocalDateTime.of(2023, 10, 27, 20, 0), Set.of(e1)); c1 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 6, 0), LocalDateTime.of(2023, 10, 27, 20, 0), Set.of(e1));
c2 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 8, 0), LocalDateTime.of(2023, 10, 27, 16, 0), Set.of(e2)); c2 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 8, 0), LocalDateTime.of(2023, 10, 27, 16, 0), Set.of(e2));