From 19196fbe052ea627d618800124c2b8bff3ed59a4 Mon Sep 17 00:00:00 2001 From: Alexey Zinchenko Date: Wed, 15 May 2019 00:05:19 +0300 Subject: [PATCH] Added DTO classes. --- pom.xml | 21 +++ .../carrepair/CarRepairApplication.java | 1 - .../controller/ClientController.java | 17 +- .../controller/MechanicController.java | 17 +- .../carrepair/controller/OrderController.java | 19 ++- .../api/AutocompleteApiController.java | 12 +- .../carrepair/demo/DemoDataPopulator.java | 6 +- .../formatter/CustomDateTimeFormatter.java | 9 +- .../carrepair/model/{ => domain}/Client.java | 6 +- .../model/{ => domain}/Mechanic.java | 8 +- .../carrepair/model/{ => domain}/Order.java | 23 +-- .../carrepair/model/{ => domain}/Person.java | 15 +- .../carrepair/model/dto/ClientDto.java | 66 ++++++++ .../carrepair/model/dto/MechanicDto.java | 69 ++++++++ .../carrepair/model/dto/OrderDto.java | 155 ++++++++++++++++++ .../carrepair/model/mapper/ClientMapper.java | 25 +++ .../model/mapper/MechanicMapper.java | 24 +++ .../carrepair/model/mapper/OrderMapper.java | 35 ++++ .../repository/ClientRepository.java | 2 +- .../repository/MechanicRepository.java | 2 +- .../carrepair/repository/OrderRepository.java | 2 +- .../repository/spec/OrderSpecifications.java | 4 +- .../carrepair/service/ClientService.java | 30 +++- .../carrepair/service/MechanicService.java | 30 +++- .../carrepair/service/OrderService.java | 42 ++++- .../carrepair/validation/OrderValidator.java | 51 ++++-- src/main/resources/templates/client/edit.html | 12 +- .../resources/templates/client/index.html | 2 +- .../resources/templates/mechanic/edit.html | 10 +- src/main/resources/templates/order/edit.html | 32 ++-- src/main/resources/templates/order/index.html | 8 +- 31 files changed, 617 insertions(+), 138 deletions(-) rename src/main/java/com/github/prominence/carrepair/model/{ => domain}/Client.java (90%) rename src/main/java/com/github/prominence/carrepair/model/{ => domain}/Mechanic.java (87%) rename src/main/java/com/github/prominence/carrepair/model/{ => domain}/Order.java (86%) rename src/main/java/com/github/prominence/carrepair/model/{ => domain}/Person.java (83%) create mode 100644 src/main/java/com/github/prominence/carrepair/model/dto/ClientDto.java create mode 100644 src/main/java/com/github/prominence/carrepair/model/dto/MechanicDto.java create mode 100644 src/main/java/com/github/prominence/carrepair/model/dto/OrderDto.java create mode 100644 src/main/java/com/github/prominence/carrepair/model/mapper/ClientMapper.java create mode 100644 src/main/java/com/github/prominence/carrepair/model/mapper/MechanicMapper.java create mode 100644 src/main/java/com/github/prominence/carrepair/model/mapper/OrderMapper.java diff --git a/pom.xml b/pom.xml index eced845..a2c620d 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,11 @@ javafaker 0.15 + + org.mapstruct + mapstruct-jdk8 + 1.3.0.Final + org.webjars @@ -147,6 +152,22 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + org.mapstruct + mapstruct-processor + 1.3.0.Final + + + + diff --git a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java index 7c94374..c977c92 100644 --- a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java +++ b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java @@ -15,7 +15,6 @@ public class CarRepairApplication { } } -// TODO: DTO // TODO: i18n // TODO: tests // TODO: big data \ No newline at end of file diff --git a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java index 143b484..443c1e2 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java @@ -1,6 +1,7 @@ package com.github.prominence.carrepair.controller; -import com.github.prominence.carrepair.model.Client; +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.dto.ClientDto; import com.github.prominence.carrepair.service.ClientService; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,7 +32,7 @@ public class ClientController { @GetMapping public String index(@PageableDefault Pageable pageable, ModelMap modelMap) { - Page clientList = clientService.findAll(pageable); + Page clientList = clientService.convertToDtoPage(clientService.findAll(pageable)); logger.trace("Request to open list page for Clients. Returning {} page.", () -> pageable.getPageNumber() + 1); modelMap.addAttribute("clientList", clientList.getContent()); @@ -43,7 +44,7 @@ public class ClientController { @GetMapping(value = "/create") public String create(Model model) { logger.trace("Request to open create page for Client."); - model.addAttribute("client", new Client()); + model.addAttribute("clientDto", new ClientDto()); return "client/edit"; } @@ -53,7 +54,7 @@ public class ClientController { logger.trace("Request to open edit page for Client[{}].", () -> id); Optional clientOptional = clientService.findById(id); if (clientOptional.isPresent()) { - model.addAttribute("client", clientOptional.get()); + model.addAttribute("clientDto", clientService.convertToDto(clientOptional.get())); return "client/edit"; } else { return "redirect:/client"; @@ -61,10 +62,10 @@ public class ClientController { } @PostMapping(value = "/update/{id}") - public String update(@Valid Client client, BindingResult bindingResult, @PathVariable long id) { + public String update(@Valid ClientDto client, BindingResult bindingResult, @PathVariable long id) { logger.trace("Request to save {}.", () -> client); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be saved.", () -> client, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be saved.", () -> client, bindingResult::getErrorCount); client.setId(id); // why should we do this? return "client/edit"; } @@ -74,10 +75,10 @@ public class ClientController { } @PostMapping(value = "/create") - public String save(@Valid Client client, BindingResult bindingResult) { + public String save(@Valid ClientDto client, BindingResult bindingResult) { logger.trace("Request to create {}.", () -> client); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be created.", () -> client, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be created.", () -> client, bindingResult::getErrorCount); return "client/edit"; } diff --git a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java index d18d781..6ea8885 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java @@ -1,7 +1,8 @@ package com.github.prominence.carrepair.controller; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Mechanic; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.model.dto.MechanicDto; import com.github.prominence.carrepair.service.MechanicService; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,7 +33,7 @@ public class MechanicController { @GetMapping public String index(@PageableDefault Pageable pageable, ModelMap modelMap) { - Page mechanicList = mechanicService.findAll(pageable); + Page mechanicList = mechanicService.convertToDtoPage(mechanicService.findAll(pageable)); logger.trace("Request to open list page for Mechanics. Returning {} page.", () -> pageable.getPageNumber() + 1); modelMap.addAttribute("mechanicList", mechanicList.getContent()); @@ -44,7 +45,7 @@ public class MechanicController { @GetMapping(value = "/create") public String create(Model model) { logger.trace("Request to open create page for Mechanic."); - model.addAttribute("mechanic", new Mechanic()); + model.addAttribute("mechanicDto", new MechanicDto()); return "mechanic/edit"; } @@ -54,7 +55,7 @@ public class MechanicController { logger.trace("Request to open edit page for Mechanic[{}].", () -> id); Optional mechanicOptional = mechanicService.findById(id); if (mechanicOptional.isPresent()) { - model.addAttribute("mechanic", mechanicOptional.get()); + model.addAttribute("mechanicDto", mechanicService.convertToDto(mechanicOptional.get())); return "mechanic/edit"; } else { return "redirect:/mechanic"; @@ -62,10 +63,10 @@ public class MechanicController { } @PostMapping(value = "/update/{id}") - public String update(@Valid Mechanic mechanic, BindingResult bindingResult, @PathVariable long id) { + public String update(@Valid MechanicDto mechanic, BindingResult bindingResult, @PathVariable long id) { logger.trace("Request to save {}.", () -> mechanic); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be saved.", () -> mechanic, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be saved.", () -> mechanic, bindingResult::getErrorCount); mechanic.setId(id); // why should we do this? return "mechanic/edit"; } @@ -75,10 +76,10 @@ public class MechanicController { } @PostMapping(value = "/create") - public String save(@Valid Mechanic mechanic, BindingResult bindingResult) { + public String save(@Valid MechanicDto mechanic, BindingResult bindingResult) { logger.trace("Request to create {}.", () -> mechanic); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be created.", () -> mechanic, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be created.", () -> mechanic, bindingResult::getErrorCount); return "mechanic/edit"; } diff --git a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java index 79afcc6..1b22f77 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java @@ -1,7 +1,8 @@ package com.github.prominence.carrepair.controller; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Order; +import com.github.prominence.carrepair.model.dto.OrderDto; import com.github.prominence.carrepair.repository.spec.OrderSpecifications; import com.github.prominence.carrepair.service.OrderService; import org.apache.logging.log4j.LogManager; @@ -32,7 +33,9 @@ public class OrderController { @GetMapping public String index(@PageableDefault Pageable pageable, @RequestParam(required = false) String client, @RequestParam(required = false) String description, @RequestParam(required = false) OrderStatus orderStatus, ModelMap modelMap) { - Page orderList = orderService.findAll(OrderSpecifications.search(client, description, orderStatus), pageable); + Page orderList = orderService.convertToDtoPage( + orderService.findAll(OrderSpecifications.search(client, description, orderStatus), pageable) + ); logger.trace("Request to open list page for Orders. Returning {} page.", () -> pageable.getPageNumber() + 1); modelMap.addAttribute("orderList", orderList.getContent()); @@ -45,7 +48,7 @@ public class OrderController { @GetMapping(value = "/create") public String create(Model model) { logger.trace("Request to open create page for Order."); - model.addAttribute("order", new Order()); + model.addAttribute("orderDto", new OrderDto()); model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; @@ -56,7 +59,7 @@ public class OrderController { logger.trace("Request to open edit page for Order[{}].", () -> id); Optional orderOptional = orderService.findById(id); if (orderOptional.isPresent()) { - model.addAttribute("order", orderOptional.get()); + model.addAttribute("orderDto", orderService.convertToDto(orderOptional.get())); model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; } else { @@ -65,11 +68,11 @@ public class OrderController { } @PostMapping(value = "/update/{id}") - public String update(Order order, BindingResult bindingResult, @PathVariable long id, Long clientId, Long mechanicId, Model model) { + public String update(OrderDto order, BindingResult bindingResult, @PathVariable long id, Long clientId, Long mechanicId, Model model) { logger.trace("Request to save {}.", () -> order); orderService.fetchNestedObjectsAndValidate(order, clientId, mechanicId, bindingResult); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be saved.", () -> order, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be saved.", () -> order, bindingResult::getErrorCount); order.setId(id); // why should we do this? model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; @@ -80,11 +83,11 @@ public class OrderController { } @PostMapping(value = "/create") - public String save(Order order, BindingResult bindingResult, Long clientId, Long mechanicId, Model model) { + public String save(OrderDto order, BindingResult bindingResult, Long clientId, Long mechanicId, Model model) { logger.trace("Request to create {}.", () -> order); orderService.fetchNestedObjectsAndValidate(order, clientId, mechanicId, bindingResult); if (bindingResult.hasErrors()) { - logger.trace("{} has validation {} errors and won't be created.", () -> order, bindingResult::getErrorCount); + logger.trace("{} has {} validation errors and won't be created.", () -> order, bindingResult::getErrorCount); model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; } diff --git a/src/main/java/com/github/prominence/carrepair/controller/api/AutocompleteApiController.java b/src/main/java/com/github/prominence/carrepair/controller/api/AutocompleteApiController.java index 2e9405d..0741f7a 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/api/AutocompleteApiController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/api/AutocompleteApiController.java @@ -1,7 +1,7 @@ package com.github.prominence.carrepair.controller.api; -import com.github.prominence.carrepair.model.Client; -import com.github.prominence.carrepair.model.Mechanic; +import com.github.prominence.carrepair.model.dto.ClientDto; +import com.github.prominence.carrepair.model.dto.MechanicDto; import com.github.prominence.carrepair.service.ClientService; import com.github.prominence.carrepair.service.MechanicService; import org.springframework.http.MediaType; @@ -25,12 +25,12 @@ public class AutocompleteApiController { } @GetMapping(value = "/client", produces = MediaType.APPLICATION_JSON_VALUE) - public List clientAutocomplete(@RequestParam String query) { - return clientService.searchByInitials(query); + public List clientAutocomplete(@RequestParam String query) { + return clientService.convertToDtoList(clientService.searchByInitials(query)); } @GetMapping(value = "/mechanic", produces = MediaType.APPLICATION_JSON_VALUE) - public List mechanicAutocomplete(@RequestParam String query) { - return mechanicService.searchByInitials(query); + public List mechanicAutocomplete(@RequestParam String query) { + return mechanicService.convertToDtoList(mechanicService.searchByInitials(query)); } } diff --git a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java index 1a02dfe..273e1c0 100644 --- a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java +++ b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java @@ -2,9 +2,9 @@ package com.github.prominence.carrepair.demo; import com.github.javafaker.Faker; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Client; -import com.github.prominence.carrepair.model.Mechanic; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.model.domain.Order; import com.github.prominence.carrepair.service.ClientService; import com.github.prominence.carrepair.service.MechanicService; import com.github.prominence.carrepair.service.OrderService; diff --git a/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java b/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java index b76fc99..1edf72a 100644 --- a/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java +++ b/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java @@ -1,11 +1,11 @@ package com.github.prominence.carrepair.formatter; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.format.Formatter; import org.springframework.stereotype.Component; -import java.text.ParseException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; @@ -13,16 +13,19 @@ import java.util.Locale; @Component public class CustomDateTimeFormatter implements Formatter { private static final Logger logger = LogManager.getLogger(CustomDateTimeFormatter.class); + public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; @Override - public LocalDateTime parse(String text, Locale locale) throws ParseException { - final LocalDateTime parsedDateTime = LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + public LocalDateTime parse(String text, Locale locale) { + if (StringUtils.isEmpty(text)) return null; + final LocalDateTime parsedDateTime = LocalDateTime.parse(text, DateTimeFormatter.ofPattern(DATETIME_PATTERN)); logger.trace("Parsing String[{}] to LocalDateTime instance: {}.", () -> text, () -> parsedDateTime); return parsedDateTime; } @Override public String print(LocalDateTime object, Locale locale) { + if (object == null) return null; final String formattedString = object.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); logger.trace("Formatting LocalDateTime[{}] to String instance: {}.", () -> object, () -> formattedString); return formattedString; diff --git a/src/main/java/com/github/prominence/carrepair/model/Client.java b/src/main/java/com/github/prominence/carrepair/model/domain/Client.java similarity index 90% rename from src/main/java/com/github/prominence/carrepair/model/Client.java rename to src/main/java/com/github/prominence/carrepair/model/domain/Client.java index 95ad174..1dd28b1 100644 --- a/src/main/java/com/github/prominence/carrepair/model/Client.java +++ b/src/main/java/com/github/prominence/carrepair/model/domain/Client.java @@ -1,17 +1,15 @@ -package com.github.prominence.carrepair.model; +package com.github.prominence.carrepair.model.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; -import javax.validation.constraints.Size; import java.util.Objects; @Entity @Table(name = "client") public class Client extends Person { - @Size(max = 32) - @Column(name = "phoneNo") + @Column(name = "phoneNo", length = 32) private String phoneNo; public Client(String firstName, String middleName, String lastName, String phoneNo) { diff --git a/src/main/java/com/github/prominence/carrepair/model/Mechanic.java b/src/main/java/com/github/prominence/carrepair/model/domain/Mechanic.java similarity index 87% rename from src/main/java/com/github/prominence/carrepair/model/Mechanic.java rename to src/main/java/com/github/prominence/carrepair/model/domain/Mechanic.java index 61a904f..b1de919 100644 --- a/src/main/java/com/github/prominence/carrepair/model/Mechanic.java +++ b/src/main/java/com/github/prominence/carrepair/model/domain/Mechanic.java @@ -1,10 +1,8 @@ -package com.github.prominence.carrepair.model; +package com.github.prominence.carrepair.model.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.util.Objects; @@ -12,9 +10,7 @@ import java.util.Objects; @Table(name = "mechanic") public class Mechanic extends Person { - @NotNull - @Min(value = 0) - @Column(name = "hourlyPayment") + @Column(name = "hourlyPayment", nullable = false) private BigDecimal hourlyPayment; public Mechanic(String firstName, String middleName, String lastName, BigDecimal hourlyPayment) { diff --git a/src/main/java/com/github/prominence/carrepair/model/Order.java b/src/main/java/com/github/prominence/carrepair/model/domain/Order.java similarity index 86% rename from src/main/java/com/github/prominence/carrepair/model/Order.java rename to src/main/java/com/github/prominence/carrepair/model/domain/Order.java index 2084d00..a6c6fb2 100644 --- a/src/main/java/com/github/prominence/carrepair/model/Order.java +++ b/src/main/java/com/github/prominence/carrepair/model/domain/Order.java @@ -1,11 +1,8 @@ -package com.github.prominence.carrepair.model; +package com.github.prominence.carrepair.model.domain; import com.github.prominence.carrepair.enums.OrderStatus; import javax.persistence.*; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Objects; @@ -18,33 +15,27 @@ public class Order { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NotNull - @Size(max = 1024) + @Column(nullable = false) private String description; - @NotNull - @ManyToOne(fetch = FetchType.EAGER, optional = false) // change to LAZY after DTO implementation + @ManyToOne(optional = false) @JoinColumn(name = "client_id", nullable = false) private Client client; - @NotNull - @ManyToOne(fetch = FetchType.EAGER, optional = false) // change to LAZY after DTO implementation + @ManyToOne(optional = false) @JoinColumn(name = "mechanic_id", nullable = false) private Mechanic mechanic; - @NotNull - @Column(name = "createdOn") + @Column(name = "createdOn", nullable = false) private LocalDateTime createdOn; @Column(name = "finishedOn") private LocalDateTime finishedOn; - @Min(value = 0) - @Column(name = "totalPrice") + @Column(name = "totalPrice", nullable = false) private BigDecimal totalPrice; - @NotNull - @Column(name = "orderStatus") + @Column(name = "orderStatus", nullable = false) private String orderStatus = OrderStatus.SCHEDULED.toString(); public Order(String description, Client client, Mechanic mechanic, LocalDateTime createdOn, LocalDateTime finishedOn, BigDecimal totalPrice, String orderStatus) { diff --git a/src/main/java/com/github/prominence/carrepair/model/Person.java b/src/main/java/com/github/prominence/carrepair/model/domain/Person.java similarity index 83% rename from src/main/java/com/github/prominence/carrepair/model/Person.java rename to src/main/java/com/github/prominence/carrepair/model/domain/Person.java index d614254..65f7774 100644 --- a/src/main/java/com/github/prominence/carrepair/model/Person.java +++ b/src/main/java/com/github/prominence/carrepair/model/domain/Person.java @@ -1,8 +1,6 @@ -package com.github.prominence.carrepair.model; +package com.github.prominence.carrepair.model.domain; import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; import java.util.Objects; @MappedSuperclass @@ -12,18 +10,13 @@ abstract public class Person { @GeneratedValue(strategy = GenerationType.IDENTITY) protected Long id; - @NotBlank - @Size(max = 64) - @Column(name = "firstName") + @Column(name = "firstName", length = 64, nullable = false) protected String firstName; - @Size(max = 64) - @Column(name = "middleName") + @Column(name = "middleName", length = 64) protected String middleName; - @NotBlank - @Size(max = 64) - @Column(name = "lastName") + @Column(name = "lastName", length = 64, nullable = false) protected String lastName; public Person(String firstName, String middleName, String lastName) { diff --git a/src/main/java/com/github/prominence/carrepair/model/dto/ClientDto.java b/src/main/java/com/github/prominence/carrepair/model/dto/ClientDto.java new file mode 100644 index 0000000..4a36a1b --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/dto/ClientDto.java @@ -0,0 +1,66 @@ +package com.github.prominence.carrepair.model.dto; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +public class ClientDto { + + private Long id; + + @NotBlank + @Size(max = 64) + private String firstName; + + @Size(max = 64) + private String middleName; + + @NotBlank + @Size(max = 64) + private String lastName; + + @Size(max = 32) + private String phone; + + public ClientDto() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/src/main/java/com/github/prominence/carrepair/model/dto/MechanicDto.java b/src/main/java/com/github/prominence/carrepair/model/dto/MechanicDto.java new file mode 100644 index 0000000..f6856fd --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/dto/MechanicDto.java @@ -0,0 +1,69 @@ +package com.github.prominence.carrepair.model.dto; + +import javax.validation.constraints.*; +import java.math.BigDecimal; + +public class MechanicDto { + + private Long id; + + @NotBlank + @Size(max = 64) + private String firstName; + + @Size(max = 64) + private String middleName; + + @NotBlank + @Size(max = 64) + private String lastName; + + @NotNull + @PositiveOrZero + private BigDecimal hourlyPayment; + + public MechanicDto() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public BigDecimal getHourlyPayment() { + return hourlyPayment; + } + + public void setHourlyPayment(BigDecimal hourlyPayment) { + this.hourlyPayment = hourlyPayment; + } +} + + \ No newline at end of file diff --git a/src/main/java/com/github/prominence/carrepair/model/dto/OrderDto.java b/src/main/java/com/github/prominence/carrepair/model/dto/OrderDto.java new file mode 100644 index 0000000..f4bedac --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/dto/OrderDto.java @@ -0,0 +1,155 @@ +package com.github.prominence.carrepair.model.dto; + +import javax.validation.constraints.*; +import java.math.BigDecimal; + +public class OrderDto { + + private Long id; + + @NotNull + @Positive + private Long clientId; + + private String clientFirstName; + private String clientMiddleName; + private String clientLastName; + + @NotNull + @Positive + private Long mechanicId; + + private String mechanicFirstName; + private String mechanicMiddleName; + private String mechanicLastName; + + @Size(min = 1, max = 1024) + private String description; + + @NotBlank + private String orderStatus; + + @NotBlank + private String createdOnDate; + + private String finishedOnDate; + + @NotNull + @PositiveOrZero + private BigDecimal totalPrice; + + public OrderDto() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getClientId() { + return clientId; + } + + public void setClientId(Long clientId) { + this.clientId = clientId; + } + + public String getClientFirstName() { + return clientFirstName; + } + + public void setClientFirstName(String clientFirstName) { + this.clientFirstName = clientFirstName; + } + + public String getClientMiddleName() { + return clientMiddleName; + } + + public void setClientMiddleName(String clientMiddleName) { + this.clientMiddleName = clientMiddleName; + } + + public String getClientLastName() { + return clientLastName; + } + + public void setClientLastName(String clientLastName) { + this.clientLastName = clientLastName; + } + + public Long getMechanicId() { + return mechanicId; + } + + public void setMechanicId(Long mechanicId) { + this.mechanicId = mechanicId; + } + + public String getMechanicFirstName() { + return mechanicFirstName; + } + + public void setMechanicFirstName(String mechanicFirstName) { + this.mechanicFirstName = mechanicFirstName; + } + + public String getMechanicMiddleName() { + return mechanicMiddleName; + } + + public void setMechanicMiddleName(String mechanicMiddleName) { + this.mechanicMiddleName = mechanicMiddleName; + } + + public String getMechanicLastName() { + return mechanicLastName; + } + + public void setMechanicLastName(String mechanicLastName) { + this.mechanicLastName = mechanicLastName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getOrderStatus() { + return orderStatus; + } + + public void setOrderStatus(String orderStatus) { + this.orderStatus = orderStatus; + } + + public String getCreatedOnDate() { + return createdOnDate; + } + + public void setCreatedOnDate(String createdOnDate) { + this.createdOnDate = createdOnDate; + } + + public String getFinishedOnDate() { + return finishedOnDate; + } + + public void setFinishedOnDate(String finishedOnDate) { + this.finishedOnDate = finishedOnDate; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } + + public void setTotalPrice(BigDecimal totalPrice) { + this.totalPrice = totalPrice; + } +} diff --git a/src/main/java/com/github/prominence/carrepair/model/mapper/ClientMapper.java b/src/main/java/com/github/prominence/carrepair/model/mapper/ClientMapper.java new file mode 100644 index 0000000..77d19d1 --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/mapper/ClientMapper.java @@ -0,0 +1,25 @@ +package com.github.prominence.carrepair.model.mapper; + +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.dto.ClientDto; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface ClientMapper { + + @Mappings({ + @Mapping(source = "id", target = "id"), + @Mapping(source = "phoneNo", target = "phone") + }) + ClientDto clientToClientDto(Client client); + + @InheritInverseConfiguration + Client clientDtoToClient(ClientDto clientDto); + + List clientsToClientDtoList(List clients); +} diff --git a/src/main/java/com/github/prominence/carrepair/model/mapper/MechanicMapper.java b/src/main/java/com/github/prominence/carrepair/model/mapper/MechanicMapper.java new file mode 100644 index 0000000..6e91984 --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/mapper/MechanicMapper.java @@ -0,0 +1,24 @@ +package com.github.prominence.carrepair.model.mapper; + +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.model.dto.MechanicDto; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface MechanicMapper { + + @Mappings({ + @Mapping(source = "id", target = "id"), + }) + MechanicDto mechanicToMechanicDto(Mechanic mechanic); + + @InheritInverseConfiguration + Mechanic mechanicDtoToMechanic(MechanicDto mechanicDto); + + List mechanicsToMechanicDtoList(List mechanics); +} diff --git a/src/main/java/com/github/prominence/carrepair/model/mapper/OrderMapper.java b/src/main/java/com/github/prominence/carrepair/model/mapper/OrderMapper.java new file mode 100644 index 0000000..9e4aeab --- /dev/null +++ b/src/main/java/com/github/prominence/carrepair/model/mapper/OrderMapper.java @@ -0,0 +1,35 @@ +package com.github.prominence.carrepair.model.mapper; + +import com.github.prominence.carrepair.formatter.CustomDateTimeFormatter; +import com.github.prominence.carrepair.model.domain.Order; +import com.github.prominence.carrepair.model.dto.OrderDto; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface OrderMapper { + + @Mappings({ + @Mapping(source = "id", target = "id"), + @Mapping(source = "client.id", target = "clientId"), + @Mapping(source = "client.firstName", target = "clientFirstName"), + @Mapping(source = "client.middleName", target = "clientMiddleName"), + @Mapping(source = "client.lastName", target = "clientLastName"), + @Mapping(source = "mechanic.id", target = "mechanicId"), + @Mapping(source = "mechanic.firstName", target = "mechanicFirstName"), + @Mapping(source = "mechanic.middleName", target = "mechanicMiddleName"), + @Mapping(source = "mechanic.lastName", target = "mechanicLastName"), + @Mapping(source = "createdOn", target = "createdOnDate", dateFormat = CustomDateTimeFormatter.DATETIME_PATTERN), + @Mapping(source = "finishedOn", target = "finishedOnDate", dateFormat = CustomDateTimeFormatter.DATETIME_PATTERN) + }) + OrderDto orderToOrderDto(Order order); + + @InheritInverseConfiguration + Order orderDtoToOrder(OrderDto orderDto); + + List ordersToOrderDtoList(List orders); +} diff --git a/src/main/java/com/github/prominence/carrepair/repository/ClientRepository.java b/src/main/java/com/github/prominence/carrepair/repository/ClientRepository.java index b18b00c..9d84a05 100644 --- a/src/main/java/com/github/prominence/carrepair/repository/ClientRepository.java +++ b/src/main/java/com/github/prominence/carrepair/repository/ClientRepository.java @@ -1,6 +1,6 @@ package com.github.prominence.carrepair.repository; -import com.github.prominence.carrepair.model.Client; +import com.github.prominence.carrepair.model.domain.Client; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/github/prominence/carrepair/repository/MechanicRepository.java b/src/main/java/com/github/prominence/carrepair/repository/MechanicRepository.java index 8ac78a5..f02c2f0 100644 --- a/src/main/java/com/github/prominence/carrepair/repository/MechanicRepository.java +++ b/src/main/java/com/github/prominence/carrepair/repository/MechanicRepository.java @@ -1,6 +1,6 @@ package com.github.prominence.carrepair.repository; -import com.github.prominence.carrepair.model.Mechanic; +import com.github.prominence.carrepair.model.domain.Mechanic; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/github/prominence/carrepair/repository/OrderRepository.java b/src/main/java/com/github/prominence/carrepair/repository/OrderRepository.java index 1134062..62a4e58 100644 --- a/src/main/java/com/github/prominence/carrepair/repository/OrderRepository.java +++ b/src/main/java/com/github/prominence/carrepair/repository/OrderRepository.java @@ -1,6 +1,6 @@ package com.github.prominence.carrepair.repository; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Order; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java b/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java index dfc446b..cc44362 100644 --- a/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java +++ b/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java @@ -1,8 +1,8 @@ package com.github.prominence.carrepair.repository.spec; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Client; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.domain.Order; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/com/github/prominence/carrepair/service/ClientService.java b/src/main/java/com/github/prominence/carrepair/service/ClientService.java index df446b6..d88dfa0 100644 --- a/src/main/java/com/github/prominence/carrepair/service/ClientService.java +++ b/src/main/java/com/github/prominence/carrepair/service/ClientService.java @@ -1,10 +1,13 @@ package com.github.prominence.carrepair.service; -import com.github.prominence.carrepair.model.Client; +import com.github.prominence.carrepair.model.domain.Client; +import com.github.prominence.carrepair.model.dto.ClientDto; +import com.github.prominence.carrepair.model.mapper.ClientMapper; import com.github.prominence.carrepair.repository.ClientRepository; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -16,14 +19,16 @@ public class ClientService { private static final Logger logger = LogManager.getLogger(ClientService.class); private ClientRepository clientRepository; + private ClientMapper clientMapper; - public ClientService(ClientRepository clientRepository) { + public ClientService(ClientRepository clientRepository, ClientMapper clientMapper) { this.clientRepository = clientRepository; + this.clientMapper = clientMapper; } public Page findAll(Pageable pageable) { final Page clientPage = clientRepository.findAll(pageable); - logger.trace(clientPage); + logger.trace("Original page: {}.", () -> clientPage); return clientPage; } @@ -39,6 +44,10 @@ public class ClientService { return clientToSave; } + public Client save(ClientDto clientDto) { + return save(clientMapper.clientDtoToClient(clientDto)); + } + public boolean deleteClientById(Long id) { try { clientRepository.deleteById(id); @@ -61,4 +70,19 @@ public class ClientService { logger.debug("Found {} clients by initials: {}.", allByInitials::size, () -> query); return allByInitials; } + + public Page convertToDtoPage(Page clientPage) { + final Page clientDtoPage = new PageImpl<> (clientMapper.clientsToClientDtoList(clientPage.getContent()), + clientPage.getPageable(), clientPage.getTotalElements()); + logger.trace("Dto page: {}.", () -> clientDtoPage); + return clientDtoPage; + } + + public ClientDto convertToDto(Client client) { + return clientMapper.clientToClientDto(client); + } + + public List convertToDtoList(List clientList) { + return clientMapper.clientsToClientDtoList(clientList); + } } diff --git a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java index db545b7..8556766 100644 --- a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java +++ b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java @@ -1,13 +1,16 @@ package com.github.prominence.carrepair.service; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Mechanic; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Mechanic; +import com.github.prominence.carrepair.model.domain.Order; +import com.github.prominence.carrepair.model.dto.MechanicDto; +import com.github.prominence.carrepair.model.mapper.MechanicMapper; import com.github.prominence.carrepair.repository.MechanicRepository; import com.github.prominence.carrepair.repository.OrderRepository; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -22,10 +25,12 @@ public class MechanicService { private MechanicRepository mechanicRepository; private OrderRepository orderRepository; + private MechanicMapper mechanicMapper; - public MechanicService(MechanicRepository mechanicRepository, OrderRepository orderRepository) { + public MechanicService(MechanicRepository mechanicRepository, OrderRepository orderRepository, MechanicMapper mechanicMapper) { this.mechanicRepository = mechanicRepository; this.orderRepository = orderRepository; + this.mechanicMapper = mechanicMapper; } public Page findAll(Pageable pageable) { @@ -46,6 +51,10 @@ public class MechanicService { return mechanicToSave; } + public Mechanic save(MechanicDto mechanicDto) { + return save(mechanicMapper.mechanicDtoToMechanic(mechanicDto)); + } + public boolean deleteMechanicById(Long id) { try { mechanicRepository.deleteById(id); @@ -82,4 +91,19 @@ public class MechanicService { logger.debug("Found {} mechanics by initials: {}.", allByInitials::size, () -> query); return allByInitials; } + + public Page convertToDtoPage(Page mechanicPage) { + final Page mechanicDtoPage = new PageImpl<>(mechanicMapper.mechanicsToMechanicDtoList(mechanicPage.getContent()), + mechanicPage.getPageable(), mechanicPage.getTotalElements()); + logger.trace("Dto page: {}.", () -> mechanicDtoPage); + return mechanicDtoPage; + } + + public MechanicDto convertToDto(Mechanic mechanic) { + return mechanicMapper.mechanicToMechanicDto(mechanic); + } + + public List convertToDtoList(List mechanicList) { + return mechanicMapper.mechanicsToMechanicDtoList(mechanicList); + } } diff --git a/src/main/java/com/github/prominence/carrepair/service/OrderService.java b/src/main/java/com/github/prominence/carrepair/service/OrderService.java index 5a39bab..96cb05f 100644 --- a/src/main/java/com/github/prominence/carrepair/service/OrderService.java +++ b/src/main/java/com/github/prominence/carrepair/service/OrderService.java @@ -1,11 +1,14 @@ package com.github.prominence.carrepair.service; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.model.domain.Order; +import com.github.prominence.carrepair.model.dto.OrderDto; +import com.github.prominence.carrepair.model.mapper.OrderMapper; import com.github.prominence.carrepair.repository.OrderRepository; import com.github.prominence.carrepair.validation.OrderValidator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; @@ -19,18 +22,20 @@ public class OrderService { private static final Logger logger = LogManager.getLogger(OrderService.class); private OrderRepository orderRepository; - private ClientService clientService; private MechanicService mechanicService; private SmartValidator smartValidator; private OrderValidator orderValidator; + private OrderMapper orderMapper; - public OrderService(OrderRepository orderRepository, ClientService clientService, MechanicService mechanicService, SmartValidator smartValidator, OrderValidator orderValidator) { + public OrderService(OrderRepository orderRepository, ClientService clientService, MechanicService mechanicService, SmartValidator smartValidator, + OrderValidator orderValidator, OrderMapper orderMapper) { this.orderRepository = orderRepository; this.clientService = clientService; this.mechanicService = mechanicService; this.smartValidator = smartValidator; this.orderValidator = orderValidator; + this.orderMapper = orderMapper; } public Page findAll(Specification specification, Pageable pageable) { @@ -51,6 +56,10 @@ public class OrderService { return orderToSave; } + public Order save(OrderDto orderDto) { + return save(orderMapper.orderDtoToOrder(orderDto)); + } + public boolean deleteOrderById(Long id) { try { orderRepository.deleteById(id); @@ -68,16 +77,37 @@ public class OrderService { return orderCount; } - public void fetchNestedObjectsAndValidate(Order order, Long clientId, Long mechanicId, BindingResult bindingResult) { + public void fetchNestedObjectsAndValidate(OrderDto order, Long clientId, Long mechanicId, BindingResult bindingResult) { if (clientId != null) { logger.trace("Fetching Client[{}] for {}.", () -> clientId, () -> order); - clientService.findById(clientId).ifPresent(order::setClient); + clientService.findById(clientId).ifPresent(client -> { + order.setClientId(client.getId()); + order.setClientFirstName(client.getFirstName()); + order.setClientMiddleName(client.getMiddleName()); + order.setClientLastName(client.getLastName()); + }); } if (mechanicId != null) { logger.trace("Fetching Mechanic[{}] for {}.", () -> clientId, () -> order); - mechanicService.findById(mechanicId).ifPresent(order::setMechanic); + mechanicService.findById(mechanicId).ifPresent(mechanic -> { + order.setMechanicId(mechanic.getId()); + order.setMechanicFirstName(mechanic.getFirstName()); + order.setClientMiddleName(mechanic.getMiddleName()); + order.setMechanicLastName(mechanic.getLastName()); + }); } smartValidator.validate(order, bindingResult); orderValidator.validate(order, bindingResult); } + + public Page convertToDtoPage(Page orderPage) { + final Page orderDtoPage = new PageImpl<>(orderMapper.ordersToOrderDtoList(orderPage.getContent()), + orderPage.getPageable(), orderPage.getTotalElements()); + logger.trace("Dto page: {}.", () -> orderDtoPage); + return orderDtoPage; + } + + public OrderDto convertToDto(Order order) { + return orderMapper.orderToOrderDto(order); + } } diff --git a/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java b/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java index 3d3511b..41df7b4 100644 --- a/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java +++ b/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java @@ -1,40 +1,61 @@ package com.github.prominence.carrepair.validation; import com.github.prominence.carrepair.enums.OrderStatus; -import com.github.prominence.carrepair.model.Order; +import com.github.prominence.carrepair.formatter.CustomDateTimeFormatter; +import com.github.prominence.carrepair.formatter.OrderStatusFormatter; +import com.github.prominence.carrepair.model.dto.OrderDto; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.Validator; +import java.text.ParseException; import java.time.LocalDateTime; +import java.util.Locale; @Component public class OrderValidator implements Validator { private static final Logger logger = LogManager.getLogger(OrderValidator.class); + private CustomDateTimeFormatter customDateTimeFormatter; + private OrderStatusFormatter orderStatusFormatter; + + public OrderValidator(CustomDateTimeFormatter customDateTimeFormatter, OrderStatusFormatter orderStatusFormatter) { + this.customDateTimeFormatter = customDateTimeFormatter; + this.orderStatusFormatter = orderStatusFormatter; + } + @Override public boolean supports(Class aClass) { - return Order.class.isAssignableFrom(aClass); + return OrderDto.class.isAssignableFrom(aClass); } @Override public void validate(Object o, Errors errors) { - Order order = (Order) o; - LocalDateTime finishedOn = order.getFinishedOn(); - if (finishedOn != null) { - LocalDateTime createdOn = order.getCreatedOn(); - if (createdOn != null && order.getFinishedOn().isBefore(order.getCreatedOn())) { - logger.debug("[{}] validation error: \"finishedOn\" value[{}] is before \"createdOn\"[{}].", - () -> order, () -> finishedOn, () -> createdOn); - errors.rejectValue("finishedOn", "error.finishedOn.finishedBeforeStarted"); - } + OrderDto order = (OrderDto) o; - if (order.getOrderStatus() != OrderStatus.ACCEPTED) { - logger.debug("[{}] validation error: \"finishedOn\" cannot be set for order in status differ from {}.", - () -> order, () -> OrderStatus.ACCEPTED); - errors.rejectValue("finishedOn", "error.finishedOn.incompatibleStatus"); + Locale locale = LocaleContextHolder.getLocale(); + + if (order.getFinishedOnDate() != null) { + try { + LocalDateTime finishedOn = customDateTimeFormatter.parse(order.getFinishedOnDate(), locale); + LocalDateTime createdOn = customDateTimeFormatter.parse(order.getCreatedOnDate(), locale); + if (createdOn != null && finishedOn != null && finishedOn.isBefore(createdOn)) { + logger.debug("[{}] validation error: \"finishedOnDate\" value[{}] is before \"createdOn\"[{}].", + () -> order, () -> finishedOn, () -> createdOn); + errors.rejectValue("finishedOnDate", "error.finishedOn.finishedBeforeStarted"); + } + + OrderStatus orderStatus = orderStatusFormatter.parse(order.getOrderStatus(), locale); + if (finishedOn != null && orderStatus != OrderStatus.ACCEPTED) { + logger.debug("[{}] validation error: \"finishedOn\" cannot be set for order in status differ from {}.", + () -> order, () -> OrderStatus.ACCEPTED); + errors.rejectValue("finishedOnDate", "error.finishedOn.incompatibleStatus"); + } + } catch (ParseException ex) { + logger.debug("Cannot parse: {}", () -> ex); } } } diff --git a/src/main/resources/templates/client/edit.html b/src/main/resources/templates/client/edit.html index 8ab2f2a..020b99a 100644 --- a/src/main/resources/templates/client/edit.html +++ b/src/main/resources/templates/client/edit.html @@ -9,33 +9,33 @@

-
+
- +
- +
- +
- -
+ +
diff --git a/src/main/resources/templates/client/index.html b/src/main/resources/templates/client/index.html index cb2bb45..334f6d5 100644 --- a/src/main/resources/templates/client/index.html +++ b/src/main/resources/templates/client/index.html @@ -45,7 +45,7 @@ - +
diff --git a/src/main/resources/templates/mechanic/edit.html b/src/main/resources/templates/mechanic/edit.html index 6e36600..79961e2 100644 --- a/src/main/resources/templates/mechanic/edit.html +++ b/src/main/resources/templates/mechanic/edit.html @@ -9,32 +9,32 @@

- +
- +
- +
- +
- +
diff --git a/src/main/resources/templates/order/edit.html b/src/main/resources/templates/order/edit.html index feab8e1..7477fd9 100644 --- a/src/main/resources/templates/order/edit.html +++ b/src/main/resources/templates/order/edit.html @@ -10,56 +10,56 @@

- +
- +
-
+
- - -
+ + +
-
+
- - -
+ + +
- + -
+
- + -
+
- + EUR
@@ -67,7 +67,7 @@
-
diff --git a/src/main/resources/templates/order/index.html b/src/main/resources/templates/order/index.html index 4f11dc5..70c070b 100644 --- a/src/main/resources/templates/order/index.html +++ b/src/main/resources/templates/order/index.html @@ -74,11 +74,11 @@ - - + + - - + +