mirror of
https://github.com/st-tu-dresden-praktikum/swt23w23
synced 2024-07-19 21:04:36 +02:00
Add getAvailableStaffByJob to staff package
Co-authored-by: Simon Bruder <simon.bruder@mailbox.tu-dresden.de>
This commit is contained in:
parent
2dff2842fc
commit
17a0e29dad
|
@ -10,6 +10,11 @@ package Spring {
|
|||
class Model
|
||||
}
|
||||
|
||||
package catering.order {
|
||||
class OrderManagement
|
||||
class CustomOrder
|
||||
}
|
||||
|
||||
package catering.staff {
|
||||
|
||||
class Employee {
|
||||
|
@ -48,13 +53,16 @@ package catering.staff {
|
|||
StaffController ..> Errors
|
||||
|
||||
class StaffManagement {
|
||||
+ StaffManagement(staffRepository: StaffRepository)
|
||||
+ StaffManagement(staffRepository: StaffRepository, orderManagement:OrderManagement<CustomOrder>)
|
||||
+ findById(id: Long): Optional<Employee>
|
||||
+ save(employee: Employee): Employee
|
||||
+ findAll(): Streamable<Employee>
|
||||
+ delete(id: Long): void
|
||||
+ getAvailableStaffByJob(job: JobType, start:LocalDateTime, finish:LocalDateTime): Set<Employee>
|
||||
}
|
||||
StaffManagement --> StaffRepository : -staffRepository
|
||||
StaffManagement --> OrderManagement : -orderManagement
|
||||
StaffManagement ..> Set
|
||||
|
||||
interface StaffRepository {
|
||||
+ findAll(): Streamable<Employee>
|
||||
|
|
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.
|
@ -2,6 +2,8 @@ package catering.staff;
|
|||
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
@ -10,9 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
@Controller
|
||||
public class StaffController {
|
||||
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
package catering.staff;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.salespointframework.order.OrderManagement;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.data.util.Streamable;
|
||||
|
||||
import catering.order.CustomOrder;
|
||||
|
||||
@Component
|
||||
@Transactional
|
||||
|
@ -12,9 +21,11 @@ import org.springframework.data.util.Streamable;
|
|||
public class StaffManagement {
|
||||
|
||||
private final StaffRepository staffRepository;
|
||||
private final OrderManagement<CustomOrder> orderManagement;
|
||||
|
||||
public StaffManagement(StaffRepository staffRepository) {
|
||||
public StaffManagement(StaffRepository staffRepository, OrderManagement<CustomOrder> orderManagement) {
|
||||
this.staffRepository = staffRepository;
|
||||
this.orderManagement = orderManagement;
|
||||
}
|
||||
|
||||
public Optional<Employee> findById(Long id) {
|
||||
|
@ -33,4 +44,64 @@ public class StaffManagement {
|
|||
staffRepository.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of all {@link Employee}s of given {@link JobType}
|
||||
* available in the full time range between the given start and end
|
||||
* {@link LocalDateTime}s.
|
||||
*
|
||||
* The range is inclusive, e.g., {@link Employee}s part of an order that lasts
|
||||
* until the given start
|
||||
* are not considered available.
|
||||
*
|
||||
* @param job the {@link JobType} of {@link Employee}s to search for
|
||||
* @param start a {@link LocalDateTime} describing the start of the range the
|
||||
* employee is needed for
|
||||
* @param finish a {@link LocalDateTime} describing the end of the range the
|
||||
* employee is needed for
|
||||
* @return a {@link Set} of {@link Employee}s matching the requirements
|
||||
*/
|
||||
public Set<Employee> getAvailableStaffByJob(JobType job, LocalDateTime start, LocalDateTime finish) {
|
||||
/*
|
||||
* This function first computes all unavailable employees
|
||||
* to then later take the set difference of all employees and the previous
|
||||
* result
|
||||
* to get a set of all employees available in the given range.
|
||||
*/
|
||||
Set<Employee> unavailable = orderManagement.findAll(Pageable.unpaged()).stream()
|
||||
/*
|
||||
* The most complex part is getting all orders overlapping the given range.
|
||||
* It can be computed with the following:
|
||||
* Let (S, F) be the tuple describing the start and finish of any given order O,
|
||||
* let (S', F') be the tuple describing the start and finish of the given date range.
|
||||
* Then the following holds:
|
||||
*
|
||||
* @formatter:off
|
||||
* O overlaps with (S', F')
|
||||
* ⇔ F ≥ S' ∧ S ≤ F'
|
||||
* ⇔ ¬¬(F ≥ S' ∧ S ≤ F') (¬¬X ⇔ X ∀ X ∈ {0,1})
|
||||
* ⇔ ¬(¬(F ≥ S') ∨ ¬(S ≤ F')) (De Morgan’s laws: ¬(X ∧ Y) ⇔ ¬X ∨ ¬Y ∀ X,Y ∈ {0,1})
|
||||
* ⇔ ¬(F < S' ∨ S > F') (¬(a ≥ b) ⇔ a < b and ¬(a ≤ b) ⇔ a > b ∀ a,b totally ordered)
|
||||
* ⇔ ¬(F < S') ∧ ¬(S > F') (De Morgan’s laws: ¬(X ∨ Y) ⇔ ¬X ∧ ¬Y ∀ X,Y ∈ {0,1})
|
||||
* @formatter:on
|
||||
*
|
||||
* The last expression can be easily implemented with two filters,
|
||||
* as chaining filters is equivalent to the logical conjunction,
|
||||
* using LocalDateTime::isBefore and LocalDateTime::isAfter,
|
||||
* which are < and > on the total ordering of all LocalDateTimes.
|
||||
*
|
||||
* Sadly, we can’t really avoid lambdas here
|
||||
* as function composition and partial application are not first-class citizens in Java.
|
||||
*/
|
||||
.filter(order -> !order.getFinish().isBefore(start))
|
||||
.filter(order -> !order.getStart().isAfter(finish))
|
||||
.map(CustomOrder::getStaff)
|
||||
.flatMap(Set::stream)
|
||||
.filter(employee -> employee.getJob().equals(job))
|
||||
.collect(Collectors.toSet());
|
||||
return findAll().stream()
|
||||
.filter(e -> e.getJob().equals(job))
|
||||
.filter(Predicate.not(unavailable::contains))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package catering.staff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.salespointframework.order.OrderManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import catering.order.CustomCart;
|
||||
import catering.order.CustomOrder;
|
||||
import catering.order.OrderType;
|
||||
import catering.users.User;
|
||||
import catering.users.UserManagement;
|
||||
|
||||
@SpringBootTest
|
||||
class StaffManagmentIntegratonTest {
|
||||
|
||||
@Autowired
|
||||
private StaffManagement staffManagement;
|
||||
|
||||
@Autowired
|
||||
private OrderManagement<CustomOrder> orderManagement;
|
||||
|
||||
@Autowired
|
||||
private UserManagement userManagement;
|
||||
|
||||
private User defaultUser;
|
||||
|
||||
Employee e1;
|
||||
Employee e2;
|
||||
Employee e3;
|
||||
Employee e4;
|
||||
Employee e5;
|
||||
Employee e6;
|
||||
|
||||
CustomOrder c1;
|
||||
CustomOrder c2;
|
||||
CustomOrder c3;
|
||||
CustomOrder c4;
|
||||
CustomOrder c5;
|
||||
CustomOrder c6;
|
||||
CustomOrder c7;
|
||||
|
||||
CustomOrder createCustomOrder(LocalDateTime start, LocalDateTime end, Set<Employee> staff) {
|
||||
CustomOrder order = orderManagement.save(new CustomOrder(defaultUser.getUserAccount().getId(),
|
||||
new CustomCart(OrderType.EVENT_CATERING, start, end)));
|
||||
staff.forEach(order::addEmployee);
|
||||
return orderManagement.save(order);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void addEmployees() {
|
||||
defaultUser = userManagement.createCustomer("sarah", "Baum Weg", "123", "Sarah Klaus");
|
||||
|
||||
e1 = staffManagement.save(new Employee("Alan Turing", JobType.COOK));
|
||||
e2 = staffManagement.save(new Employee("Ada Lovelace", JobType.COOK));
|
||||
e3 = staffManagement.save(new Employee("Donald Knuth", JobType.COOK));
|
||||
e4 = staffManagement.save(new Employee("Grace Hopper", JobType.SERVICE));
|
||||
e5 = staffManagement.save(new Employee("John von Neumann", JobType.SERVICE));
|
||||
e6 = staffManagement.save(new Employee("Noam Chomsky", JobType.SERVICE));
|
||||
|
||||
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));
|
||||
c3 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 18, 0), LocalDateTime.of(2023, 10, 27, 22, 0),
|
||||
Set.of(e3));
|
||||
c4 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 16, 0), LocalDateTime.of(2023, 10, 27, 18, 0),
|
||||
Set.of(e4));
|
||||
c5 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 8, 0), LocalDateTime.of(2023, 10, 27, 12, 0), Set.of(e5));
|
||||
c6 = createCustomOrder(LocalDateTime.of(2023, 10, 21, 12, 0), LocalDateTime.of(2023, 10, 21, 22, 0),
|
||||
Set.of(e6));
|
||||
c7 = createCustomOrder(LocalDateTime.of(2023, 10, 27, 19, 0), LocalDateTime.of(2023, 10, 28, 12, 0), Set.of(e2, e3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAvailableEmployees() throws Exception {
|
||||
Set<Employee> availableService = staffManagement.getAvailableStaffByJob(JobType.SERVICE,
|
||||
LocalDateTime.of(2023, 10, 27, 16, 0), LocalDateTime.of(2023, 10, 27, 18, 0));
|
||||
Set<Employee> availableCook = staffManagement.getAvailableStaffByJob(JobType.COOK,
|
||||
LocalDateTime.of(2023, 10, 27, 16, 0), LocalDateTime.of(2023, 10, 27, 18, 0));
|
||||
|
||||
assertThat(availableCook.size()).isEqualTo(0);
|
||||
assertThat(availableService.size()).isEqualTo(2);
|
||||
assertThat(availableService).contains(e5, e6);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue