Vanya_Shestakov

empl-mngmnt-srv

Apr 2nd, 2022 (edited)
468
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 220.03 KB | None | 0 0
  1. package com.leverx.employeestat.rest.configuration;
  2.  
  3. import com.mchange.v2.c3p0.ComboPooledDataSource;
  4. import liquibase.integration.spring.SpringLiquibase;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.beans.factory.annotation.Value;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.ComponentScan;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.context.annotation.PropertySource;
  12. import org.springframework.core.env.Environment;
  13. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  14. import org.springframework.orm.jpa.JpaTransactionManager;
  15. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  16. import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  17. import org.springframework.scheduling.annotation.EnableScheduling;
  18. import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
  19. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  20. import org.springframework.security.crypto.password.PasswordEncoder;
  21. import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
  22. import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
  23. import org.springframework.security.oauth2.client.registration.ClientRegistration;
  24. import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
  25. import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
  26. import org.springframework.transaction.annotation.EnableTransactionManagement;
  27. import org.springframework.web.multipart.commons.CommonsMultipartResolver;
  28. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  29. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  30. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  31. import springfox.documentation.builders.PathSelectors;
  32. import springfox.documentation.builders.RequestHandlerSelectors;
  33. import springfox.documentation.service.ApiInfo;
  34. import springfox.documentation.service.Contact;
  35. import springfox.documentation.spi.DocumentationType;
  36. import springfox.documentation.spring.web.plugins.Docket;
  37. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  38.  
  39. import javax.sql.DataSource;
  40. import java.beans.PropertyVetoException;
  41. import java.util.*;
  42. import java.util.stream.Collectors;
  43.  
  44. @Configuration
  45. @ComponentScan("com.leverx.employeestat.rest*")
  46. @EnableWebMvc
  47. @EnableTransactionManagement
  48. @EnableSwagger2
  49. @EnableJpaRepositories(basePackages = "com.leverx.employeestat.rest.repository*")
  50. @PropertySource({
  51.         "classpath:properties/db.properties",
  52.         "classpath:properties/session-factory.properties",
  53.         "classpath:security/google-security.properties",
  54.         "classpath:application.properties"})
  55. @EnableScheduling
  56. @Slf4j
  57. public class Config implements WebMvcConfigurer {
  58.  
  59.     private final static List<String> clients = Arrays.asList("google");
  60.     private final static String CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration.";
  61.  
  62.     @Value("${driverClass}")
  63.     private String driverClass;
  64.  
  65.     @Value("${dbuser}")
  66.     private String user;
  67.  
  68.     @Value("${password}")
  69.     private String password;
  70.  
  71.     @Value("${jdbcUrl}")
  72.     private String jdbcUrl;
  73.  
  74.     private Environment env;
  75.  
  76.     @Autowired
  77.     public Config(Environment env) {
  78.         this.env = env;
  79.     }
  80.    
  81.     public Config() {
  82.  
  83.     }
  84.  
  85.     @Bean
  86.     public ClientRegistrationRepository clientRegistrationRepository() {
  87.         List<ClientRegistration> registrations = clients.stream()
  88.                 .map(this::getRegistration)
  89.                 .filter(Objects::nonNull)
  90.                 .collect(Collectors.toList());
  91.  
  92.         return new InMemoryClientRegistrationRepository(registrations);
  93.     }
  94.  
  95.     @Bean
  96.     public OAuth2AuthorizedClientService authorizedClientService() {
  97.         return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository());
  98.     }
  99.  
  100.     @Bean
  101.     public PasswordEncoder passwordEncoder() {
  102.         return new BCryptPasswordEncoder();
  103.     }
  104.  
  105.     @Bean
  106.     public SpringLiquibase liquibase() {
  107.         SpringLiquibase liquibase = new SpringLiquibase();
  108.         liquibase.setChangeLog("classpath:db/changelog/liquibase-changeLog.xml");
  109.         liquibase.setDataSource(dataSource());
  110.         return liquibase;
  111.     }
  112.  
  113.     @Bean
  114.     public DataSource dataSource() {
  115.         ComboPooledDataSource dataSource = new ComboPooledDataSource();
  116.         try {
  117.             log.info(String.format("Connecting to the datasource (driver=%s, url=%s, user=%s)", driverClass, jdbcUrl, user));
  118.  
  119.             dataSource.setDriverClass(driverClass);
  120.             dataSource.setJdbcUrl(jdbcUrl);
  121.             dataSource.setUser(user);
  122.             dataSource.setPassword(password);
  123.         } catch (PropertyVetoException e) {
  124.             e.printStackTrace();
  125.         }
  126.         return dataSource;
  127.     }
  128.  
  129.     @Bean
  130.     public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
  131.         LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
  132.         factory.setDataSource(dataSource());
  133.         factory.setJpaVendorAdapter(hibernateJpaVendorAdapter());
  134.         factory.setPackagesToScan(env.getRequiredProperty("packagesToScan"));
  135.         Properties props = new Properties();
  136.         props.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
  137.         props.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
  138.         props.put("hibernate.ddl-auto", env.getRequiredProperty("hibernate.ddl-auto"));
  139.         factory.setJpaProperties(props);
  140.         return factory;
  141.     }
  142.  
  143.     @Bean
  144.     public JpaTransactionManager transactionManager() {
  145.         JpaTransactionManager transactionManager = new JpaTransactionManager();
  146.         transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
  147.         return transactionManager;
  148.     }
  149.  
  150.     @Bean
  151.     public HibernateJpaVendorAdapter hibernateJpaVendorAdapter() {
  152.         return new HibernateJpaVendorAdapter();
  153.     }
  154.  
  155.     @Bean
  156.     public CommonsMultipartResolver multipartResolver() {
  157.         CommonsMultipartResolver resolver = new CommonsMultipartResolver();
  158.         resolver.setMaxUploadSize(10000000L);
  159.         return resolver;
  160.     }
  161.  
  162.     @Bean
  163.     public Docket api() {
  164.         Docket docket = new Docket(DocumentationType.SWAGGER_2)
  165.                 .select()
  166.                 .apis(RequestHandlerSelectors.any())
  167.                 .paths(PathSelectors.any())
  168.                 .build().apiInfo(apiInfo());
  169.  
  170.         return docket;
  171.     }
  172.  
  173.     private ApiInfo apiInfo() {
  174.         return new ApiInfo(
  175.                 "Employees Service",
  176.                 "API for keeping track of employees and their employment",
  177.                 "0.9 BETA", "",
  178.                 new Contact(
  179.                         "Ivan Shestakov",
  180.                         "https://github.com/VanyaShestakov",
  181.                         "[email protected]"),
  182.                 "", "", Collections.emptyList());
  183.     }
  184.  
  185.     @Override
  186.     public void addResourceHandlers(ResourceHandlerRegistry registry) {
  187.         registry.addResourceHandler("swagger-ui.html")
  188.                 .addResourceLocations("classpath:/META-INF/resources/");
  189.  
  190.         registry.addResourceHandler("/webjars/**")
  191.                 .addResourceLocations("classpath:/META-INF/resources/webjars/");
  192.     }
  193.  
  194.     private ClientRegistration getRegistration(String client) {
  195.         String clientId = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-id");
  196.  
  197.         if (clientId == null) {
  198.             return null;
  199.         }
  200.  
  201.         String clientSecret = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-secret");
  202.  
  203.         if (client.equals("google")) {
  204.             return CommonOAuth2Provider.GOOGLE
  205.                     .getBuilder(client)
  206.                     .clientId(clientId)
  207.                     .clientSecret(clientSecret)
  208.                     .build();
  209.         }
  210.         return null;
  211.     }
  212. }
  213.  
  214. package com.leverx.employeestat.rest.configuration;
  215.  
  216. import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
  217.  
  218. public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  219.  
  220.     @Override
  221.     protected Class<?>[] getRootConfigClasses() {
  222.         return null;
  223.     }
  224.  
  225.     @Override
  226.     protected Class<?>[] getServletConfigClasses() {
  227.         return new Class[]{Config.class};
  228.     }
  229.  
  230.     @Override
  231.     protected String[] getServletMappings() {
  232.         return new String[] {"/"};
  233.     }
  234. }
  235. package com.leverx.employeestat.rest.controller;
  236.  
  237. import com.leverx.employeestat.rest.controller.tool.BindingResultParser;
  238. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  239. import com.leverx.employeestat.rest.exception.NotValidRecordException;
  240. import com.leverx.employeestat.rest.model.RegistrationRequest;
  241. import com.leverx.employeestat.rest.model.ResetPasswordRequest;
  242. import com.leverx.employeestat.rest.service.AuthorizationService;
  243. import io.swagger.annotations.Api;
  244. import io.swagger.annotations.ApiOperation;
  245. import io.swagger.annotations.ApiParam;
  246. import lombok.extern.slf4j.Slf4j;
  247. import org.springframework.beans.factory.annotation.Autowired;
  248. import org.springframework.http.HttpStatus;
  249. import org.springframework.validation.BindingResult;
  250. import org.springframework.web.bind.annotation.*;
  251.  
  252. import javax.validation.Valid;
  253.  
  254. @RestController
  255. @RequestMapping("/api")
  256. @Api(tags = {"Authorization"})
  257. @Slf4j
  258. public class AuthorizationController {
  259.  
  260.     private final AuthorizationService authorizationService;
  261.     private final BindingResultParser bindingResultParser;
  262.  
  263.     @Autowired
  264.     public AuthorizationController(AuthorizationService authorizationService, BindingResultParser bindingResultParser) {
  265.         this.authorizationService = authorizationService;
  266.         this.bindingResultParser = bindingResultParser;
  267.     }
  268.  
  269.     @PostMapping("/register")
  270.     @ResponseStatus(HttpStatus.CREATED)
  271.     @ApiOperation(value = "Register employee", response = EmployeeDTO.class)
  272.     public EmployeeDTO registerEmployee(@ApiParam(name = "Registration request", value = "Contains mandatory fields for registration of employee")
  273.                                         @RequestBody
  274.                                         @Valid RegistrationRequest request, BindingResult result) {
  275.         log.info("executing registerEmployee() method");
  276.         if (result.hasErrors()) {
  277.             throw new NotValidRecordException
  278.                     (String.format("Fields of Employee have errors: %s", bindingResultParser.getFieldErrMismatches(result)));
  279.         }
  280.         return authorizationService.registerEmployee(request.toDTO());
  281.     }
  282.  
  283.     @PostMapping("/reset-password")
  284.     @ResponseStatus(HttpStatus.NO_CONTENT)
  285.     @ApiOperation(value = "Reset password of employee")
  286.     public void resetPassword(@ApiParam(name = "Reset password request", value = "Contains username, old and new password of employee")
  287.                               @RequestBody
  288.                               @Valid ResetPasswordRequest request, BindingResult result) {
  289.         log.info("executing resetPassword() method");
  290.         if (result.hasErrors()) {
  291.             throw new NotValidRecordException("Fields have errors: " + bindingResultParser.getFieldErrMismatches(result));
  292.         }
  293.         authorizationService.resetPassword(request);
  294.     }
  295. }
  296.  
  297. package com.leverx.employeestat.rest.controller;
  298.  
  299. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  300. import com.leverx.employeestat.rest.service.AvailableEmployeeService;
  301. import io.swagger.annotations.Api;
  302. import io.swagger.annotations.ApiOperation;
  303. import io.swagger.annotations.ApiParam;
  304. import lombok.extern.slf4j.Slf4j;
  305. import org.apache.logging.log4j.LogManager;
  306. import org.apache.logging.log4j.Logger;
  307. import org.springframework.beans.factory.annotation.Autowired;
  308. import org.springframework.http.HttpStatus;
  309. import org.springframework.web.bind.annotation.*;
  310.  
  311. import java.util.List;
  312.  
  313. @RestController
  314. @RequestMapping("/api/employees/available")
  315. @Api(tags = {"API for retrieving available employees"})
  316. @Slf4j
  317. public class AvailableEmployeeController {
  318.  
  319.     private final AvailableEmployeeService availableEmployeeService;
  320.  
  321.     @Autowired
  322.     public AvailableEmployeeController(AvailableEmployeeService availableEmployeeService) {
  323.         this.availableEmployeeService = availableEmployeeService;
  324.     }
  325.  
  326.     @GetMapping
  327.     @ResponseStatus(HttpStatus.OK)
  328.     @ApiOperation(value = "Get available employees at the current moment")
  329.     public List<EmployeeDTO> getAvailableEmployeesNow() {
  330.         log.info("executing getAvailableEmployeesNow() method");
  331.         return availableEmployeeService.getAvailableEmployeesNow();
  332.     }
  333.  
  334.     @GetMapping("/{days}")
  335.     @ResponseStatus(HttpStatus.OK)
  336.     @ApiOperation(value = "Get available employees for the next amount of days")
  337.     public List<EmployeeDTO> getAvailableEmployeesNext(@ApiParam(value = "Amount of the next days starting today")
  338.                                                        @PathVariable("days") int days) {
  339.         log.info("executing getAvailableEmployeesNext() method");
  340.         return availableEmployeeService.getAvailableEmployeesNext(days);
  341.     }
  342. }
  343.  
  344. package com.leverx.employeestat.rest.controller;
  345.  
  346. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  347. import com.leverx.employeestat.rest.service.AuthorizationService;
  348. import com.leverx.employeestat.rest.service.CSVReaderService;
  349. import io.swagger.annotations.Api;
  350. import io.swagger.annotations.ApiOperation;
  351. import io.swagger.annotations.ApiParam;
  352. import lombok.extern.slf4j.Slf4j;
  353. import org.springframework.beans.factory.annotation.Autowired;
  354. import org.springframework.http.HttpStatus;
  355. import org.springframework.web.bind.annotation.*;
  356. import org.springframework.web.multipart.MultipartFile;
  357.  
  358. import java.util.List;
  359.  
  360. @RestController
  361. @RequestMapping("api/employees/upload")
  362. @Api(tags = {"API for uploading employees from CSV file"})
  363. @Slf4j
  364. public class CSVUploadController {
  365.  
  366.     private final CSVReaderService readerService;
  367.     private final AuthorizationService authorizationService;
  368.  
  369.     @Autowired
  370.     public CSVUploadController(CSVReaderService readerService, AuthorizationService authorizationService) {
  371.         this.readerService = readerService;
  372.         this.authorizationService = authorizationService;
  373.     }
  374.  
  375.     @PostMapping
  376.     @ResponseStatus(HttpStatus.CREATED)
  377.     @ApiOperation("Upload employees")
  378.     public List<EmployeeDTO> uploadEmployees(@ApiParam(value = "File with .csv extension, that contains table with employees")
  379.                                              @RequestParam("file") MultipartFile file) {
  380.         log.info("executing uploadEmployees() method");
  381.         List<EmployeeDTO> employees = readerService.getEmployeesFromFile(file);
  382.         return authorizationService.registerAll(employees);
  383.     }
  384. }
  385.  
  386. package com.leverx.employeestat.rest.controller;
  387.  
  388. import com.leverx.employeestat.rest.controller.tool.BindingResultParser;
  389. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  390. import com.leverx.employeestat.rest.exception.NotValidRecordException;
  391. import com.leverx.employeestat.rest.service.DepartmentService;
  392. import io.swagger.annotations.Api;
  393. import io.swagger.annotations.ApiOperation;
  394. import io.swagger.annotations.ApiParam;
  395. import lombok.extern.slf4j.Slf4j;
  396. import org.springframework.beans.factory.annotation.Autowired;
  397. import org.springframework.http.HttpStatus;
  398. import org.springframework.validation.BindingResult;
  399. import org.springframework.web.bind.annotation.*;
  400.  
  401. import javax.validation.Valid;
  402. import java.util.List;
  403.  
  404. import static com.leverx.employeestat.rest.controller.tool.UUIDUtils.getUUIDFromString;
  405.  
  406. @RestController
  407. @RequestMapping("/api/departments")
  408. @Api(tags = "Department CRUD operations")
  409. @Slf4j
  410. public class DepartmentController {
  411.  
  412.     private final DepartmentService departmentService;
  413.     private final BindingResultParser bindingResultParser;
  414.  
  415.     @Autowired
  416.     public DepartmentController(DepartmentService departmentService, BindingResultParser bindingResultParser) {
  417.         this.departmentService = departmentService;
  418.         this.bindingResultParser = bindingResultParser;
  419.     }
  420.  
  421.     @GetMapping
  422.     @ResponseStatus(HttpStatus.OK)
  423.     @ApiOperation(value = "Get list of all departments")
  424.     public List<DepartmentDTO> getAllDepartments() {
  425.         log.info("executing getAllDepartments() method");
  426.         return departmentService.getAll();
  427.     }
  428.  
  429.     @GetMapping("/{id}")
  430.     @ResponseStatus(HttpStatus.OK)
  431.     @ApiOperation(value = "Get department by id")
  432.     public DepartmentDTO getDepartment(@ApiParam(value = "Id of reсeiving department (UUID)")
  433.                                        @PathVariable("id") String id) {
  434.         log.info("executing getDepartment() method");
  435.         return departmentService.getById(getUUIDFromString(id));
  436.     }
  437.  
  438.     @PostMapping
  439.     @ResponseStatus(HttpStatus.CREATED)
  440.     @ApiOperation(value = "Create department")
  441.     public DepartmentDTO postDepartment(@ApiParam(value = "Contains mandatory information of department", name = "Department")
  442.                                         @RequestBody
  443.                                         @Valid DepartmentDTO departmentDTO, BindingResult result) {
  444.         log.info("executing postDepartment() method");
  445.         if (result.hasErrors()) {
  446.             throw new NotValidRecordException("Fields of Department have errors: " + bindingResultParser.getFieldErrMismatches(result));
  447.         }
  448.         return departmentService.save(departmentDTO);
  449.     }
  450.  
  451.     @PutMapping
  452.     @ResponseStatus(HttpStatus.OK)
  453.     @ApiOperation(value = "Update department")
  454.     public DepartmentDTO putDepartment(@ApiParam(value = "Contains all information of department with changed fields", name = "Department")
  455.                                        @RequestBody
  456.                                        @Valid DepartmentDTO departmentDTO, BindingResult result) {
  457.         log.info("executing postDepartment() method");
  458.         if (result.hasErrors()) {
  459.             throw new NotValidRecordException("Fields of Department have errors: " + bindingResultParser.getFieldErrMismatches(result));
  460.         }
  461.         return departmentService.update(departmentDTO);
  462.     }
  463.  
  464.     @DeleteMapping("/{id}")
  465.     @ResponseStatus(HttpStatus.NO_CONTENT)
  466.     @ApiOperation(value = "Delete department")
  467.     public void deleteDepartment(@ApiParam(value = "Id of deleting department (UUID)")
  468.                                  @PathVariable("id") String id) {
  469.         log.info("executing deleteDepartment() method");
  470.         departmentService.deleteById(getUUIDFromString(id));
  471.     }
  472. }
  473.  
  474. package com.leverx.employeestat.rest.controller;
  475.  
  476. import com.leverx.employeestat.rest.controller.tool.BindingResultParser;
  477. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  478. import com.leverx.employeestat.rest.exception.NotValidRecordException;
  479. import com.leverx.employeestat.rest.service.EmployeeService;
  480. import io.swagger.annotations.Api;
  481. import io.swagger.annotations.ApiOperation;
  482. import io.swagger.annotations.ApiParam;
  483. import lombok.extern.slf4j.Slf4j;
  484. import org.apache.logging.log4j.LogManager;
  485. import org.apache.logging.log4j.Logger;
  486. import org.springframework.beans.factory.annotation.Autowired;
  487. import org.springframework.http.HttpStatus;
  488. import org.springframework.validation.BindingResult;
  489. import org.springframework.validation.annotation.Validated;
  490. import org.springframework.web.bind.annotation.*;
  491.  
  492. import javax.validation.Valid;
  493. import java.util.List;
  494.  
  495. import static com.leverx.employeestat.rest.controller.tool.UUIDUtils.getUUIDFromString;
  496.  
  497. @RestController
  498. @RequestMapping("/api/employees")
  499. @Api(tags = {"Employee CRUD operations"})
  500. @Slf4j
  501. public class EmployeeController {
  502.  
  503.     private final EmployeeService employeeService;
  504.     private final BindingResultParser bindingResultParser;
  505.  
  506.     @Autowired
  507.     public EmployeeController(EmployeeService employeeService, BindingResultParser bindingResultParser) {
  508.         this.employeeService = employeeService;
  509.         this.bindingResultParser = bindingResultParser;
  510.     }
  511.  
  512.     @GetMapping
  513.     @ResponseStatus(HttpStatus.OK)
  514.     @ApiOperation(value = "Get list of all employees")
  515.     public List<EmployeeDTO> getAllEmployees() {
  516.         log.info("executing getAllEmployees() method");
  517.         return employeeService.getAll();
  518.     }
  519.  
  520.     @GetMapping("/{id}")
  521.     @ResponseStatus(HttpStatus.OK)
  522.     @ApiOperation(value = "Get employee by id")
  523.     public EmployeeDTO getEmployee(@ApiParam(value = "Id of received employee")
  524.                                    @PathVariable String id) {
  525.         log.info("executing getEmployee() method");
  526.         return employeeService.getById(getUUIDFromString(id));
  527.     }
  528.  
  529.     @PutMapping
  530.     @ResponseStatus(HttpStatus.OK)
  531.     @ApiOperation(value = "Update employee")
  532.     public EmployeeDTO putEmployee(@ApiParam(value = "Contains all information of employee with changed fields", name = "Employee")
  533.                                    @RequestBody
  534.                                    @Valid EmployeeDTO employeeDTO, BindingResult result) {
  535.         log.info("executing putEmployee() method");
  536.         if (result.hasErrors()) {
  537.             throw new NotValidRecordException("Fields of Employee have errors: " + bindingResultParser.getFieldErrMismatches(result));
  538.         }
  539.         return employeeService.update(employeeDTO);
  540.     }
  541.  
  542.     @DeleteMapping("/{id}")
  543.     @ResponseStatus(HttpStatus.NO_CONTENT)
  544.     @ApiOperation(value = "Delete employee")
  545.     public void deleteEmployee(@ApiParam(value = "Id of deleting employee")
  546.                                @PathVariable String id) {
  547.         log.info("executing deleteEmployee() method");
  548.         employeeService.deleteById(getUUIDFromString(id));
  549.     }
  550. }
  551.  
  552. package com.leverx.employeestat.rest.controller;
  553.  
  554. import com.leverx.employeestat.rest.controller.tool.BindingResultParser;
  555. import com.leverx.employeestat.rest.dto.ProjectDTO;
  556. import com.leverx.employeestat.rest.exception.NotValidRecordException;
  557. import com.leverx.employeestat.rest.service.ProjectService;
  558. import io.swagger.annotations.Api;
  559. import io.swagger.annotations.ApiOperation;
  560. import io.swagger.annotations.ApiParam;
  561. import lombok.extern.slf4j.Slf4j;
  562. import org.apache.logging.log4j.LogManager;
  563. import org.apache.logging.log4j.Logger;
  564. import org.springframework.beans.factory.annotation.Autowired;
  565. import org.springframework.http.HttpStatus;
  566. import org.springframework.validation.BindingResult;
  567. import org.springframework.web.bind.annotation.*;
  568.  
  569. import javax.validation.Valid;
  570. import java.util.List;
  571.  
  572. import static com.leverx.employeestat.rest.controller.tool.UUIDUtils.getUUIDFromString;
  573.  
  574. @RestController
  575. @RequestMapping("/api/projects")
  576. @Api(tags = "Project CRUD operations")
  577. @Slf4j
  578. public class ProjectController {
  579.  
  580.     private final ProjectService projectService;
  581.     private final BindingResultParser bindingResultParser;
  582.  
  583.     @Autowired
  584.     public ProjectController(ProjectService projectService, BindingResultParser bindingResultParser) {
  585.         this.projectService = projectService;
  586.         this.bindingResultParser = bindingResultParser;
  587.     }
  588.  
  589.     @GetMapping
  590.     @ResponseStatus(HttpStatus.OK)
  591.     @ApiOperation(value = "Get list of all projects")
  592.     public List<ProjectDTO> getAllProjects() {
  593.         log.info("executing getAllProjects() method");
  594.         return projectService.getAll();
  595.     }
  596.  
  597.     @GetMapping("/{id}")
  598.     @ResponseStatus(HttpStatus.OK)
  599.     @ApiOperation(value = "Get project by id")
  600.     public ProjectDTO getProject(@ApiParam(value = "Id of reсeiving project (UUID)")
  601.                                  @PathVariable String id) {
  602.         log.info("executing getProject() method");
  603.         return projectService.getById(getUUIDFromString(id));
  604.     }
  605.  
  606.     @PostMapping
  607.     @ResponseStatus(HttpStatus.CREATED)
  608.     @ApiOperation(value = "Create project")
  609.     public ProjectDTO postProject(@ApiParam(value = "Contains mandatory information of project", name = "Project")
  610.                                   @RequestBody
  611.                                   @Valid ProjectDTO projectDTO, BindingResult result) {
  612.         log.info("executing postProject() method");
  613.         if (result.hasErrors()) {
  614.             throw new NotValidRecordException("Fields of Project have errors: " + bindingResultParser.getFieldErrMismatches(result));
  615.         }
  616.         return projectService.save(projectDTO);
  617.     }
  618.  
  619.     @PutMapping
  620.     @ResponseStatus(HttpStatus.OK)
  621.     @ApiOperation(value = "Update project")
  622.     public ProjectDTO putProject(@ApiParam(value = "Contains all information of project with changed fields", name = "Project")
  623.                                  @RequestBody
  624.                                  @Valid ProjectDTO projectDTO, BindingResult result) {
  625.         log.info("executing putProject() method");
  626.         if (result.hasErrors()) {
  627.             throw new NotValidRecordException("Fields of Project have errors: " + bindingResultParser.getFieldErrMismatches(result));
  628.         }
  629.         return projectService.update(projectDTO);
  630.     }
  631.  
  632.     @DeleteMapping("/{id}")
  633.     @ResponseStatus(HttpStatus.NO_CONTENT)
  634.     @ApiOperation(value = "Delete project")
  635.     public void deleteProject(@ApiParam(value = "Id of deleting project (UUID)")
  636.                               @PathVariable String id) {
  637.         log.info("executing putProject() method");
  638.         projectService.deleteById(getUUIDFromString(id));
  639.     }
  640.  
  641. }
  642.  
  643. package com.leverx.employeestat.rest.controller;
  644.  
  645. import com.leverx.employeestat.rest.exception.ReportWritingException;
  646. import com.leverx.employeestat.rest.service.ReportService;
  647. import io.swagger.annotations.Api;
  648. import io.swagger.annotations.ApiOperation;
  649. import lombok.extern.slf4j.Slf4j;
  650. import org.apache.logging.log4j.LogManager;
  651. import org.apache.logging.log4j.Logger;
  652. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  653. import org.springframework.beans.factory.annotation.Autowired;
  654. import org.springframework.http.HttpHeaders;
  655. import org.springframework.http.HttpStatus;
  656. import org.springframework.http.MediaType;
  657. import org.springframework.web.bind.annotation.GetMapping;
  658. import org.springframework.web.bind.annotation.RequestMapping;
  659. import org.springframework.web.bind.annotation.ResponseStatus;
  660. import org.springframework.web.bind.annotation.RestController;
  661.  
  662. import javax.servlet.ServletOutputStream;
  663. import javax.servlet.http.HttpServletResponse;
  664. import java.io.IOException;
  665.  
  666. @RestController
  667. @RequestMapping("api/employees/export")
  668. @Api(tags = "API for exporting workload reports of employees")
  669. @Slf4j
  670. public class ReportController {
  671.  
  672.     private final ReportService reportService;
  673.  
  674.     @Autowired
  675.     public ReportController(ReportService reportService) {
  676.         this.reportService = reportService;
  677.     }
  678.  
  679.     @GetMapping
  680.     @ResponseStatus(HttpStatus.OK)
  681.     @ApiOperation(value = "Export occupation-report of employees")
  682.     public void exportEmployees(HttpServletResponse response) {
  683.         log.info("executing exportEmployees() method");
  684.         response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
  685.         response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=Employees.xlsx");
  686.         XSSFWorkbook workbook = reportService.exportOccupationReport();
  687.         writeToResponse(workbook, response);
  688.     }
  689.  
  690.     @GetMapping("/last")
  691.     @ResponseStatus(HttpStatus.OK)
  692.     @ApiOperation(value = "Export last generated report of available employees for the next month")
  693.     public void exportLastGeneratedReport(HttpServletResponse response) {
  694.         log.info("executing exportLastGeneratedReport() method");
  695.         response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
  696.         response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=Employees-Last.xlsx");
  697.         XSSFWorkbook workbook = reportService.exportLastGeneratedReport();
  698.         writeToResponse(workbook, response);
  699.     }
  700.  
  701.     private void writeToResponse(XSSFWorkbook workbook, HttpServletResponse response) {
  702.         try (ServletOutputStream outputStream = response.getOutputStream()) {
  703.             workbook.write(outputStream);
  704.         } catch (IOException e) {
  705.             throw new ReportWritingException("Failed to write report", e);
  706.         }
  707.     }
  708. }
  709.  
  710. package com.leverx.employeestat.rest.controller;
  711.  
  712. import com.leverx.employeestat.rest.dto.WorkDTO;
  713. import com.leverx.employeestat.rest.service.WorkService;
  714. import io.swagger.annotations.Api;
  715. import io.swagger.annotations.ApiOperation;
  716. import io.swagger.annotations.ApiParam;
  717. import lombok.extern.slf4j.Slf4j;
  718. import org.apache.logging.log4j.LogManager;
  719. import org.apache.logging.log4j.Logger;
  720. import org.springframework.beans.factory.annotation.Autowired;
  721. import org.springframework.http.HttpStatus;
  722. import org.springframework.web.bind.annotation.*;
  723.  
  724. import java.util.List;
  725. import java.util.UUID;
  726.  
  727. import static com.leverx.employeestat.rest.controller.tool.UUIDUtils.getUUIDFromString;
  728.  
  729. @RestController
  730. @RequestMapping("/api/works")
  731. @Api(tags = "Work CRUD operations")
  732. @Slf4j
  733. public class WorkController {
  734.  
  735.     private final WorkService workService;
  736.  
  737.     @Autowired
  738.     public WorkController(WorkService workService) {
  739.         this.workService = workService;
  740.     }
  741.  
  742.     @GetMapping
  743.     @ResponseStatus(HttpStatus.OK)
  744.     @ApiOperation(value = "Get list of all works")
  745.     public List<WorkDTO> getAllWorks() {
  746.         log.info("executing getAllWorks() method");
  747.         return workService.getAll();
  748.     }
  749.  
  750.     @GetMapping("/{empId}/{projId}")
  751.     @ResponseStatus(HttpStatus.OK)
  752.     @ApiOperation(value = "Get work by employee id and project id")
  753.     public WorkDTO getWork(@ApiParam(value = "Employee id (UUID)")
  754.                            @PathVariable("empId") String employeeId,
  755.                            @ApiParam(value = "Project id (UUID)")
  756.                            @PathVariable("projId") String projectId) {
  757.         log.info("executing getWork() method");
  758.         return workService.getByIds(getUUIDFromString(employeeId), getUUIDFromString(projectId));
  759.     }
  760.  
  761.     @PutMapping
  762.     @ResponseStatus(HttpStatus.OK)
  763.     @ApiOperation(value = "Update work")
  764.     public WorkDTO putWork(@ApiParam(value = "Contains all information of employee work with changed fields", name = "Work")
  765.                            @RequestBody WorkDTO workDTO) {
  766.         log.info("executing putWork() method");
  767.         return workService.update(workDTO);
  768.     }
  769.  
  770.     @DeleteMapping("/{empId}/{projId}")
  771.     @ResponseStatus(HttpStatus.NO_CONTENT)
  772.     @ApiOperation(value = "Get work by employee id and project id")
  773.     public void deleteWork(@ApiParam(value = "Employee id (UUID)")
  774.                            @PathVariable("empId") String employeeId,
  775.                            @ApiParam(value = "Project id (UUID)")
  776.                            @PathVariable("projId") String projectId) {
  777.         log.info("executing deleteWork() method");
  778.         workService.deleteByIds(getUUIDFromString(employeeId), getUUIDFromString(projectId));
  779.     }
  780. }
  781.  
  782. package com.leverx.employeestat.rest.controller.tool;
  783.  
  784. import org.springframework.stereotype.Component;
  785. import org.springframework.validation.BindingResult;
  786. import org.springframework.validation.FieldError;
  787.  
  788. @Component
  789. public class BindingResultParser {
  790.  
  791.     public String getFieldErrMismatches(BindingResult result) {
  792.         StringBuilder sb = new StringBuilder();
  793.         for (FieldError err : result.getFieldErrors()) {
  794.             sb
  795.                     .append(err.getField()).append(": ")
  796.                     .append(err.getDefaultMessage())
  797.                     .append(", ");
  798.         }
  799.         sb.delete(sb.length() - 2, sb.length());
  800.         return sb.toString();
  801.     }
  802. }
  803.  
  804. package com.leverx.employeestat.rest.controller.tool;
  805.  
  806. import com.leverx.employeestat.rest.exception.NotValidUUIDException;
  807.  
  808. import java.util.UUID;
  809.  
  810. public class UUIDUtils {
  811.  
  812.     public static UUID getUUIDFromString(String id) {
  813.         UUID uuid = null;
  814.         try {
  815.             uuid = UUID.fromString(id);
  816.         } catch (IllegalArgumentException e) {
  817.             throw new NotValidUUIDException(String.format("Value =%s is not UUID", id), e);
  818.         }
  819.         return uuid;
  820.     }
  821. }
  822.  
  823. package com.leverx.employeestat.rest.service;
  824.  
  825. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  826. import com.leverx.employeestat.rest.model.ResetPasswordRequest;
  827.  
  828. import java.util.List;
  829.  
  830. public interface AuthorizationService {
  831.  
  832.     EmployeeDTO registerEmployee(EmployeeDTO employeeDTO);
  833.  
  834.     EmployeeDTO resetPassword(ResetPasswordRequest request);
  835.  
  836.     List<EmployeeDTO> registerAll(List<EmployeeDTO> employeeDTOs);
  837. }
  838.  
  839. package com.leverx.employeestat.rest.service;
  840.  
  841. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  842.  
  843. import java.util.List;
  844.  
  845. public interface AvailableEmployeeService {
  846.    
  847.     List<EmployeeDTO> getAvailableEmployeesNow();
  848.  
  849.     List<EmployeeDTO> getAvailableEmployeesNext(int days);
  850. }
  851.  
  852. package com.leverx.employeestat.rest.service;
  853.  
  854. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  855. import org.springframework.web.multipart.MultipartFile;
  856.  
  857. import java.util.List;
  858.  
  859. public interface CSVReaderService {
  860.  
  861.     List<EmployeeDTO> getEmployeesFromFile(MultipartFile file);
  862. }
  863.  
  864. package com.leverx.employeestat.rest.service;
  865.  
  866. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  867.  
  868. import java.util.List;
  869. import java.util.UUID;
  870.  
  871. public interface DepartmentService {
  872.  
  873.     DepartmentDTO save(DepartmentDTO departmentDTO);
  874.  
  875.     void deleteById(UUID id);
  876.  
  877.     DepartmentDTO update(DepartmentDTO departmentDTO);
  878.  
  879.     List<DepartmentDTO> getAll();
  880.  
  881.     DepartmentDTO getById(UUID id);
  882.  
  883.     boolean existsById(UUID id);
  884.  
  885.     boolean existsByName(String name);
  886. }
  887.  
  888. package com.leverx.employeestat.rest.service;
  889.  
  890. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  891.  
  892. import java.util.List;
  893. import java.util.UUID;
  894.  
  895. public interface EmployeeService {
  896.  
  897.     public List<EmployeeDTO> getAll();
  898.  
  899.     public EmployeeDTO getById(UUID id);
  900.  
  901.     public EmployeeDTO getByUsername(String username);
  902.  
  903.     public EmployeeDTO save(EmployeeDTO employeeDTO);
  904.  
  905.     public List<EmployeeDTO> saveAll(List<EmployeeDTO> employeeDTOs);
  906.  
  907.     public EmployeeDTO update(EmployeeDTO employeeDTO);
  908.  
  909.     public void deleteById(UUID id);
  910.  
  911.     public boolean existsById(UUID id);
  912. }
  913.  
  914. package com.leverx.employeestat.rest.service;
  915.  
  916. import com.leverx.employeestat.rest.dto.ProjectDTO;
  917.  
  918. import java.util.List;
  919. import java.util.UUID;
  920.  
  921. public interface ProjectService {
  922.  
  923.     ProjectDTO getById(UUID id);
  924.  
  925.     ProjectDTO getByName(String name);
  926.  
  927.     List<ProjectDTO> getAll();
  928.  
  929.     ProjectDTO save(ProjectDTO projectDTO);
  930.  
  931.     ProjectDTO update(ProjectDTO projectDTO);
  932.  
  933.     void deleteById(UUID id);
  934.  
  935.     boolean existsById(UUID id);
  936.  
  937.     boolean existsByName(String name);
  938. }
  939.  
  940. package com.leverx.employeestat.rest.service;
  941.  
  942. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  943.  
  944. public interface ReportService {
  945.  
  946.     XSSFWorkbook exportOccupationReport();
  947.  
  948.     XSSFWorkbook exportLastGeneratedReport();
  949.  
  950.     void generateAvailableEmployeesReport();
  951. }
  952.  
  953. package com.leverx.employeestat.rest.service;
  954.  
  955. import com.leverx.employeestat.rest.dto.WorkDTO;
  956.  
  957. import java.util.List;
  958. import java.util.UUID;
  959.  
  960. public interface WorkService {
  961.  
  962.     List<WorkDTO> getAll();
  963.  
  964.     WorkDTO getByIds(UUID employeeId, UUID projectId);
  965.  
  966.     //WorkDTO save(WorkDTO workDTO);
  967.  
  968.     WorkDTO update(WorkDTO workDTO);
  969.  
  970.     void deleteByIds(UUID employeeId, UUID projectId);
  971. }
  972.  
  973. package com.leverx.employeestat.rest.service.impl;
  974.  
  975. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  976. import com.leverx.employeestat.rest.dto.converter.EmployeeConverter;
  977. import com.leverx.employeestat.rest.entity.Employee;
  978. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  979. import com.leverx.employeestat.rest.exception.InvalidPasswordException;
  980. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  981. import com.leverx.employeestat.rest.model.ResetPasswordRequest;
  982. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  983. import com.leverx.employeestat.rest.service.AuthorizationService;
  984. import org.springframework.beans.factory.annotation.Autowired;
  985. import org.springframework.security.crypto.password.PasswordEncoder;
  986. import org.springframework.stereotype.Service;
  987. import org.springframework.transaction.annotation.Transactional;
  988.  
  989. import java.util.ArrayList;
  990. import java.util.List;
  991.  
  992. @Service
  993. public class AuthorizationServiceImpl implements AuthorizationService {
  994.  
  995.     private final EmployeeRepository employeeRepository;
  996.     private final EmployeeConverter converter;
  997.     private final PasswordEncoder encoder;
  998.  
  999.     @Autowired
  1000.     public AuthorizationServiceImpl(EmployeeRepository employeeRepository, EmployeeConverter converter, PasswordEncoder encoder) {
  1001.         this.employeeRepository = employeeRepository;
  1002.         this.converter = converter;
  1003.         this.encoder = encoder;
  1004.     }
  1005.  
  1006.     @Override
  1007.     @Transactional
  1008.     public EmployeeDTO registerEmployee(EmployeeDTO employeeDTO) {
  1009.         if (employeeRepository.existsByUsername(employeeDTO.getUsername())) {
  1010.             throw new DuplicateRecordException
  1011.                     (String.format("Employee with username=%s already exists", employeeDTO.getUsername()));
  1012.         }
  1013.         employeeDTO.setPassword(encoder.encode(employeeDTO.getPassword()));
  1014.         return converter.toDTO(employeeRepository.save(converter.toEntity(employeeDTO)));
  1015.     }
  1016.  
  1017.     @Override
  1018.     @Transactional
  1019.     public List<EmployeeDTO> registerAll(List<EmployeeDTO> employeeDTOs) {
  1020.         List<EmployeeDTO> saved = new ArrayList<>();
  1021.         for (EmployeeDTO employeeDTO : employeeDTOs) {
  1022.             saved.add(registerEmployee(employeeDTO));
  1023.         }
  1024.         return saved;
  1025.     }
  1026.  
  1027.     @Override
  1028.     @Transactional
  1029.     public EmployeeDTO resetPassword(ResetPasswordRequest request) {
  1030.         Employee employee = employeeRepository.findEmployeeByUsername(request.getUsername())
  1031.                 .orElseThrow(() -> new NoSuchRecordException
  1032.                         (String.format("Employee with username=%s not found", request.getUsername()))
  1033.                 );
  1034.         if (!encoder.matches(request.getOldPassword(), employee.getPassword())) {
  1035.             throw new InvalidPasswordException("You entered incorrect old password");
  1036.         }
  1037.         employee.setPassword(encoder.encode(request.getNewPassword()));
  1038.         return converter.toDTO(employee);
  1039.     }
  1040. }
  1041.  
  1042. package com.leverx.employeestat.rest.service.impl;
  1043.  
  1044. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  1045. import com.leverx.employeestat.rest.dto.converter.EmployeeConverter;
  1046. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  1047. import com.leverx.employeestat.rest.repository.WorkRepository;
  1048. import com.leverx.employeestat.rest.service.AvailableEmployeeService;
  1049. import org.springframework.beans.factory.annotation.Autowired;
  1050. import org.springframework.stereotype.Service;
  1051. import org.springframework.transaction.annotation.Transactional;
  1052.  
  1053. import java.util.List;
  1054. import java.util.stream.Collectors;
  1055.  
  1056. @Service
  1057. public class AvailableEmployeeServiceImpl implements AvailableEmployeeService {
  1058.  
  1059.     private final WorkRepository workRepository;
  1060.     private final EmployeeConverter converter;
  1061.  
  1062.     @Autowired
  1063.     public AvailableEmployeeServiceImpl(WorkRepository workRepository, EmployeeConverter converter) {
  1064.         this.workRepository = workRepository;
  1065.         this.converter = converter;
  1066.     }
  1067.  
  1068.     @Override
  1069.     @Transactional
  1070.     public List<EmployeeDTO> getAvailableEmployeesNow() {
  1071.         return workRepository.findAllAvailableNow()
  1072.                 .stream()
  1073.                 .map(work -> converter.toDTO(work.getId().getEmployee()))
  1074.                 .distinct()
  1075.                 .collect(Collectors.toList());
  1076.     }
  1077.  
  1078.     @Override
  1079.     @Transactional
  1080.     public List<EmployeeDTO> getAvailableEmployeesNext(int days) {
  1081.         return workRepository.findAllAvailableNext(days)
  1082.                 .stream()
  1083.                 .map(work -> converter.toDTO(work.getId().getEmployee()))
  1084.                 .distinct()
  1085.                 .collect(Collectors.toList());
  1086.     }
  1087. }
  1088.  
  1089. package com.leverx.employeestat.rest.service.impl;
  1090.  
  1091. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  1092. import com.leverx.employeestat.rest.exception.CSVReadingException;
  1093. import com.leverx.employeestat.rest.service.CSVReaderService;
  1094. import com.opencsv.CSVReader;
  1095. import com.opencsv.exceptions.CsvValidationException;
  1096. import org.apache.logging.log4j.LogManager;
  1097. import org.apache.logging.log4j.Logger;
  1098. import org.springframework.stereotype.Service;
  1099. import org.springframework.web.multipart.MultipartFile;
  1100.  
  1101. import java.io.IOException;
  1102. import java.io.InputStreamReader;
  1103. import java.util.ArrayList;
  1104. import java.util.List;
  1105. import java.util.UUID;
  1106.  
  1107. @Service
  1108. public class CSVReaderServiceImpl implements CSVReaderService {
  1109.  
  1110.     private final Logger log = LogManager.getLogger(CSVReaderServiceImpl.class);
  1111.  
  1112.     private final static int FIRST_NAME_COLUMN = 0;
  1113.     private final static int LAST_NAME_COLUMN = 1;
  1114.     private final static int USERNAME_COLUMN = 2;
  1115.     private final static int PASSWORD_COLUMN = 3;
  1116.     private final static int POSITION_COLUMN = 4;
  1117.     private final static int ROLE_COLUMN = 5;
  1118.     private final static int DEPARTMENT_ID_COLUMN = 6;
  1119.  
  1120.     public List<EmployeeDTO> getEmployeesFromFile(MultipartFile file) {
  1121.         List<EmployeeDTO> employees = new ArrayList<>();
  1122.         try(CSVReader reader = new CSVReader(new InputStreamReader(file.getInputStream()))) {
  1123.             String[] cells;
  1124.             while ((cells = reader.readNext()) != null) {
  1125.                 EmployeeDTO employee = new EmployeeDTO();
  1126.                 employee.setFirstName(cells[FIRST_NAME_COLUMN]);
  1127.                 employee.setLastName(cells[LAST_NAME_COLUMN]);
  1128.                 employee.setUsername(cells[USERNAME_COLUMN]);
  1129.                 employee.setPassword(cells[PASSWORD_COLUMN]);
  1130.                 employee.setPosition(cells[POSITION_COLUMN]);
  1131.                 employee.setRole(cells[ROLE_COLUMN]);
  1132.                 employee.setDepartmentId(UUID.fromString(cells[DEPARTMENT_ID_COLUMN]));
  1133.                 employees.add(employee);
  1134.             }
  1135.         } catch (IOException | CsvValidationException e) {
  1136.             throw new CSVReadingException(e.getMessage(), e);
  1137.         }
  1138.         log.info("Multipart file (CSV) read successfully");
  1139.         return employees;
  1140.     }
  1141. }
  1142.  
  1143. package com.leverx.employeestat.rest.service.impl;
  1144.  
  1145. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  1146. import com.leverx.employeestat.rest.dto.converter.DepartmentConverter;
  1147. import com.leverx.employeestat.rest.entity.Department;
  1148. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  1149. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  1150. import com.leverx.employeestat.rest.repository.DepartmentRepository;
  1151. import com.leverx.employeestat.rest.service.DepartmentService;
  1152. import org.springframework.beans.factory.annotation.Autowired;
  1153. import org.springframework.stereotype.Service;
  1154. import org.springframework.transaction.annotation.Transactional;
  1155.  
  1156. import java.util.List;
  1157. import java.util.UUID;
  1158. import java.util.stream.Collectors;
  1159.  
  1160. @Service
  1161. public class DepartmentServiceImpl implements DepartmentService {
  1162.  
  1163.     private final DepartmentRepository departmentRepository;
  1164.     private final DepartmentConverter converter;
  1165.  
  1166.     @Autowired
  1167.     public DepartmentServiceImpl(DepartmentRepository departmentRepository, DepartmentConverter converter) {
  1168.         this.departmentRepository = departmentRepository;
  1169.         this.converter = converter;
  1170.     }
  1171.  
  1172.     @Override
  1173.     @Transactional
  1174.     public DepartmentDTO save(DepartmentDTO departmentDTO) {
  1175.         if (departmentRepository.existsByName(departmentDTO.getName())) {
  1176.             throw new DuplicateRecordException
  1177.                     (String.format("Department with name=%s already exists", departmentDTO.getName()));
  1178.         }
  1179.         return converter.toDTO(departmentRepository.save(converter.toEntity(departmentDTO)));
  1180.     }
  1181.  
  1182.     @Override
  1183.     @Transactional
  1184.     public void deleteById(UUID id) {
  1185.         if (!departmentRepository.existsById(id)) {
  1186.             throw new NoSuchRecordException
  1187.                     (String.format("Department with id=%s not found for deleting", id));
  1188.         }
  1189.         departmentRepository.deleteById(id);
  1190.     }
  1191.  
  1192.     @Override
  1193.     @Transactional
  1194.     public DepartmentDTO update(DepartmentDTO departmentDTO) {
  1195.         if (departmentDTO.getId() != null && departmentRepository.existsById(departmentDTO.getId())) {
  1196.             return converter.toDTO(departmentRepository.save(converter.toEntity(departmentDTO)));
  1197.         } else if (!departmentRepository.existsByName(departmentDTO.getName())) {
  1198.             return converter.toDTO(departmentRepository.save(converter.toEntity(departmentDTO)));
  1199.         } else {
  1200.             throw new DuplicateRecordException
  1201.                     (String.format("Department with name=%s already exists", departmentDTO.getName()));
  1202.         }
  1203.     }
  1204.  
  1205.     @Override
  1206.     @Transactional(readOnly = true)
  1207.     public List<DepartmentDTO> getAll() {
  1208.         return departmentRepository.findAll()
  1209.                 .stream()
  1210.                 .map(converter::toDTO)
  1211.                 .collect(Collectors.toList());
  1212.     }
  1213.  
  1214.     @Override
  1215.     @Transactional(readOnly = true)
  1216.     public DepartmentDTO getById(UUID id) {
  1217.         Department department = departmentRepository.findById(id)
  1218.                 .orElseThrow(() ->
  1219.                     new NoSuchRecordException(String.format("Department with id=%s not found", id))
  1220.                 );
  1221.         return converter.toDTO(department);
  1222.     }
  1223.  
  1224.     @Override
  1225.     @Transactional(readOnly = true)
  1226.     public boolean existsById(UUID id) {
  1227.         return departmentRepository.existsById(id);
  1228.     }
  1229.  
  1230.     @Override
  1231.     @Transactional(readOnly = true)
  1232.     public boolean existsByName(String name) {
  1233.         return departmentRepository.existsByName(name);
  1234.     }
  1235. }
  1236.  
  1237. package com.leverx.employeestat.rest.service.impl;
  1238.  
  1239. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  1240. import com.leverx.employeestat.rest.dto.converter.EmployeeConverter;
  1241. import com.leverx.employeestat.rest.entity.Employee;
  1242. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  1243. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  1244. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  1245. import com.leverx.employeestat.rest.service.EmployeeService;
  1246. import org.springframework.beans.factory.annotation.Autowired;
  1247. import org.springframework.stereotype.Service;
  1248. import org.springframework.transaction.annotation.Transactional;
  1249.  
  1250. import java.util.ArrayList;
  1251. import java.util.List;
  1252. import java.util.UUID;
  1253. import java.util.stream.Collectors;
  1254.  
  1255. @Service
  1256. public class EmployeeServiceImpl implements EmployeeService {
  1257.  
  1258.     private final EmployeeRepository employeeRepository;
  1259.     private final EmployeeConverter converter;
  1260.  
  1261.     @Autowired
  1262.     public EmployeeServiceImpl(EmployeeRepository employeeRepository, EmployeeConverter converter) {
  1263.         this.employeeRepository = employeeRepository;
  1264.         this.converter = converter;
  1265.     }
  1266.  
  1267.     @Override
  1268.     @Transactional(readOnly = true)
  1269.     public List<EmployeeDTO> getAll() {
  1270.         return employeeRepository.findAll()
  1271.                 .stream()
  1272.                 .map(converter::toDTO)
  1273.                 .collect(Collectors.toList());
  1274.     }
  1275.  
  1276.     @Override
  1277.     @Transactional(readOnly = true)
  1278.     public EmployeeDTO getById(UUID id) {
  1279.         Employee employee = employeeRepository.findEmployeeById(id)
  1280.                 .orElseThrow(() -> new NoSuchRecordException
  1281.                         (String.format("Employee with id=%s not found", id))
  1282.                 );
  1283.         return converter.toDTO(employee);
  1284.     }
  1285.  
  1286.     @Override
  1287.     @Transactional(readOnly = true)
  1288.     public EmployeeDTO getByUsername(String username) {
  1289.         Employee employee = employeeRepository.findEmployeeByUsername(username)
  1290.                 .orElseThrow(() -> new NoSuchRecordException
  1291.                         (String.format("Employee with username=%s not found", username))
  1292.                 );
  1293.         return converter.toDTO(employee);
  1294.     }
  1295.  
  1296.     @Override
  1297.     @Transactional
  1298.     public EmployeeDTO save(EmployeeDTO employeeDTO) {
  1299.         if (employeeRepository.existsByUsername(employeeDTO.getUsername())) {
  1300.             throw new DuplicateRecordException
  1301.                     (String.format("Employee with username=%s already exists", employeeDTO.getUsername()));
  1302.         }
  1303.         return converter.toDTO(employeeRepository.save(converter.toEntity(employeeDTO)));
  1304.     }
  1305.  
  1306.     @Override
  1307.     @Transactional
  1308.     public List<EmployeeDTO> saveAll(List<EmployeeDTO> employeeDTOs) {
  1309.         List<EmployeeDTO> saved = new ArrayList<>();
  1310.         for (EmployeeDTO employeeDTO : employeeDTOs) {
  1311.             saved.add(save(employeeDTO));
  1312.         }
  1313.         return saved;
  1314.     }
  1315.  
  1316.     @Override
  1317.     @Transactional
  1318.     public EmployeeDTO update(EmployeeDTO employeeDTO) {
  1319.         Employee employee = employeeRepository.findEmployeeById(employeeDTO.getId())
  1320.                 .orElseThrow(() -> new NoSuchRecordException
  1321.                         (String.format("Employee with id=%s not found", employeeDTO.getId()))
  1322.                 );
  1323.         converter.updateEmployeeFields(employeeDTO, employee);
  1324.         return converter.toDTO(employee);
  1325.     }
  1326.  
  1327.     @Override
  1328.     @Transactional
  1329.     public void deleteById(UUID id) {
  1330.         if (!employeeRepository.existsById(id)) {
  1331.             throw new NoSuchRecordException
  1332.                     (String.format("Employee with id=%s not found for deleting", id));
  1333.         }
  1334.         employeeRepository.deleteById(id);
  1335.     }
  1336.  
  1337.     @Override
  1338.     @Transactional(readOnly = true)
  1339.     public boolean existsById(UUID id) {
  1340.         return employeeRepository.existsById(id);
  1341.     }
  1342. }
  1343.  
  1344. package com.leverx.employeestat.rest.service.impl;
  1345.  
  1346. import com.leverx.employeestat.rest.dto.ProjectDTO;
  1347. import com.leverx.employeestat.rest.dto.converter.ProjectConverter;
  1348. import com.leverx.employeestat.rest.entity.Project;
  1349. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  1350. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  1351. import com.leverx.employeestat.rest.repository.ProjectRepository;
  1352. import com.leverx.employeestat.rest.service.ProjectService;
  1353. import org.springframework.beans.factory.annotation.Autowired;
  1354. import org.springframework.stereotype.Service;
  1355. import org.springframework.transaction.annotation.Transactional;
  1356.  
  1357. import java.util.List;
  1358. import java.util.UUID;
  1359. import java.util.stream.Collectors;
  1360.  
  1361. @Service
  1362. public class ProjectServiceImpl implements ProjectService {
  1363.  
  1364.     private final ProjectRepository projectRepository;
  1365.     private final ProjectConverter converter;
  1366.  
  1367.     @Autowired
  1368.     public ProjectServiceImpl(ProjectRepository projectRepository, ProjectConverter converter) {
  1369.         this.projectRepository = projectRepository;
  1370.         this.converter = converter;
  1371.     }
  1372.  
  1373.     @Override
  1374.     @Transactional(readOnly = true)
  1375.     public ProjectDTO getById(UUID id) {
  1376.         Project project = projectRepository.findProjectById(id)
  1377.                 .orElseThrow(() -> new NoSuchRecordException
  1378.                         (String.format("Project with id=%s not found", id))
  1379.                 );
  1380.         return converter.toDTO(project);
  1381.     }
  1382.  
  1383.     @Override
  1384.     @Transactional(readOnly = true)
  1385.     public ProjectDTO getByName(String name) {
  1386.         Project project = projectRepository.findProjectByName(name).
  1387.                 orElseThrow(() -> new NoSuchRecordException
  1388.                         (String.format("Project with name=%s not found", name))
  1389.                 );
  1390.         return converter.toDTO(project);
  1391.     }
  1392.  
  1393.     @Override
  1394.     @Transactional(readOnly = true)
  1395.     public List<ProjectDTO> getAll() {
  1396.         return projectRepository.findAll()
  1397.                 .stream()
  1398.                 .map(converter::toDTO)
  1399.                 .collect(Collectors.toList());
  1400.     }
  1401.  
  1402.     @Override
  1403.     public ProjectDTO save(ProjectDTO projectDTO) {
  1404.         if (projectRepository.existsByName(projectDTO.getName())) {
  1405.             throw new DuplicateRecordException
  1406.                     (String.format("Project with name=%s already exists", projectDTO.getName()));
  1407.         }
  1408.         return converter.toDTO(projectRepository.save(converter.toEntity(projectDTO)));
  1409.     }
  1410.  
  1411.     @Override
  1412.     @Transactional
  1413.     public ProjectDTO update(ProjectDTO projectDTO) {
  1414.         if (projectDTO.getId() != null && projectRepository.existsById(projectDTO.getId())) {
  1415.             return converter.toDTO(projectRepository.save(converter.toEntity(projectDTO)));
  1416.         } else if (!projectRepository.existsByName(projectDTO.getName())) {
  1417.             return converter.toDTO(projectRepository.save(converter.toEntity(projectDTO)));
  1418.         } else {
  1419.             throw new DuplicateRecordException
  1420.                     (String.format("Project with name=%s already exists", projectDTO.getName()));
  1421.         }
  1422.     }
  1423.  
  1424.     @Override
  1425.     @Transactional
  1426.     public void deleteById(UUID id) {
  1427.         if (!projectRepository.existsById(id)) {
  1428.             throw new NoSuchRecordException
  1429.                     (String.format("Department with id=%s not found for deleting", id));
  1430.         }
  1431.         projectRepository.deleteById(id);
  1432.     }
  1433.  
  1434.     @Override
  1435.     @Transactional(readOnly = true)
  1436.     public boolean existsById(UUID id) {
  1437.         return projectRepository.existsById(id);
  1438.     }
  1439.  
  1440.     @Override
  1441.     @Transactional(readOnly = true)
  1442.     public boolean existsByName(String name) {
  1443.         return projectRepository.existsByName(name);
  1444.     }
  1445. }
  1446.  
  1447. package com.leverx.employeestat.rest.service.impl;
  1448.  
  1449. import com.leverx.employeestat.rest.entity.*;
  1450. import com.leverx.employeestat.rest.exception.AttributesReadingException;
  1451. import com.leverx.employeestat.rest.exception.NoSuchReportException;
  1452. import com.leverx.employeestat.rest.exception.ReportWritingException;
  1453. import com.leverx.employeestat.rest.repository.WorkRepository;
  1454. import com.leverx.employeestat.rest.service.ReportService;
  1455. import org.apache.logging.log4j.LogManager;
  1456. import org.apache.logging.log4j.Logger;
  1457. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  1458. import org.apache.poi.ss.usermodel.Cell;
  1459. import org.apache.poi.ss.usermodel.Row;
  1460. import org.apache.poi.xssf.usermodel.XSSFSheet;
  1461. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  1462. import org.springframework.beans.factory.annotation.Autowired;
  1463. import org.springframework.beans.factory.annotation.Value;
  1464. import org.springframework.scheduling.annotation.Scheduled;
  1465. import org.springframework.stereotype.Service;
  1466. import org.springframework.transaction.annotation.Transactional;
  1467.  
  1468. import java.io.File;
  1469. import java.io.FileOutputStream;
  1470. import java.io.IOException;
  1471. import java.nio.file.Files;
  1472. import java.nio.file.attribute.BasicFileAttributes;
  1473. import java.time.LocalDate;
  1474. import java.util.Arrays;
  1475. import java.util.List;
  1476. import java.util.stream.Collectors;
  1477.  
  1478. @Service
  1479. public class ReportServiceImpl implements ReportService {
  1480.  
  1481.     private final Logger log = LogManager.getLogger(ReportServiceImpl.class);
  1482.  
  1483.     private final static String FIRST_NAME_COL = "First Name";
  1484.     private final static String LAST_NAME_COL = "Last Name";
  1485.     private final static String DEPARTMENT_COL = "Department";
  1486.     private final static String PROJECT_OCCUPATION_COL = "Project - Occupation";
  1487.  
  1488.     @Value("${reports-path}")
  1489.     private String reportsPath;
  1490.     private XSSFWorkbook workbook;
  1491.     private final XSSFSheet sheet;
  1492.     private final WorkRepository workRepository;
  1493.  
  1494.     @Autowired
  1495.     public ReportServiceImpl(WorkRepository workRepository) {
  1496.         this.workbook = new XSSFWorkbook();
  1497.         this.sheet = (workbook.createSheet("Employees info"));
  1498.         this.workRepository = workRepository;
  1499.     }
  1500.  
  1501.     @Override
  1502.     @Scheduled(cron = "${reports-generating-cron}")
  1503.     @Transactional
  1504.     public void generateAvailableEmployeesReport() {
  1505.         createTableHeaders(FIRST_NAME_COL, LAST_NAME_COL, DEPARTMENT_COL);
  1506.         List<Employee> availableEmployees = workRepository.findAllAvailableNext(30)
  1507.                 .stream()
  1508.                 .map(Work::getId)
  1509.                 .map(WorkId::getEmployee)
  1510.                 .collect(Collectors.toList());
  1511.  
  1512.         for (int i = 0; i < availableEmployees.size(); i++) {
  1513.             Employee employee = availableEmployees.get(i);
  1514.             Row row = sheet.createRow(i + 1);
  1515.  
  1516.             Cell firstName = row.createCell(0);
  1517.             firstName.setCellValue(employee.getFirstName());
  1518.  
  1519.             Cell lastName = row.createCell(1);
  1520.             lastName.setCellValue(employee.getLastName());
  1521.  
  1522.             Cell department = row.createCell(2);
  1523.             department.setCellValue(employee.getDepartment().getName());
  1524.         }
  1525.  
  1526.         File file = new File(String.format("%s/AvailableEmployees-%s.xlsx", reportsPath, LocalDate.now()));
  1527.         try (FileOutputStream outputStream = new FileOutputStream(file)) {
  1528.             workbook.write(outputStream);
  1529.         } catch (IOException e) {
  1530.             throw new ReportWritingException("Failed to write report", e);
  1531.         }
  1532.         log.info("Report generated successfully (every month report)");
  1533.     }
  1534.  
  1535.     @Override
  1536.     @Transactional
  1537.     public XSSFWorkbook exportOccupationReport() {
  1538.         createTableHeaders(FIRST_NAME_COL, LAST_NAME_COL, DEPARTMENT_COL, PROJECT_OCCUPATION_COL);
  1539.         List<Work> works = workRepository.findAll();
  1540.         for (int i = 0; i < works.size(); i++) {
  1541.             Work work = works.get(i);
  1542.             Employee employee = work.getId().getEmployee();
  1543.             Project project = work.getId().getProject();
  1544.  
  1545.             Row row = sheet.createRow(i + 1);
  1546.  
  1547.             Cell firstName = row.createCell(0);
  1548.             firstName.setCellValue(employee.getFirstName());
  1549.  
  1550.             Cell lastName = row.createCell(1);
  1551.             lastName.setCellValue(employee.getLastName());
  1552.  
  1553.             Cell departmentName = row.createCell(2);
  1554.             Department department = employee.getDepartment();
  1555.             departmentName.setCellValue(department == null ? null : department.getName());
  1556.  
  1557.             Cell occupation = row.createCell(3);
  1558.             occupation.setCellValue(String.format("%s - (%s - %s)", project.getName(), work.getPositionStartDate(), work.getPositionEndDate()));
  1559.         }
  1560.         log.info("Occupation report created successfully");
  1561.         return workbook;
  1562.     }
  1563.  
  1564.     @Override
  1565.     public XSSFWorkbook exportLastGeneratedReport() {
  1566.         File latestReport = getLatestReport();
  1567.         log.info("Latest report retrieved successfully");
  1568.         try {
  1569.             return new XSSFWorkbook(latestReport);
  1570.         } catch (IOException | InvalidFormatException e) {
  1571.             throw new ReportWritingException("Failed to write report", e);
  1572.         }
  1573.     }
  1574.  
  1575.     private File getLatestReport() {
  1576.         File[] reports = new File(reportsPath).listFiles();
  1577.         return Arrays.stream(reports)
  1578.                 .sorted((f1, f2) -> {
  1579.                     BasicFileAttributes attr1 = null;
  1580.                     BasicFileAttributes attr2 = null;
  1581.                     try {
  1582.                         attr1 = Files.readAttributes(f1.toPath(), BasicFileAttributes.class);
  1583.                         attr2 = Files.readAttributes(f2.toPath(), BasicFileAttributes.class);
  1584.                     } catch (IOException e) {
  1585.                         throw new AttributesReadingException("Failed to read file attributes", e);
  1586.                     }
  1587.                     return (-1) * attr1.creationTime().compareTo(attr2.creationTime());
  1588.                 })
  1589.                 .findFirst()
  1590.                 .orElseThrow(() -> new NoSuchReportException("No reports found"));
  1591.     }
  1592.  
  1593.     private void createTableHeaders(String ... names) {
  1594.         Row row = sheet.createRow(0);
  1595.         for (int i = 0; i < names.length; i++) {
  1596.             sheet.setColumnWidth(i, 12000);
  1597.             Cell cell = row.createCell(i);
  1598.             cell.setCellValue(names[i]);
  1599.         }
  1600.     }
  1601. }
  1602.  
  1603. package com.leverx.employeestat.rest.service.impl;
  1604.  
  1605. import com.leverx.employeestat.rest.dto.WorkDTO;
  1606. import com.leverx.employeestat.rest.dto.converter.WorkConverter;
  1607. import com.leverx.employeestat.rest.entity.Work;
  1608. import com.leverx.employeestat.rest.entity.WorkId;
  1609. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  1610. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  1611. import com.leverx.employeestat.rest.repository.ProjectRepository;
  1612. import com.leverx.employeestat.rest.repository.WorkRepository;
  1613. import com.leverx.employeestat.rest.service.WorkService;
  1614. import org.springframework.beans.factory.annotation.Autowired;
  1615. import org.springframework.stereotype.Service;
  1616. import org.springframework.transaction.annotation.Transactional;
  1617.  
  1618. import java.util.List;
  1619. import java.util.UUID;
  1620. import java.util.stream.Collectors;
  1621.  
  1622. @Service
  1623. public class WorkServiceImpl implements WorkService {
  1624.  
  1625.     private final WorkRepository workRepository;
  1626.     private final EmployeeRepository employeeRepository;
  1627.     private final ProjectRepository projectRepository;
  1628.     private final WorkConverter converter;
  1629.  
  1630.     @Autowired
  1631.     public WorkServiceImpl(WorkRepository workRepository,
  1632.                            EmployeeRepository employeeRepository,
  1633.                            ProjectRepository projectRepository,
  1634.                            WorkConverter converter) {
  1635.         this.workRepository = workRepository;
  1636.         this.employeeRepository = employeeRepository;
  1637.         this.projectRepository = projectRepository;
  1638.         this.converter = converter;
  1639.     }
  1640.  
  1641.     @Override
  1642.     @Transactional
  1643.     public List<WorkDTO> getAll() {
  1644.         return workRepository.findAll()
  1645.                 .stream()
  1646.                 .map(converter::toDTO)
  1647.                 .collect(Collectors.toList());
  1648.     }
  1649.  
  1650.     @Override
  1651.     @Transactional
  1652.     public WorkDTO getByIds(UUID employeeId, UUID projectId) {
  1653.         WorkId workId = createWorkId(employeeId, projectId);
  1654.         Work work = workRepository.findWorkById(workId)
  1655.                 .orElseThrow(() -> new NoSuchRecordException
  1656.                         (String.format("Work with id=%s not found", workId))
  1657.                 );
  1658.         return converter.toDTO(work);
  1659.     }
  1660.  
  1661.     @Override
  1662.     @Transactional
  1663.     public WorkDTO update(WorkDTO workDTO) {
  1664.         WorkId workId = createWorkId(workDTO.getEmployeeId(), workDTO.getProjectId());
  1665.         Work work = workRepository.findWorkById(workId)
  1666.                 .orElseThrow(() -> new NoSuchRecordException
  1667.                         (String.format("Work with id=%s not found", workId))
  1668.                 );
  1669.  
  1670.         work.setPositionEndDate(workDTO.getPositionEndDate());
  1671.         work.setPositionStartDate(workDTO.getPositionStartDate());
  1672.         work.setWorkingHours(workDTO.getWorkingHours());
  1673.         return converter.toDTO(work);
  1674.     }
  1675.  
  1676.     @Override
  1677.     @Transactional
  1678.     public void deleteByIds(UUID employeeId, UUID projectId) {
  1679.         WorkId workId = createWorkId(employeeId, projectId);
  1680.         if (!workRepository.existsById(workId)) {
  1681.             throw new NoSuchRecordException
  1682.                     (String.format("Work with id=%s not found", workId));
  1683.         }
  1684.         workRepository.deleteById(workId);
  1685.     }
  1686.  
  1687.     private WorkId createWorkId(UUID employeeId, UUID projectId) {
  1688.         WorkId workId = new WorkId();
  1689.         workId.setEmployee(employeeRepository.findEmployeeById(employeeId)
  1690.                 .orElseThrow(() -> new NoSuchRecordException
  1691.                         (String.format("Employee with id=%s not found", employeeId)))
  1692.         );
  1693.         workId.setProject(projectRepository.findProjectById(projectId)
  1694.                 .orElseThrow(() -> new NoSuchRecordException
  1695.                         (String.format("Project with id=%s not found", projectId)))
  1696.         );
  1697.         return workId;
  1698.     }
  1699. }
  1700.  
  1701. package com.leverx.employeestat.rest.repository;
  1702.  
  1703. import com.leverx.employeestat.rest.entity.Department;
  1704. import org.springframework.data.jpa.repository.JpaRepository;
  1705.  
  1706. import java.util.Optional;
  1707. import java.util.UUID;
  1708.  
  1709. public interface DepartmentRepository extends JpaRepository<Department, UUID> {
  1710.  
  1711.     @Override
  1712.     Optional<Department> findById(UUID uuid);
  1713.  
  1714.     boolean existsById(UUID uuid);
  1715.  
  1716.     boolean existsByName(String name);
  1717. }
  1718.  
  1719. package com.leverx.employeestat.rest.repository;
  1720.  
  1721. import com.leverx.employeestat.rest.entity.Employee;
  1722. import org.springframework.data.jpa.repository.JpaRepository;
  1723.  
  1724. import java.util.Optional;
  1725. import java.util.UUID;
  1726.  
  1727. public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
  1728.  
  1729.     Optional<Employee> findEmployeeById(UUID id);
  1730.  
  1731.     Optional<Employee> findEmployeeByUsername(String username);
  1732.  
  1733.     boolean existsByUsername(String username);
  1734. }
  1735.  
  1736. package com.leverx.employeestat.rest.repository;
  1737.  
  1738. import com.leverx.employeestat.rest.entity.Project;
  1739. import org.springframework.data.jpa.repository.JpaRepository;
  1740.  
  1741. import java.util.List;
  1742. import java.util.Optional;
  1743. import java.util.UUID;
  1744.  
  1745. public interface ProjectRepository extends JpaRepository<Project, UUID> {
  1746.  
  1747.     Optional<Project> findProjectById(UUID uuid);
  1748.  
  1749.     Optional<Project> findProjectByName(String name);
  1750.  
  1751.     @Override
  1752.     List<Project> findAll();
  1753.  
  1754.     boolean existsByName(String name);
  1755. }
  1756.  
  1757. package com.leverx.employeestat.rest.repository;
  1758.  
  1759. import com.leverx.employeestat.rest.entity.Role;
  1760. import org.springframework.data.jpa.repository.JpaRepository;
  1761.  
  1762. import java.util.Optional;
  1763. import java.util.UUID;
  1764.  
  1765. public interface RoleRepository extends JpaRepository<Role, UUID> {
  1766.     Optional<Role> findByName(String name);
  1767. }
  1768.  
  1769. package com.leverx.employeestat.rest.repository;
  1770.  
  1771. import com.leverx.employeestat.rest.entity.Work;
  1772. import com.leverx.employeestat.rest.entity.WorkId;
  1773. import org.springframework.data.jpa.repository.JpaRepository;
  1774. import org.springframework.data.jpa.repository.Query;
  1775.  
  1776. import java.util.List;
  1777. import java.util.Optional;
  1778.  
  1779. public interface WorkRepository extends JpaRepository<Work, WorkId> {
  1780.  
  1781.     Optional<Work> findWorkById(WorkId workId);
  1782.  
  1783.     @Override
  1784.     List<Work> findAll();
  1785.  
  1786.     void deleteById(WorkId workId);
  1787.  
  1788.     @Query(nativeQuery = true, value =
  1789.             "SELECT * FROM project_employee " +
  1790.             "WHERE position_end_date < current_date OR position_start_date > current_date")
  1791.     List<Work> findAllAvailableNow();
  1792.  
  1793.     @Query(nativeQuery = true, value =
  1794.             "SELECT * FROM project_employee " +
  1795.             "WHERE position_start_date < current_date and position_end_date < current_date " +
  1796.             "or position_start_date > current_date + ?1 and position_end_date > current_date + ?1")
  1797.     List<Work> findAllAvailableNext(int days);
  1798.  
  1799. }
  1800.  
  1801. package com.leverx.employeestat.rest.security.config;
  1802.  
  1803. import com.leverx.employeestat.rest.security.employeedetails.EmployeeDetailsService;
  1804. import org.springframework.beans.factory.annotation.Autowired;
  1805. import org.springframework.context.annotation.Configuration;
  1806. import org.springframework.core.annotation.Order;
  1807. import org.springframework.http.HttpMethod;
  1808. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  1809. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  1810. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  1811. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  1812. import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
  1813. import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
  1814.  
  1815. @Configuration
  1816. @EnableWebSecurity
  1817. public class MultipleSecurityConfig {
  1818.  
  1819.     @Order(1)
  1820.     @Configuration
  1821.     public static class OAuth2Config extends WebSecurityConfigurerAdapter {
  1822.  
  1823.         private final ClientRegistrationRepository clientRegistrationRepository;
  1824.         private final OAuth2AuthorizedClientService authorizedClientService;
  1825.  
  1826.         @Autowired
  1827.         public OAuth2Config(ClientRegistrationRepository clientRegistrationRepository,
  1828.                             OAuth2AuthorizedClientService authorizedClientService) {
  1829.             this.clientRegistrationRepository = clientRegistrationRepository;
  1830.             this.authorizedClientService = authorizedClientService;
  1831.         }
  1832.  
  1833.         @Override
  1834.         protected void configure(HttpSecurity http) throws Exception {
  1835.             http
  1836.                     .requestMatchers()
  1837.                     .antMatchers(
  1838.                             "/oauth2/authorization/google",
  1839.                             "/api/employees/export",
  1840.                             "/api/employees/export/last",
  1841.                             "/login/oauth2/code/google/**")
  1842.                     .and()
  1843.                     .authorizeRequests()
  1844.                     .anyRequest().authenticated()
  1845.                     .and()
  1846.                     .oauth2Login()
  1847.                     .clientRegistrationRepository(clientRegistrationRepository)
  1848.                     .authorizedClientService(authorizedClientService);
  1849.         }
  1850.     }
  1851.  
  1852.     @Order(2)
  1853.     @Configuration
  1854.     public static class BasicAuthorizationConfig extends WebSecurityConfigurerAdapter {
  1855.  
  1856.         private final EmployeeDetailsService employeeDetailsService;
  1857.         private final CustomBasicAuthenticationEntryPoint authenticationEntryPoint;
  1858.         private final CustomAccessDeniedHandler accessDeniedHandler;
  1859.  
  1860.         @Autowired
  1861.         public BasicAuthorizationConfig(EmployeeDetailsService employeeDetailsService,
  1862.                                         CustomBasicAuthenticationEntryPoint authenticationEntryPoint,
  1863.                                         CustomAccessDeniedHandler accessDeniedHandler) {
  1864.             this.employeeDetailsService = employeeDetailsService;
  1865.             this.authenticationEntryPoint = authenticationEntryPoint;
  1866.             this.accessDeniedHandler = accessDeniedHandler;
  1867.         }
  1868.  
  1869.         @Override
  1870.         protected void configure(HttpSecurity http) throws Exception {
  1871.             http
  1872.                     .csrf().disable()
  1873.                     .authorizeRequests()
  1874.                     .antMatchers("/api/register").permitAll()
  1875.                     .antMatchers("/api/reset-password").permitAll()
  1876.                     .antMatchers("/api/doc").permitAll()
  1877.                     .antMatchers(HttpMethod.GET, "/api/**/**/").permitAll()
  1878.                     .antMatchers(HttpMethod.POST, "/api/*").hasRole("MANAGER")
  1879.                     .antMatchers(HttpMethod.PUT, "/api/*").hasRole("MANAGER")
  1880.                     .antMatchers(HttpMethod.DELETE, "/api/**/**").hasRole("MANAGER")
  1881.                     .anyRequest().authenticated()
  1882.                     .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint)
  1883.                     .and().sessionManagement().disable()
  1884.                     .exceptionHandling().accessDeniedHandler(accessDeniedHandler);
  1885.         }
  1886.  
  1887.         @Override
  1888.         public void configure(AuthenticationManagerBuilder builder) throws Exception {
  1889.             builder.userDetailsService(employeeDetailsService);
  1890.         }
  1891.     }
  1892. }
  1893.  
  1894. package com.leverx.employeestat.rest.security.config;
  1895.  
  1896. import com.leverx.employeestat.rest.exceptionhandler.ExceptionInfo;
  1897. import lombok.extern.slf4j.Slf4j;
  1898. import org.springframework.context.annotation.ComponentScan;
  1899. import org.springframework.http.HttpStatus;
  1900. import org.springframework.http.MediaType;
  1901. import org.springframework.security.access.AccessDeniedException;
  1902. import org.springframework.security.web.access.AccessDeniedHandler;
  1903. import org.springframework.stereotype.Component;
  1904.  
  1905. import javax.servlet.ServletException;
  1906. import javax.servlet.http.HttpServletRequest;
  1907. import javax.servlet.http.HttpServletResponse;
  1908. import java.io.IOException;
  1909.  
  1910. import static com.leverx.employeestat.rest.util.JsonUtils.toJson;
  1911.  
  1912. @Slf4j
  1913. @Component
  1914. public class CustomAccessDeniedHandler implements AccessDeniedHandler {
  1915.  
  1916.     @Override
  1917.     public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
  1918.         response.setStatus(HttpStatus.FORBIDDEN.value());
  1919.         ExceptionInfo info = new ExceptionInfo(accessDeniedException.getMessage(), HttpStatus.FORBIDDEN);
  1920.         response.getOutputStream().println(toJson(info));
  1921.         response.setContentType(MediaType.APPLICATION_JSON_VALUE);
  1922.  
  1923.         log.info("Access denied: " + accessDeniedException.getMessage());
  1924.     }
  1925. }
  1926.  
  1927. package com.leverx.employeestat.rest.security.config;
  1928.  
  1929. import com.leverx.employeestat.rest.exceptionhandler.ExceptionInfo;
  1930. import lombok.extern.slf4j.Slf4j;
  1931. import org.springframework.context.annotation.ComponentScan;
  1932. import org.springframework.http.HttpStatus;
  1933. import org.springframework.http.MediaType;
  1934. import org.springframework.security.core.AuthenticationException;
  1935. import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
  1936. import org.springframework.stereotype.Component;
  1937.  
  1938. import javax.servlet.http.HttpServletRequest;
  1939. import javax.servlet.http.HttpServletResponse;
  1940. import java.io.IOException;
  1941.  
  1942. import static com.leverx.employeestat.rest.util.JsonUtils.toJson;
  1943.  
  1944. @Component
  1945. @Slf4j
  1946. public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
  1947.  
  1948.     @Override
  1949.     public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
  1950.         response.setStatus(HttpStatus.UNAUTHORIZED.value());
  1951.         ExceptionInfo info = new ExceptionInfo(authException.getMessage(), HttpStatus.UNAUTHORIZED);
  1952.         response.getOutputStream().println(toJson(info));
  1953.         response.setContentType(MediaType.APPLICATION_JSON_VALUE);
  1954.  
  1955.         log.info("Authentication failed: " + authException.getMessage());
  1956.     }
  1957.  
  1958.     @Override
  1959.     public void afterPropertiesSet() {
  1960.         setRealmName("Access to secured endpoints");
  1961.         super.afterPropertiesSet();
  1962.     }
  1963. }
  1964.  
  1965. package com.leverx.employeestat.rest.security.employeedetails;
  1966.  
  1967. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  1968. import org.springframework.security.core.GrantedAuthority;
  1969. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  1970. import org.springframework.security.core.userdetails.UserDetails;
  1971. import org.springframework.stereotype.Component;
  1972.  
  1973. import java.util.Collection;
  1974. import java.util.Collections;
  1975.  
  1976. @Component
  1977. public class EmployeeDetails implements UserDetails {
  1978.  
  1979.     private String username;
  1980.     private String password;
  1981.     private Collection<? extends GrantedAuthority> grantedAuthorities;
  1982.  
  1983.     public EmployeeDetails toEmployeeDetails(EmployeeDTO employee) {
  1984.         this.username = employee.getUsername();
  1985.         this.password = employee.getPassword();
  1986.         this.grantedAuthorities = Collections.singletonList(new SimpleGrantedAuthority(employee.getRole()));
  1987.         return this;
  1988.     }
  1989.  
  1990.     @Override
  1991.     public Collection<? extends GrantedAuthority> getAuthorities() {
  1992.         return grantedAuthorities;
  1993.     }
  1994.  
  1995.     @Override
  1996.     public String getPassword() {
  1997.         return password;
  1998.     }
  1999.  
  2000.     @Override
  2001.     public String getUsername() {
  2002.         return username;
  2003.     }
  2004.  
  2005.     @Override
  2006.     public boolean isAccountNonExpired() {
  2007.         return true;
  2008.     }
  2009.  
  2010.     @Override
  2011.     public boolean isAccountNonLocked() {
  2012.         return true;
  2013.     }
  2014.  
  2015.     @Override
  2016.     public boolean isCredentialsNonExpired() {
  2017.         return true;
  2018.     }
  2019.  
  2020.     @Override
  2021.     public boolean isEnabled() {
  2022.         return true;
  2023.     }
  2024. }
  2025.  
  2026. package com.leverx.employeestat.rest.security.employeedetails;
  2027.  
  2028. import com.leverx.employeestat.rest.service.EmployeeService;
  2029. import org.springframework.beans.factory.annotation.Autowired;
  2030. import org.springframework.security.core.userdetails.UserDetails;
  2031. import org.springframework.security.core.userdetails.UserDetailsService;
  2032. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  2033. import org.springframework.stereotype.Service;
  2034.  
  2035. @Service
  2036. public class EmployeeDetailsService implements UserDetailsService {
  2037.  
  2038.     private final EmployeeDetails employeeDetails;
  2039.     private final EmployeeService employeeService;
  2040.  
  2041.     @Autowired
  2042.     public EmployeeDetailsService(EmployeeDetails employeeDetails, EmployeeService employeeService) {
  2043.         this.employeeDetails = employeeDetails;
  2044.         this.employeeService = employeeService;
  2045.     }
  2046.  
  2047.     @Override
  2048.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  2049.         return employeeDetails.toEmployeeDetails(employeeService.getByUsername(username));
  2050.     }
  2051. }
  2052.  
  2053. package com.leverx.employeestat.rest.exceptionhandler;
  2054.  
  2055. import com.leverx.employeestat.rest.exception.*;
  2056. import lombok.extern.slf4j.Slf4j;
  2057. import org.springframework.core.Ordered;
  2058. import org.springframework.core.annotation.Order;
  2059. import org.springframework.http.HttpStatus;
  2060. import org.springframework.http.ResponseEntity;
  2061. import org.springframework.web.bind.annotation.ExceptionHandler;
  2062. import org.springframework.web.bind.annotation.RestControllerAdvice;
  2063. import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
  2064.  
  2065. @Slf4j
  2066. @Order(Ordered.HIGHEST_PRECEDENCE)
  2067. @RestControllerAdvice("com.leverx.employeestat.rest.controller")
  2068. public class GlobalControllerAdvice extends ResponseEntityExceptionHandler {
  2069.  
  2070.     @ExceptionHandler(NoSuchRecordException.class)
  2071.     public ResponseEntity<ExceptionInfo> handleNoSuchRecordException(NoSuchRecordException exception) {
  2072.         log.info(String.format("Handled exception - %s", exception), exception);
  2073.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.NOT_FOUND);
  2074.         return new ResponseEntity<>(info, HttpStatus.NOT_FOUND);
  2075.     }
  2076.  
  2077.     @ExceptionHandler(DuplicateRecordException.class)
  2078.     public ResponseEntity<ExceptionInfo> handleDuplicateRecordException(DuplicateRecordException exception) {
  2079.         log.info(String.format("Handled exception - %s", exception), exception);
  2080.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.BAD_REQUEST);
  2081.         return new ResponseEntity<>(info, HttpStatus.BAD_REQUEST);
  2082.     }
  2083.  
  2084.     @ExceptionHandler(EntityConversionException.class)
  2085.     public ResponseEntity<ExceptionInfo> handleEntityConversionException(EntityConversionException exception) {
  2086.         log.info(String.format("Handled exception - %s", exception), exception);
  2087.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.BAD_REQUEST);
  2088.         return new ResponseEntity<>(info, HttpStatus.BAD_REQUEST);
  2089.     }
  2090.  
  2091.     @ExceptionHandler(NotValidRecordException.class)
  2092.     public ResponseEntity<ExceptionInfo> handleNotValidRecordException(NotValidRecordException exception) {
  2093.         log.info(String.format("Handled exception - %s", exception), exception);
  2094.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.BAD_REQUEST);
  2095.         return new ResponseEntity<>(info, HttpStatus.BAD_REQUEST);
  2096.     }
  2097.  
  2098.     @ExceptionHandler(NotValidUUIDException.class)
  2099.     public ResponseEntity<ExceptionInfo> handleNotValidUUIDException(NotValidUUIDException exception) {
  2100.         log.info(String.format("Handled exception - %s", exception), exception);
  2101.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.BAD_REQUEST);
  2102.         return new ResponseEntity<>(info, HttpStatus.BAD_REQUEST);
  2103.     }
  2104.  
  2105.     @ExceptionHandler(InvalidPasswordException.class)
  2106.     public ResponseEntity<ExceptionInfo> handleInvalidPasswordException(InvalidPasswordException exception) {
  2107.         log.info(String.format("Handled exception - %s", exception), exception);
  2108.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.UNAUTHORIZED);
  2109.         return new ResponseEntity<>(info, HttpStatus.UNAUTHORIZED);
  2110.     }
  2111.  
  2112.     @ExceptionHandler(CSVReadingException.class)
  2113.     public ResponseEntity<ExceptionInfo> handleCSVReadingException(CSVReadingException exception) {
  2114.         log.info(String.format("Handled exception - %s", exception), exception);
  2115.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.BAD_REQUEST);
  2116.         return new ResponseEntity<>(info, HttpStatus.BAD_REQUEST);
  2117.     }
  2118.  
  2119.     @ExceptionHandler(NoSuchReportException.class)
  2120.     public ResponseEntity<ExceptionInfo> handleNoSuchReportException(NoSuchReportException exception) {
  2121.         log.info(String.format("Handled exception - %s", exception), exception);
  2122.         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
  2123.     }
  2124.  
  2125.     @ExceptionHandler(ReportWritingException.class)
  2126.     public ResponseEntity<ExceptionInfo> handleReportWritingException(ReportWritingException exception) {
  2127.         log.info(String.format("Handled exception - %s", exception), exception);
  2128.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
  2129.         return new ResponseEntity<>(info, HttpStatus.INTERNAL_SERVER_ERROR);
  2130.     }
  2131.  
  2132.     @ExceptionHandler(AttributesReadingException.class)
  2133.     public ResponseEntity<ExceptionInfo> handleAttributesReadingException(AttributesReadingException exception) {
  2134.         log.info(String.format("Handled exception - %s", exception), exception);
  2135.         ExceptionInfo info = new ExceptionInfo(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
  2136.         return new ResponseEntity<>(info, HttpStatus.INTERNAL_SERVER_ERROR);
  2137.     }
  2138. }
  2139.  
  2140. package com.leverx.employeestat.rest.dto.converter;
  2141.  
  2142. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  2143. import com.leverx.employeestat.rest.entity.Department;
  2144. import com.leverx.employeestat.rest.entity.Employee;
  2145. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  2146. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  2147. import org.springframework.beans.factory.annotation.Autowired;
  2148. import org.springframework.stereotype.Component;
  2149.  
  2150. import java.util.List;
  2151. import java.util.Optional;
  2152. import java.util.UUID;
  2153.  
  2154. @Component
  2155. public class DepartmentConverter {
  2156.  
  2157.     private final EmployeeRepository employeeRepository;
  2158.  
  2159.     @Autowired
  2160.     public DepartmentConverter(EmployeeRepository employeeRepository) {
  2161.         this.employeeRepository = employeeRepository;
  2162.     }
  2163.  
  2164.     public Department toEntity(DepartmentDTO departmentDTO) {
  2165.         Department department = Department.builder()
  2166.                 .name(departmentDTO.getName())
  2167.                 .id(departmentDTO.getId())
  2168.                 .build();
  2169.  
  2170.         Optional.ofNullable(departmentDTO.getEmployeeIds())
  2171.                 .ifPresent(employeeIds -> employeeIds.forEach(id -> {
  2172.                     department.addEmployee(employeeRepository.findEmployeeById(id)
  2173.                             .orElseThrow(() -> new NoSuchRecordException
  2174.                                     (String.format("Employee with id=%s not found", id)))
  2175.                     );
  2176.                 }));
  2177.  
  2178.         return department;
  2179.     }
  2180.  
  2181.     public DepartmentDTO toDTO(Department department) {
  2182.         DepartmentDTO departmentDTO = DepartmentDTO.builder()
  2183.                 .name(department.getName())
  2184.                 .id(department.getId())
  2185.                 .build();
  2186.  
  2187.         Optional.ofNullable(department.getEmployees())
  2188.                 .ifPresent(employees -> employees.forEach(employee -> departmentDTO.addEmployeeId(employee.getId())));
  2189.  
  2190.         return departmentDTO;
  2191.     }
  2192. }
  2193.  
  2194. package com.leverx.employeestat.rest.dto.converter;
  2195.  
  2196. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  2197. import com.leverx.employeestat.rest.entity.Department;
  2198. import com.leverx.employeestat.rest.entity.Employee;
  2199. import com.leverx.employeestat.rest.entity.Project;
  2200. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  2201. import com.leverx.employeestat.rest.repository.DepartmentRepository;
  2202. import com.leverx.employeestat.rest.repository.ProjectRepository;
  2203. import com.leverx.employeestat.rest.repository.RoleRepository;
  2204. import org.springframework.beans.factory.annotation.Autowired;
  2205. import org.springframework.stereotype.Component;
  2206.  
  2207. import java.util.List;
  2208. import java.util.Optional;
  2209. import java.util.UUID;
  2210.  
  2211. @Component
  2212. public class EmployeeConverter {
  2213.  
  2214.     private final DepartmentRepository departmentRepository;
  2215.     private final ProjectRepository projectRepository;
  2216.     private final RoleRepository roleRepository;
  2217.  
  2218.     @Autowired
  2219.     public EmployeeConverter(DepartmentRepository departmentRepository,
  2220.                              ProjectRepository projectRepository,
  2221.                              RoleRepository roleRepository) {
  2222.         this.departmentRepository = departmentRepository;
  2223.         this.projectRepository = projectRepository;
  2224.         this.roleRepository = roleRepository;
  2225.     }
  2226.  
  2227.     public Employee toEntity(EmployeeDTO employeeDTO) {
  2228.         Employee employee = Employee.builder()
  2229.                 .username(employeeDTO.getUsername())
  2230.                 .id(employeeDTO.getId())
  2231.                 .firstName(employeeDTO.getFirstName())
  2232.                 .lastName(employeeDTO.getLastName())
  2233.                 .password(employeeDTO.getPassword())
  2234.                 .position(employeeDTO.getPosition())
  2235.                 .build();
  2236.  
  2237.         employee.setRole(roleRepository.findByName(employeeDTO.getRole())
  2238.                 .orElseThrow(() -> new NoSuchRecordException
  2239.                         (String.format("Role with name=%s does not exists", employeeDTO.getRole())))
  2240.         );
  2241.  
  2242.         Optional.ofNullable(employeeDTO.getDepartmentId())
  2243.                 .ifPresent(id -> {
  2244.                     Department department = departmentRepository.findById(employeeDTO.getDepartmentId())
  2245.                             .orElseThrow(() -> new NoSuchRecordException
  2246.                                     (String.format("Department with id=%s not found", employeeDTO.getDepartmentId()))
  2247.                             );
  2248.                     employee.setDepartment(department);
  2249.                 });
  2250.  
  2251.         Optional.ofNullable(employeeDTO.getProjectIds())
  2252.                 .ifPresent(projectIds -> projectIds.forEach(id -> {
  2253.                     Project project = projectRepository.findProjectById(id)
  2254.                             .orElseThrow(() -> new NoSuchRecordException
  2255.                                     (String.format("Project with id=%s not found", id))
  2256.                             );
  2257.                     employee.addProject(project);
  2258.                 }));
  2259.  
  2260.         return employee;
  2261.     }
  2262.  
  2263.     public void updateEmployeeFields(EmployeeDTO employeeDTO, Employee employee) {
  2264.         employee.setUsername(employeeDTO.getUsername());
  2265.         employee.setFirstName(employeeDTO.getFirstName());
  2266.         employee.setLastName(employeeDTO.getLastName());
  2267.         employee.setPosition(employeeDTO.getPosition());
  2268.  
  2269.         employee.setRole(roleRepository.findByName(employeeDTO.getRole())
  2270.                 .orElseThrow(() -> new NoSuchRecordException
  2271.                         ("Role with name=" + employeeDTO.getRole() + " does not exists"))
  2272.         );
  2273.  
  2274.         if (employeeDTO.getDepartmentId() != null) {
  2275.             Department department = departmentRepository.findById(employeeDTO.getDepartmentId())
  2276.                     .orElseThrow(() -> new NoSuchRecordException
  2277.                             (String.format("Department with id=%s not found", employeeDTO.getDepartmentId()))
  2278.                     );
  2279.             employee.setDepartment(department);
  2280.         } else {
  2281.             employee.setDepartment(null);
  2282.         }
  2283.  
  2284.         if (employeeDTO.getProjectIds() != null) {
  2285.             employee.setProjects(null);
  2286.             for (UUID id : employeeDTO.getProjectIds()) {
  2287.                 Project project = projectRepository.findProjectById(id)
  2288.                         .orElseThrow(() -> new NoSuchRecordException
  2289.                                 (String.format("Project with id=%s not found", id))
  2290.                         );
  2291.                 employee.addProject(project);
  2292.             }
  2293.         } else {
  2294.             employee.setProjects(null);
  2295.         }
  2296.     }
  2297.  
  2298.     public EmployeeDTO toDTO(Employee employee) {
  2299.         EmployeeDTO employeeDTO = EmployeeDTO.builder()
  2300.                 .username(employee.getUsername())
  2301.                 .id(employee.getId())
  2302.                 .firstName(employee.getFirstName())
  2303.                 .lastName(employee.getLastName())
  2304.                 .password(employee.getPassword())
  2305.                 .position(employee.getPosition())
  2306.                 .role(employee.getRoleName())
  2307.                 .build();
  2308.  
  2309.         Optional.ofNullable(employee.getDepartment())
  2310.                 .ifPresent(department -> employeeDTO.setDepartmentId(department.getId()));
  2311.  
  2312.         Optional.ofNullable(employee.getProjects())
  2313.                 .ifPresent((projects -> projects.forEach(project -> employeeDTO.addProjectId(project.getId()))));
  2314.  
  2315.         return employeeDTO;
  2316.     }
  2317.  
  2318. package com.leverx.employeestat.rest.dto.converter;
  2319.  
  2320. import com.leverx.employeestat.rest.dto.ProjectDTO;
  2321. import com.leverx.employeestat.rest.entity.Employee;
  2322. import com.leverx.employeestat.rest.entity.Project;
  2323. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  2324. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  2325. import org.springframework.beans.factory.annotation.Autowired;
  2326. import org.springframework.stereotype.Component;
  2327.  
  2328. import java.util.List;
  2329. import java.util.Optional;
  2330. import java.util.UUID;
  2331.  
  2332. @Component
  2333. public class ProjectConverter {
  2334.  
  2335.     private final EmployeeRepository employeeRepository;
  2336.  
  2337.     @Autowired
  2338.     public ProjectConverter(EmployeeRepository employeeRepository) {
  2339.         this.employeeRepository = employeeRepository;
  2340.     }
  2341.  
  2342.     public Project toEntity(ProjectDTO projectDTO) {
  2343.         Project project = Project.builder()
  2344.                 .id(projectDTO.getId())
  2345.                 .name(projectDTO.getName())
  2346.                 .begin(projectDTO.getBegin())
  2347.                 .end(projectDTO.getEnd())
  2348.                 .build();
  2349.  
  2350.         Optional.ofNullable(projectDTO.getEmployeeIds())
  2351.                 .ifPresent(employeeIds -> employeeIds.forEach(id -> {
  2352.                     project.addEmployee(employeeRepository.findEmployeeById(id)
  2353.                             .orElseThrow(() -> new NoSuchRecordException
  2354.                                     (String.format("Employee with id=%s not found", id)))
  2355.                     );
  2356.                 }));
  2357.  
  2358.         return project;
  2359.     }
  2360.  
  2361.     public ProjectDTO toDTO(Project project) {
  2362.         ProjectDTO projectDTO = ProjectDTO.builder()
  2363.                 .name(project.getName())
  2364.                 .begin(project.getBegin())
  2365.                 .end(project.getEnd())
  2366.                 .id(project.getId())
  2367.                 .build();
  2368.  
  2369.         Optional.ofNullable(project.getEmployees())
  2370.                 .ifPresent(employees -> employees.forEach(employee -> projectDTO.addEmployeeId(employee.getId())));
  2371.  
  2372.         return projectDTO;
  2373.     }
  2374. }
  2375.  
  2376. package com.leverx.employeestat.rest.dto.converter;
  2377.  
  2378. import com.leverx.employeestat.rest.dto.WorkDTO;
  2379. import com.leverx.employeestat.rest.entity.Work;
  2380. import com.leverx.employeestat.rest.entity.WorkId;
  2381. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  2382. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  2383. import com.leverx.employeestat.rest.repository.ProjectRepository;
  2384. import org.springframework.beans.factory.annotation.Autowired;
  2385. import org.springframework.stereotype.Component;
  2386.  
  2387. import java.util.UUID;
  2388.  
  2389. @Component
  2390. public class WorkConverter {
  2391.  
  2392.     private final EmployeeRepository employeeRepository;
  2393.     private final ProjectRepository projectRepository;
  2394.  
  2395.     @Autowired
  2396.     public WorkConverter(EmployeeRepository employeeRepository, ProjectRepository projectRepository) {
  2397.         this.employeeRepository = employeeRepository;
  2398.         this.projectRepository = projectRepository;
  2399.     }
  2400.  
  2401.     public Work toEntity(WorkDTO workDTO) {
  2402.         UUID employeeId = workDTO.getEmployeeId();
  2403.         UUID projectId = workDTO.getProjectId();
  2404.         WorkId workId = new WorkId();
  2405.         workId.setEmployee(employeeRepository.findEmployeeById(employeeId)
  2406.                 .orElseThrow(() -> new NoSuchRecordException
  2407.                         (String.format("Employee with id=%s not found", employeeId)))
  2408.         );
  2409.         workId.setProject(projectRepository.findProjectById(projectId)
  2410.                 .orElseThrow(() -> new NoSuchRecordException
  2411.                         (String.format("Project with id=%s not found", projectId)))
  2412.         );
  2413.  
  2414.         Work work = Work.builder()
  2415.                 .id(workId)
  2416.                 .positionEndDate(workDTO.getPositionEndDate())
  2417.                 .positionStartDate(workDTO.getPositionStartDate())
  2418.                 .workingHours(workDTO.getWorkingHours())
  2419.                 .build();
  2420.  
  2421.         return work;
  2422.     }
  2423.  
  2424.     public WorkDTO toDTO(Work work) {
  2425.         return WorkDTO.builder()
  2426.                 .employeeId(work.getId().getEmployee().getId())
  2427.                 .projectId(work.getId().getProject().getId())
  2428.                 .workingHours(work.getWorkingHours())
  2429.                 .positionEndDate(work.getPositionEndDate())
  2430.                 .positionStartDate(work.getPositionStartDate())
  2431.                 .build();
  2432.     }
  2433. }
  2434.  
  2435. package com.leverx.employeestat.rest.dto;
  2436.  
  2437. import io.swagger.annotations.ApiModel;
  2438. import lombok.AllArgsConstructor;
  2439. import lombok.Builder;
  2440. import lombok.Data;
  2441. import lombok.NoArgsConstructor;
  2442.  
  2443. import javax.validation.constraints.NotBlank;
  2444. import java.util.ArrayList;
  2445. import java.util.List;
  2446. import java.util.UUID;
  2447.  
  2448. @ApiModel(value = "Department", description = "Contains all information about department and its employees(ids)")
  2449. @Data
  2450. @NoArgsConstructor
  2451. @AllArgsConstructor
  2452. @Builder
  2453. public class DepartmentDTO {
  2454.  
  2455.     private UUID id;
  2456.  
  2457.     @NotBlank
  2458.     private String name;
  2459.  
  2460.     private List<UUID> employeeIds;
  2461.  
  2462.     public void addEmployeeId(UUID id) {
  2463.         if (employeeIds == null) {
  2464.             employeeIds = new ArrayList<>();
  2465.         }
  2466.         employeeIds.add(id);
  2467.     }
  2468. }
  2469.  
  2470. package com.leverx.employeestat.rest.dto;
  2471.  
  2472. import com.fasterxml.jackson.annotation.JsonIgnore;
  2473. import io.swagger.annotations.ApiModel;
  2474. import lombok.AllArgsConstructor;
  2475. import lombok.Builder;
  2476. import lombok.Data;
  2477. import lombok.NoArgsConstructor;
  2478.  
  2479. import javax.validation.constraints.NotBlank;
  2480. import java.util.ArrayList;
  2481. import java.util.List;
  2482. import java.util.Objects;
  2483. import java.util.UUID;
  2484.  
  2485. @ApiModel(value = "Employee", description = "Contains all information about employee and its projects(ids) and department(id)")
  2486. @Data
  2487. @NoArgsConstructor
  2488. @AllArgsConstructor
  2489. @Builder
  2490. public class EmployeeDTO {
  2491.  
  2492.     private UUID id;
  2493.  
  2494.     @NotBlank
  2495.     private String firstName;
  2496.  
  2497.     @NotBlank
  2498.     private String lastName;
  2499.  
  2500.     @NotBlank
  2501.     private String username;
  2502.  
  2503.     @JsonIgnore
  2504.     private String password;
  2505.  
  2506.     @NotBlank
  2507.     private String position;
  2508.  
  2509.     @NotBlank
  2510.     private String role;
  2511.  
  2512.     private UUID departmentId;
  2513.  
  2514.     private List<UUID> projectIds;
  2515.  
  2516.     public void addProjectId(UUID id) {
  2517.         if (projectIds == null) {
  2518.             projectIds = new ArrayList<>();
  2519.         }
  2520.         projectIds.add(id);
  2521.     }
  2522.  
  2523.     @Override
  2524.     public String toString() {
  2525.         return "EmployeeDTO{" +
  2526.                 "id=" + id +
  2527.                 ", firstName='" + firstName + '\'' +
  2528.                 ", lastName='" + lastName + '\'' +
  2529.                 ", username='" + username + '\'' +
  2530.                 ", password='" + password + '\'' +
  2531.                 ", position='" + position + '\'' +
  2532.                 ", role='" + role + '\'' +
  2533.                 ", departmentId=" + departmentId +
  2534.                 ", projectsIds=" + projectIds +
  2535.                 '}';
  2536.     }
  2537.  
  2538.     @Override
  2539.     public boolean equals(Object o) {
  2540.         if (this == o) return true;
  2541.         if (o == null || getClass() != o.getClass()) return false;
  2542.         EmployeeDTO that = (EmployeeDTO) o;
  2543.         return Objects.equals(id, that.id) && firstName.equals(that.firstName) && lastName.equals(that.lastName) && username.equals(that.username) && password.equals(that.password) && position.equals(that.position) && role.equals(that.role) && Objects.equals(departmentId, that.departmentId) && Objects.equals(projectIds, that.projectIds);
  2544.     }
  2545.  
  2546.     @Override
  2547.     public int hashCode() {
  2548.         return Objects.hash(id, firstName, lastName, username, password, position, role, departmentId, projectIds);
  2549.     }
  2550. }
  2551.  
  2552. package com.leverx.employeestat.rest.dto;
  2553.  
  2554. import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
  2555. import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  2556. import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
  2557. import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
  2558. import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
  2559. import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
  2560. import io.swagger.annotations.ApiModel;
  2561. import lombok.AllArgsConstructor;
  2562. import lombok.Builder;
  2563. import lombok.Data;
  2564. import lombok.NoArgsConstructor;
  2565.  
  2566. import javax.validation.constraints.NotBlank;
  2567. import javax.validation.constraints.NotNull;
  2568. import java.time.LocalDate;
  2569. import java.util.ArrayList;
  2570. import java.util.List;
  2571. import java.util.UUID;
  2572.  
  2573. @ApiModel(value = "Project", description = "Contains all information about project and its employees(ids)")
  2574. @Data
  2575. @NoArgsConstructor
  2576. @AllArgsConstructor
  2577. @Builder
  2578. public class ProjectDTO {
  2579.  
  2580.     private UUID id;
  2581.  
  2582.     @NotBlank
  2583.     private String name;
  2584.  
  2585.     @NotNull
  2586.     @JsonSerialize(using = ToStringSerializer.class)
  2587.     @JsonDeserialize(using = LocalDateDeserializer.class)
  2588.     private LocalDate begin;
  2589.  
  2590.     @NotNull
  2591.     @JsonSerialize(using = ToStringSerializer.class)
  2592.     @JsonDeserialize(using = LocalDateDeserializer.class)
  2593.     private LocalDate end;
  2594.  
  2595.     private List<UUID> employeeIds;
  2596.  
  2597.     public void addEmployeeId(UUID id) {
  2598.         if (employeeIds == null) {
  2599.             employeeIds = new ArrayList<>();
  2600.         }
  2601.         employeeIds.add(id);
  2602.     }
  2603. }
  2604.  
  2605. package com.leverx.employeestat.rest.dto;
  2606.  
  2607. import com.fasterxml.jackson.databind.annotation.JsonSerialize;
  2608. import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
  2609. import io.swagger.annotations.ApiModel;
  2610. import lombok.AllArgsConstructor;
  2611. import lombok.Builder;
  2612. import lombok.Data;
  2613. import lombok.NoArgsConstructor;
  2614.  
  2615. import java.time.LocalDate;
  2616. import java.util.UUID;
  2617.  
  2618. @ApiModel(value = "Works", description = "Representation of the workload of employees on the project")
  2619. @Data
  2620. @NoArgsConstructor
  2621. @AllArgsConstructor
  2622. @Builder
  2623. public class WorkDTO {
  2624.  
  2625.     private UUID employeeId;
  2626.  
  2627.     private UUID projectId;
  2628.  
  2629.     @JsonSerialize(using = ToStringSerializer.class)
  2630.     private LocalDate positionStartDate;
  2631.  
  2632.     @JsonSerialize(using = ToStringSerializer.class)
  2633.     private LocalDate positionEndDate;
  2634.  
  2635.     private Integer workingHours;
  2636.  
  2637. }
  2638.  
  2639. package com.leverx.employeestat.rest.entity;
  2640.  
  2641. import lombok.*;
  2642. import org.hibernate.annotations.Cascade;
  2643. import org.hibernate.annotations.GenericGenerator;
  2644.  
  2645. import javax.persistence.*;
  2646. import java.util.ArrayList;
  2647. import java.util.List;
  2648. import java.util.UUID;
  2649.  
  2650. @Entity
  2651. @Table(name = "department")
  2652. @Data
  2653. @AllArgsConstructor
  2654. @NoArgsConstructor
  2655. @Builder
  2656. public class Department {
  2657.  
  2658.     @Id
  2659.     @GeneratedValue(generator = "UUID")
  2660.     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  2661.     @Column(name = "id")
  2662.     private UUID id;
  2663.  
  2664.     @Column(name = "name")
  2665.     private String name;
  2666.  
  2667.     @OneToMany(mappedBy = "department", fetch = FetchType.EAGER)
  2668.     @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
  2669.     private List<Employee> employees;
  2670.  
  2671.     public void addEmployee(Employee employee) {
  2672.         if (employees == null) {
  2673.             employees = new ArrayList<>();
  2674.         }
  2675.         employees.add(employee);
  2676.         employee.setDepartment(this);
  2677.     }
  2678. }
  2679.  
  2680. package com.leverx.employeestat.rest.entity;
  2681.  
  2682. import lombok.*;
  2683. import org.hibernate.annotations.Cascade;
  2684. import org.hibernate.annotations.CascadeType;
  2685. import org.hibernate.annotations.GenericGenerator;
  2686.  
  2687. import javax.persistence.*;
  2688. import java.util.ArrayList;
  2689. import java.util.List;
  2690. import java.util.Objects;
  2691. import java.util.UUID;
  2692.  
  2693. @Entity
  2694. @Table(name = "employee")
  2695. @Data
  2696. @NoArgsConstructor
  2697. @AllArgsConstructor
  2698. @Builder
  2699. public class Employee {
  2700.  
  2701.     @Id
  2702.     @GeneratedValue(generator = "UUID")
  2703.     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  2704.     @Column(name = "id")
  2705.     private UUID id;
  2706.  
  2707.     @Column(name = "first_name")
  2708.     private String firstName;
  2709.  
  2710.     @Column(name = "last_name")
  2711.     private String lastName;
  2712.  
  2713.     @Column(name = "username")
  2714.     private String username;
  2715.  
  2716.     @Column(name = "password")
  2717.     private String password;
  2718.  
  2719.     @Column(name = "position")
  2720.     private String position;
  2721.  
  2722.     @ManyToOne(fetch = FetchType.LAZY)
  2723.     @JoinColumn(name = "role_id")
  2724.     private Role role;
  2725.  
  2726.     @ManyToOne(fetch = FetchType.EAGER)
  2727.     @JoinColumn(name = "department_id")
  2728.     @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
  2729.     private Department department;
  2730.  
  2731.     @ManyToMany(fetch = FetchType.EAGER)
  2732.     @Cascade({CascadeType.SAVE_UPDATE, CascadeType.PERSIST})
  2733.     @JoinTable(name = "project_employee",
  2734.                joinColumns = @JoinColumn(name = "employee_id"),
  2735.                inverseJoinColumns = @JoinColumn(name = "project_id"))
  2736.     private List<Project> projects;
  2737.  
  2738.     public String getRoleName() {
  2739.         return role.getName();
  2740.     }
  2741.  
  2742.     public void addProject(Project project) {
  2743.         if (projects == null) {
  2744.             projects = new ArrayList<>();
  2745.         }
  2746.         projects.add(project);
  2747.     }
  2748.  
  2749.     @Override
  2750.     public boolean equals(Object o) {
  2751.         if (this == o) return true;
  2752.         if (o == null || getClass() != o.getClass()) return false;
  2753.         Employee employee = (Employee) o;
  2754.         return id.equals(employee.id) && firstName.equals(employee.firstName) && lastName.equals(employee.lastName) && username.equals(employee.username) && password.equals(employee.password) && position.equals(employee.position) && Objects.equals(role, employee.role) && Objects.equals(department, employee.department) && Objects.equals(projects, employee.projects);
  2755.     }
  2756.  
  2757.     @Override
  2758.     public int hashCode() {
  2759.         return Objects.hash(id, firstName, lastName, username, password, position, role, department, projects);
  2760.     }
  2761. }
  2762.  
  2763. package com.leverx.employeestat.rest.entity;
  2764.  
  2765. import lombok.*;
  2766. import org.hibernate.annotations.Cascade;
  2767. import org.hibernate.annotations.CascadeType;
  2768. import org.hibernate.annotations.GenericGenerator;
  2769.  
  2770. import javax.persistence.*;
  2771. import java.time.LocalDate;
  2772. import java.util.ArrayList;
  2773. import java.util.List;
  2774. import java.util.Objects;
  2775. import java.util.UUID;
  2776.  
  2777. @Entity
  2778. @Table(name = "project")
  2779. @Data
  2780. @AllArgsConstructor
  2781. @NoArgsConstructor
  2782. @Builder
  2783. public class Project {
  2784.     @Id
  2785.     @GeneratedValue(generator = "UUID")
  2786.     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  2787.     @Column(name = "id")
  2788.     private UUID id;
  2789.  
  2790.     @Column(name = "name")
  2791.     private String name;
  2792.  
  2793.     @Column(name = "begin_date")
  2794.     private LocalDate begin;
  2795.  
  2796.     @Column(name = "end_date")
  2797.     private LocalDate end;
  2798.  
  2799.     @ManyToMany(fetch = FetchType.EAGER)
  2800.     @Cascade({CascadeType.SAVE_UPDATE, CascadeType.PERSIST})
  2801.     @JoinTable(name = "project_employee",
  2802.             joinColumns = @JoinColumn(name = "project_id"),
  2803.             inverseJoinColumns = @JoinColumn(name = "employee_id"))
  2804.     private List<Employee> employees;
  2805.  
  2806.     public void addEmployee(Employee employee) {
  2807.         if (employees == null) {
  2808.             employees = new ArrayList<>();
  2809.         }
  2810.         employees.add(employee);
  2811.     }
  2812.  
  2813.     @Override
  2814.     public boolean equals(Object o) {
  2815.         if (this == o) return true;
  2816.         if (o == null || getClass() != o.getClass()) return false;
  2817.         Project project = (Project) o;
  2818.         return Objects.equals(id, project.id) && Objects.equals(name, project.name) && Objects.equals(begin, project.begin) && Objects.equals(end, project.end) && Objects.equals(employees, project.employees);
  2819.     }
  2820.  
  2821.     @Override
  2822.     public int hashCode() {
  2823.         return Objects.hash(id, name, begin, end, employees);
  2824.     }
  2825. }
  2826.  
  2827. package com.leverx.employeestat.rest.entity;
  2828.  
  2829. import lombok.*;
  2830. import org.hibernate.annotations.GenericGenerator;
  2831.  
  2832. import javax.persistence.*;
  2833. import java.util.List;
  2834. import java.util.UUID;
  2835.  
  2836. @Entity
  2837. @Table(name = "role")
  2838. @Data
  2839. @NoArgsConstructor
  2840. @AllArgsConstructor
  2841. @Builder
  2842. public class Role {
  2843.  
  2844.     @Id
  2845.     @GeneratedValue(generator = "UUID")
  2846.     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  2847.     @Column(name = "id")
  2848.     private UUID id;
  2849.  
  2850.     @Column(name = "name")
  2851.     private String name;
  2852.  
  2853.     @OneToMany(mappedBy = "role")
  2854.     private List<Employee> employees;
  2855.  
  2856. }
  2857.  
  2858. package com.leverx.employeestat.rest.entity;
  2859.  
  2860. import lombok.*;
  2861.  
  2862. import javax.persistence.Column;
  2863. import javax.persistence.EmbeddedId;
  2864. import javax.persistence.Entity;
  2865. import javax.persistence.Table;
  2866. import java.time.LocalDate;
  2867.  
  2868. @Entity
  2869. @Table(name = "project_employee")
  2870. @Data
  2871. @NoArgsConstructor
  2872. @AllArgsConstructor
  2873. @Builder
  2874. public class Work {
  2875.  
  2876.     @EmbeddedId
  2877.     private WorkId id;
  2878.  
  2879.     @Column(name = "position_start_date")
  2880.     private LocalDate positionStartDate;
  2881.  
  2882.     @Column(name = "position_end_date")
  2883.     private LocalDate positionEndDate;
  2884.  
  2885.     @Column(name = "working_hours")
  2886.     private Integer workingHours;
  2887.  
  2888. }
  2889.  
  2890. package com.leverx.employeestat.rest.entity;
  2891.  
  2892. import lombok.*;
  2893.  
  2894. import javax.persistence.Embeddable;
  2895. import javax.persistence.ManyToOne;
  2896. import java.io.Serializable;
  2897. import java.util.Objects;
  2898.  
  2899. @Embeddable
  2900. @Data
  2901. @NoArgsConstructor
  2902. @AllArgsConstructor
  2903. @Builder
  2904. public class WorkId implements Serializable {
  2905.  
  2906.     @ManyToOne(targetEntity = Employee.class)
  2907.     private Employee employee;
  2908.  
  2909.     @ManyToOne(targetEntity = Project.class)
  2910.     private Project project;
  2911.  
  2912.     @Override
  2913.     public String toString(){
  2914.         return "(employeeId=" + employee.getId() + "; projectId=" + project.getId() + ")";
  2915.     }
  2916.  
  2917.     @Override
  2918.     public boolean equals(Object o) {
  2919.         if (this == o) return true;
  2920.         if (o == null || getClass() != o.getClass()) return false;
  2921.         WorkId workId = (WorkId) o;
  2922.         return employee.equals(workId.employee) && project.equals(workId.project);
  2923.     }
  2924.  
  2925.     @Override
  2926.     public int hashCode() {
  2927.         return Objects.hash(employee, project);
  2928.     }
  2929. }
  2930.  
  2931. package com.leverx.employeestat.rest.model;
  2932.  
  2933. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  2934. import io.swagger.annotations.ApiModel;
  2935. import lombok.AllArgsConstructor;
  2936. import lombok.Builder;
  2937. import lombok.Data;
  2938. import lombok.NoArgsConstructor;
  2939.  
  2940. import javax.validation.constraints.NotBlank;
  2941.  
  2942. @ApiModel(value = "Registration request", description = "Contains mandatory fields for registration of employee")
  2943. @Data
  2944. @NoArgsConstructor
  2945. @AllArgsConstructor
  2946. @Builder
  2947. public class RegistrationRequest {
  2948.  
  2949.     @NotBlank
  2950.     private String firstName;
  2951.  
  2952.     @NotBlank
  2953.     private String lastName;
  2954.  
  2955.     @NotBlank
  2956.     private String username;
  2957.  
  2958.     @NotBlank
  2959.     private String password;
  2960.  
  2961.     @NotBlank
  2962.     private String position;
  2963.  
  2964.     @NotBlank
  2965.     private String role;
  2966.  
  2967.     public EmployeeDTO toDTO() {
  2968.         return EmployeeDTO.builder()
  2969.                 .firstName(firstName)
  2970.                 .lastName(lastName)
  2971.                 .password(password)
  2972.                 .role(role)
  2973.                 .position(position)
  2974.                 .username(username)
  2975.                 .build();
  2976.     }
  2977. }
  2978.  
  2979. package com.leverx.employeestat.rest.model;
  2980.  
  2981. import io.swagger.annotations.ApiModel;
  2982. import lombok.AllArgsConstructor;
  2983. import lombok.Builder;
  2984. import lombok.Data;
  2985. import lombok.NoArgsConstructor;
  2986.  
  2987. import javax.validation.constraints.NotBlank;
  2988.  
  2989. @ApiModel(value = "Reset password request", description = "Contains username, old and new password of employee")
  2990. @Data
  2991. @NoArgsConstructor
  2992. @AllArgsConstructor
  2993. @Builder
  2994. public class ResetPasswordRequest {
  2995.  
  2996.     @NotBlank
  2997.     private String username;
  2998.  
  2999.     @NotBlank
  3000.     private String oldPassword;
  3001.  
  3002.     @NotBlank
  3003.     private String newPassword;
  3004.  
  3005. }
  3006.  
  3007. ------------------------------
  3008. TESTS
  3009. ------------------------------
  3010.  
  3011. package com.leverx.employeestat.rest.integration.config;
  3012.  
  3013. import com.leverx.employeestat.rest.configuration.Config;
  3014. import com.mchange.v2.c3p0.ComboPooledDataSource;
  3015. import liquibase.integration.spring.SpringLiquibase;
  3016. import org.springframework.beans.factory.annotation.Autowired;
  3017. import org.springframework.context.annotation.Bean;
  3018. import org.springframework.core.env.Environment;
  3019. import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
  3020.  
  3021. import javax.sql.DataSource;
  3022. import java.beans.PropertyVetoException;
  3023.  
  3024. public class TestConfig extends Config {
  3025.  
  3026.     private final Environment env;
  3027.  
  3028.     @Autowired
  3029.     public TestConfig(Environment env) {
  3030.         super(env);
  3031.         this.env = env;
  3032.     }
  3033.  
  3034.     @Bean
  3035.     @Override
  3036.     public DataSource dataSource() {
  3037.         ComboPooledDataSource dataSource = new ComboPooledDataSource();
  3038.         try {
  3039.             dataSource.setDriverClass(env.getRequiredProperty("driverClass"));
  3040.             dataSource.setJdbcUrl(env.getRequiredProperty("testUrl"));
  3041.             dataSource.setUser(env.getRequiredProperty("dbuser"));
  3042.             dataSource.setPassword(env.getRequiredProperty("password"));
  3043.         } catch (PropertyVetoException e) {
  3044.             e.printStackTrace();
  3045.         }
  3046.         return dataSource;
  3047.     }
  3048.  
  3049.     @Bean
  3050.     @Override
  3051.     public SpringLiquibase liquibase() {
  3052.         SpringLiquibase liquibase = new SpringLiquibase();
  3053.         liquibase.setChangeLog("classpath:db/changelog/liquibase-changeLog-test.xml");
  3054.         liquibase.setDataSource(dataSource());
  3055.         return liquibase;
  3056.     }
  3057.  
  3058.     @Bean
  3059.     public MethodValidationPostProcessor methodValidationPostProcessor() {
  3060.         return new MethodValidationPostProcessor();
  3061.     }
  3062.  
  3063.  
  3064. }
  3065.  
  3066. package com.leverx.employeestat.rest.integration;
  3067.  
  3068. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3069. import com.leverx.employeestat.rest.exceptionhandler.GlobalControllerAdvice;
  3070. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3071. import com.leverx.employeestat.rest.model.RegistrationRequest;
  3072. import com.leverx.employeestat.rest.model.ResetPasswordRequest;
  3073. import org.junit.jupiter.api.BeforeEach;
  3074. import org.junit.jupiter.api.Test;
  3075. import org.junit.jupiter.api.extension.ExtendWith;
  3076. import org.springframework.beans.factory.annotation.Autowired;
  3077. import org.springframework.http.MediaType;
  3078. import org.springframework.test.context.ContextConfiguration;
  3079. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3080. import org.springframework.test.context.web.WebAppConfiguration;
  3081. import org.springframework.test.web.servlet.MockMvc;
  3082. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3083. import org.springframework.transaction.annotation.Transactional;
  3084. import org.springframework.web.context.WebApplicationContext;
  3085.  
  3086. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toJson;
  3087. import static org.junit.jupiter.api.Assertions.assertNotNull;
  3088. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
  3089. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
  3090. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  3091.  
  3092. @ExtendWith(SpringExtension.class)
  3093. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3094. @WebAppConfiguration
  3095. @Transactional
  3096. public class AuthorizationIntegrationTest {
  3097.  
  3098.     private static final String REGISTER_ENDPOINT = "/api/register";
  3099.     private static final String RESET_ENDPOINT = "/api/reset-password";
  3100.  
  3101.     private final WebApplicationContext webAppContext;
  3102.  
  3103.     private MockMvc mvc;
  3104.  
  3105.     private RegistrationRequest registrationRequest;
  3106.     private ResetPasswordRequest resetPasswordRequest;
  3107.  
  3108.     @Autowired
  3109.     public AuthorizationIntegrationTest(WebApplicationContext webAppContext) {
  3110.         this.webAppContext = webAppContext;
  3111.     }
  3112.  
  3113.     @BeforeEach
  3114.     public void setup() {
  3115.         this.mvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
  3116.     }
  3117.  
  3118.     @BeforeEach
  3119.     public void init() {
  3120.         registrationRequest = new RegistrationRequest();
  3121.         resetPasswordRequest = new ResetPasswordRequest();
  3122.  
  3123.         registrationRequest.setFirstName("name");
  3124.         registrationRequest.setLastName("last name");
  3125.         registrationRequest.setPassword("init");
  3126.         registrationRequest.setPosition("position");
  3127.         registrationRequest.setUsername("username");
  3128.         registrationRequest.setRole("ROLE_EMPLOYEE");
  3129.  
  3130.         resetPasswordRequest.setOldPassword("init");
  3131.         resetPasswordRequest.setNewPassword("new");
  3132.         resetPasswordRequest.setUsername("username");
  3133.     }
  3134.  
  3135.     @Test
  3136.     public void shouldExistsGlobalControllerAdvice() {
  3137.         GlobalControllerAdvice advice = this.webAppContext.getBean(GlobalControllerAdvice.class);
  3138.         assertNotNull(advice);
  3139.     }
  3140.  
  3141.     @Test
  3142.     public void shouldReturnOkStatusIfJsonIsCorrectForRegisterEmployee() throws Exception {
  3143.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3144.                 .andExpect(status().isCreated())
  3145.                 .andExpect(jsonPath("$.id").isNotEmpty());
  3146.     }
  3147.  
  3148.     @Test
  3149.     public void shouldReturnBadRequestStatusIfJsonFieldsIsNotValidForRegisterEmployee() throws Exception {
  3150.         registrationRequest.setUsername("");
  3151.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3152.                 .andExpect(status().isBadRequest());
  3153.     }
  3154.  
  3155.     @Test
  3156.     public void shouldReturnBadRequestStatusIfJsonContainsExistingUsernameForRegisterEmployee() throws Exception {
  3157.         registrationRequest.setUsername("Vanechka");
  3158.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3159.                 .andExpect(status().isBadRequest())
  3160.                 .andExpect(jsonPath("$.message").value(String.format("Employee with username=%s already exists", registrationRequest.getUsername())));
  3161.     }
  3162.  
  3163.     @Test
  3164.     public void shouldReturnBadRequestStatusIfJsonIsNotCorrectForRegisterEmployee() throws Exception {
  3165.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3166.                 .andExpect(status().isBadRequest());
  3167.     }
  3168.  
  3169.     @Test
  3170.     public void shouldReturnNotFoundStatusIfJsonContainsNotExistingRoleForRegisterEmployee() throws Exception {
  3171.         registrationRequest.setRole("not existing");
  3172.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3173.                 .andExpect(status().isNotFound())
  3174.                 .andExpect(jsonPath("$.message").value(String.format("Role with name=%s does not exists", registrationRequest.getRole())));
  3175.     }
  3176.  
  3177.     @Test
  3178.     public void shouldReturnOkStatusIfJsonIsCorrectAndContainsIsValidOldPasswordForResetPassword() throws Exception {
  3179.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3180.                 .andExpect(status().isCreated());
  3181.  
  3182.         mvc.perform(post(RESET_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(resetPasswordRequest)))
  3183.                 .andExpect(status().isNoContent());
  3184.     }
  3185.  
  3186.     @Test
  3187.     public void shouldReturnNotFoundStatusIfEmployeeDoesNotExistByUsernameForResetPassword() throws Exception {
  3188.         mvc.perform(post(RESET_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(resetPasswordRequest)))
  3189.                 .andExpect(status().isNotFound())
  3190.                 .andExpect(jsonPath("$.message").value(String.format("Employee with username=%s not found", resetPasswordRequest.getUsername())));
  3191.     }
  3192.  
  3193.     @Test
  3194.     public void shouldReturnUnauthorizedStatusIfOldPasswordMismatchesWithCurrentForResetPassword() throws Exception {
  3195.         mvc.perform(post(REGISTER_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(registrationRequest)))
  3196.                 .andExpect(status().isCreated());
  3197.         resetPasswordRequest.setOldPassword("incorrect");
  3198.         mvc.perform(post(RESET_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(resetPasswordRequest)))
  3199.                 .andExpect(status().isUnauthorized())
  3200.                 .andExpect(jsonPath("$.message").value("You entered incorrect old password"));
  3201.     }
  3202. }
  3203.  
  3204. package com.leverx.employeestat.rest.integration;
  3205.  
  3206. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3207. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3208. import org.junit.jupiter.api.BeforeEach;
  3209. import org.junit.jupiter.api.Test;
  3210. import org.junit.jupiter.api.extension.ExtendWith;
  3211. import org.springframework.beans.factory.annotation.Autowired;
  3212. import org.springframework.http.MediaType;
  3213. import org.springframework.test.context.ContextConfiguration;
  3214. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3215. import org.springframework.test.context.web.WebAppConfiguration;
  3216. import org.springframework.test.web.servlet.MockMvc;
  3217. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3218. import org.springframework.transaction.annotation.Transactional;
  3219. import org.springframework.web.context.WebApplicationContext;
  3220.  
  3221. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
  3222. import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
  3223. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  3224.  
  3225. @ExtendWith(SpringExtension.class)
  3226. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3227. @WebAppConfiguration
  3228. @Transactional
  3229. public class AvailableEmployeeIntegrationTest {
  3230.  
  3231.     public static final String AVAILABLE_EMPLOYEES_ENDPOINT = "/api/employees/available";
  3232.  
  3233.     private final WebApplicationContext webAppContext;
  3234.     private MockMvc mvc;
  3235.  
  3236.     private String firstEmployeeId;
  3237.     private String secondEmployeeId;
  3238.  
  3239.     @Autowired
  3240.     public AvailableEmployeeIntegrationTest(WebApplicationContext webAppContext) {
  3241.         this.webAppContext = webAppContext;
  3242.     }
  3243.  
  3244.     @BeforeEach
  3245.     public void setup() {
  3246.         this.mvc = MockMvcBuilders.webAppContextSetup(this.webAppContext).build();
  3247.     }
  3248.  
  3249.     @Test
  3250.     public void shouldReturnTwoAvailableEmployeesNow() throws Exception {
  3251.         final String firstExpectedId = "c7fa1cd3-b281-47b1-b72f-92b9391fc5c7";
  3252.         final String secondExpectedId = "e9a4e12b-1555-48bd-9275-629856bcdb51";
  3253.         final String thirdExpectedId = "2174c05c-e885-4521-985d-774b1f05cd37";
  3254.  
  3255.         mvc.perform(get(AVAILABLE_EMPLOYEES_ENDPOINT))
  3256.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3257.                 .andExpect(status().isOk()).andDo(print())
  3258.                 .andExpect(jsonPath("$[0].id").value(firstExpectedId))
  3259.                 .andExpect(jsonPath("$[1].id").value(secondExpectedId))
  3260.                 .andExpect(jsonPath("$[2].id").value(thirdExpectedId));
  3261.     }
  3262.  
  3263.     @Test
  3264.     public void shouldReturnOneAvailableEmployeeWithinMonth() throws Exception {
  3265.         final String firstExpectedId = "c7fa1cd3-b281-47b1-b72f-92b9391fc5c7";
  3266.         mvc.perform(get(AVAILABLE_EMPLOYEES_ENDPOINT + "/20"))
  3267.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3268.                 .andExpect(status().isOk()).andDo(print())
  3269.                 .andExpect(jsonPath("$[0].id").value(firstExpectedId));
  3270.     }
  3271. }
  3272.  
  3273. package com.leverx.employeestat.rest.integration;
  3274.  
  3275. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3276. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  3277. import com.leverx.employeestat.rest.exceptionhandler.GlobalControllerAdvice;
  3278. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3279. import org.junit.jupiter.api.BeforeEach;
  3280. import org.junit.jupiter.api.Test;
  3281. import org.junit.jupiter.api.extension.ExtendWith;
  3282. import org.springframework.beans.factory.annotation.Autowired;
  3283. import org.springframework.http.MediaType;
  3284. import org.springframework.test.context.ContextConfiguration;
  3285. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3286. import org.springframework.test.context.web.WebAppConfiguration;
  3287. import org.springframework.test.web.servlet.MockMvc;
  3288. import org.springframework.test.web.servlet.MvcResult;
  3289. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3290. import org.springframework.transaction.annotation.Transactional;
  3291. import org.springframework.web.context.WebApplicationContext;
  3292.  
  3293. import java.util.UUID;
  3294.  
  3295. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toJson;
  3296. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toObject;
  3297. import static org.junit.jupiter.api.Assertions.assertNotNull;
  3298. import static org.junit.jupiter.api.Assertions.assertNull;
  3299. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  3300. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  3301.  
  3302. @ExtendWith(SpringExtension.class)
  3303. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3304. @WebAppConfiguration
  3305. @Transactional
  3306. public class DepartmentIntegrationTest {
  3307.  
  3308.     private static final String DEPARTMENTS_ENDPOINT = "/api/departments";
  3309.  
  3310.     private final WebApplicationContext webAppContext;
  3311.     private MockMvc mvc;
  3312.  
  3313.     @Autowired
  3314.     public DepartmentIntegrationTest(WebApplicationContext webAppContext) {
  3315.         this.webAppContext = webAppContext;
  3316.     }
  3317.  
  3318.     @BeforeEach
  3319.     public void setup() {
  3320.         this.mvc = MockMvcBuilders.webAppContextSetup(this.webAppContext).build();
  3321.     }
  3322.  
  3323.     @Test
  3324.     public void shouldExistsGlobalControllerAdvice() {
  3325.         GlobalControllerAdvice advice = this.webAppContext.getBean(GlobalControllerAdvice.class);
  3326.         assertNotNull(advice);
  3327.     }
  3328.  
  3329.     @Test
  3330.     public void shouldReturnJsonIfGetRequest() throws Exception {
  3331.         mvc.perform(get(DEPARTMENTS_ENDPOINT))
  3332.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3333.                 .andExpect(status().isOk());
  3334.     }
  3335.  
  3336.     @Test
  3337.     public void shouldReturnCorrectJsonIfGetRequestById() throws Exception {
  3338.         mvc.perform(get(DEPARTMENTS_ENDPOINT + "/{id}", "edf939d2-dbc2-4473-80a1-4bb3826e666e"))
  3339.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3340.                 .andExpect(jsonPath("$.name").value("HR"));
  3341.     }
  3342.  
  3343.     @Test
  3344.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForGetRequestById() throws Exception {
  3345.         mvc.perform(get(DEPARTMENTS_ENDPOINT + "/{id}", "incorrect"))
  3346.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3347.                 .andExpect(status().isBadRequest())
  3348.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3349.                 .andExpect(jsonPath("$.code").value(400));
  3350.     }
  3351.  
  3352.     @Test
  3353.     public void shouldReturnNotFoundIfRecordNotFoundById() throws Exception {
  3354.         String id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
  3355.  
  3356.         mvc.perform(get(DEPARTMENTS_ENDPOINT + "/{id}", id))
  3357.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3358.                 .andExpect(status().isNotFound())
  3359.                 .andExpect(jsonPath("$.status").value("NOT_FOUND"))
  3360.                 .andExpect(jsonPath("$.code").value(404));
  3361.     }
  3362.  
  3363.     @Test
  3364.     public void shouldReturnBadRequestStatusIfJsonIsNotCorrectForPost() throws Exception {
  3365.         mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3366.                 .andExpect(status().isBadRequest());
  3367.     }
  3368.  
  3369.     @Test
  3370.     public void shouldReturnBadRequestIfNameOfDepartmentAlreadyExistsForPost() throws Exception {
  3371.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3372.         String name = "Department";
  3373.         departmentDTO.setName(name);
  3374.  
  3375.         mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3376.                 .andExpect(status().isCreated());
  3377.  
  3378.         mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3379.                 .andExpect(status().isBadRequest())
  3380.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3381.                 .andExpect(jsonPath("$.code").value(400));
  3382.     }
  3383.  
  3384.     @Test
  3385.     public void shouldReturnOkStatusIfJsonIsCorrectForPost() throws Exception {
  3386.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3387.         String expected = "Test";
  3388.         departmentDTO.setName(expected);
  3389.  
  3390.         mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3391.                 .andExpect(status().isCreated())
  3392.                 .andExpect(jsonPath("$.name").value(expected))
  3393.                 .andExpect(jsonPath("$.id").isNotEmpty());
  3394.     }
  3395.  
  3396.     @Test
  3397.     public void shouldReturnBadRequestIfNameOfDepartmentAlreadyExistsForPut() throws Exception {
  3398.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3399.         String name = "Department";
  3400.         departmentDTO.setName(name);
  3401.  
  3402.         mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3403.                 .andExpect(status().isCreated());
  3404.  
  3405.         mvc.perform(put(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3406.                 .andExpect(status().isBadRequest())
  3407.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3408.                 .andExpect(jsonPath("$.code").value(400));
  3409.     }
  3410.  
  3411.     @Test
  3412.     public void shouldReturnBadRequestStatusIfJsonIsNotCorrectForPut() throws Exception {
  3413.         mvc.perform(put(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3414.                 .andExpect(status().isBadRequest());
  3415.     }
  3416.  
  3417.     @Test
  3418.     public void shouldReturnOkStatusIfJsonWithoutIdIsCorrectForPut() throws Exception{
  3419.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3420.         String expected = "Test";
  3421.         departmentDTO.setName(expected);
  3422.  
  3423.         mvc.perform(put(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3424.                 .andExpect(status().isOk())
  3425.                 .andExpect(jsonPath("$.name").value(expected))
  3426.                 .andExpect(jsonPath("$.id").isNotEmpty());
  3427.  
  3428.         assertNull(departmentDTO.getId());
  3429.     }
  3430.  
  3431.     @Test
  3432.     public void shouldReturnUpdatedDepartmentIfItExistsById() throws Exception {
  3433.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3434.         String name = "Test";
  3435.         String expectedName = "Expected";
  3436.         departmentDTO.setName(name);
  3437.  
  3438.         MvcResult result = mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3439.                 .andExpect(status().isCreated())
  3440.                 .andReturn();
  3441.  
  3442.         departmentDTO = toObject(result.getResponse().getContentAsString(), DepartmentDTO.class);
  3443.         departmentDTO.setName(expectedName);
  3444.         UUID expectedId = departmentDTO.getId();
  3445.  
  3446.         mvc.perform(put(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3447.                 .andExpect(status().isOk())
  3448.                 .andExpect(jsonPath("$.id").value(expectedId.toString()))
  3449.                 .andExpect(jsonPath("$.name").value(expectedName));
  3450.     }
  3451.  
  3452.     @Test
  3453.     public void shouldDeleteDepartmentIfIdIsCorrectAndExists() throws Exception{
  3454.         DepartmentDTO departmentDTO = new DepartmentDTO();
  3455.         departmentDTO.setName("Test");
  3456.         MvcResult result = mvc.perform(post(DEPARTMENTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(departmentDTO)))
  3457.                 .andExpect(status().isCreated())
  3458.                 .andReturn();
  3459.         departmentDTO = toObject(result.getResponse().getContentAsString(), DepartmentDTO.class);
  3460.         UUID id = departmentDTO.getId();
  3461.         mvc.perform(delete(DEPARTMENTS_ENDPOINT + "/{id}", id.toString()))
  3462.                 .andExpect(status().isNoContent());
  3463.     }
  3464.  
  3465.     @Test
  3466.     public void shouldReturnMethodNotAllowedIfUUIDIsEmptyForDelete() throws Exception {
  3467.         mvc.perform(delete(DEPARTMENTS_ENDPOINT + "/{id}", ""))
  3468.                 .andExpect(status().isMethodNotAllowed());
  3469.     }
  3470.  
  3471.     @Test
  3472.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForDeleteRequestById() throws Exception {
  3473.         mvc.perform(delete(DEPARTMENTS_ENDPOINT + "/{id}", "incorrect"))
  3474.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3475.                 .andExpect(status().isBadRequest())
  3476.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3477.                 .andExpect(jsonPath("$.code").value(400));
  3478.     }
  3479. }
  3480.  
  3481. package com.leverx.employeestat.rest.integration;
  3482.  
  3483. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3484. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  3485. import com.leverx.employeestat.rest.exceptionhandler.GlobalControllerAdvice;
  3486. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3487. import org.junit.jupiter.api.BeforeEach;
  3488. import org.junit.jupiter.api.Test;
  3489. import org.junit.jupiter.api.extension.ExtendWith;
  3490. import org.springframework.beans.factory.annotation.Autowired;
  3491. import org.springframework.http.MediaType;
  3492. import org.springframework.test.context.ContextConfiguration;
  3493. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3494. import org.springframework.test.context.web.WebAppConfiguration;
  3495. import org.springframework.test.web.servlet.MockMvc;
  3496. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3497. import org.springframework.transaction.annotation.Transactional;
  3498. import org.springframework.web.context.WebApplicationContext;
  3499.  
  3500. import java.util.UUID;
  3501.  
  3502. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toJson;
  3503. import static org.junit.jupiter.api.Assertions.assertNotNull;
  3504. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  3505. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  3506.  
  3507. @ExtendWith(SpringExtension.class)
  3508. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3509. @WebAppConfiguration
  3510. @Transactional
  3511. public class EmployeeIntegrationTest {
  3512.  
  3513.     public static final String EMPLOYEES_ENDPOINT = "/api/employees";
  3514.  
  3515.     private final WebApplicationContext webAppContext;
  3516.     private MockMvc mvc;
  3517.     private EmployeeDTO employeeDTO;
  3518.  
  3519.     @Autowired
  3520.     public EmployeeIntegrationTest(WebApplicationContext webAppContext) {
  3521.         this.webAppContext = webAppContext;
  3522.     }
  3523.  
  3524.     @BeforeEach
  3525.     public void setup() {
  3526.         this.mvc = MockMvcBuilders.webAppContextSetup(this.webAppContext).build();
  3527.     }
  3528.  
  3529.     @BeforeEach
  3530.     public void init() {
  3531.         employeeDTO = new EmployeeDTO();
  3532.         String id = "c7fa1cd3-b281-47b1-b72f-92b9391fc5c7";
  3533.         String expectedFirstName = "Ivan";
  3534.         String expectedLastName = "Shestakov";
  3535.         String expectedUsername = "Vanechka";
  3536.         String expectedPosition = "Java Developer";
  3537.         String role = "ROLE_MANAGER";
  3538.         employeeDTO.setFirstName(expectedFirstName);
  3539.         employeeDTO.setLastName(expectedLastName);
  3540.         employeeDTO.setUsername(expectedUsername);
  3541.         employeeDTO.setPosition(expectedPosition);
  3542.         employeeDTO.setRole(role);
  3543.         employeeDTO.setId(UUID.fromString(id));
  3544.     }
  3545.  
  3546.     @Test
  3547.     public void shouldExistsGlobalControllerAdvice() {
  3548.         GlobalControllerAdvice advice = this.webAppContext.getBean(GlobalControllerAdvice.class);
  3549.         assertNotNull(advice);
  3550.     }
  3551.  
  3552.     @Test
  3553.     public void shouldReturnJsonIfGetRequest() throws Exception {
  3554.         mvc.perform(get(EMPLOYEES_ENDPOINT))
  3555.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3556.                 .andExpect(status().isOk());
  3557.     }
  3558.  
  3559.     @Test
  3560.     public void shouldReturnCorrectJsonIfGetRequestById() throws Exception {
  3561.         mvc.perform(get(EMPLOYEES_ENDPOINT + "/{id}", employeeDTO.getId().toString()))
  3562.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3563.                 .andExpect(jsonPath("$.firstName").value(employeeDTO.getFirstName()))
  3564.                 .andExpect(jsonPath("$.lastName").value(employeeDTO.getLastName()))
  3565.                 .andExpect(jsonPath("$.username").value(employeeDTO.getUsername()))
  3566.                 .andExpect(jsonPath("$.position").value(employeeDTO.getPosition()));
  3567.     }
  3568.  
  3569.     @Test
  3570.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForGetRequestById() throws Exception {
  3571.         mvc.perform(get(EMPLOYEES_ENDPOINT + "/{id}", "incorrect"))
  3572.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3573.                 .andExpect(status().isBadRequest())
  3574.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3575.                 .andExpect(jsonPath("$.code").value(400));
  3576.     }
  3577.  
  3578.     @Test
  3579.     public void shouldReturnMethodNotAllowedForPost() throws Exception {
  3580.         mvc.perform(post(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(employeeDTO)))
  3581.                 .andExpect(status().isMethodNotAllowed());
  3582.     }
  3583.  
  3584.     @Test
  3585.     public void shouldReturnBadRequestStatusIfJsonIsEmptyForPut() throws Exception {
  3586.         mvc.perform(put(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3587.                 .andExpect(status().isBadRequest());
  3588.     }
  3589.  
  3590.     @Test
  3591.     public void shouldReturnBadRequestIfJsonHasEmptyFieldsForPut() throws Exception {
  3592.         employeeDTO.setPosition("");
  3593.         employeeDTO.setUsername("");
  3594.         mvc.perform(put(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(employeeDTO)))
  3595.                 .andExpect(status().isBadRequest());
  3596.     }
  3597.  
  3598.     @Test
  3599.     public void shouldReturnNotFoundIfRoleDoesNotExistForPut() throws Exception {
  3600.         employeeDTO.setRole("Test");
  3601.         mvc.perform(put(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(employeeDTO)))
  3602.                 .andExpect(status().isNotFound());
  3603.     }
  3604.  
  3605.     @Test
  3606.     public void shouldReturnOkStatusIfJsonIsCorrectForPut() throws Exception {
  3607.         mvc.perform(put(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(employeeDTO)))
  3608.                 .andExpect(status().isOk())
  3609.                 .andExpect(jsonPath("$.firstName").value(employeeDTO.getFirstName()))
  3610.                 .andExpect(jsonPath("$.lastName").value(employeeDTO.getLastName()))
  3611.                 .andExpect(jsonPath("$.username").value(employeeDTO.getUsername()))
  3612.                 .andExpect(jsonPath("$.position").value(employeeDTO.getPosition()))
  3613.                 .andExpect(jsonPath("$.id").value(employeeDTO.getId().toString()));
  3614.     }
  3615.  
  3616.     @Test
  3617.     public void shouldReturnUpdatedEmployeeIfItExistsById() throws Exception {
  3618.         mvc.perform(put(EMPLOYEES_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(employeeDTO)))
  3619.                 .andExpect(status().isOk())
  3620.                 .andExpect(jsonPath("$.id").value(employeeDTO.getId().toString()))
  3621.                 .andExpect(jsonPath("$.firstName").value(employeeDTO.getFirstName()));
  3622.     }
  3623.  
  3624.     @Test
  3625.     public void shouldDeleteEmployeeIfIdIsCorrectAndExists() throws Exception{
  3626.         mvc.perform(delete(EMPLOYEES_ENDPOINT + "/{id}", "c7fa1cd3-b281-47b1-b72f-92b9391fc5c7"))
  3627.                 .andExpect(status().isNoContent());
  3628.     }
  3629.  
  3630.     @Test
  3631.     public void shouldReturnMethodNotAllowedIfUUIDIsEmptyForDelete() throws Exception {
  3632.         mvc.perform(delete(EMPLOYEES_ENDPOINT + "/{id}", ""))
  3633.                 .andExpect(status().isMethodNotAllowed());
  3634.     }
  3635.  
  3636.     @Test
  3637.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForDeleteRequestById() throws Exception {
  3638.         mvc.perform(delete(EMPLOYEES_ENDPOINT + "/{id}", "incorrect"))
  3639.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3640.                 .andExpect(status().isBadRequest())
  3641.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3642.                 .andExpect(jsonPath("$.code").value(400));
  3643.     }
  3644. }
  3645.  
  3646. package com.leverx.employeestat.rest.integration;
  3647.  
  3648. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3649. import com.leverx.employeestat.rest.dto.ProjectDTO;
  3650. import com.leverx.employeestat.rest.exceptionhandler.GlobalControllerAdvice;
  3651. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3652. import org.junit.jupiter.api.BeforeEach;
  3653. import org.junit.jupiter.api.Test;
  3654. import org.junit.jupiter.api.extension.ExtendWith;
  3655. import org.springframework.beans.factory.annotation.Autowired;
  3656. import org.springframework.http.MediaType;
  3657. import org.springframework.test.context.ContextConfiguration;
  3658. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3659. import org.springframework.test.context.web.WebAppConfiguration;
  3660. import org.springframework.test.web.servlet.MockMvc;
  3661. import org.springframework.test.web.servlet.MvcResult;
  3662. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3663. import org.springframework.transaction.annotation.Transactional;
  3664. import org.springframework.web.context.WebApplicationContext;
  3665.  
  3666. import java.time.LocalDate;
  3667. import java.util.UUID;
  3668.  
  3669. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toJson;
  3670. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toObject;
  3671. import static org.junit.jupiter.api.Assertions.assertNotNull;
  3672. import static org.junit.jupiter.api.Assertions.assertNull;
  3673. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  3674. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  3675.  
  3676. @ExtendWith(SpringExtension.class)
  3677. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3678. @WebAppConfiguration
  3679. @Transactional
  3680. public class ProjectIntegrationTest {
  3681.  
  3682.     public static final String PROJECTS_ENDPOINT = "/api/projects";
  3683.  
  3684.     private final WebApplicationContext webAppContext;
  3685.     private MockMvc mvc;
  3686.     private ProjectDTO projectDTO;
  3687.  
  3688.     @Autowired
  3689.     public ProjectIntegrationTest(WebApplicationContext webAppContext) {
  3690.         this.webAppContext = webAppContext;
  3691.     }
  3692.  
  3693.     @BeforeEach
  3694.     public void setup() {
  3695.         this.mvc = MockMvcBuilders.webAppContextSetup(this.webAppContext).build();
  3696.         String name = "project";
  3697.         String begin = "2021-09-11";
  3698.         String end = "2021-11-20";
  3699.         projectDTO = new ProjectDTO();
  3700.         projectDTO.setName(name);
  3701.         projectDTO.setBegin(LocalDate.parse(begin));
  3702.         projectDTO.setEnd(LocalDate.parse(end));
  3703.     }
  3704.  
  3705.     @Test
  3706.     public void shouldExistsGlobalControllerAdvice() {
  3707.         GlobalControllerAdvice advice = this.webAppContext.getBean(GlobalControllerAdvice.class);
  3708.         assertNotNull(advice);
  3709.     }
  3710.  
  3711.     @Test
  3712.     public void shouldReturnJsonIfGetRequest() throws Exception {
  3713.         mvc.perform(get(PROJECTS_ENDPOINT))
  3714.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3715.                 .andExpect(status().isOk());
  3716.     }
  3717.  
  3718.     @Test
  3719.     public void shouldReturnCorrectJsonIfGetRequestById() throws Exception {
  3720.         String expectedName = "Bank system";
  3721.         String expectedBeginDate = "2020-10-08";
  3722.         String expectedEndDate = "2020-12-16";
  3723.  
  3724.         mvc.perform(get(PROJECTS_ENDPOINT + "/{id}", "7c8697b8-530d-4a00-ba00-3dfec6b1bb79"))
  3725.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3726.                 .andExpect(status().isOk())
  3727.                 .andExpect(jsonPath("$.name").value(expectedName))
  3728.                 .andExpect(jsonPath("$.begin").value(expectedBeginDate))
  3729.                 .andExpect((jsonPath("$.end").value(expectedEndDate)));
  3730.     }
  3731.  
  3732.     @Test
  3733.     public void shouldReturnBadRequestStatusIfJsonIsNotCorrectForPosting() throws Exception {
  3734.         mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3735.                 .andExpect(status().isBadRequest());
  3736.     }
  3737.  
  3738.     @Test
  3739.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForGetRequestById() throws Exception {
  3740.         mvc.perform(get(PROJECTS_ENDPOINT + "/{id}", "incorrect"))
  3741.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3742.                 .andExpect(status().isBadRequest())
  3743.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3744.                 .andExpect(jsonPath("$.code").value(400));
  3745.     }
  3746.  
  3747.     @Test
  3748.     public void shouldReturnOkStatusIfJsonIsCorrectForPosting() throws Exception{
  3749.         String expectedName = "project";
  3750.         String expectedBeginDate = "2021-09-11";
  3751.         String expectedEndDate = "2021-11-20";
  3752.  
  3753.         mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3754.                 .andExpect(status().isCreated())
  3755.                 .andExpect(jsonPath("$.name").value(expectedName))
  3756.                 .andExpect(jsonPath("$.begin").value(expectedBeginDate))
  3757.                 .andExpect((jsonPath("$.end").value(expectedEndDate)))
  3758.                 .andExpect(jsonPath("$.id").isNotEmpty());
  3759.     }
  3760.  
  3761.     @Test
  3762.     public void shouldReturnBadRequestIfNameOfProjectAlreadyExistsForPosting() throws Exception {
  3763.         mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3764.                 .andExpect(status().isCreated());
  3765.  
  3766.         mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3767.                 .andExpect(status().isBadRequest())
  3768.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3769.                 .andExpect(jsonPath("$.code").value(400));
  3770.     }
  3771.  
  3772.     @Test
  3773.     public void shouldReturnBadRequestStatusIfJsonIsNotCorrectForPutting() throws Exception {
  3774.         mvc.perform(put(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(""))
  3775.                 .andExpect(status().isBadRequest());
  3776.     }
  3777.  
  3778.     @Test
  3779.     public void shouldReturnOkStatusIfJsonWithoutIdIsCorrectForPutting() throws Exception {
  3780.         ProjectDTO projectDTO = new ProjectDTO();
  3781.         projectDTO.setName("expected");
  3782.         projectDTO.setEnd(LocalDate.of(2021, 5, 11));
  3783.         projectDTO.setBegin(LocalDate.of(2021, 2, 11));
  3784.  
  3785.         mvc.perform(put(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3786.                 .andExpect(status().isOk())
  3787.                 .andExpect(jsonPath("$.name").value(projectDTO.getName()))
  3788.                 .andExpect(jsonPath("$.begin").value(projectDTO.getBegin().toString()))
  3789.                 .andExpect(jsonPath("$.end").value(projectDTO.getEnd().toString()))
  3790.                 .andExpect(jsonPath("$.id").isNotEmpty());
  3791.  
  3792.         assertNull(projectDTO.getId());
  3793.     }
  3794.  
  3795.     @Test
  3796.     public void shouldReturnBadRequestIfNameOfProjectAlreadyExistsForPutting() throws Exception {
  3797.         mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3798.                 .andExpect(status().isCreated());
  3799.  
  3800.         mvc.perform(put(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3801.                 .andExpect(status().isBadRequest())
  3802.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3803.                 .andExpect(jsonPath("$.code").value(400));
  3804.     }
  3805.  
  3806.     @Test
  3807.     public void shouldReturnUpdatedProjectIfItExistsById() throws Exception {
  3808.         MvcResult result = mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3809.                 .andExpect(status().isCreated())
  3810.                 .andReturn();
  3811.  
  3812.         String expectedName = "New";
  3813.         projectDTO = toObject(result.getResponse().getContentAsString(), ProjectDTO.class);
  3814.         projectDTO.setName(expectedName);
  3815.         UUID expectedId = projectDTO.getId();
  3816.  
  3817.         mvc.perform(put(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3818.                 .andExpect(status().isOk())
  3819.                 .andExpect(jsonPath("$.id").value(expectedId.toString()))
  3820.                 .andExpect(jsonPath("$.name").value(expectedName));
  3821.     }
  3822.  
  3823.     @Test
  3824.     public void shouldDeleteProjectIfIdIsCorrectAndExists() throws Exception {
  3825.         MvcResult result = mvc.perform(post(PROJECTS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(projectDTO)))
  3826.                 .andExpect(status().isCreated())
  3827.                 .andReturn();
  3828.  
  3829.         projectDTO = toObject(result.getResponse().getContentAsString(), ProjectDTO.class);
  3830.         UUID id = projectDTO.getId();
  3831.  
  3832.         mvc.perform(delete(PROJECTS_ENDPOINT + "/{id}", id.toString()))
  3833.                 .andExpect(status().isNoContent());
  3834.     }
  3835.  
  3836.     @Test
  3837.     public void shouldReturnMethodNotAllowedIfUUIDIsEmptyForDeleting() throws Exception {
  3838.         mvc.perform(delete(PROJECTS_ENDPOINT + "/{id}", ""))
  3839.                 .andExpect(status().isMethodNotAllowed());
  3840.     }
  3841.  
  3842.     @Test
  3843.     public void shouldReturnBadRequestIfUUIDIsNotCorrectForDeleteRequestById() throws Exception {
  3844.         mvc.perform(delete(PROJECTS_ENDPOINT + "/{id}", "incorrect"))
  3845.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3846.                 .andExpect(status().isBadRequest())
  3847.                 .andExpect(jsonPath("$.status").value("BAD_REQUEST"))
  3848.                 .andExpect(jsonPath("$.code").value(400));
  3849.     }
  3850. }
  3851.  
  3852. package com.leverx.employeestat.rest.integration;
  3853.  
  3854. import com.leverx.employeestat.rest.configuration.WebInitializer;
  3855. import com.leverx.employeestat.rest.dto.WorkDTO;
  3856. import com.leverx.employeestat.rest.exceptionhandler.GlobalControllerAdvice;
  3857. import com.leverx.employeestat.rest.integration.config.TestConfig;
  3858. import org.junit.jupiter.api.BeforeEach;
  3859. import org.junit.jupiter.api.Test;
  3860. import org.junit.jupiter.api.extension.ExtendWith;
  3861. import org.springframework.beans.factory.annotation.Autowired;
  3862. import org.springframework.http.MediaType;
  3863. import org.springframework.test.context.ContextConfiguration;
  3864. import org.springframework.test.context.junit.jupiter.SpringExtension;
  3865. import org.springframework.test.context.web.WebAppConfiguration;
  3866. import org.springframework.test.web.servlet.MockMvc;
  3867. import org.springframework.test.web.servlet.setup.MockMvcBuilders;
  3868. import org.springframework.transaction.annotation.Transactional;
  3869. import org.springframework.web.context.WebApplicationContext;
  3870.  
  3871. import java.util.UUID;
  3872.  
  3873. import static com.leverx.employeestat.rest.integration.util.JsonUtils.toJson;
  3874. import static org.junit.jupiter.api.Assertions.assertNotNull;
  3875. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  3876. import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
  3877. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  3878.  
  3879. @ExtendWith(SpringExtension.class)
  3880. @ContextConfiguration(classes = {TestConfig.class, WebInitializer.class})
  3881. @WebAppConfiguration
  3882. @Transactional
  3883. public class WorkIntegrationTest {
  3884.  
  3885.     private final static String WORKS_ENDPOINT = "/api/works";
  3886.     private final static String IDS_POSTFIX = "/{empId}/{projId}";
  3887.     private final static String NON_EXISTING_ID = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
  3888.     private final WebApplicationContext webAppContext;
  3889.     private MockMvc mvc;
  3890.  
  3891.     private WorkDTO firstWork;
  3892.     private WorkDTO secondWork;
  3893.     private WorkDTO thirdWork;
  3894.  
  3895.     @Autowired
  3896.     public WorkIntegrationTest(WebApplicationContext webAppContext) {
  3897.         this.webAppContext = webAppContext;
  3898.     }
  3899.  
  3900.     @BeforeEach
  3901.     void setup() {
  3902.         this.mvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
  3903.     }
  3904.  
  3905.     @BeforeEach
  3906.     public void init() {
  3907.         firstWork = new WorkDTO();
  3908.         secondWork = new WorkDTO();
  3909.         thirdWork = new WorkDTO();
  3910.  
  3911.         firstWork.setEmployeeId(UUID.fromString("c7fa1cd3-b281-47b1-b72f-92b9391fc5c7"));
  3912.         firstWork.setProjectId(UUID.fromString("7c8697b8-530d-4a00-ba00-3dfec6b1bb79"));
  3913.  
  3914.         secondWork.setEmployeeId(UUID.fromString("e9a4e12b-1555-48bd-9275-629856bcdb51"));
  3915.         secondWork.setProjectId(UUID.fromString("7c8697b8-530d-4a00-ba00-3dfec6b1bb79"));
  3916.  
  3917.         thirdWork.setEmployeeId(UUID.fromString("2174c05c-e885-4521-985d-774b1f05cd37"));
  3918.         thirdWork.setProjectId(UUID.fromString("6f6bd93b-fcdd-4c3f-a144-1e03139559d6"));
  3919.     }
  3920.  
  3921.     @Test
  3922.     public void shouldExistsGlobalControllerAdvice() {
  3923.         GlobalControllerAdvice advice = this.webAppContext.getBean(GlobalControllerAdvice.class);
  3924.         assertNotNull(advice);
  3925.     }
  3926.  
  3927.     @Test
  3928.     public void shouldReturnJsonListForGetAllWorks() throws Exception {
  3929.         mvc.perform(get(WORKS_ENDPOINT))
  3930.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3931.                 .andExpect(status().isOk()).andDo(print())
  3932.                 .andExpect(jsonPath("$[0].employeeId").value(firstWork.getEmployeeId().toString()))
  3933.                 .andExpect(jsonPath("$[1].employeeId").value(secondWork.getEmployeeId().toString()))
  3934.                 .andExpect(jsonPath("$[2].employeeId").value(thirdWork.getEmployeeId().toString()))
  3935.                 .andExpect(jsonPath("$[0].projectId").value(firstWork.getProjectId().toString()))
  3936.                 .andExpect(jsonPath("$[1].projectId").value(secondWork.getProjectId().toString()))
  3937.                 .andExpect(jsonPath("$[2].projectId").value(thirdWork.getProjectId().toString()));
  3938.     }
  3939.  
  3940.     @Test
  3941.     public void shouldReturnWorkByEmployeeIdAndProjectIdIfTheyAreCorrectForGetWork() throws Exception {
  3942.         final String expectedEmpId = firstWork.getEmployeeId().toString();
  3943.         final String expectedProjId = firstWork.getProjectId().toString();
  3944.  
  3945.         mvc.perform(get(WORKS_ENDPOINT + IDS_POSTFIX, expectedEmpId, expectedProjId))
  3946.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3947.                 .andExpect(status().isOk())
  3948.                 .andExpect(jsonPath("$.projectId").value(expectedProjId))
  3949.                 .andExpect(jsonPath("$.employeeId").value(expectedEmpId));
  3950.     }
  3951.  
  3952.     @Test
  3953.     public void shouldReturnBadRequestIfEmployeeIdAndProjectIdIsNotValidForGetWork() throws Exception {
  3954.         final String notValidEmpId = "not valid";
  3955.         final String notValidProjId = "not valid";
  3956.  
  3957.         mvc.perform(get(WORKS_ENDPOINT + IDS_POSTFIX, notValidEmpId, notValidEmpId))
  3958.                 .andExpect(status().isBadRequest());
  3959.     }
  3960.  
  3961.     @Test
  3962.     public void shouldReturnNotFoundIfEmployeeDoesNotExistByEmployeeIdForGetWork() throws Exception {
  3963.         final String projId = firstWork.getProjectId().toString();
  3964.  
  3965.         mvc.perform(get(WORKS_ENDPOINT + IDS_POSTFIX, NON_EXISTING_ID, projId))
  3966.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3967.                 .andExpect(status().isNotFound())
  3968.                 .andExpect(jsonPath("$.message").value(String.format("Employee with id=%s not found", NON_EXISTING_ID)));
  3969.     }
  3970.  
  3971.     @Test
  3972.     public void shouldReturnNotFoundIfProjectDoesNotExistByProjectIdForGetWork() throws Exception {
  3973.         final String empId = firstWork.getEmployeeId().toString();
  3974.  
  3975.         mvc.perform(get(WORKS_ENDPOINT + IDS_POSTFIX, empId, NON_EXISTING_ID))
  3976.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3977.                 .andExpect(status().isNotFound())
  3978.                 .andExpect(jsonPath("$.message").value(String.format("Project with id=%s not found", NON_EXISTING_ID)));
  3979.     }
  3980.  
  3981.     @Test
  3982.     public void shouldReturnNotFoundStatusIfProjectIdAndEmployeeIdExistButWorkIdDoesNotExistForGetWork() throws Exception {
  3983.         final String empId = firstWork.getEmployeeId().toString();
  3984.         final String projId = thirdWork.getProjectId().toString();
  3985.  
  3986.         mvc.perform(get(WORKS_ENDPOINT + IDS_POSTFIX, empId, projId))
  3987.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3988.                 .andExpect(status().isNotFound())
  3989.                 .andExpect(jsonPath("$.message").value(String.format("Work with id=(employeeId=%s; projectId=%s) not found", empId, projId)));
  3990.     }
  3991.  
  3992.     @Test
  3993.     public void shouldReturnOkStatusIfWorkExistsByIdForPutWork() throws Exception {
  3994.         final int expectedWorkingHours = 0;
  3995.         firstWork.setWorkingHours(expectedWorkingHours);
  3996.         mvc.perform(put(WORKS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(firstWork)))
  3997.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  3998.                 .andExpect(status().isOk())
  3999.                 .andExpect(jsonPath("$.workingHours").value(expectedWorkingHours));
  4000.     }
  4001.  
  4002.     @Test
  4003.     public void shouldThrowExceptionIfWorkDoesNotExistByIdForPutWork() throws Exception {
  4004.         firstWork.setProjectId(thirdWork.getProjectId());
  4005.         mvc.perform(put(WORKS_ENDPOINT).contentType(MediaType.APPLICATION_JSON).content(toJson(firstWork)))
  4006.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  4007.                 .andExpect(status().isNotFound())
  4008.                 .andExpect(jsonPath("$.message").value(String.format("Work with id=(employeeId=%s; projectId=%s) not found", firstWork.getEmployeeId(), firstWork.getProjectId())));
  4009.     }
  4010.  
  4011.     @Test
  4012.     public void shouldReturnNoContentStatusIfWorkExistsByIdForDeleteWork() throws Exception {
  4013.         final String empId = firstWork.getEmployeeId().toString();
  4014.         final String projId = firstWork.getProjectId().toString();
  4015.  
  4016.         mvc.perform(delete(WORKS_ENDPOINT + IDS_POSTFIX, empId, projId))
  4017.                 .andExpect(status().isNoContent());
  4018.     }
  4019.  
  4020.     @Test
  4021.     public void shouldReturnNotFoundStatusIfProjectIdAndEmployeeIdExistButWorkIdDoesNotExistForDeleteWork() throws Exception {
  4022.         final String empId = firstWork.getEmployeeId().toString();
  4023.         final String projId = thirdWork.getProjectId().toString();
  4024.  
  4025.         mvc.perform(delete(WORKS_ENDPOINT + IDS_POSTFIX, empId, projId))
  4026.                 .andExpect(content().contentType(MediaType.APPLICATION_JSON))
  4027.                 .andExpect(status().isNotFound())
  4028.                 .andExpect(jsonPath("$.message").value(String.format("Work with id=(employeeId=%s; projectId=%s) not found", empId, projId)));
  4029.     }
  4030. }
  4031.  
  4032. package com.leverx.employeestat.rest.unit;
  4033.  
  4034. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  4035. import com.leverx.employeestat.rest.dto.converter.EmployeeConverter;
  4036. import com.leverx.employeestat.rest.entity.Employee;
  4037. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  4038. import com.leverx.employeestat.rest.exception.InvalidPasswordException;
  4039. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  4040. import com.leverx.employeestat.rest.model.ResetPasswordRequest;
  4041. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  4042. import com.leverx.employeestat.rest.service.impl.AuthorizationServiceImpl;
  4043. import org.junit.jupiter.api.BeforeEach;
  4044. import org.junit.jupiter.api.Test;
  4045. import org.junit.jupiter.api.extension.ExtendWith;
  4046. import org.mockito.InjectMocks;
  4047. import org.mockito.Mock;
  4048. import org.mockito.junit.jupiter.MockitoExtension;
  4049. import org.springframework.security.crypto.password.PasswordEncoder;
  4050.  
  4051. import java.util.ArrayList;
  4052. import java.util.List;
  4053. import java.util.Optional;
  4054.  
  4055. import static org.junit.jupiter.api.Assertions.assertThrows;
  4056. import static org.junit.jupiter.api.Assertions.assertEquals;
  4057. import static org.mockito.Mockito.*;
  4058.  
  4059. @ExtendWith(MockitoExtension.class)
  4060. public class AuthorizationServiceTest {
  4061.  
  4062.     @Mock
  4063.     private EmployeeRepository employeeRepository;
  4064.  
  4065.     @Mock
  4066.     private EmployeeConverter converter;
  4067.  
  4068.     @Mock
  4069.     private PasswordEncoder encoder;
  4070.  
  4071.     @InjectMocks
  4072.     private AuthorizationServiceImpl authorizationService;
  4073.  
  4074.     private EmployeeDTO employeeDTO;
  4075.     private Employee employee;
  4076.     private ResetPasswordRequest request;
  4077.  
  4078.     @BeforeEach
  4079.     public void init() {
  4080.         employeeDTO = new EmployeeDTO();
  4081.         employee = new Employee();
  4082.         request = new ResetPasswordRequest();
  4083.  
  4084.         employeeDTO.setUsername("username");
  4085.         employeeDTO.setPassword("password");
  4086.  
  4087.         employee.setUsername("username");
  4088.         employee.setPassword("password");
  4089.  
  4090.         request.setUsername("username");
  4091.         request.setOldPassword("password");
  4092.         request.setNewPassword("new");
  4093.     }
  4094.  
  4095.     @Test
  4096.     public void shouldReturnRegisteredEmployeeIfItDoesNotExistByUsernameWhenRegisterEmployee() {
  4097.         final String expected = "encoded";
  4098.  
  4099.         when(employeeRepository.existsByUsername(employeeDTO.getUsername())).thenReturn(false);
  4100.         when(encoder.encode(employeeDTO.getPassword())).thenReturn(expected);
  4101.         when(converter.toEntity(employeeDTO)).thenReturn(employee);
  4102.         when(employeeRepository.save(employee)).thenReturn(employee);
  4103.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4104.  
  4105.         assertEquals(expected, authorizationService.registerEmployee(employeeDTO).getPassword());
  4106.  
  4107.         verify(employeeRepository).existsByUsername(employeeDTO.getUsername());
  4108.         verify(encoder).encode("password");
  4109.         verify(converter).toEntity(employeeDTO);
  4110.         verify(converter).toDTO(employee);
  4111.         verify(employeeRepository).save(employee);
  4112.     }
  4113.  
  4114.     @Test
  4115.     public void shouldThrowExceptionIfEmployeeAlreadyExistsByUsernameWhenRegisterEmployee() {
  4116.         when(employeeRepository.existsByUsername(employeeDTO.getUsername())).thenReturn(true);
  4117.  
  4118.         assertThrows(DuplicateRecordException.class, () -> authorizationService.registerEmployee(employeeDTO));
  4119.  
  4120.         verify(employeeRepository).existsByUsername(employeeDTO.getUsername());
  4121.     }
  4122.  
  4123.     @Test
  4124.     public void shouldResetPasswordIfEmployeeExistsByUsernameAndHasCorrectOldPasswordWhenResetPassword() {
  4125.         final String expected = "encoded";
  4126.         when(employeeRepository.findEmployeeByUsername(request.getUsername())).thenReturn(Optional.of(employee));
  4127.         when(encoder.matches(request.getOldPassword(), "password")).thenReturn(true);
  4128.         when(encoder.encode(request.getNewPassword())).thenReturn(expected);
  4129.         employeeDTO.setPassword(expected);
  4130.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4131.  
  4132.         assertEquals(expected, authorizationService.resetPassword(request).getPassword());
  4133.  
  4134.         verify(employeeRepository).findEmployeeByUsername(request.getUsername());
  4135.         verify(encoder).matches(request.getOldPassword(), "password");
  4136.         verify(encoder).encode(request.getNewPassword());
  4137.         verify(converter).toDTO(employee);
  4138.     }
  4139.  
  4140.     @Test
  4141.     public void shouldThrowExceptionIfEmployeeDoesNotExistsByUsernameWhenResetPassword() {
  4142.         when(employeeRepository.findEmployeeByUsername(request.getUsername())).thenReturn(Optional.ofNullable(null));
  4143.  
  4144.         assertThrows(NoSuchRecordException.class, () -> authorizationService.resetPassword(request));
  4145.  
  4146.         verify(employeeRepository).findEmployeeByUsername(request.getUsername());
  4147.     }
  4148.  
  4149.     @Test
  4150.     public void shouldThrowExceptionIfOldPasswordMismatchesCurrentPasswordWhenResetPassword() {
  4151.         when(employeeRepository.findEmployeeByUsername(request.getUsername())).thenReturn(Optional.of(employee));
  4152.         when(encoder.matches(request.getOldPassword(), "password")).thenReturn(false);
  4153.  
  4154.         assertThrows(InvalidPasswordException.class, () -> authorizationService.resetPassword(request));
  4155.  
  4156.         verify(employeeRepository).findEmployeeByUsername(request.getUsername());
  4157.         verify(encoder).matches(request.getOldPassword(), "password");
  4158.     }
  4159.  
  4160.     @Test
  4161.     public void test() {
  4162.         final String expectedPassword = "encoded";
  4163.         final int expectedAmount = 3;
  4164.         when(employeeRepository.existsByUsername(employeeDTO.getUsername())).thenReturn(false);
  4165.         when(encoder.encode(employeeDTO.getPassword())).thenReturn(expectedPassword);
  4166.         when(converter.toEntity(employeeDTO)).thenReturn(employee);
  4167.         when(employeeRepository.save(employee)).thenReturn(employee);
  4168.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4169.  
  4170.         List<EmployeeDTO> employees = new ArrayList<>();
  4171.         for (int i = 0; i < expectedAmount; i++) {
  4172.             employees.add(employeeDTO);
  4173.         }
  4174.  
  4175.         assertEquals(expectedAmount, authorizationService.registerAll(employees).size());
  4176.  
  4177.         verify(employeeRepository, times(expectedAmount)).existsByUsername(employeeDTO.getUsername());
  4178.         verify(encoder).encode("password");
  4179.         verify(converter, times(expectedAmount)).toEntity(employeeDTO);
  4180.         verify(converter, times(expectedAmount)).toDTO(employee);
  4181.         verify(employeeRepository, times(expectedAmount)).save(employee);
  4182.     }
  4183. }
  4184.  
  4185. package com.leverx.employeestat.rest.unit;
  4186.  
  4187. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  4188. import com.leverx.employeestat.rest.service.CSVReaderService;
  4189. import com.leverx.employeestat.rest.service.impl.CSVReaderServiceImpl;
  4190. import com.leverx.employeestat.rest.unit.fileitems.FileItemImpl;
  4191. import org.junit.jupiter.api.Assertions;
  4192. import org.junit.jupiter.api.BeforeEach;
  4193. import org.junit.jupiter.api.Test;
  4194. import org.springframework.web.multipart.MultipartFile;
  4195. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  4196.  
  4197. import java.util.Arrays;
  4198. import java.util.List;
  4199. import java.util.stream.Collectors;
  4200.  
  4201. public class CSVReaderServiceTest {
  4202.  
  4203.     private final static String CORRECT_FILE = "csv-test/employees.csv";
  4204.  
  4205.     private CSVReaderService csvReaderService;
  4206.  
  4207.     @BeforeEach
  4208.     public void init() {
  4209.         csvReaderService = new CSVReaderServiceImpl();
  4210.     }
  4211.  
  4212.     @Test
  4213.     public void shouldReturnNotEmptyListIfFileIsCorrect() {
  4214.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4215.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4216.         Assertions.assertFalse(employees.isEmpty());
  4217.     }
  4218.  
  4219.     @Test
  4220.     public void shouldReturnCorrectEmployeesAmountIfFileIsCorrect() {
  4221.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4222.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4223.  
  4224.         int expectedAmount = 5;
  4225.         int actualAmount = employees.size();
  4226.  
  4227.         Assertions.assertEquals(expectedAmount, actualAmount);
  4228.     }
  4229.  
  4230.     @Test
  4231.     public void shouldReturnCorrectFirstNamesIfFileIsCorrect() {
  4232.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4233.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4234.  
  4235.         List<String> expectedNames = Arrays.asList(new String[] { "Vlad", "Artiom", "Kirill", "Aleksander", "Dasha"});
  4236.         List<String> actualNames = employees
  4237.                 .stream()
  4238.                 .map(EmployeeDTO::getFirstName)
  4239.                 .collect(Collectors.toList());
  4240.  
  4241.         Assertions.assertEquals(expectedNames, actualNames);
  4242.     }
  4243.  
  4244.     @Test
  4245.     public void shouldReturnCorrectLastNamesIfFileIsCorrect() {
  4246.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4247.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4248.  
  4249.         List<String> expectedLastNames = Arrays.asList(new String[] {"Vladov", "Ivanov", "Avtobusov", "Sosiskin", "Glavnaya"});
  4250.         List<String> actualLastNames = employees
  4251.                 .stream()
  4252.                 .map(EmployeeDTO::getLastName)
  4253.                 .collect(Collectors.toList());
  4254.  
  4255.         Assertions.assertEquals(expectedLastNames, actualLastNames);
  4256.     }
  4257.  
  4258.     @Test
  4259.     public void shouldReturnCorrectUsernamesIfFileIsCorrect() {
  4260.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4261.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4262.  
  4263.         List<String> expectedUsernames = Arrays.asList(new String[] {"Turbo3000", "Tema", "Kiruha", "Sanek1000", "Dashka"});
  4264.         List<String> actualUsernames = employees
  4265.                 .stream()
  4266.                 .map(EmployeeDTO::getUsername)
  4267.                 .collect(Collectors.toList());
  4268.  
  4269.         Assertions.assertEquals(expectedUsernames, actualUsernames);
  4270.     }
  4271.  
  4272.     @Test
  4273.     public void shouldReturnCorrectPositionIfFileIsCorrect() {
  4274.         MultipartFile file = new CommonsMultipartFile(new FileItemImpl(CORRECT_FILE));
  4275.         List<EmployeeDTO> employees = csvReaderService.getEmployeesFromFile(file);
  4276.  
  4277.         List<String> expectedPositions = Arrays.asList(new String[] {"Java Developer", "JS Developer", ".NET Developer", "HR", "Boss"});
  4278.         List<String> actualPositions = employees
  4279.                 .stream()
  4280.                 .map(EmployeeDTO::getPosition)
  4281.                 .collect(Collectors.toList());
  4282.  
  4283.         Assertions.assertEquals(expectedPositions, actualPositions);
  4284.     }
  4285. }
  4286.  
  4287. package com.leverx.employeestat.rest.unit;
  4288.  
  4289. import com.leverx.employeestat.rest.dto.DepartmentDTO;
  4290. import com.leverx.employeestat.rest.dto.converter.DepartmentConverter;
  4291. import com.leverx.employeestat.rest.entity.Department;
  4292. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  4293. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  4294. import com.leverx.employeestat.rest.repository.DepartmentRepository;
  4295. import com.leverx.employeestat.rest.service.impl.DepartmentServiceImpl;
  4296. import org.junit.jupiter.api.Assertions;
  4297. import org.junit.jupiter.api.Test;
  4298. import org.junit.jupiter.api.extension.ExtendWith;
  4299. import org.mockito.InjectMocks;
  4300. import org.mockito.Mock;
  4301. import org.mockito.Mockito;
  4302. import org.mockito.junit.jupiter.MockitoExtension;
  4303.  
  4304. import java.util.*;
  4305.  
  4306. import static org.mockito.ArgumentMatchers.any;
  4307. import static org.mockito.Mockito.verify;
  4308. import static org.mockito.Mockito.when;
  4309.  
  4310. @ExtendWith(MockitoExtension.class)
  4311. public class DepartmentServiceTest {
  4312.  
  4313.     @Mock
  4314.     private DepartmentRepository departmentRepository;
  4315.  
  4316.     @Mock
  4317.     private DepartmentConverter converter;
  4318.  
  4319.     @InjectMocks
  4320.     private DepartmentServiceImpl departmentService;
  4321.  
  4322.  
  4323.     @Test
  4324.     public void shouldReturnDepartmentIfItExistsById() {
  4325.         UUID id = UUID.randomUUID();
  4326.         Department department = new Department();
  4327.         DepartmentDTO departmentDTO = new DepartmentDTO();
  4328.  
  4329.         when(converter.toDTO(department)).thenReturn(departmentDTO);
  4330.         when(departmentRepository.findById(id)).thenReturn(Optional.of(department));
  4331.  
  4332.         Assertions.assertNotNull(departmentService.getById(id));
  4333.  
  4334.         verify(converter).toDTO(department);
  4335.         verify(departmentRepository).findById(id);
  4336.     }
  4337.  
  4338.     @Test
  4339.     public void shouldThrowExceptionIfDepartmentDoesNotExistsById() {
  4340.         UUID id = UUID.randomUUID();
  4341.         when(departmentRepository.findById(id)).thenReturn(Optional.ofNullable(null));
  4342.  
  4343.         Assertions.assertThrows(NoSuchRecordException.class, () -> departmentService.getById(id));
  4344.  
  4345.         verify(departmentRepository).findById(id);
  4346.     }
  4347.  
  4348.     @Test
  4349.     public void shouldReturnEmptyListIfDbTableIsEmpty() {
  4350.         when(departmentRepository.findAll()).thenReturn(new ArrayList<Department>());
  4351.  
  4352.         Assertions.assertTrue(departmentService.getAll().isEmpty());
  4353.  
  4354.         verify(departmentRepository).findAll();
  4355.     }
  4356.  
  4357.     @Test
  4358.     public void shouldReturnNotEmptyListIfDbTableIsNotEmpty() {
  4359.         when(departmentRepository.findAll()).thenReturn(Arrays.asList(new Department[] {new Department(), new Department()}));
  4360.  
  4361.         Assertions.assertFalse(departmentService.getAll().isEmpty());
  4362.  
  4363.         verify(departmentRepository).findAll();
  4364.     }
  4365.  
  4366.     @Test
  4367.     public void shouldReturnSavedDepartmentIfProjectDoesNotExists() {
  4368.         String name = "Department name";
  4369.         DepartmentDTO departmentDTO = new DepartmentDTO();
  4370.         departmentDTO.setName(name);
  4371.         Department department = new Department();
  4372.         department.setName(name);
  4373.  
  4374.         when(converter.toEntity(departmentDTO)).thenReturn(department);
  4375.         when(converter.toDTO(department)).thenReturn(departmentDTO);
  4376.         when(departmentRepository.existsByName(name)).thenReturn(false);
  4377.         when(departmentRepository.save(department)).thenReturn(department);
  4378.  
  4379.         Assertions.assertEquals(departmentService.save(departmentDTO), departmentDTO);
  4380.  
  4381.         verify(converter).toEntity(departmentDTO);
  4382.         verify(converter).toDTO(department);
  4383.         verify(departmentRepository).existsByName(name);
  4384.         verify(departmentRepository).save(department);
  4385.     }
  4386.  
  4387.     @Test
  4388.     public void shouldThrowExceptionIfDepartmentExists() {
  4389.         String name = "Department name";
  4390.         DepartmentDTO departmentDTO = new DepartmentDTO();
  4391.         departmentDTO.setName(name);
  4392.  
  4393.         when(departmentRepository.existsByName(name)).thenReturn(true);
  4394.  
  4395.         Assertions.assertThrows(DuplicateRecordException.class, () -> departmentService.save(departmentDTO));
  4396.  
  4397.         verify(departmentRepository).existsByName(name);
  4398.     }
  4399.  
  4400.     @Test
  4401.     public void shouldReturnUpdatedDepartmentIfItExistsById() {
  4402.         UUID id = UUID.randomUUID();
  4403.         DepartmentDTO departmentDTO = new DepartmentDTO();
  4404.         departmentDTO.setId(id);
  4405.         Department department = new Department();
  4406.         department.setId(id);
  4407.  
  4408.         when(converter.toEntity(departmentDTO)).thenReturn(department);
  4409.         when(converter.toDTO(department)).thenReturn(departmentDTO);
  4410.         when(departmentRepository.existsById(id)).thenReturn(true);
  4411.         when(departmentRepository.save(department)).thenReturn(department);
  4412.  
  4413.         Assertions.assertEquals(departmentDTO, departmentService.update(departmentDTO));
  4414.  
  4415.         verify(converter).toEntity(departmentDTO);
  4416.         verify(converter).toDTO(department);
  4417.         verify(departmentRepository).existsById(id);
  4418.         verify(departmentRepository).save(department);
  4419.     }
  4420.  
  4421.     @Test
  4422.     public void shouldThrowExceptionIfDepartmentAlreadyExists() {
  4423.         DepartmentDTO departmentDTO = new DepartmentDTO();
  4424.         UUID id = UUID.randomUUID();
  4425.         String name = "Department";
  4426.  
  4427.         departmentDTO.setId(id);
  4428.         departmentDTO.setName(name);
  4429.  
  4430.         when(departmentRepository.existsById(departmentDTO.getId())).thenReturn(false);
  4431.         when(departmentRepository.existsByName(departmentDTO.getName())).thenReturn(true);
  4432.         Assertions.assertThrows(DuplicateRecordException.class,
  4433.                 () -> departmentService.update(departmentDTO));
  4434.  
  4435.         verify(departmentRepository).existsByName(departmentDTO.getName());
  4436.         verify(departmentRepository).existsById(departmentDTO.getId());
  4437.     }
  4438.  
  4439.     @Test
  4440.     public void shouldReturnTrueIfDepartmentExistsById() {
  4441.         when(departmentRepository.existsById(any())).thenReturn(true);
  4442.  
  4443.         Assertions.assertTrue(departmentService.existsById(UUID.randomUUID()));
  4444.  
  4445.         verify(departmentRepository).existsById(any());
  4446.     }
  4447.  
  4448.     @Test
  4449.     public void shouldReturnFalseIfDepartmentExistsById() {
  4450.         when(departmentRepository.existsById(any())).thenReturn(false);
  4451.  
  4452.         Assertions.assertFalse(departmentService.existsById(UUID.randomUUID()));
  4453.  
  4454.         verify(departmentRepository).existsById(any());
  4455.     }
  4456.  
  4457.     @Test
  4458.     public void shouldReturnTrueIfDepartmentExistsByName() {
  4459.         String name = "Department name";
  4460.         when(departmentRepository.existsByName(any())).thenReturn(true);
  4461.  
  4462.         Assertions.assertTrue(departmentService.existsByName(name));
  4463.  
  4464.         verify(departmentRepository).existsByName(any());
  4465.     }
  4466.  
  4467.     @Test
  4468.     public void shouldReturnFalseIfDepartmentExistsByName() {
  4469.         String name = "Department name";
  4470.         when(departmentRepository.existsByName(any())).thenReturn(false);
  4471.  
  4472.         Assertions.assertFalse(departmentService.existsByName(name));
  4473.  
  4474.         verify(departmentRepository).existsByName(any());
  4475.     }
  4476. }
  4477.  
  4478. package com.leverx.employeestat.rest.unit;
  4479.  
  4480. import com.leverx.employeestat.rest.dto.EmployeeDTO;
  4481. import com.leverx.employeestat.rest.dto.converter.EmployeeConverter;
  4482. import com.leverx.employeestat.rest.entity.Employee;
  4483. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  4484. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  4485. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  4486. import com.leverx.employeestat.rest.service.impl.EmployeeServiceImpl;
  4487. import org.junit.jupiter.api.Assertions;
  4488. import org.junit.jupiter.api.Test;
  4489. import org.junit.jupiter.api.extension.ExtendWith;
  4490. import org.mockito.InjectMocks;
  4491. import org.mockito.Mock;
  4492. import org.mockito.junit.jupiter.MockitoExtension;
  4493.  
  4494. import java.util.ArrayList;
  4495. import java.util.Arrays;
  4496. import java.util.Optional;
  4497. import java.util.UUID;
  4498.  
  4499. import static org.mockito.ArgumentMatchers.any;
  4500. import static org.mockito.Mockito.verify;
  4501. import static org.mockito.Mockito.when;
  4502.  
  4503. @ExtendWith(MockitoExtension.class)
  4504. public class EmployeeServiceTest {
  4505.  
  4506.     @Mock
  4507.     private EmployeeRepository employeeRepository;
  4508.  
  4509.     @Mock
  4510.     private EmployeeConverter converter;
  4511.  
  4512.     @InjectMocks
  4513.     private EmployeeServiceImpl employeeService;
  4514.  
  4515.     @Test
  4516.     public void shouldReturnEmployeeIfItExistsById() {
  4517.         UUID id = UUID.randomUUID();
  4518.         Employee employee = new Employee();
  4519.         employee.setId(id);
  4520.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4521.         employeeDTO.setId(id);
  4522.  
  4523.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4524.         when(employeeRepository.findEmployeeById(id)).thenReturn(Optional.of(employee));
  4525.  
  4526.         Assertions.assertNotNull(employeeService.getById(id));
  4527.  
  4528.         verify(converter).toDTO(employee);
  4529.         verify(employeeRepository).findEmployeeById(id);
  4530.     }
  4531.  
  4532.     @Test
  4533.     public void shouldThrowExceptionIfEmployeeDoesNotExistsById() {
  4534.         UUID id = UUID.randomUUID();
  4535.         when(employeeRepository.findEmployeeById(id)).thenReturn(Optional.ofNullable(null));
  4536.  
  4537.         Assertions.assertThrows(NoSuchRecordException.class, () -> employeeService.getById(id));
  4538.  
  4539.         verify(employeeRepository).findEmployeeById(id);
  4540.     }
  4541.  
  4542.     @Test
  4543.     public void shouldReturnEmployeeIfItExistsByUsername() {
  4544.         String name = "employee";
  4545.         Employee employee = new Employee();
  4546.         employee.setUsername(name);
  4547.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4548.         employeeDTO.setUsername(name);
  4549.  
  4550.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4551.         when(employeeRepository.findEmployeeByUsername(name)).thenReturn(Optional.of(employee));
  4552.  
  4553.         Assertions.assertNotNull(employeeService.getByUsername(name));
  4554.  
  4555.         verify(converter).toDTO(employee);
  4556.         verify(employeeRepository).findEmployeeByUsername(name);
  4557.     }
  4558.  
  4559.     @Test
  4560.     public void shouldThrowExceptionIfEmployeeDoesNotExistsByUsername() {
  4561.         String name = "employee";
  4562.         when(employeeRepository.findEmployeeByUsername(name)).thenReturn(Optional.ofNullable(null));
  4563.  
  4564.         Assertions.assertThrows(NoSuchRecordException.class, () -> employeeService.getByUsername(name));
  4565.  
  4566.         verify(employeeRepository).findEmployeeByUsername(name);
  4567.     }
  4568.  
  4569.     @Test
  4570.     public void shouldReturnEmptyListIfDbTableIsEmpty() {
  4571.         when(employeeRepository.findAll()).thenReturn(new ArrayList<Employee>());
  4572.  
  4573.         Assertions.assertTrue(employeeService.getAll().isEmpty());
  4574.  
  4575.         verify(employeeRepository).findAll();
  4576.     }
  4577.  
  4578.     @Test
  4579.     public void shouldReturnNotEmptyListIfRepositoryIsNotEmpty() {
  4580.         when(employeeRepository.findAll()).thenReturn(Arrays.asList(new Employee(), new Employee()));
  4581.  
  4582.         Assertions.assertFalse(employeeService.getAll().isEmpty());
  4583.  
  4584.         verify(employeeRepository).findAll();
  4585.     }
  4586.  
  4587.     @Test
  4588.     public void shouldReturnSavedEmployeeIfEmployeeDoesNotExists() {
  4589.         String name = "Employee name";
  4590.         Employee employee = new Employee();
  4591.         employee.setUsername(name);
  4592.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4593.         employeeDTO.setUsername(name);
  4594.  
  4595.         when(converter.toEntity(employeeDTO)).thenReturn(employee);
  4596.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4597.         when(employeeRepository.existsByUsername(name)).thenReturn(false);
  4598.         when(employeeRepository.save(employee)).thenReturn(employee);
  4599.  
  4600.         Assertions.assertEquals(employeeService.save(employeeDTO), employeeDTO);
  4601.  
  4602.         verify(converter).toEntity(employeeDTO);
  4603.         verify(converter).toDTO(employee);
  4604.         verify(employeeRepository).existsByUsername(name);
  4605.         verify(employeeRepository).save(employee);
  4606.     }
  4607.  
  4608.     @Test
  4609.     public void shouldThrowExceptionIfEmployeeExists() {
  4610.         String name = "Employee name";
  4611.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4612.         employeeDTO.setUsername(name);
  4613.  
  4614.         when(employeeRepository.existsByUsername(name)).thenReturn(true);
  4615.  
  4616.         Assertions.assertThrows(DuplicateRecordException.class, () -> employeeService.save(employeeDTO));
  4617.  
  4618.         verify(employeeRepository).existsByUsername(name);
  4619.     }
  4620.  
  4621.     @Test
  4622.     public void shouldReturnUpdatedEmployeeIfItExistsById() {
  4623.         UUID id = UUID.randomUUID();
  4624.         Employee employee = new Employee();
  4625.         employee.setId(id);
  4626.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4627.         employeeDTO.setId(id);
  4628.  
  4629.         when(converter.toDTO(employee)).thenReturn(employeeDTO);
  4630.         when(employeeRepository.findEmployeeById(employeeDTO.getId())).thenReturn(Optional.of(employee));
  4631.  
  4632.         Assertions.assertEquals(employeeDTO, employeeService.update(employeeDTO));
  4633.  
  4634.         verify(converter).toDTO(employee);
  4635.         verify(employeeRepository).findEmployeeById(employeeDTO.getId());
  4636.     }
  4637.  
  4638.     @Test
  4639.     public void shouldThrowExceptionIfEmployeeNotFound() {
  4640.         EmployeeDTO employeeDTO = new EmployeeDTO();
  4641.         employeeDTO.setId(UUID.randomUUID());
  4642.         employeeDTO.setUsername("Username");
  4643.  
  4644.         when(employeeRepository.findEmployeeById(employeeDTO.getId())).thenReturn(Optional.ofNullable(null));
  4645.  
  4646.         Assertions.assertThrows(NoSuchRecordException.class, () -> employeeService.update(employeeDTO));
  4647.  
  4648.         verify(employeeRepository).findEmployeeById(employeeDTO.getId());
  4649.     }
  4650.  
  4651.     @Test
  4652.     public void shouldReturnTrueIfEmployeeExistsById() {
  4653.         when(employeeRepository.existsById(any())).thenReturn(true);
  4654.  
  4655.         Assertions.assertTrue(employeeService.existsById(UUID.randomUUID()));
  4656.  
  4657.         verify(employeeRepository).existsById(any());
  4658.     }
  4659.  
  4660.     @Test
  4661.     public void shouldReturnFalseIfEmployeeExistsById() {
  4662.         when(employeeRepository.existsById(any())).thenReturn(false);
  4663.  
  4664.         Assertions.assertFalse(employeeService.existsById(UUID.randomUUID()));
  4665.  
  4666.         verify(employeeRepository).existsById(any());
  4667.     }
  4668. }
  4669.  
  4670. package com.leverx.employeestat.rest.unit;
  4671.  
  4672. import com.leverx.employeestat.rest.dto.ProjectDTO;
  4673. import com.leverx.employeestat.rest.dto.converter.ProjectConverter;
  4674. import com.leverx.employeestat.rest.entity.Project;
  4675. import com.leverx.employeestat.rest.exception.DuplicateRecordException;
  4676. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  4677. import com.leverx.employeestat.rest.repository.ProjectRepository;
  4678. import com.leverx.employeestat.rest.service.impl.ProjectServiceImpl;
  4679. import org.junit.jupiter.api.Assertions;
  4680. import org.junit.jupiter.api.Test;
  4681. import org.junit.jupiter.api.extension.ExtendWith;
  4682. import org.mockito.InjectMocks;
  4683. import org.mockito.Mock;
  4684. import org.mockito.Mockito;
  4685. import org.mockito.junit.jupiter.MockitoExtension;
  4686.  
  4687. import java.util.*;
  4688.  
  4689. import static org.mockito.ArgumentMatchers.any;
  4690. import static org.mockito.Mockito.verify;
  4691. import static org.mockito.Mockito.when;
  4692.  
  4693. @ExtendWith(MockitoExtension.class)
  4694. public class ProjectServiceTest {
  4695.  
  4696.     @Mock
  4697.     private ProjectRepository projectRepository;
  4698.  
  4699.     @Mock
  4700.     private ProjectConverter converter;
  4701.  
  4702.     @InjectMocks
  4703.     private ProjectServiceImpl projectService;
  4704.  
  4705.     @Test
  4706.     public void shouldReturnProjectIfItExistsById() {
  4707.         UUID id = UUID.randomUUID();
  4708.         Project project = new Project();
  4709.         ProjectDTO projectDTO = new ProjectDTO();
  4710.  
  4711.         when(converter.toDTO(project)).thenReturn(projectDTO);
  4712.         when(projectRepository.findProjectById(id)).thenReturn(Optional.of(project));
  4713.  
  4714.         Assertions.assertNotNull(projectService.getById(id));
  4715.  
  4716.         verify(converter).toDTO(project);
  4717.         verify(projectRepository).findProjectById(id);
  4718.     }
  4719.  
  4720.     @Test
  4721.     public void shouldThrowExceptionIfProjectDoesNotExistsById() {
  4722.         UUID id = UUID.randomUUID();
  4723.         when(projectRepository.findProjectById(id)).thenReturn(Optional.ofNullable(null));
  4724.  
  4725.         Assertions.assertThrows(NoSuchRecordException.class, () -> projectService.getById(id));
  4726.  
  4727.         verify(projectRepository).findProjectById(id);
  4728.     }
  4729.  
  4730.     @Test
  4731.     public void shouldReturnProjectIfItExistsByName() {
  4732.         String name = "project";
  4733.         Project project = new Project();
  4734.         ProjectDTO projectDTO = new ProjectDTO();
  4735.         project.setName(name);
  4736.         projectDTO.setName(name);
  4737.  
  4738.         when(converter.toDTO(project)).thenReturn(projectDTO);
  4739.         when(projectRepository.findProjectByName(name)).thenReturn(Optional.of(project));
  4740.  
  4741.         Assertions.assertNotNull(projectService.getByName(name));
  4742.  
  4743.         verify(converter).toDTO(project);
  4744.         verify(projectRepository).findProjectByName(name);
  4745.     }
  4746.  
  4747.     @Test
  4748.     public void shouldThrowExceptionIfProjectDoesNotExistsByName() {
  4749.         String name = "project";
  4750.  
  4751.         when(projectRepository.findProjectByName(name)).thenReturn(Optional.ofNullable(null));
  4752.  
  4753.         Assertions.assertThrows(NoSuchRecordException.class, () -> projectService.getByName(name));
  4754.  
  4755.         verify(projectRepository).findProjectByName(name);
  4756.     }
  4757.  
  4758.     @Test
  4759.     public void shouldReturnEmptyListIfDbTableIsEmpty() {
  4760.         when(projectRepository.findAll()).thenReturn(new ArrayList<Project>());
  4761.  
  4762.         Assertions.assertTrue(projectService.getAll().isEmpty());
  4763.  
  4764.         verify(projectRepository).findAll();
  4765.     }
  4766.  
  4767.     @Test
  4768.     public void shouldReturnNotEmptyListIfDbTableIsNotEmpty() {
  4769.         when(projectRepository.findAll()).thenReturn(Arrays.asList( new Project[] {new Project(), new Project()}));
  4770.  
  4771.         Assertions.assertFalse(projectService.getAll().isEmpty());
  4772.  
  4773.         verify(projectRepository).findAll();
  4774.     }
  4775.  
  4776.     @Test
  4777.     public void shouldReturnSavedProjectIfProjectDoesNotExists() {
  4778.         String name = "Project name";
  4779.         Project project = new Project();
  4780.         project.setName(name);
  4781.         ProjectDTO projectDTO = new ProjectDTO();
  4782.         projectDTO.setName(name);
  4783.  
  4784.         when(converter.toEntity(projectDTO)).thenReturn(project);
  4785.         when(converter.toDTO(project)).thenReturn(projectDTO);
  4786.         when(projectRepository.existsByName(name)).thenReturn(false);
  4787.         when(projectRepository.save(project)).thenReturn(project);
  4788.  
  4789.         Assertions.assertEquals(projectService.save(projectDTO), projectDTO);
  4790.  
  4791.         verify(converter).toEntity(projectDTO);
  4792.         verify(converter).toDTO(project);
  4793.         verify(projectRepository).existsByName(name);
  4794.         verify(projectRepository).save(project);
  4795.     }
  4796.  
  4797.     @Test
  4798.     public void shouldThrowExceptionIfProjectExists() {
  4799.         String name = "Project name";
  4800.         ProjectDTO projectDTO = new ProjectDTO();
  4801.         projectDTO.setName(name);
  4802.  
  4803.         when(projectRepository.existsByName(name)).thenReturn(true);
  4804.  
  4805.         Assertions.assertThrows(DuplicateRecordException.class, () -> projectService.save(projectDTO));
  4806.  
  4807.         verify(projectRepository).existsByName(name);
  4808.     }
  4809.  
  4810.     @Test
  4811.     public void shouldReturnUpdatedProjectIfItExistsById() {
  4812.         UUID id = UUID.randomUUID();
  4813.         Project project = new Project();
  4814.         project.setId(id);
  4815.         ProjectDTO projectDTO = new ProjectDTO();
  4816.         projectDTO.setId(id);
  4817.  
  4818.         when(converter.toEntity(projectDTO)).thenReturn(project);
  4819.         when(converter.toDTO(project)).thenReturn(projectDTO);
  4820.         when(projectRepository.existsById(id)).thenReturn(true);
  4821.         when(projectRepository.save(project)).thenReturn(project);
  4822.  
  4823.         Assertions.assertEquals(projectDTO, projectService.update(projectDTO));
  4824.  
  4825.         verify(converter).toEntity(projectDTO);
  4826.         verify(converter).toDTO(project);
  4827.         verify(projectRepository).existsById(id);
  4828.         verify(projectRepository).save(project);
  4829.     }
  4830.  
  4831.     @Test
  4832.     public void shouldThrowExceptionIfProjectAlreadyExists() {
  4833.         ProjectDTO projectDTO = new ProjectDTO();
  4834.         projectDTO.setId(UUID.randomUUID());
  4835.         projectDTO.setName("Project");
  4836.  
  4837.         when(projectRepository.existsById(projectDTO.getId())).thenReturn(false);
  4838.         when(projectRepository.existsByName(projectDTO.getName())).thenReturn(true);
  4839.  
  4840.         Assertions.assertThrows(DuplicateRecordException.class, () -> projectService.update(projectDTO));
  4841.  
  4842.         verify(projectRepository).existsById(projectDTO.getId());
  4843.         verify(projectRepository).existsByName(projectDTO.getName());
  4844.     }
  4845.  
  4846.     @Test
  4847.     public void shouldReturnTrueIfProjectExistsById() {
  4848.         when(projectRepository.existsById(any())).thenReturn(true);
  4849.  
  4850.         Assertions.assertTrue(projectService.existsById(UUID.randomUUID()));
  4851.  
  4852.         verify(projectRepository).existsById(any());
  4853.     }
  4854.  
  4855.     @Test
  4856.     public void shouldReturnFalseIfProjectExistsById() {
  4857.         when(projectRepository.existsById(any())).thenReturn(false);
  4858.  
  4859.         Assertions.assertFalse(projectService.existsById(UUID.randomUUID()));
  4860.  
  4861.         verify(projectRepository).existsById(any());
  4862.     }
  4863.  
  4864.     @Test
  4865.     public void shouldReturnTrueIfProjectExistsByName() {
  4866.         String name = "Project name";
  4867.         when(projectRepository.existsByName(any())).thenReturn(true);
  4868.  
  4869.         Assertions.assertTrue(projectService.existsByName(name));
  4870.  
  4871.         verify(projectRepository).existsByName(any());
  4872.     }
  4873.  
  4874.     @Test
  4875.     public void shouldReturnFalseIfProjectExistsByName() {
  4876.         String name = "Project name";
  4877.         when(projectRepository.existsByName(any())).thenReturn(false);
  4878.  
  4879.         Assertions.assertFalse(projectService.existsByName(name));
  4880.  
  4881.         verify(projectRepository).existsByName(any());
  4882.     }
  4883. }
  4884.  
  4885. package com.leverx.employeestat.rest.unit;
  4886.  
  4887. import com.leverx.employeestat.rest.dto.WorkDTO;
  4888. import com.leverx.employeestat.rest.dto.converter.WorkConverter;
  4889. import com.leverx.employeestat.rest.entity.Employee;
  4890. import com.leverx.employeestat.rest.entity.Project;
  4891. import com.leverx.employeestat.rest.entity.Work;
  4892. import com.leverx.employeestat.rest.entity.WorkId;
  4893. import com.leverx.employeestat.rest.exception.NoSuchRecordException;
  4894. import com.leverx.employeestat.rest.repository.EmployeeRepository;
  4895. import com.leverx.employeestat.rest.repository.ProjectRepository;
  4896. import com.leverx.employeestat.rest.repository.WorkRepository;
  4897. import com.leverx.employeestat.rest.service.impl.WorkServiceImpl;
  4898. import org.junit.jupiter.api.BeforeEach;
  4899. import org.junit.jupiter.api.Test;
  4900. import org.junit.jupiter.api.extension.ExtendWith;
  4901. import org.mockito.InjectMocks;
  4902. import org.mockito.Mock;
  4903. import org.mockito.junit.jupiter.MockitoExtension;
  4904.  
  4905. import java.time.LocalDate;
  4906. import java.util.*;
  4907.  
  4908. import static org.junit.jupiter.api.Assertions.*;
  4909. import static org.mockito.Mockito.*;
  4910.  
  4911. @ExtendWith(MockitoExtension.class)
  4912. public class WorkServiceTest {
  4913.  
  4914.     @Mock
  4915.     private WorkRepository workRepository;
  4916.  
  4917.     @Mock
  4918.     private EmployeeRepository employeeRepository;
  4919.  
  4920.     @Mock
  4921.     private ProjectRepository projectRepository;
  4922.  
  4923.     @Mock
  4924.     private WorkConverter converter;
  4925.  
  4926.     @InjectMocks
  4927.     private WorkServiceImpl workService;
  4928.  
  4929.     private WorkDTO workDTO;
  4930.     private Work work;
  4931.     private WorkId workId;
  4932.     private Employee employee;
  4933.     private Project project;
  4934.  
  4935.     @BeforeEach
  4936.     public void init() {
  4937.         workDTO = new WorkDTO();
  4938.         work = new Work();
  4939.         workId = new WorkId();
  4940.         employee = new Employee();
  4941.         project = new Project();
  4942.  
  4943.         UUID empId = UUID.randomUUID();
  4944.         UUID projId = UUID.randomUUID();
  4945.         employee.setId(empId);
  4946.         project.setId(projId);
  4947.  
  4948.         workId.setEmployee(employee);
  4949.         workId.setProject(project);
  4950.  
  4951.         workDTO.setEmployeeId(empId);
  4952.         workDTO.setProjectId(projId);
  4953.     }
  4954.  
  4955.     @Test
  4956.     public void shouldReturnNotEmptyListOfWorksIfRepositoryIsNotEmptyWhenGetAll() {
  4957.         final int expectedSize = 3;
  4958.  
  4959.         when(workRepository.findAll()).thenReturn(Arrays.asList(work, work, work));
  4960.         when(converter.toDTO(work)).thenReturn(workDTO);
  4961.  
  4962.         List<WorkDTO> actualList = workService.getAll();
  4963.         assertFalse(actualList.isEmpty());
  4964.         assertEquals(expectedSize, actualList.size());
  4965.         assertSame(actualList.get(0).getClass(), WorkDTO.class);
  4966.  
  4967.         verify(workRepository).findAll();
  4968.         verify(converter, times(expectedSize)).toDTO(work);
  4969.     }
  4970.  
  4971.     @Test
  4972.     public void shouldReturnEmptyListOfWorksIfRepositoryIsEmptyWhenGetAll() {
  4973.         when(workRepository.findAll()).thenReturn(new ArrayList<>());
  4974.  
  4975.         List<WorkDTO> actualList = workService.getAll();
  4976.         assertTrue(actualList.isEmpty());
  4977.  
  4978.         verify(workRepository).findAll();
  4979.     }
  4980.  
  4981.     @Test
  4982.     public void shouldReturnWorkByIdsIfTheyExistInRepositoryWhenGetByIds() {
  4983.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  4984.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.of(project));
  4985.         when(workRepository.findWorkById(workId)).thenReturn(Optional.of(work));
  4986.         when(converter.toDTO(work)).thenReturn(workDTO);
  4987.  
  4988.         assertSame(WorkDTO.class, workService.getByIds(employee.getId(), project.getId()).getClass());
  4989.         assertDoesNotThrow(() -> workService.getByIds(employee.getId(), project.getId()));
  4990.  
  4991.         verify(employeeRepository, times(2)).findEmployeeById(employee.getId());
  4992.         verify(projectRepository, times(2)).findProjectById(project.getId());
  4993.         verify(workRepository, times(2)).findWorkById(workId);
  4994.         verify(converter, times(2)).toDTO(work);
  4995.     }
  4996.  
  4997.     @Test
  4998.     public void shouldThrowExceptionIfEmployeeDoesNotExistByEmployeeIdWhenGetByIds() {
  4999.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.ofNullable(null));
  5000.  
  5001.         assertThrows(NoSuchRecordException.class, () -> workService.getByIds(employee.getId(), project.getId()));
  5002.  
  5003.         verify(employeeRepository).findEmployeeById(employee.getId());
  5004.     }
  5005.  
  5006.     @Test
  5007.     public void shouldThrowExceptionIfProjectDoesNotExistByProjectIdWhenGetByIds() {
  5008.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5009.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.ofNullable(null));
  5010.  
  5011.         assertThrows(NoSuchRecordException.class, () -> workService.getByIds(employee.getId(), project.getId()));
  5012.  
  5013.         verify(employeeRepository).findEmployeeById(employee.getId());
  5014.         verify(projectRepository).findProjectById(project.getId());
  5015.     }
  5016.  
  5017.     @Test
  5018.     public void shouldThrowExceptionIfWorkDoesNotExistByWorkIdWhenGetByIds() {
  5019.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5020.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.of(project));
  5021.         when(workRepository.findWorkById(workId)).thenReturn(Optional.ofNullable(null));
  5022.  
  5023.         assertThrows(NoSuchRecordException.class, () -> workService.getByIds(employee.getId(), project.getId()));
  5024.  
  5025.         verify(employeeRepository).findEmployeeById(employee.getId());
  5026.         verify(projectRepository).findProjectById(project.getId());
  5027.         verify(workRepository).findWorkById(workId);
  5028.     }
  5029.  
  5030.     @Test
  5031.     public void shouldUpdateWorkIfItExistsByIdWhenUpdate() {
  5032.         final int expectedWorkingHours = 3;
  5033.         final LocalDate expectedPositionStartDate = LocalDate.of(2021, 1, 1);
  5034.         final LocalDate expectedPositionEndDate = LocalDate.of(2022, 1, 1);
  5035.  
  5036.         workDTO.setWorkingHours(3);
  5037.         workDTO.setPositionStartDate(expectedPositionStartDate);
  5038.         workDTO.setPositionEndDate(expectedPositionEndDate);
  5039.  
  5040.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5041.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.of(project));
  5042.         when(workRepository.findWorkById(workId)).thenReturn(Optional.of(work));
  5043.         when(converter.toDTO(work)).thenReturn(workDTO);
  5044.  
  5045.         WorkDTO actual =  workService.update(workDTO);
  5046.  
  5047.         assertSame(WorkDTO.class, actual.getClass());
  5048.         assertDoesNotThrow(() -> workService.update(workDTO));
  5049.         assertEquals(expectedWorkingHours, actual.getWorkingHours());
  5050.         assertEquals(expectedPositionStartDate, actual.getPositionStartDate());
  5051.         assertEquals(expectedPositionEndDate, actual.getPositionEndDate());
  5052.  
  5053.         verify(employeeRepository, times(2)).findEmployeeById(employee.getId());
  5054.         verify(projectRepository, times(2)).findProjectById(project.getId());
  5055.         verify(workRepository, times(2)).findWorkById(workId);
  5056.         verify(converter, times(2)).toDTO(work);
  5057.     }
  5058.  
  5059.     @Test
  5060.     public void shouldThrowExceptionIfEmployeeDoesNotExistByEmployeeIdWhenUpdate() {
  5061.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.ofNullable(null));
  5062.  
  5063.         assertThrows(NoSuchRecordException.class, () -> workService.update(workDTO));
  5064.  
  5065.         verify(employeeRepository).findEmployeeById(employee.getId());
  5066.     }
  5067.  
  5068.     @Test
  5069.     public void shouldThrowExceptionIfProjectDoesNotExistByProjectIdWhenUpdate() {
  5070.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5071.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.ofNullable(null));
  5072.  
  5073.         assertThrows(NoSuchRecordException.class, () -> workService.update(workDTO));
  5074.  
  5075.         verify(employeeRepository).findEmployeeById(employee.getId());
  5076.         verify(projectRepository).findProjectById(project.getId());
  5077.     }
  5078.  
  5079.     @Test
  5080.     public void shouldThrowExceptionIfWorkDoesNotExistByWorkIdWhenUpdate() {
  5081.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5082.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.of(project));
  5083.         when(workRepository.findWorkById(workId)).thenReturn(Optional.ofNullable(null));
  5084.  
  5085.         assertThrows(NoSuchRecordException.class, () -> workService.update(workDTO));
  5086.  
  5087.         verify(employeeRepository).findEmployeeById(employee.getId());
  5088.         verify(projectRepository).findProjectById(project.getId());
  5089.         verify(workRepository).findWorkById(workId);
  5090.     }
  5091.  
  5092.     @Test
  5093.     public void shouldThrowExceptionIfEmployeeDoesNotExistByEmployeeIdWhenDeleteByIds() {
  5094.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.ofNullable(null));
  5095.  
  5096.         assertThrows(NoSuchRecordException.class, () -> workService.deleteByIds(employee.getId(), project.getId()));
  5097.  
  5098.         verify(employeeRepository).findEmployeeById(employee.getId());
  5099.     }
  5100.  
  5101.     @Test
  5102.     public void shouldThrowExceptionIfProjectDoesNotExistByProjectIdWhenDeleteByIds() {
  5103.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5104.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.ofNullable(null));
  5105.  
  5106.         assertThrows(NoSuchRecordException.class, () -> workService.deleteByIds(employee.getId(), project.getId()));
  5107.  
  5108.         verify(employeeRepository).findEmployeeById(employee.getId());
  5109.         verify(projectRepository).findProjectById(project.getId());
  5110.     }
  5111.  
  5112.     @Test
  5113.     public void shouldThrowExceptionIfWorkDoesNotExistByWorkIdWhenDeleteByIds() {
  5114.         when(employeeRepository.findEmployeeById(employee.getId())).thenReturn(Optional.of(employee));
  5115.         when(projectRepository.findProjectById(project.getId())).thenReturn(Optional.of(project));
  5116.         when(workRepository.existsById(workId)).thenReturn(false);
  5117.  
  5118.         assertThrows(NoSuchRecordException.class, () -> workService.deleteByIds(employee.getId(), project.getId()));
  5119.  
  5120.         verify(employeeRepository).findEmployeeById(employee.getId());
  5121.         verify(projectRepository).findProjectById(project.getId());
  5122.         verify(workRepository).existsById(workId);
  5123.     }
  5124.  
  5125. }
  5126.  
  5127. ------------------
  5128. RESOURCES
  5129. ------------------
  5130.  
  5131.  
  5132. <databaseChangeLog
  5133.         xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  5134.         xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
  5135.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5136.         xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
  5137.   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
  5138.   http://www.liquibase.org/xml/ns/dbchangelog
  5139.   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
  5140.    
  5141.     <preConditions>
  5142.         <dbms type="postgresql"/>
  5143.     </preConditions>
  5144.  
  5145.     <changeSet id="4" author="Ivan">
  5146. <!--        <sqlFile dbms="postgresql"-->
  5147. <!--                 encoding="UTF-8"-->
  5148. <!--                 relativeToChangelogFile="true"-->
  5149. <!--                 splitStatements="true"-->
  5150. <!--                 stripComments="true"-->
  5151. <!--                 path="sql-scripts/create-db.sql"/>-->
  5152.  
  5153.         <sql dbms="postgresql" endDelimiter=";">CREATE SCHEMA employee_db_test</sql>
  5154.         <sqlFile dbms="postgresql"
  5155.                  encoding="UTF-8"
  5156.                  relativeToChangelogFile="true"
  5157.                  splitStatements="true"
  5158.                  stripComments="true"
  5159.                  path="sql-scripts/create-department-table.sql"/>
  5160.         <sqlFile dbms="postgresql"
  5161.                  encoding="UTF-8"
  5162.                  relativeToChangelogFile="true"
  5163.                  splitStatements="true"
  5164.                  stripComments="true"
  5165.                  path="sql-scripts/create-project-table.sql"/>
  5166.         <sqlFile dbms="postgresql"
  5167.                  encoding="UTF-8"
  5168.                  relativeToChangelogFile="true"
  5169.                  splitStatements="true"
  5170.                  stripComments="true"
  5171.                  path="sql-scripts/create-role-table.sql"/>
  5172.         <sqlFile dbms="postgresql"
  5173.                  encoding="UTF-8"
  5174.                  relativeToChangelogFile="true"
  5175.                  splitStatements="true"
  5176.                  stripComments="true"
  5177.                  path="sql-scripts/create-employee-table.sql"/>
  5178.         <sqlFile dbms="postgresql"
  5179.                  encoding="UTF-8"
  5180.                  relativeToChangelogFile="true"
  5181.                  splitStatements="true"
  5182.                  stripComments="true"
  5183.                  path="sql-scripts/create-project_employee-table.sql"/>
  5184.         <sqlFile dbms="postgresql"
  5185.                  encoding="UTF-8"
  5186.                  endDelimiter="\n"
  5187.                  relativeToChangelogFile="true"
  5188.                  splitStatements="true"
  5189.                  stripComments="true"
  5190.                  path="sql-scripts/insert-roles.sql"/>
  5191.     </changeSet>
  5192. </databaseChangeLog>
  5193.  
  5194. <databaseChangeLog
  5195.         xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  5196.         xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
  5197.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5198.         xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
  5199.   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
  5200.   http://www.liquibase.org/xml/ns/dbchangelog
  5201.   http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
  5202.  
  5203.     <preConditions>
  5204.         <dbms type="postgresql"/>
  5205.     </preConditions>
  5206.  
  5207.     <changeSet id="6" author="Ivan">
  5208.         <preConditions onFail="MARK_RAN">
  5209.             <and>
  5210.                 <tableExists tableName="department"/>
  5211.                 <tableExists tableName="employee"/>
  5212.                 <tableExists tableName="project"/>
  5213.                 <tableExists tableName="project_employee"/>
  5214.                 <tableExists tableName="role"/>
  5215.             </and>
  5216.         </preConditions>
  5217.         <sqlFile dbms="postgresql"
  5218.                  encoding="UTF-8"
  5219.                  endDelimiter=";"
  5220.                  relativeToChangelogFile="true"
  5221.                  splitStatements="true"
  5222.                  stripComments="true"
  5223.                  path="sql-scripts/drop-tables.sql"/>
  5224.     </changeSet>
  5225.  
  5226.     <changeSet id="4" author="Ivan">
  5227.         <sqlFile dbms="postgresql"
  5228.                  encoding="UTF-8"
  5229.                  relativeToChangelogFile="true"
  5230.                  splitStatements="true"
  5231.                  stripComments="true"
  5232.                  path="sql-scripts/create-department-table.sql"/>
  5233.         <sqlFile dbms="postgresql"
  5234.                  encoding="UTF-8"
  5235.                  relativeToChangelogFile="true"
  5236.                  splitStatements="true"
  5237.                  stripComments="true"
  5238.                  path="sql-scripts/create-project-table.sql"/>
  5239.         <sqlFile dbms="postgresql"
  5240.                  encoding="UTF-8"
  5241.                  relativeToChangelogFile="true"
  5242.                  splitStatements="true"
  5243.                  stripComments="true"
  5244.                  path="sql-scripts/create-role-table.sql"/>
  5245.         <sqlFile dbms="postgresql"
  5246.                  encoding="UTF-8"
  5247.                  relativeToChangelogFile="true"
  5248.                  splitStatements="true"
  5249.                  stripComments="true"
  5250.                  path="sql-scripts/create-employee-table.sql"/>
  5251.         <sqlFile dbms="postgresql"
  5252.                  encoding="UTF-8"
  5253.                  relativeToChangelogFile="true"
  5254.                  splitStatements="true"
  5255.                  stripComments="true"
  5256.                  path="sql-scripts/create-project_employee-table.sql"/>
  5257.  
  5258.         <sqlFile dbms="postgresql"
  5259.                  encoding="UTF-8"
  5260.                  endDelimiter="\n"
  5261.                  relativeToChangelogFile="true"
  5262.                  splitStatements="true"
  5263.                  stripComments="true"
  5264.                  path="sql-scripts/init-role-table.sql"/>
  5265.         <sqlFile dbms="postgresql"
  5266.                  encoding="UTF-8"
  5267.                  endDelimiter="\n"
  5268.                  relativeToChangelogFile="true"
  5269.                  splitStatements="true"
  5270.                  stripComments="true"
  5271.                  path="sql-scripts/init-department-table.sql"/>
  5272.         <sqlFile dbms="postgresql"
  5273.                  encoding="UTF-8"
  5274.                  endDelimiter="\n"
  5275.                  relativeToChangelogFile="true"
  5276.                  splitStatements="true"
  5277.                  stripComments="true"
  5278.                  path="sql-scripts/init-project-table.sql"/>
  5279.         <sqlFile dbms="postgresql"
  5280.                  encoding="UTF-8"
  5281.                  endDelimiter="\n"
  5282.                  relativeToChangelogFile="true"
  5283.                  splitStatements="true"
  5284.                  stripComments="true"
  5285.                  path="sql-scripts/init-employee-table.sql"/>
  5286.     </changeSet>
  5287.     <changeSet id="5" author="Ivan">
  5288.         <sqlFile dbms="postgresql"
  5289.                  encoding="UTF-8"
  5290.                  endDelimiter=";"
  5291.                  relativeToChangelogFile="true"
  5292.                  splitStatements="true"
  5293.                  stripComments="true"
  5294.                  path="sql-scripts/init-project_employee-table.sql"/>
  5295.     </changeSet>
  5296. </databaseChangeLog>
  5297.  
  5298. SQL
  5299. create database employee_db_test;
  5300.  
  5301. create table department (
  5302.       id uuid primary key unique not null,
  5303.       name varchar(64) not null
  5304. )
  5305.  
  5306. create table employee (
  5307.     id uuid primary key unique not null,
  5308.     first_name varchar(32) not null,
  5309.     last_name varchar(32) not null,
  5310.     username varchar(32) not null,
  5311.     password varchar(256) not null,
  5312.     position varchar(32) not null,
  5313.     role_id uuid not null,
  5314.     department_id uuid,
  5315.     foreign key (role_id) references "role" (id),
  5316.     foreign key (department_id) references department (id)
  5317. )
  5318.  
  5319. create table project (
  5320.     id uuid primary key unique not null,
  5321.     name varchar(64) not null,
  5322.     begin_date date not null,
  5323.     end_date date not null
  5324. )
  5325.  
  5326. create table project_employee (
  5327.     employee_id uuid not null,
  5328.     project_id uuid not null,
  5329.     position_start_date date,
  5330.     position_end_date date,
  5331.     working_hours int,
  5332.     primary key (employee_id, project_id),
  5333.     foreign key (employee_id) references employee (id),
  5334.     foreign key (project_id) references project (id)
  5335. )
  5336.  
  5337. create table role (
  5338.     id uuid primary key unique not null,
  5339.     name varchar(16) not null
  5340. )
  5341.  
  5342. drop table employee cascade;
  5343. drop table department cascade;
  5344. drop table project cascade;
  5345. drop table role cascade;
  5346. drop table project_employee cascade;
  5347.  
  5348. insert into department (id, name) values ('7bb734c1-c5c6-436f-8b28-ca9ccfc474d5', 'Web-development');
  5349. insert into department (id, name) values ('da8f36e3-f2b1-4ee8-a8c1-9fbcb9cfe4bd', 'Mobile-development');
  5350. insert into department (id, name) values ('edf939d2-dbc2-4473-80a1-4bb3826e666e', 'HR');
  5351. insert into department (id, name) values ('46e3f891-4a03-4133-8ba4-760849a947bb', 'Game-development');
  5352.  
  5353. insert into employee (id, first_name, last_name, username, password, position, role_id, department_id)
  5354.     values ('c7fa1cd3-b281-47b1-b72f-92b9391fc5c7', 'Ivan', 'Shestakov', 'Vanechka', 'test', 'Java Developer', 'c7e1b538-92a1-414e-85e7-7d90b9d2d861', '7bb734c1-c5c6-436f-8b28-ca9ccfc474d5');
  5355.  
  5356. insert into employee (id, first_name, last_name, username, password, position, role_id, department_id)
  5357.     values ('e9a4e12b-1555-48bd-9275-629856bcdb51', 'Artiom', 'Ivanov', 'Tema', 'test', 'Dev', 'c7e1b538-92a1-414e-85e7-7d90b9d2d861', 'da8f36e3-f2b1-4ee8-a8c1-9fbcb9cfe4bd');
  5358.  
  5359. insert into employee (id, first_name, last_name, username, password, position, role_id, department_id)
  5360.     values ('2174c05c-e885-4521-985d-774b1f05cd37', 'Vlad', 'Vladov', 'Turbo3000', 'test', 'HR', 'a8727b4b-d91d-4e42-bd83-13261ae7bd64', 'edf939d2-dbc2-4473-80a1-4bb3826e666e');
  5361.  
  5362. insert into project (id, name, begin_date, end_date)
  5363.     values ('7c8697b8-530d-4a00-ba00-3dfec6b1bb79', 'Bank system', to_date('2020-10-08', 'YYYY-MM-DD'), to_date('2020-12-16', 'YYYY-MM-DD'));
  5364.  
  5365. insert into project (id, name, begin_date, end_date)
  5366.     values ('507eeff6-3563-4a43-99c8-b1706d6b17cd', 'Online shop', to_date('2018-11-09', 'YYYY-MM-DD'), to_date('2021-10-16', 'YYYY-MM-DD'));
  5367.  
  5368. insert into project (id, name, begin_date, end_date)
  5369.     values ('6f6bd93b-fcdd-4c3f-a144-1e03139559d6', 'Employees service', to_date('2019-05-18', 'YYYY-MM-DD'), to_date('2021-11-25', 'YYYY-MM-DD'));
  5370.  
  5371. insert into project_employee (employee_id, project_id, position_start_date, position_end_date, working_hours)
  5372. values ('c7fa1cd3-b281-47b1-b72f-92b9391fc5c7',
  5373.         '7c8697b8-530d-4a00-ba00-3dfec6b1bb79',
  5374.         to_date('2021-01-01', 'YYYY-MM-DD'),
  5375.         to_date('2021-06-01', 'YYYY-MM-DD'),
  5376.         8);
  5377.  
  5378. insert into project_employee (employee_id, project_id, position_start_date, position_end_date, working_hours)
  5379. values ('e9a4e12b-1555-48bd-9275-629856bcdb51',
  5380.         '7c8697b8-530d-4a00-ba00-3dfec6b1bb79',
  5381.         to_date('2021-02-01', 'YYYY-MM-DD'),
  5382.         to_date('2021-08-01', 'YYYY-MM-DD'),
  5383.         6);
  5384.  
  5385. insert into project_employee (employee_id, project_id, position_start_date, position_end_date, working_hours)
  5386. values ('2174c05c-e885-4521-985d-774b1f05cd37',
  5387.         '6f6bd93b-fcdd-4c3f-a144-1e03139559d6',
  5388.         to_date('2020-01-01', 'YYYY-MM-DD'),
  5389.         to_date('2020-04-01', 'YYYY-MM-DD'),
  5390.         8);
  5391.  
  5392. insert into role (id, name) values ('a8727b4b-d91d-4e42-bd83-13261ae7bd64', 'ROLE_EMPLOYEE');
  5393. insert into role (id, name) values ('c7e1b538-92a1-414e-85e7-7d90b9d2d861', 'ROLE_MANAGER');
  5394.  
  5395. CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  5396. insert into role (id, name) values (uuid_generate_v4(), 'ROLE_EMPLOYEE');
  5397. insert into role (id, name) values (uuid_generate_v4(), 'ROLE_MANAGER');
  5398.  
  5399. PROPERTIES
  5400.  
  5401. driverClass=org.postgresql.Driver
  5402. jdbcUrl=${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/employee_db_liquibase}
  5403. testUrl=jdbc:postgresql://localhost:5432/test_db?useSSL=false&amp
  5404. dbuser=${SPRING_DATASOURCE_USERNAME:postgres}
  5405. password=${SPRING_DATASOURCE_PASSWORD:postgres}
  5406.  
  5407. packagesToScan=com.leverx.employeestat.rest.entity
  5408. hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
  5409. hibernate.show_sql=false
  5410. hibernate.ddl-auto=none
  5411.  
  5412. spring.security.oauth2.client.registration.google.client-id=854909843289-i6kivqbpjvt6di44ur0f0p2li5novibf.apps.googleusercontent.com
  5413. spring.security.oauth2.client.registration.google.client-secret=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
  5414.  
  5415. reports-path=C:/Users/ivan.shastakou/IdeaProjects/employeestat/reports
  5416. reports-generating-cron=0 0 0 1 * *
  5417.  
  5418. LOGGER CONFIG
  5419.  
  5420. <?xml version="1.0" encoding="UTF-8"?>
  5421. <Configuration status="WARN" monitorInterval="30">
  5422.     <Properties>
  5423.         <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %m%n</Property>
  5424.         <Property name="APP_LOG_ROOT">log</Property>
  5425.     </Properties>
  5426.     <Appenders>
  5427.         <Console name="Console" target="SYSTEM_OUT" follow="true">
  5428.             <PatternLayout pattern="${LOG_PATTERN}" />
  5429.         </Console>
  5430.  
  5431.         <RollingFile name="appLog"
  5432.                      fileName="${APP_LOG_ROOT}/application.log"
  5433.                      filePattern="${APP_LOG_ROOT}/SpringBoot2App/application-%d{yyyy-MM-dd}-%i.log">
  5434.             <PatternLayout pattern="${LOG_PATTERN}" />
  5435.             <Policies>
  5436.                 <SizeBasedTriggeringPolicy size="19500KB" />
  5437.             </Policies>
  5438.             <DefaultRolloverStrategy max="1" />
  5439.         </RollingFile>
  5440.  
  5441.     </Appenders>
  5442.     <Loggers>
  5443.  
  5444.         <Logger name="com.employeestat.app" additivity="false">
  5445.             <AppenderRef ref="appLog" />
  5446.             <AppenderRef ref="Console" />
  5447.         </Logger>
  5448.  
  5449.         <Root level="debug">
  5450.             <AppenderRef ref="Console" />
  5451.             <AppenderRef ref="appLog" />
  5452.         </Root>
  5453.  
  5454.     </Loggers>
  5455. </Configuration>
  5456.  
  5457. ----------------------
  5458. DOCKER
  5459. ----------------------
  5460. app:
  5461.  
  5462. FROM tomcat:8-jre8
  5463.  
  5464. RUN echo "export JAVA_OPTS=\"-Dapp.env=employeestat\"" > /usr/local/tomcat/bin/setenv.sh
  5465. COPY employeestat.war /usr/local/tomcat/webapps/employeestat.war
  5466.  
  5467. CMD ["catalina.sh", "run"]
  5468.  
  5469. db:
  5470.  
  5471. FROM postgres:9.4
  5472.  
  5473. ENV POSTGRES_USER postgres
  5474. ENV POSTGRES_PASSWORD user
  5475. ENV POSTGRES_DB employee_db
  5476.  
  5477. docker-compose.yml
  5478.  
  5479. services:
  5480.  
  5481.   app-web:
  5482.     build: app
  5483.     container_name: application
  5484.     ports:
  5485.       - "8089:8080"
  5486.     links:
  5487.       - app-db
  5488.  
  5489.   app-db:
  5490.     build: db
  5491.     container_name: db
  5492.     expose:
  5493.       - "5433"
  5494.     volumes_from:
  5495.       - app-db-data
  5496.  
  5497.   app-db-data:
  5498.     image: cogniteev/echo
  5499.     command: echo 'Data Container for PostgreSQL'
  5500.     volumes:
  5501.       - /var/lib/postgresql/data
  5502.  
  5503. -------------------
  5504. MAVEN
  5505. -------------------
  5506.  
  5507. <?xml version="1.0" encoding="UTF-8"?>
  5508.  
  5509. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5510.   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5511.   <modelVersion>4.0.0</modelVersion>
  5512.  
  5513.   <groupId>com.leverx</groupId>
  5514.   <artifactId>employeestat</artifactId>
  5515.   <version>1.0</version>
  5516.   <packaging>war</packaging>
  5517.  
  5518.   <name>employeestat Maven Webapp</name>
  5519.   <!-- FIXME change it to the project's website -->
  5520.  <url>http://www.example.com</url>
  5521.  
  5522.    <properties>
  5523.        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  5524.        <maven.compiler.source>1.8</maven.compiler.source>
  5525.        <maven.compiler.target>1.8</maven.compiler.target>
  5526.        <java.version>1.8</java.version>
  5527.        <spring-webmvc-orm.version>5.3.14</spring-webmvc-orm.version>
  5528.        <javax.servlet.version>4.0.1</javax.servlet.version>
  5529.        <org.hibernate.version>5.5.0.Final</org.hibernate.version>
  5530.        <c3p0.version>0.9.5.2</c3p0.version>
  5531.        <org.hibernate.validator.version>6.2.0.Final</org.hibernate.validator.version>
  5532.        <org.aspectj.version>1.9.6</org.aspectj.version>
  5533.        <spring-data-jpa.version>2.6.0</spring-data-jpa.version>
  5534.        <jackson-databind.version>2.12.3</jackson-databind.version>
  5535.        <postgresql.version>42.3.1</postgresql.version>
  5536.        <org.apache.poi.version>5.0.0</org.apache.poi.version>
  5537.        <mockito-junit-jupiter.version>3.9.0</mockito-junit-jupiter.version>
  5538.        <spring-security-oauth2.version>5.6.0</spring-security-oauth2.version>
  5539.    </properties>
  5540.  
  5541.    <dependencies>
  5542.  
  5543.        <dependency>
  5544.            <groupId>org.liquibase</groupId>
  5545.            <artifactId>liquibase-core</artifactId>
  5546.            <version>4.6.1</version>
  5547.        </dependency>
  5548.  
  5549.        <dependency>
  5550.            <groupId>org.springframework</groupId>
  5551.            <artifactId>spring-orm</artifactId>
  5552.            <version>${spring-webmvc-orm.version}</version>
  5553.        </dependency>
  5554.  
  5555.        <dependency>
  5556.            <groupId>org.springframework</groupId>
  5557.            <artifactId>spring-webmvc</artifactId>
  5558.            <version>${spring-webmvc-orm.version}</version>
  5559.        </dependency>
  5560.  
  5561.        <dependency>
  5562.            <groupId>org.springframework.data</groupId>
  5563.            <artifactId>spring-data-jpa</artifactId>
  5564.            <version>${spring-data-jpa.version}</version>
  5565.        </dependency>
  5566.  
  5567.        <dependency>
  5568.            <groupId>org.springframework.security</groupId>
  5569.            <artifactId>spring-security-web</artifactId>
  5570.            <version>5.6.0</version>
  5571.        </dependency>
  5572.  
  5573.        <dependency>
  5574.            <groupId>org.springframework.security</groupId>
  5575.            <artifactId>spring-security-config</artifactId>
  5576.            <version>5.6.0</version>
  5577.        </dependency>
  5578.  
  5579.        <dependency>
  5580.            <groupId>org.hibernate</groupId>
  5581.            <artifactId>hibernate-core</artifactId>
  5582.            <version>${org.hibernate.version}</version>
  5583.        </dependency>
  5584.  
  5585.        <dependency>
  5586.            <groupId>org.hibernate.validator</groupId>
  5587.            <artifactId>hibernate-validator</artifactId>
  5588.            <version>${org.hibernate.validator.version}</version>
  5589.        </dependency>
  5590.  
  5591.        <dependency>
  5592.            <groupId>com.mchange</groupId>
  5593.            <artifactId>c3p0</artifactId>
  5594.            <version>${c3p0.version}</version>
  5595.        </dependency>
  5596.  
  5597.        <dependency>
  5598.            <groupId>org.aspectj</groupId>
  5599.            <artifactId>aspectjweaver</artifactId>
  5600.            <version>${org.aspectj.version}</version>
  5601.        </dependency>
  5602.  
  5603.        <dependency>
  5604.            <groupId>javax.servlet</groupId>
  5605.            <artifactId>javax.servlet-api</artifactId>
  5606.            <version>${javax.servlet.version}</version>
  5607.            <scope>provided</scope>
  5608.        </dependency>
  5609.  
  5610.        <dependency>
  5611.            <groupId>com.fasterxml.jackson.core</groupId>
  5612.            <artifactId>jackson-databind</artifactId>
  5613.            <version>${jackson-databind.version}</version>
  5614.        </dependency>
  5615.  
  5616.        <dependency>
  5617.            <groupId>com.fasterxml.jackson.datatype</groupId>
  5618.            <artifactId>jackson-datatype-jsr310</artifactId>
  5619.            <version>${jackson-databind.version}</version>
  5620.        </dependency>
  5621.  
  5622.        <dependency>
  5623.            <groupId>org.postgresql</groupId>
  5624.            <artifactId>postgresql</artifactId>
  5625.            <version>${postgresql.version}</version>
  5626.        </dependency>
  5627.  
  5628.        <dependency>
  5629.            <groupId>org.apache.poi</groupId>
  5630.            <artifactId>poi</artifactId>
  5631.            <version>${org.apache.poi.version}</version>
  5632.        </dependency>
  5633.  
  5634.        <dependency>
  5635.            <groupId>org.apache.poi</groupId>
  5636.            <artifactId>poi-ooxml</artifactId>
  5637.            <version>${org.apache.poi.version}</version>
  5638.        </dependency>
  5639.  
  5640.        <dependency>
  5641.            <groupId>org.springframework</groupId>
  5642.            <artifactId>spring-test</artifactId>
  5643.            <version>5.3.14</version>
  5644.            <scope>test</scope>
  5645.        </dependency>
  5646.  
  5647.        <dependency>
  5648.            <groupId>org.mockito</groupId>
  5649.            <artifactId>mockito-junit-jupiter</artifactId>
  5650.            <version>${mockito-junit-jupiter.version}</version>
  5651.        </dependency>
  5652.  
  5653.        <dependency>
  5654.            <groupId>org.hamcrest</groupId>
  5655.            <artifactId>hamcrest-library</artifactId>
  5656.            <version>2.2</version>
  5657.            <scope>test</scope>
  5658.        </dependency>
  5659.  
  5660.        <dependency>
  5661.            <groupId>com.jayway.jsonpath</groupId>
  5662.            <artifactId>json-path</artifactId>
  5663.            <version>2.5.0</version>
  5664.            <scope>test</scope>
  5665.        </dependency>
  5666.  
  5667.        <dependency>
  5668.            <groupId>au.com.dius.pact.provider</groupId>
  5669.            <artifactId>junit5spring</artifactId>
  5670.            <version>4.3.0</version>
  5671.            <scope>compile</scope>
  5672.        </dependency>
  5673.  
  5674.        <dependency>
  5675.            <groupId>com.opencsv</groupId>
  5676.            <artifactId>opencsv</artifactId>
  5677.            <version>5.5.2</version>
  5678.        </dependency>
  5679.  
  5680.        <dependency>
  5681.            <groupId>io.springfox</groupId>
  5682.            <artifactId>springfox-swagger2</artifactId>
  5683.            <version>2.9.2</version>
  5684.        </dependency>
  5685.  
  5686.        <dependency>
  5687.            <groupId>io.springfox</groupId>
  5688.            <artifactId>springfox-swagger-ui</artifactId>
  5689.            <version>2.9.2</version>
  5690.        </dependency>
  5691.  
  5692.        <dependency>
  5693.            <groupId>io.springfox</groupId>
  5694.            <artifactId>springfox-bean-validators</artifactId>
  5695.            <version>2.9.2</version>
  5696.        </dependency>
  5697.  
  5698.        <dependency>
  5699.            <groupId>commons-fileupload</groupId>
  5700.            <artifactId>commons-fileupload</artifactId>
  5701.            <version>1.4</version>
  5702.        </dependency>
  5703.  
  5704.        <dependency>
  5705.            <groupId>org.springframework.boot</groupId>
  5706.            <artifactId>spring-boot-starter-log4j2</artifactId>
  5707.            <version>2.6.1</version>
  5708.        </dependency>
  5709.  
  5710.        <dependency>
  5711.            <groupId>org.springframework.security</groupId>
  5712.            <artifactId>spring-security-oauth2-client</artifactId>
  5713.            <version>${spring-security-oauth2.version}</version>
  5714.        </dependency>
  5715.  
  5716.        <dependency>
  5717.            <groupId>org.springframework.security</groupId>
  5718.            <artifactId>spring-security-oauth2-jose</artifactId>
  5719.            <version>${spring-security-oauth2.version}</version>
  5720.        </dependency>
  5721.  
  5722.        <dependency>
  5723.            <groupId>javax.el</groupId>
  5724.            <artifactId>javax.el-api</artifactId>
  5725.            <version>3.0.0</version>
  5726.        </dependency>
  5727.  
  5728.        <dependency>
  5729.            <groupId>org.glassfish.web</groupId>
  5730.            <artifactId>javax.el</artifactId>
  5731.            <version>2.2.6</version>
  5732.        </dependency>
  5733.  
  5734.        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
  5735.        <dependency>
  5736.            <groupId>org.projectlombok</groupId>
  5737.            <artifactId>lombok</artifactId>
  5738.            <version>1.18.22</version>
  5739.            <scope>provided</scope>
  5740.        </dependency>
  5741.  
  5742.  
  5743.    </dependencies>
  5744.  
  5745.  <build>
  5746.    <finalName>employeestat</finalName>
  5747.    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
  5748.      <plugins>
  5749.  
  5750.        <plugin>
  5751.          <artifactId>maven-clean-plugin</artifactId>
  5752.          <version>3.1.0</version>
  5753.        </plugin>
  5754.  
  5755.        <plugin>
  5756.          <artifactId>maven-resources-plugin</artifactId>
  5757.          <version>3.0.2</version>
  5758.        </plugin>
  5759.  
  5760.        <plugin>
  5761.          <artifactId>maven-compiler-plugin</artifactId>
  5762.          <version>3.8.1</version>
  5763.        </plugin>
  5764.  
  5765.        <plugin>
  5766.          <artifactId>maven-surefire-plugin</artifactId>
  5767.          <version>2.22.1</version>
  5768.            <configuration>
  5769.                <skipTests>false</skipTests>
  5770.            </configuration>
  5771.        </plugin>
  5772.  
  5773.        <plugin>
  5774.          <artifactId>maven-war-plugin</artifactId>
  5775.          <version>3.2.2</version>
  5776.        </plugin>
  5777.  
  5778.        <plugin>
  5779.          <artifactId>maven-install-plugin</artifactId>
  5780.          <version>2.5.2</version>
  5781.        </plugin>
  5782.  
  5783.        <plugin>
  5784.          <artifactId>maven-deploy-plugin</artifactId>
  5785.          <version>2.8.2</version>
  5786.        </plugin>
  5787.  
  5788.      </plugins>
  5789.    </pluginManagement>
  5790.    <plugins>
  5791.  
  5792.      <plugin>
  5793.        <groupId>org.apache.maven.plugins</groupId>
  5794.        <artifactId>maven-compiler-plugin</artifactId>
  5795.        <configuration>
  5796.          <source>1.8</source>
  5797.          <target>1.8</target>
  5798. <!--          <fork>true</fork>-->
  5799. <!--          <executable>C:\Program Files\Java\jdk1.8.0_301\bin\javac</executable>-->
  5800.        </configuration>
  5801.      </plugin>
  5802.  
  5803.      <plugin>
  5804.        <groupId>org.apache.maven.plugins</groupId>
  5805.        <artifactId>maven-dependency-plugin</artifactId>
  5806.        <executions>
  5807.          <execution>
  5808.            <phase>package</phase>
  5809.            <goals><goal>copy</goal></goals>
  5810.            <configuration>
  5811.              <artifactItems>
  5812.                <artifactItem>
  5813.                  <groupId>com.heroku</groupId>
  5814.                  <artifactId>webapp-runner</artifactId>
  5815.                  <version>9.0.52.1</version>
  5816.                  <destFileName>webapp-runner.jar</destFileName>
  5817.                </artifactItem>
  5818.              </artifactItems>
  5819.            </configuration>
  5820.          </execution>
  5821.        </executions>
  5822.      </plugin>
  5823.    </plugins>
  5824.  </build>
  5825. </project>
Add Comment
Please, Sign In to add comment