mirror of
https://github.com/Prominence/car-repair-site.git
synced 2026-01-09 03:36:46 +03:00
Added DTO classes.
This commit is contained in:
parent
fd4bbd66c5
commit
19196fbe05
21
pom.xml
21
pom.xml
@ -72,6 +72,11 @@
|
||||
<artifactId>javafaker</artifactId>
|
||||
<version>0.15</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-jdk8</artifactId>
|
||||
<version>1.3.0.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
@ -147,6 +152,22 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>1.3.0.Final</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@ -15,7 +15,6 @@ public class CarRepairApplication {
|
||||
}
|
||||
|
||||
}
|
||||
// TODO: DTO
|
||||
// TODO: i18n
|
||||
// TODO: tests
|
||||
// TODO: big data
|
||||
@ -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<Client> clientList = clientService.findAll(pageable);
|
||||
Page<ClientDto> 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<Client> 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";
|
||||
}
|
||||
|
||||
|
||||
@ -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<Mechanic> mechanicList = mechanicService.findAll(pageable);
|
||||
Page<MechanicDto> 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<Mechanic> 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";
|
||||
}
|
||||
|
||||
|
||||
@ -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<Order> orderList = orderService.findAll(OrderSpecifications.search(client, description, orderStatus), pageable);
|
||||
Page<OrderDto> 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<Order> 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";
|
||||
}
|
||||
|
||||
@ -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<Client> clientAutocomplete(@RequestParam String query) {
|
||||
return clientService.searchByInitials(query);
|
||||
public List<ClientDto> clientAutocomplete(@RequestParam String query) {
|
||||
return clientService.convertToDtoList(clientService.searchByInitials(query));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/mechanic", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public List<Mechanic> mechanicAutocomplete(@RequestParam String query) {
|
||||
return mechanicService.searchByInitials(query);
|
||||
public List<MechanicDto> mechanicAutocomplete(@RequestParam String query) {
|
||||
return mechanicService.convertToDtoList(mechanicService.searchByInitials(query));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<LocalDateTime> {
|
||||
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;
|
||||
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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<ClientDto> clientsToClientDtoList(List<Client> clients);
|
||||
}
|
||||
@ -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<MechanicDto> mechanicsToMechanicDtoList(List<Mechanic> mechanics);
|
||||
}
|
||||
@ -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<OrderDto> ordersToOrderDtoList(List<Order> orders);
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<Client> findAll(Pageable pageable) {
|
||||
final Page<Client> 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<ClientDto> convertToDtoPage(Page<Client> clientPage) {
|
||||
final Page<ClientDto> 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<ClientDto> convertToDtoList(List<Client> clientList) {
|
||||
return clientMapper.clientsToClientDtoList(clientList);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Mechanic> 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<MechanicDto> convertToDtoPage(Page<Mechanic> mechanicPage) {
|
||||
final Page<MechanicDto> 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<MechanicDto> convertToDtoList(List<Mechanic> mechanicList) {
|
||||
return mechanicMapper.mechanicsToMechanicDtoList(mechanicList);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Order> findAll(Specification<Order> 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<OrderDto> convertToDtoPage(Page<Order> orderPage) {
|
||||
final Page<OrderDto> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,33 +9,33 @@
|
||||
<h1 th:text="#{client.title}"></h1>
|
||||
</div>
|
||||
<div layout:fragment="content">
|
||||
<form th:action="'/client/' + ${client.id != null ? 'update/' + client.id : 'create'}" th:object="${client}" method="post">
|
||||
<form th:action="'/client/' + ${clientDto.id != null ? 'update/' + clientDto.id : 'create'}" th:object="${clientDto}" method="post">
|
||||
<div class="form-group row">
|
||||
<label for="clientFirstName" class="col-sm-2 col-form-label" th:text="#{firstName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="firstName" class="form-control" id="clientFirstName" th:field="*{firstName}" th:errorclass="is-invalid" th:value="${client.firstName}">
|
||||
<input type="text" name="firstName" class="form-control" id="clientFirstName" th:field="*{firstName}" th:errorclass="is-invalid" th:value="${clientDto.firstName}">
|
||||
<div th:replace="common::errors('firstName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="clientMiddleName" class="col-sm-2 col-form-label" th:text="#{middleName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="middleName" class="form-control" id="clientMiddleName" th:field="*{middleName}" th:errorclass="is-invalid" th:value="${client.middleName}">
|
||||
<input type="text" name="middleName" class="form-control" id="clientMiddleName" th:field="*{middleName}" th:errorclass="is-invalid" th:value="${clientDto.middleName}">
|
||||
<div th:replace="common::errors('middleName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="clientLastName" class="col-sm-2 col-form-label" th:text="#{lastName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="lastName" class="form-control" id="clientLastName" th:field="*{lastName}" th:errorclass="is-invalid" th:value="${client.lastName}">
|
||||
<input type="text" name="lastName" class="form-control" id="clientLastName" th:field="*{lastName}" th:errorclass="is-invalid" th:value="${clientDto.lastName}">
|
||||
<div th:replace="common::errors('lastName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="clientPhoneNo" class="col-sm-2 col-form-label" th:text="#{phoneNo.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="phoneNo" class="form-control" id="clientPhoneNo" th:field="*{phoneNo}" th:errorclass="is-invalid" th:value="${client.phoneNo}">
|
||||
<div th:replace="common::errors('phoneNo')"></div>
|
||||
<input type="text" name="phone" class="form-control" id="clientPhoneNo" th:field="*{phone}" th:errorclass="is-invalid" th:value="${clientDto.phone}">
|
||||
<div th:replace="common::errors('phone')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row float-right">
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
<td th:text="${client.firstName}"></td>
|
||||
<td th:text="${client.middleName}"></td>
|
||||
<td th:text="${client.lastName}"></td>
|
||||
<td th:text="${client.phoneNo}"></td>
|
||||
<td th:text="${client.phone}"></td>
|
||||
<td>
|
||||
<div class="btn-group float-right">
|
||||
<a th:href="@{/client/edit/{id}(id=${client.id})}" class="btn btn-secondary" th:text="#{common.edit.button}"></a>
|
||||
|
||||
@ -9,32 +9,32 @@
|
||||
<h1 th:text="#{mechanic.title}"></h1>
|
||||
</div>
|
||||
<div layout:fragment="content">
|
||||
<form th:action="'/mechanic/' + ${mechanic.id != null ? 'update/' + mechanic.id : 'create'}" th:object="${mechanic}" method="post">
|
||||
<form th:action="'/mechanic/' + ${mechanicDto.id != null ? 'update/' + mechanicDto.id : 'create'}" th:object="${mechanicDto}" method="post">
|
||||
<div class="form-group row">
|
||||
<label for="mechanicFirstName" class="col-sm-2 col-form-label" th:text="#{firstName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="firstName" class="form-control" id="mechanicFirstName" th:field="*{firstName}" th:errorclass="is-invalid" th:value="${mechanic.firstName}">
|
||||
<input type="text" name="firstName" class="form-control" id="mechanicFirstName" th:field="*{firstName}" th:errorclass="is-invalid" th:value="${mechanicDto.firstName}">
|
||||
<div th:replace="common::errors('firstName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="mechanicMiddleName" class="col-sm-2 col-form-label" th:text="#{middleName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="middleName" class="form-control" id="mechanicMiddleName" th:field="*{middleName}" th:errorclass="is-invalid" th:value="${mechanic.middleName}">
|
||||
<input type="text" name="middleName" class="form-control" id="mechanicMiddleName" th:field="*{middleName}" th:errorclass="is-invalid" th:value="${mechanicDto.middleName}">
|
||||
<div th:replace="common::errors('middleName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="mechanicLastName" class="col-sm-2 col-form-label" th:text="#{lastName.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="lastName" class="form-control" id="mechanicLastName" th:field="*{lastName}" th:errorclass="is-invalid" th:value="${mechanic.lastName}">
|
||||
<input type="text" name="lastName" class="form-control" id="mechanicLastName" th:field="*{lastName}" th:errorclass="is-invalid" th:value="${mechanicDto.lastName}">
|
||||
<div th:replace="common::errors('lastName')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="mechanicHourlyPayment" class="col-sm-2 col-form-label" th:text="#{hourlyPayment.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" name="hourlyPayment" class="form-control" id="mechanicHourlyPayment" th:field="*{hourlyPayment}" th:errorclass="is-invalid" th:value="${mechanic.hourlyPayment}">
|
||||
<input type="number" name="hourlyPayment" class="form-control" id="mechanicHourlyPayment" th:field="*{hourlyPayment}" th:errorclass="is-invalid" th:value="${mechanicDto.hourlyPayment}">
|
||||
<div th:replace="common::errors('hourlyPayment')"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -10,56 +10,56 @@
|
||||
<h1 th:text="#{order.title}"></h1>
|
||||
</div>
|
||||
<div layout:fragment="content">
|
||||
<form th:action="'/order/' + ${order.id != null ? 'update/' + order.id : 'create'}" th:object="${order}" method="post">
|
||||
<form th:action="'/order/' + ${orderDto.id != null ? 'update/' + orderDto.id : 'create'}" th:object="${orderDto}" method="post">
|
||||
<div class="form-group row">
|
||||
<label for="orderDescription" class="col-sm-2 col-form-label" th:text="#{description.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<textarea name="description" class="form-control" id="orderDescription" th:field="*{description}" th:errorclass="is-invalid" th:value="${order.description}"></textarea>
|
||||
<textarea name="description" class="form-control" id="orderDescription" th:field="*{description}" th:errorclass="is-invalid" th:value="${orderDto.description}"></textarea>
|
||||
<div th:replace="common::errors('description')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="orderClient_tmp" class="col-sm-2 col-form-label" th:text="#{client.label}"></label>
|
||||
<div class="input-group col-sm-10" th:with="client=${order.client}, clientInitials=${(client != null && client.id != null) ? (client.firstName+ ' ' + client.lastName) : null}">
|
||||
<div class="input-group col-sm-10" th:with="clientInitials=${(orderDto.clientId != null) ? (orderDto.clientFirstName + ' ' + orderDto.clientLastName) : null}">
|
||||
<span class="input-group-prepend input-group-text" id="orderClientPlaceholder" th:text="${clientInitials}"></span>
|
||||
<input type="text" name="clientId_tmp" class="form-control" id="orderClient_tmp" th:classappend="${#fields.hasErrors('client') ? 'is-invalid' : null}">
|
||||
<input type="hidden" name="clientId" id="orderClient" th:value="${client != null && client.id != null ? client.id : ''}">
|
||||
<div th:replace="common::errors('client')"></div>
|
||||
<input type="text" name="clientId_tmp" class="form-control" id="orderClient_tmp" th:classappend="${#fields.hasErrors('clientId') ? 'is-invalid' : null}">
|
||||
<input type="hidden" name="clientId" id="orderClient" th:value="${orderDto.clientId}">
|
||||
<div th:replace="common::errors('clientId')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="orderMechanic" class="col-sm-2 col-form-label" th:text="#{mechanic.label}"></label>
|
||||
<div class="input-group col-sm-10" th:with="mechanic=${order.mechanic}, mechanicInitials=${(mechanic != null && mechanic.id != null) ? (mechanic.firstName+ ' ' + mechanic.lastName) : null}">
|
||||
<div class="input-group col-sm-10" th:with="mechanicInitials=${(orderDto.mechanicId != null) ? (orderDto.mechanicFirstName + ' ' + orderDto.mechanicLastName) : null}">
|
||||
<span class="input-group-prepend input-group-text" id="orderMechanicPlaceholder" th:text="${mechanicInitials}"></span>
|
||||
<input type="text" name="mechanicId_tmp" class="form-control" id="orderMechanic_tmp" th:classappend="${#fields.hasErrors('mechanic') ? 'is-invalid' : null}">
|
||||
<input type="hidden" name="mechanicId" id="orderMechanic" th:value="${mechanic != null && mechanic.id != null ? mechanic.id : ''}">
|
||||
<div th:replace="common::errors('mechanic')"></div>
|
||||
<input type="text" name="mechanicId_tmp" class="form-control" id="orderMechanic_tmp" th:classappend="${#fields.hasErrors('mechanicId') ? 'is-invalid' : null}">
|
||||
<input type="hidden" name="mechanicId" id="orderMechanic" th:value="${orderDto.mechanicId}">
|
||||
<div th:replace="common::errors('mechanicId')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="orderCreatedOn" class="col-sm-2 col-form-label" th:text="#{createdOn.label}"></label>
|
||||
<div class="input-group col-sm-10">
|
||||
<input type="datetime-local" name="createdOn" class="form-control" id="orderCreatedOn" th:field="*{createdOn}" th:errorclass="is-invalid" th:value="${order.createdOn}">
|
||||
<input type="datetime-local" name="createdOnDate" class="form-control" id="orderCreatedOn" th:field="*{createdOnDate}" th:errorclass="is-invalid" th:value="${orderDto.createdOnDate}">
|
||||
<span class="input-group-append input-group-text">
|
||||
<i class="far fa-calendar"></i>
|
||||
</span>
|
||||
<div th:replace="common::errors('createdOn')"></div>
|
||||
<div th:replace="common::errors('createdOnDate')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="orderFinishedOn" class="col-sm-2 col-form-label" th:text="#{finishedOn.label}"></label>
|
||||
<div class="input-group col-sm-10">
|
||||
<input type="datetime-local" name="finishedOn" class="form-control" id="orderFinishedOn" th:field="*{finishedOn}" th:errorclass="is-invalid" th:value="${order.finishedOn}">
|
||||
<input type="datetime-local" name="finishedOnDate" class="form-control" id="orderFinishedOn" th:field="*{finishedOnDate}" th:errorclass="is-invalid" th:value="${orderDto.finishedOnDate}">
|
||||
<span class="input-group-append input-group-text">
|
||||
<i class="far fa-calendar"></i>
|
||||
</span>
|
||||
<div th:replace="common::errors('finishedOn')"></div>
|
||||
<div th:replace="common::errors('finishedOnDate')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="orderTotalPrice" class="col-sm-2 col-form-label" th:text="#{totalPrice.label}"></label>
|
||||
<div class="input-group col-sm-10">
|
||||
<input type="number" name="totalPrice" class="form-control" id="orderTotalPrice" th:field="*{totalPrice}" th:errorclass="is-invalid" th:value="${order.totalPrice}">
|
||||
<input type="number" name="totalPrice" class="form-control" id="orderTotalPrice" th:field="*{totalPrice}" th:errorclass="is-invalid" th:value="${orderDto.totalPrice}">
|
||||
<span class="input-group-append input-group-text">EUR</span>
|
||||
<div th:replace="common::errors('totalPrice')"></div>
|
||||
</div>
|
||||
@ -67,7 +67,7 @@
|
||||
<div class="form-group row">
|
||||
<label for="orderStatus" class="col-sm-2 col-form-label" th:text="#{status.label}"></label>
|
||||
<div class="col-sm-10">
|
||||
<select name="orderStatus" class="form-control custom-select" id="orderStatus" th:field="*{orderStatus}" th:errorclass="is-invalid" th:value="${order.orderStatus}">
|
||||
<select name="orderStatus" class="form-control custom-select" id="orderStatus" th:field="*{orderStatus}" th:errorclass="is-invalid" th:value="${orderDto.orderStatus}">
|
||||
<option th:each="orderStatus : ${orderStatuses}" th:value="${orderStatus.toString()}" th:text="${{orderStatus}}"></option>
|
||||
</select>
|
||||
<div th:replace="common::errors('orderStatus')"></div>
|
||||
|
||||
@ -74,11 +74,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="order : ${orderList}" th:id="'order-row-' + ${order.id}">
|
||||
<td th:text="${order.client.firstName + ' ' + order.client.lastName + '(' + order.client.id + ')'}"></td>
|
||||
<td th:text="${order.mechanic.firstName + ' ' + order.mechanic.lastName + '(' + order.mechanic.id + ')'}"></td>
|
||||
<td th:text="${order.clientFirstName + ' ' + order.clientLastName + '(' + order.clientId + ')'}"></td>
|
||||
<td th:text="${order.mechanicFirstName + ' ' + order.mechanicLastName + '(' + order.mechanicId + ')'}"></td>
|
||||
<td class="word-breakable" th:text="${T(org.apache.commons.lang3.StringUtils).abbreviate(order.description, 128)}"></td>
|
||||
<td th:text="${{order.createdOn}}"></td>
|
||||
<td th:text="${{order.finishedOn}}"></td>
|
||||
<td th:text="${{order.createdOnDate}}"></td>
|
||||
<td th:text="${{order.finishedOnDate}}"></td>
|
||||
<td th:text="${{order.orderStatus}}"></td>
|
||||
<td th:text="${{order.totalPrice}}"></td>
|
||||
<td style="break-inside: avoid">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user