diff --git a/department-service.http b/department-service.http new file mode 100644 index 0000000..4b0c8d5 --- /dev/null +++ b/department-service.http @@ -0,0 +1,9 @@ +###– возвращает список сотрудников по департаменту +GET http://localhost:8080/department/employees +### – возвращает сумму зарплат по департаменту +GET http://localhost:8080/department/2/salary/sum + +### – возвращает максимальную зарплату по департаменту +GET http://localhost:8080/department/2/salary/max +### – возвращает минимальную зарплату по департаменту +GET http://localhost:8080/department/2/salary/min \ No newline at end of file diff --git a/pom.xml b/pom.xml index 34eb14c..8742f55 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,12 @@ org.apache.commons commons-lang3 + + org.jetbrains + annotations + RELEASE + test + diff --git a/src/main/java/ru/skypro/weblibrary/controller/DepartmentController.java b/src/main/java/ru/skypro/weblibrary/controller/DepartmentController.java new file mode 100644 index 0000000..94ecfe6 --- /dev/null +++ b/src/main/java/ru/skypro/weblibrary/controller/DepartmentController.java @@ -0,0 +1,40 @@ +package ru.skypro.weblibrary.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.skypro.weblibrary.entity.Employee; +import ru.skypro.weblibrary.service.DepartmentService; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("department") +public class DepartmentController { + private final DepartmentService departmentService; + + public DepartmentController(DepartmentService departmentService) { + this.departmentService = departmentService; + } + + @GetMapping("/employees") + public Map> getEmployees(){ + return departmentService.getEmployees(); + } + + @GetMapping("/{id}/salary/sum") + public Integer getSalarySum(@PathVariable Integer id){ + return departmentService.getSalarySum(id); + } + @GetMapping("/{id}/salary/min") + public Integer getSalaryMin(@PathVariable Integer id){ + return departmentService.getSalaryMin(id); + } + @GetMapping("/{id}/salary/max") + public Integer getSalaryMax(@PathVariable Integer id){ + return departmentService.getSalaryMax(id); + } +} diff --git a/src/main/java/ru/skypro/weblibrary/controller/EmployeeController.java b/src/main/java/ru/skypro/weblibrary/controller/EmployeeController.java index df1ff7f..2fcb77c 100644 --- a/src/main/java/ru/skypro/weblibrary/controller/EmployeeController.java +++ b/src/main/java/ru/skypro/weblibrary/controller/EmployeeController.java @@ -29,15 +29,15 @@ public Employee addEmployee(@RequestBody EmployeeRequest employee){ @GetMapping("employee/salary/sum") public Integer getSumAlary(){ - return employeeService.getSumAlary(); + return employeeService.getSumSalary(); } @GetMapping("employee/salary/min") public Employee getMinAlary(){ - return employeeService.getMinAlary(); + return employeeService.getMinSalary(); } @GetMapping("employee/salary/max") public Employee getMaxAlary(){ - return employeeService.getMaxAlary(); + return employeeService.getMaxSalary(); } @GetMapping("employee/high-salary") public List getHighSalary(@RequestParam Integer salary){ diff --git a/src/main/java/ru/skypro/weblibrary/entity/Employee.java b/src/main/java/ru/skypro/weblibrary/entity/Employee.java index d52ed83..c02c14e 100644 --- a/src/main/java/ru/skypro/weblibrary/entity/Employee.java +++ b/src/main/java/ru/skypro/weblibrary/entity/Employee.java @@ -1,5 +1,7 @@ package ru.skypro.weblibrary.entity; +import java.util.Objects; + public class Employee { private static int counter; private final Integer id; @@ -41,4 +43,16 @@ public Integer getDepartment() { public Integer getSalary() { return salary; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Employee employee)) return false; + return getId().equals(employee.getId()) && getFirstName().equals(employee.getFirstName()) && getLastName().equals(employee.getLastName()) && getSecondName().equals(employee.getSecondName()) && getDepartment().equals(employee.getDepartment()) && getSalary().equals(employee.getSalary()); + } + + @Override + public int hashCode() { + return Objects.hash(getId(), getFirstName(), getLastName(), getSecondName(), getDepartment(), getSalary()); + } } diff --git a/src/main/java/ru/skypro/weblibrary/service/DepartmentService.java b/src/main/java/ru/skypro/weblibrary/service/DepartmentService.java new file mode 100644 index 0000000..3344298 --- /dev/null +++ b/src/main/java/ru/skypro/weblibrary/service/DepartmentService.java @@ -0,0 +1,17 @@ +package ru.skypro.weblibrary.service; + +import ru.skypro.weblibrary.entity.Employee; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public interface DepartmentService { + Map> getEmployees(); + + Integer getSalarySum(Integer id); + + Integer getSalaryMin(Integer id); + + Integer getSalaryMax(Integer id); +} diff --git a/src/main/java/ru/skypro/weblibrary/service/DepartmentServiceImpl.java b/src/main/java/ru/skypro/weblibrary/service/DepartmentServiceImpl.java new file mode 100644 index 0000000..dde5603 --- /dev/null +++ b/src/main/java/ru/skypro/weblibrary/service/DepartmentServiceImpl.java @@ -0,0 +1,47 @@ +package ru.skypro.weblibrary.service; + +import org.springframework.stereotype.Service; +import ru.skypro.weblibrary.entity.Employee; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class DepartmentServiceImpl implements DepartmentService { + + final EmployeeService employeeService; + + public DepartmentServiceImpl(EmployeeService employeeService) { + this.employeeService = employeeService; + } + + @Override + public Map> getEmployees() { + return employeeService.getListEmployee().stream().collect(Collectors.groupingBy(Employee::getDepartment)); + } + + @Override + public Integer getSalarySum(Integer id) { + return employeeService.getListEmployee().stream() + .filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .sum(); + } + + @Override + public Integer getSalaryMin(Integer id) { + return employeeService.getListEmployee().stream() + .filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .min().orElseThrow(); + } + + @Override + public Integer getSalaryMax(Integer id) { + return employeeService.getListEmployee().stream() + .filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .max().orElseThrow(); + } +} diff --git a/src/main/java/ru/skypro/weblibrary/service/EmployeeService.java b/src/main/java/ru/skypro/weblibrary/service/EmployeeService.java index 81f360b..0463c13 100644 --- a/src/main/java/ru/skypro/weblibrary/service/EmployeeService.java +++ b/src/main/java/ru/skypro/weblibrary/service/EmployeeService.java @@ -12,11 +12,11 @@ public interface EmployeeService { Employee addEmployee(EmployeeRequest employeeRequest); - Integer getSumAlary(); + Integer getSumSalary(); - Employee getMinAlary(); + Employee getMinSalary(); - Employee getMaxAlary(); + Employee getMaxSalary(); List getHighSalary(Integer salary); } diff --git a/src/main/java/ru/skypro/weblibrary/service/EmployeeServiceImpl.java b/src/main/java/ru/skypro/weblibrary/service/EmployeeServiceImpl.java index 55990db..ebb0067 100644 --- a/src/main/java/ru/skypro/weblibrary/service/EmployeeServiceImpl.java +++ b/src/main/java/ru/skypro/weblibrary/service/EmployeeServiceImpl.java @@ -24,6 +24,9 @@ public Employee addEmployee(EmployeeRequest employeeRequest) { if (employeeRequest.getFirstName() == null || employeeRequest.getLastName() == null) { throw new IllegalArgumentException("Employee name should be set"); } + if (employeeRequest.getSalary() == null || employeeRequest.getDepartment() == null){ + throw new IllegalArgumentException("Department or Salary is not defined"); + } if (!StringUtils.isAlpha(employeeRequest.getFirstName()) || !StringUtils.isAlpha(employeeRequest.getLastName()) || !StringUtils.isAlpha(employeeRequest.getSecondName()) @@ -40,17 +43,17 @@ public Employee addEmployee(EmployeeRequest employeeRequest) { } @Override - public Integer getSumAlary() { + public Integer getSumSalary() { return employees.values().stream().mapToInt(Employee::getSalary).sum(); } @Override - public Employee getMinAlary() { + public Employee getMinSalary() { return employees.values().stream().reduce((e1, e2) -> e1.getSalary() < e2.getSalary() ? e1 : e2).orElseThrow(); } @Override - public Employee getMaxAlary() { + public Employee getMaxSalary() { return employees.values().stream().reduce((e1, e2) -> e1.getSalary() > e2.getSalary() ? e1 : e2).orElseThrow(); } diff --git a/src/test/java/ru/skypro/weblibrary/service/DepartmentServiceTest.java b/src/test/java/ru/skypro/weblibrary/service/DepartmentServiceTest.java new file mode 100644 index 0000000..6d8cfe9 --- /dev/null +++ b/src/test/java/ru/skypro/weblibrary/service/DepartmentServiceTest.java @@ -0,0 +1,92 @@ +package ru.skypro.weblibrary.service; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import ru.skypro.weblibrary.dto.EmployeeRequest; +import ru.skypro.weblibrary.entity.Employee; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class DepartmentServiceTest { + static List ret = new ArrayList(); + @Mock + EmployeeService employeeService; + @InjectMocks + DepartmentServiceImpl departmentService; + + @BeforeAll + static void init(){ + Employee employee; + var letArr = new String[]{"A", "B", "C", "D","E"}; + var i = 0; + for (String let:letArr + ) { + i++; + employee = new Employee( + "FirstName"+let, + "LastName"+let, + "SecondName"+let, + i%2+1, + (i%3+1)*1000 + ); + ret.add(employee); + } + } + + @Test + void getEmployees() { + Mockito.when(employeeService.getListEmployee()).thenReturn(ret); + var expected = ret.stream().collect(Collectors.groupingBy(Employee::getDepartment)); + var actual = departmentService.getEmployees(); + assertEquals(expected,actual); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2}) + void getSalarySum(Integer id) { + Mockito.when(employeeService.getListEmployee()).thenReturn(ret); + var expected = ret.stream().filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .sum(); + var actual = departmentService.getSalarySum(id); + assertEquals(expected,actual); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2}) + void getSalaryMin(Integer id) { + Mockito.when(employeeService.getListEmployee()).thenReturn(ret); + var expected = ret.stream().filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .min().orElseThrow(); + var actual = departmentService.getSalaryMin(id); + assertEquals(expected,actual); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2}) + void getSalaryMax(Integer id) { + Mockito.when(employeeService.getListEmployee()).thenReturn(ret); + var expected = ret.stream().filter(e-> e.getDepartment().equals(id)) + .mapToInt(Employee::getSalary) + .max().orElseThrow(); + var actual = departmentService.getSalaryMax(id); + assertEquals(expected,actual); + } +} \ No newline at end of file diff --git a/src/test/java/ru/skypro/weblibrary/service/EmployeeServiceTest.java b/src/test/java/ru/skypro/weblibrary/service/EmployeeServiceTest.java new file mode 100644 index 0000000..fd649c6 --- /dev/null +++ b/src/test/java/ru/skypro/weblibrary/service/EmployeeServiceTest.java @@ -0,0 +1,118 @@ +package ru.skypro.weblibrary.service; + +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.web.server.ResponseStatusException; +import ru.skypro.weblibrary.dto.EmployeeRequest; +import ru.skypro.weblibrary.entity.Employee; + + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class EmployeeServiceTest { + + @NotNull + private static Stream provideParamsForTest(){ + return Stream.of( + Arguments.of("FirstNameA","LastNameA","SecondNameA",1,1000), + Arguments.of("FirstNameB","LastNameB","SecondNameB",1,6000), + Arguments.of("FirstNameC","LastNameC","SecondNameC",1,null), + Arguments.of("FirstNameD",null,"SecondNameD",2,5000), + Arguments.of(null,"LastNameE","SecondNameE",2,1000), + Arguments.of("FirstNameF","LastNameF",null,2,3000), + Arguments.of("FirstNameG","LastNameG","SecondNameG",null,5000) + ); + } + private final EmployeeService employeeService = new EmployeeServiceImpl(); + + private final Map testDb= new HashMap<>(); + + void initSomeEntites(){ + EmployeeRequest employee; + var letArr = new String[]{"A", "B", "C", "D","E"}; + var i = 0; + for (String let:letArr + ) { + i++; + employee = new EmployeeRequest(); + employee.setFirstName("FirstName"+let); + employee.setLastName("LastName"+let); + employee.setSecondName("SecondName"+let); + employee.setDepartment(i%2+1); + employee.setSalary((i%3+1)*1000); + employeeService.addEmployee(employee); + } + } + + @Test + void getListEmployee() { + var expected = new HashMap().values(); + var actual = employeeService.getListEmployee(); + assertIterableEquals(expected,actual); + } + + @ParameterizedTest + @MethodSource("provideParamsForTest") + void addEmployee(String paramFirstName,String paramLastName,String paramSecondName,Integer paramDepartment,Integer paramSalary) { + EmployeeRequest employee = new EmployeeRequest(); + employee.setFirstName(paramFirstName); + employee.setLastName(paramLastName); + employee.setSecondName(paramSecondName); + employee.setDepartment(paramDepartment); + employee.setSalary(paramSalary); + if (!StringUtils.isAlpha(paramFirstName) + && !StringUtils.isAlpha(paramSecondName) + && !StringUtils.isAlpha(paramLastName) || paramSecondName == null){ + assertThrows(ResponseStatusException.class,()->employeeService.addEmployee(employee)); + } else + if (paramFirstName == null || paramLastName == null) { + assertThrows(IllegalArgumentException.class,()->employeeService.addEmployee(employee)); + } else + if (paramSalary == null || paramDepartment == null){ + assertThrows(IllegalArgumentException.class,()->employeeService.addEmployee(employee)); + } else { + employeeService.addEmployee(employee); + Employee actual = (Employee) employeeService.getListEmployee().toArray()[0]; + assertEquals(paramFirstName, actual.getFirstName()); + assertEquals(paramLastName, actual.getLastName()); + assertEquals(paramSecondName, actual.getSecondName()); + assertEquals(paramDepartment, actual.getDepartment()); + assertEquals(paramSalary, actual.getSalary()); + } + } + + @Test + void getSumSalary() { + initSomeEntites(); + assertEquals(2*2000+2*3000+1000,employeeService.getSumSalary()); + } + + @Test + void getMinSalary() { + initSomeEntites(); + assertEquals(employeeService.getListEmployee().toArray()[2],employeeService.getMinSalary()); + } + + @Test + void getMaxSalary() { + initSomeEntites(); + assertEquals(employeeService.getListEmployee().toArray()[4],employeeService.getMaxSalary()); + } + + @Test + void getHighSalary() { + initSomeEntites(); + assertEquals(employeeService.getListEmployee().stream() + .filter(e->e.getSalary()>=2001).collect(Collectors.toList()), + employeeService.getHighSalary(2001)); + } +} \ No newline at end of file