mirror of
https://github.com/Prominence/car-repair-site.git
synced 2026-01-10 12:16:44 +03:00
Added CRUD for 'Orders' entity, formatters, translations. Removed useless service.
This commit is contained in:
parent
0124899525
commit
5f15555f4e
@ -20,3 +20,4 @@ public class CarRepairApplication {
|
|||||||
// TODO: i18n
|
// TODO: i18n
|
||||||
// TODO: tests
|
// TODO: tests
|
||||||
// TODO: big data
|
// TODO: big data
|
||||||
|
// TODO: add autocomplete
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
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.service.ClientService;
|
||||||
|
import com.github.prominence.carrepair.service.MechanicService;
|
||||||
|
import com.github.prominence.carrepair.service.OrderService;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping(value = "/order")
|
||||||
|
public class OrderController {
|
||||||
|
|
||||||
|
private OrderService orderService;
|
||||||
|
private ClientService clientService;
|
||||||
|
private MechanicService mechanicService;
|
||||||
|
|
||||||
|
public OrderController(OrderService orderService, ClientService clientService, MechanicService mechanicService) {
|
||||||
|
this.orderService = orderService;
|
||||||
|
this.clientService = clientService;
|
||||||
|
this.mechanicService = mechanicService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String index(ModelMap modelMap) {
|
||||||
|
Page<Order> orderList = orderService.findAll((Pageable) modelMap.get("pagination"));
|
||||||
|
|
||||||
|
modelMap.addAttribute("orderList", orderList.getContent());
|
||||||
|
modelMap.addAttribute("totalPages", orderList.getTotalPages());
|
||||||
|
|
||||||
|
return "order/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/create")
|
||||||
|
public String create(Model model) {
|
||||||
|
model.addAttribute("order", new Order());
|
||||||
|
model.addAttribute("clientIdsList", clientService.getAllClientIds());
|
||||||
|
model.addAttribute("mechanicIdsList", mechanicService.getAllMechanicIds());
|
||||||
|
model.addAttribute("orderStatuses", new OrderStatus[] { OrderStatus.SCHEDULED, OrderStatus.DONE, OrderStatus.ACCEPTED });
|
||||||
|
|
||||||
|
return "order/edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/edit/{id}")
|
||||||
|
public String edit(@PathVariable Long id, Model model) {
|
||||||
|
Optional<Order> orderOptional = orderService.findById(id);
|
||||||
|
if (orderOptional.isPresent()) {
|
||||||
|
model.addAttribute("order", orderOptional.get());
|
||||||
|
model.addAttribute("clientIdsList", clientService.getAllClientIds());
|
||||||
|
model.addAttribute("mechanicIdsList", mechanicService.getAllMechanicIds());
|
||||||
|
model.addAttribute("orderStatuses", new OrderStatus[] { OrderStatus.SCHEDULED, OrderStatus.DONE, OrderStatus.ACCEPTED });
|
||||||
|
return "order/edit";
|
||||||
|
} else {
|
||||||
|
// TODO: need to show warning
|
||||||
|
return "redirect:/order";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/update/{id}")
|
||||||
|
public String update(@Valid Order order, BindingResult bindingResult, @PathVariable long id, Model model) {
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
order.setId(id); // why should we do this?
|
||||||
|
model.addAttribute("clientIdsList", clientService.getAllClientIds());
|
||||||
|
model.addAttribute("mechanicIdsList", mechanicService.getAllMechanicIds());
|
||||||
|
model.addAttribute("orderStatuses", new OrderStatus[] { OrderStatus.SCHEDULED, OrderStatus.DONE, OrderStatus.ACCEPTED });
|
||||||
|
return "order/edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
orderService.save(order);
|
||||||
|
return "redirect:/order";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/create")
|
||||||
|
public String save(@Valid Order order, BindingResult bindingResult, Model model) {
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
model.addAttribute("clientIdsList", clientService.getAllClientIds());
|
||||||
|
model.addAttribute("mechanicIdsList", mechanicService.getAllMechanicIds());
|
||||||
|
model.addAttribute("orderStatuses", new OrderStatus[] { OrderStatus.SCHEDULED, OrderStatus.DONE, OrderStatus.ACCEPTED });
|
||||||
|
return "order/edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
orderService.save(order);
|
||||||
|
return "redirect:/order";
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping(value = "/delete/{id}")
|
||||||
|
public ResponseEntity delete(@PathVariable Long id) {
|
||||||
|
boolean deleteSuccess = orderService.deleteOrderById(id);
|
||||||
|
|
||||||
|
if (deleteSuccess) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
package com.github.prominence.carrepair.controller.advice;
|
package com.github.prominence.carrepair.controller.advice;
|
||||||
|
|
||||||
import com.github.prominence.carrepair.service.CarRepairService;
|
import com.github.prominence.carrepair.service.ClientService;
|
||||||
|
import com.github.prominence.carrepair.service.MechanicService;
|
||||||
|
import com.github.prominence.carrepair.service.OrderService;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@ -8,16 +10,20 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
|||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
public class GlobalInfoAdvice {
|
public class GlobalInfoAdvice {
|
||||||
|
|
||||||
private final CarRepairService carRepairService;
|
private final ClientService clientService;
|
||||||
|
private final MechanicService mechanicService;
|
||||||
|
private final OrderService orderService;
|
||||||
|
|
||||||
public GlobalInfoAdvice(CarRepairService carRepairService) {
|
public GlobalInfoAdvice(ClientService clientService, MechanicService mechanicService, OrderService orderService) {
|
||||||
this.carRepairService = carRepairService;
|
this.clientService = clientService;
|
||||||
|
this.mechanicService = mechanicService;
|
||||||
|
this.orderService = orderService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelAttribute("globalInfo")
|
@ModelAttribute("globalInfo")
|
||||||
public void addBadgeInfo(Model model) {
|
public void addBadgeInfo(Model model) {
|
||||||
model.addAttribute("clientsCount", carRepairService.getClientCount());
|
model.addAttribute("clientsCount", clientService.getClientCount());
|
||||||
model.addAttribute("mechanicsCount", carRepairService.getMechanicCount());
|
model.addAttribute("mechanicsCount", mechanicService.getMechanicCount());
|
||||||
model.addAttribute("ordersCount", carRepairService.getOrderCount());
|
model.addAttribute("ordersCount", orderService.getOrderCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,31 @@
|
|||||||
package com.github.prominence.carrepair.demo;
|
package com.github.prominence.carrepair.demo;
|
||||||
|
|
||||||
import com.github.javafaker.Faker;
|
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.Client;
|
||||||
import com.github.prominence.carrepair.model.Mechanic;
|
import com.github.prominence.carrepair.model.Mechanic;
|
||||||
|
import com.github.prominence.carrepair.model.Order;
|
||||||
import com.github.prominence.carrepair.service.ClientService;
|
import com.github.prominence.carrepair.service.ClientService;
|
||||||
import com.github.prominence.carrepair.service.MechanicService;
|
import com.github.prominence.carrepair.service.MechanicService;
|
||||||
|
import com.github.prominence.carrepair.service.OrderService;
|
||||||
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class DemoDataPopulator {
|
public class DemoDataPopulator {
|
||||||
private static final int COUNT = 10;
|
private static final int COUNT = 100;
|
||||||
|
|
||||||
private Faker faker = new Faker();
|
private Faker faker = new Faker();
|
||||||
|
|
||||||
@ -32,9 +41,7 @@ public class DemoDataPopulator {
|
|||||||
return client;
|
return client;
|
||||||
}).limit(COUNT).collect(Collectors.toList());
|
}).limit(COUNT).collect(Collectors.toList());
|
||||||
|
|
||||||
return args -> {
|
return args -> demoClientList.forEach(clientService::save);
|
||||||
demoClientList.forEach(clientService::save);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -49,9 +56,46 @@ public class DemoDataPopulator {
|
|||||||
return mechanic;
|
return mechanic;
|
||||||
}).limit(COUNT).collect(Collectors.toList());
|
}).limit(COUNT).collect(Collectors.toList());
|
||||||
|
|
||||||
return args -> {
|
return args -> demoMechanicList.forEach(mechanicService::save);
|
||||||
demoMechanicList.forEach(mechanicService::save);
|
}
|
||||||
};
|
|
||||||
|
@Bean
|
||||||
|
public CommandLineRunner orderDemoData(OrderService orderService, ClientService clientService, MechanicService mechanicService) {
|
||||||
|
final OrderStatus[] orderStatuses = OrderStatus.values();
|
||||||
|
long mechanicsCount = mechanicService.getMechanicCount();
|
||||||
|
long clientsCount = clientService.getClientCount();
|
||||||
|
|
||||||
|
List<Order> demoOrderList = Stream.generate(() -> {
|
||||||
|
Order order = new Order();
|
||||||
|
order.setOrderStatus(orderStatuses[RandomUtils.nextInt(0, 3)]);
|
||||||
|
order.setDescription(faker.lorem().characters(10, 1024));
|
||||||
|
order.setTotalPrice(BigDecimal.valueOf(faker.number().randomDouble(4, 100, 9999)));
|
||||||
|
order.setCreatedOn(LocalDateTime.ofInstant(faker.date().past(5, TimeUnit.DAYS).toInstant(), ZoneId.systemDefault()));
|
||||||
|
|
||||||
|
if (order.getOrderStatus() == OrderStatus.ACCEPTED) {
|
||||||
|
order.setFinishedOn(LocalDateTime.ofInstant(faker.date().future(10, TimeUnit.DAYS).toInstant(), ZoneId.systemDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Client> clientListSlice = clientService.findAll(getRandomPageable(clientsCount)).getContent();
|
||||||
|
final Client randomClient = clientListSlice.get(RandomUtils.nextInt(0, clientListSlice.size()));
|
||||||
|
order.setClient(randomClient);
|
||||||
|
|
||||||
|
final List<Mechanic> mechanicListSlise = mechanicService.findAll(getRandomPageable(mechanicsCount)).getContent();
|
||||||
|
final Mechanic randomMechanic = mechanicListSlise.get(RandomUtils.nextInt(0, mechanicListSlise.size()));
|
||||||
|
order.setMechanic(randomMechanic);
|
||||||
|
|
||||||
|
System.out.println(order); // demo output
|
||||||
|
return order;
|
||||||
|
}).limit(COUNT).collect(Collectors.toList());
|
||||||
|
|
||||||
|
return args -> demoOrderList.forEach(orderService::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pageable getRandomPageable(long totalRecords) {
|
||||||
|
final int size = 10;
|
||||||
|
final int totalPages = (int) (totalRecords / size);
|
||||||
|
|
||||||
|
return PageRequest.of(RandomUtils.nextInt(0, totalPages), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.github.prominence.carrepair.formatter;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CustomDateTimeFormatter implements Formatter<LocalDateTime> {
|
||||||
|
@Override
|
||||||
|
public LocalDateTime parse(String text, Locale locale) throws ParseException {
|
||||||
|
return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String print(LocalDateTime object, Locale locale) {
|
||||||
|
return object.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.github.prominence.carrepair.formatter;
|
||||||
|
|
||||||
|
import com.github.prominence.carrepair.enums.OrderStatus;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.format.Formatter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OrderStatusFormatter implements Formatter<OrderStatus> {
|
||||||
|
@Override
|
||||||
|
public OrderStatus parse(String text, Locale locale) throws ParseException {
|
||||||
|
return OrderStatus.valueOf(text.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String print(OrderStatus object, Locale locale) {
|
||||||
|
return StringUtils.capitalize(object.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,9 +3,12 @@ package com.github.prominence.carrepair.model;
|
|||||||
import com.github.prominence.carrepair.enums.OrderStatus;
|
import com.github.prominence.carrepair.enums.OrderStatus;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "orders")
|
@Table(name = "orders")
|
||||||
@ -16,13 +19,14 @@ public class Order {
|
|||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@Size(max = 1024)
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.EAGER) // change to LAZY after DTO implementation
|
||||||
@JoinColumn(name = "client_id", nullable = false)
|
@JoinColumn(name = "client_id", nullable = false)
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.EAGER) // change to LAZY after DTO implementation
|
||||||
@JoinColumn(name = "mechanic_id", nullable = false)
|
@JoinColumn(name = "mechanic_id", nullable = false)
|
||||||
private Mechanic mechanic;
|
private Mechanic mechanic;
|
||||||
|
|
||||||
@ -33,6 +37,7 @@ public class Order {
|
|||||||
@Column(name = "finishedOn")
|
@Column(name = "finishedOn")
|
||||||
private LocalDateTime finishedOn;
|
private LocalDateTime finishedOn;
|
||||||
|
|
||||||
|
@Min(value = 0)
|
||||||
@Column(name = "totalPrice")
|
@Column(name = "totalPrice")
|
||||||
private BigDecimal totalPrice;
|
private BigDecimal totalPrice;
|
||||||
|
|
||||||
@ -116,4 +121,38 @@ public class Order {
|
|||||||
public void setOrderStatus(OrderStatus orderStatus) {
|
public void setOrderStatus(OrderStatus orderStatus) {
|
||||||
this.orderStatus = orderStatus.toString();
|
this.orderStatus = orderStatus.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof Order)) return false;
|
||||||
|
Order order = (Order) o;
|
||||||
|
return id == order.id &&
|
||||||
|
Objects.equals(description, order.description) &&
|
||||||
|
Objects.equals(client, order.client) &&
|
||||||
|
Objects.equals(mechanic, order.mechanic) &&
|
||||||
|
Objects.equals(createdOn, order.createdOn) &&
|
||||||
|
Objects.equals(finishedOn, order.finishedOn) &&
|
||||||
|
Objects.equals(totalPrice, order.totalPrice) &&
|
||||||
|
Objects.equals(orderStatus, order.orderStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, description, client, mechanic, createdOn, finishedOn, totalPrice, orderStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Order{" +
|
||||||
|
"id=" + id +
|
||||||
|
", description='" + description + '\'' +
|
||||||
|
", client=" + client +
|
||||||
|
", mechanic=" + mechanic +
|
||||||
|
", createdOn=" + createdOn +
|
||||||
|
", finishedOn=" + finishedOn +
|
||||||
|
", totalPrice=" + totalPrice +
|
||||||
|
", orderStatus='" + orderStatus + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,14 @@ package com.github.prominence.carrepair.repository;
|
|||||||
|
|
||||||
import com.github.prominence.carrepair.model.Client;
|
import com.github.prominence.carrepair.model.Client;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface ClientRepository extends JpaRepository<Client, Long> {
|
public interface ClientRepository extends JpaRepository<Client, Long> {
|
||||||
|
|
||||||
|
@Query(value = "select c.id from Client c")
|
||||||
|
public List<Long> findAllClientIds();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,14 @@ package com.github.prominence.carrepair.repository;
|
|||||||
|
|
||||||
import com.github.prominence.carrepair.model.Mechanic;
|
import com.github.prominence.carrepair.model.Mechanic;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface MechanicRepository extends JpaRepository<Mechanic, Long> {
|
public interface MechanicRepository extends JpaRepository<Mechanic, Long> {
|
||||||
|
|
||||||
|
@Query(value = "select m.id from Mechanic m")
|
||||||
|
public List<Long> findAllMechanicIds();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
package com.github.prominence.carrepair.service;
|
|
||||||
|
|
||||||
import com.github.prominence.carrepair.repository.ClientRepository;
|
|
||||||
import com.github.prominence.carrepair.repository.MechanicRepository;
|
|
||||||
import com.github.prominence.carrepair.repository.OrderRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class CarRepairService {
|
|
||||||
|
|
||||||
private ClientRepository clientRepository;
|
|
||||||
private MechanicRepository mechanicRepository;
|
|
||||||
private OrderRepository orderRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public CarRepairService(ClientRepository clientRepository, MechanicRepository mechanicRepository, OrderRepository orderRepository) {
|
|
||||||
this.clientRepository = clientRepository;
|
|
||||||
this.mechanicRepository = mechanicRepository;
|
|
||||||
this.orderRepository = orderRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getClientCount() {
|
|
||||||
return clientRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMechanicCount() {
|
|
||||||
return mechanicRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getOrderCount() {
|
|
||||||
return orderRepository.count();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,6 +6,7 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -37,4 +38,12 @@ public class ClientService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getClientCount() {
|
||||||
|
return clientRepository.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllClientIds() {
|
||||||
|
return clientRepository.findAllClientIds();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,4 +58,12 @@ public class MechanicService {
|
|||||||
|
|
||||||
return statistics;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMechanicCount() {
|
||||||
|
return mechanicRepository.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllMechanicIds() {
|
||||||
|
return mechanicRepository.findAllMechanicIds();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.github.prominence.carrepair.service;
|
||||||
|
|
||||||
|
import com.github.prominence.carrepair.model.Order;
|
||||||
|
import com.github.prominence.carrepair.repository.OrderRepository;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
private OrderRepository orderRepository;
|
||||||
|
|
||||||
|
public OrderService(OrderRepository orderRepository) {
|
||||||
|
this.orderRepository = orderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<Order> findAll(Pageable pageable) {
|
||||||
|
return orderRepository.findAll(pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Order> findById(Long id) {
|
||||||
|
return orderRepository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order save(Order client) {
|
||||||
|
return orderRepository.save(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean deleteOrderById(Long id) {
|
||||||
|
try {
|
||||||
|
orderRepository.deleteById(id);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOrderCount() {
|
||||||
|
return orderRepository.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ home.requirements.label = Requirements
|
|||||||
|
|
||||||
client.title = Clients
|
client.title = Clients
|
||||||
mechanic.title = Mechanics
|
mechanic.title = Mechanics
|
||||||
|
order.title = Orders
|
||||||
|
|
||||||
firstName.label = First Name
|
firstName.label = First Name
|
||||||
middleName.label = Middle Name
|
middleName.label = Middle Name
|
||||||
@ -16,6 +17,12 @@ phoneNo.label = Phone No
|
|||||||
hourlyPayment.label = Hourly Payment
|
hourlyPayment.label = Hourly Payment
|
||||||
status.label = Status
|
status.label = Status
|
||||||
amount.label = Amount
|
amount.label = Amount
|
||||||
|
client.label = Client
|
||||||
|
mechanic.label = Mechanic
|
||||||
|
description.label = Description
|
||||||
|
createdOn.label = Created On
|
||||||
|
finishedOn.label = Finished On
|
||||||
|
totalPrice.label = Total Price
|
||||||
|
|
||||||
showStatistics.button = Statistics
|
showStatistics.button = Statistics
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ home.requirements.label = Requirements
|
|||||||
|
|
||||||
client.title = Clients
|
client.title = Clients
|
||||||
mechanic.title = Mechanics
|
mechanic.title = Mechanics
|
||||||
|
order.title = Orders
|
||||||
|
|
||||||
firstName.label = First Name
|
firstName.label = First Name
|
||||||
middleName.label = Middle Name
|
middleName.label = Middle Name
|
||||||
@ -16,6 +17,12 @@ phoneNo.label = Phone No
|
|||||||
hourlyPayment.label = Hourly Payment
|
hourlyPayment.label = Hourly Payment
|
||||||
status.label = Status
|
status.label = Status
|
||||||
amount.label = Amount
|
amount.label = Amount
|
||||||
|
client.label = Client
|
||||||
|
mechanic.label = Mechanic
|
||||||
|
description.label = Description
|
||||||
|
createdOn.label = Created On
|
||||||
|
finishedOn.label = Finished On
|
||||||
|
totalPrice.label = Total Price
|
||||||
|
|
||||||
showStatistics.button = Statistics
|
showStatistics.button = Statistics
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ home.requirements.label = Требования
|
|||||||
|
|
||||||
client.title = Клиенты
|
client.title = Клиенты
|
||||||
mechanic.title = Механики
|
mechanic.title = Механики
|
||||||
|
order.title = Заказы
|
||||||
|
|
||||||
firstName.label = Имя
|
firstName.label = Имя
|
||||||
middleName.label = Отчество
|
middleName.label = Отчество
|
||||||
@ -16,6 +17,12 @@ phoneNo.label = Номер телефона
|
|||||||
hourlyPayment.label = Почасовая оплата
|
hourlyPayment.label = Почасовая оплата
|
||||||
status.label = Статус
|
status.label = Статус
|
||||||
amount.label = Количество
|
amount.label = Количество
|
||||||
|
client.label = Клиент
|
||||||
|
mechanic.label = Механик
|
||||||
|
description.label = Описание
|
||||||
|
createdOn.label = Дата создания
|
||||||
|
finishedOn.label = Дата окончания
|
||||||
|
totalPrice.label = Итоговая цена
|
||||||
|
|
||||||
showStatistics.button = Статистика
|
showStatistics.button = Статистика
|
||||||
|
|
||||||
|
|||||||
@ -4,3 +4,11 @@ body {
|
|||||||
.fieldError {
|
.fieldError {
|
||||||
border: 1px solid red;
|
border: 1px solid red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.word-breakable {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
@ -16,5 +16,9 @@
|
|||||||
<li th:each="err : ${#fields.errors(fieldName)}" th:text="${err}"></li>
|
<li th:each="err : ${#fields.errors(fieldName)}" th:text="${err}"></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<th:block th:fragment="formatDateTime(dateTime)" th:if="${dateTime != null}">
|
||||||
|
<th:block th:value="${dateTime.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyy-MM-dd HH:mm:ss'))}"/>
|
||||||
|
</th:block>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li><a th:href="@{/client/}"><th:block th:text="#{badge.clients}"/> <span class="badge" th:text="${clientsCount}"></span></a></li>
|
<li><a th:href="@{/client/}"><th:block th:text="#{badge.clients}"/> <span class="badge" th:text="${clientsCount}"></span></a></li>
|
||||||
<li><a th:href="@{/mechanic/}"><th:block th:text="#{badge.mechanics}"/> <span class="badge" th:text="${mechanicsCount}"></span></a></li>
|
<li><a th:href="@{/mechanic/}"><th:block th:text="#{badge.mechanics}"/> <span class="badge" th:text="${mechanicsCount}"></span></a></li>
|
||||||
<li><a href="#"><th:block th:text="#{badge.orders}"/> <span class="badge" th:text="${ordersCount}"></span></a></li>
|
<li><a th:href="@{/order/}"><th:block th:text="#{badge.orders}"/> <span class="badge" th:text="${ordersCount}"></span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="mechanicHourlyPayment" class="col-sm-2 col-form-label" th:text="#{hourlyPayment.label}"></label>
|
<label for="mechanicHourlyPayment" class="col-sm-2 col-form-label" th:text="#{hourlyPayment.label}"></label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="number" name="phoneNo" class="form-control" id="mechanicHourlyPayment" th:field="*{hourlyPayment}" th:errorclass="fieldError" th:value="${mechanic.hourlyPayment}">
|
<input type="number" name="hourlyPayment" class="form-control" id="mechanicHourlyPayment" th:field="*{hourlyPayment}" th:errorclass="fieldError" th:value="${mechanic.hourlyPayment}">
|
||||||
<div th:replace="common::errors('hourlyPayment')"></div>
|
<div th:replace="common::errors('hourlyPayment')"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
77
src/main/resources/templates/order/edit.html
Normal file
77
src/main/resources/templates/order/edit.html
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{main}">
|
||||||
|
<head>
|
||||||
|
<title th:text="#{default.title}"></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<h1 th:text="#{order.title}"></h1>
|
||||||
|
|
||||||
|
<form th:action="'/order/' + ${order.id != null ? 'update/' + order.id : 'create'}" th:object="${order}" 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="fieldError" th:value="${order.description}"></textarea>
|
||||||
|
<div th:replace="common::errors('description')"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="orderClient" class="col-sm-2 col-form-label" th:text="#{client.label}"></label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select name="client.id" class="form-control" id="orderClient" th:field="*{client.id}" th:errorclass="fieldError" th:value="${order.client.id}">
|
||||||
|
<option th:each="clientId : ${clientIdsList}" th:value="${clientId}" th:text="${clientId}"></option>
|
||||||
|
</select>
|
||||||
|
<div th:replace="common::errors('client')"></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="col-sm-10">
|
||||||
|
<select name="mechanic.id" class="form-control" id="orderMechanic" th:field="*{mechanic.id}" th:errorclass="fieldError" th:value="${order.mechanic.id}">
|
||||||
|
<option th:each="mechanicId : ${mechanicIdsList}" th:value="${mechanicId}" th:text="${mechanicId}"></option>
|
||||||
|
</select>
|
||||||
|
<div th:replace="common::errors('mechanic')"></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="col-sm-10">
|
||||||
|
<input type="datetime-local" name="createdOn" class="form-control" id="orderCreatedOn" th:field="*{createdOn}" th:errorclass="fieldError" th:value="${order.createdOn}">
|
||||||
|
<div th:replace="common::errors('createdOn')"></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="col-sm-10">
|
||||||
|
<input type="datetime-local" name="finishedOn" class="form-control" id="orderFinishedOn" th:field="*{finishedOn}" th:errorclass="fieldError" th:value="${order.finishedOn}">
|
||||||
|
<div th:replace="common::errors('finishedOn')"></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="col-sm-10">
|
||||||
|
<input type="number" name="totalPrice" class="form-control" id="orderTotalPrice" th:field="*{totalPrice}" th:errorclass="fieldError" th:value="${order.totalPrice}">
|
||||||
|
<div th:replace="common::errors('totalPrice')"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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" id="orderStatus" th:field="*{orderStatus}" th:errorclass="fieldError" th:value="${order.orderStatus}">
|
||||||
|
<option th:each="orderStatus : ${orderStatuses}" th:value="${orderStatus.toString()}" th:text="${{orderStatus}}"></option>
|
||||||
|
</select>
|
||||||
|
<div th:replace="common::errors('orderStatus')"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row pull-right">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<a href="/order" class="btn btn-default" th:text="#{common.back.button}"></a>
|
||||||
|
<button type="submit" class="btn btn-primary" th:text="#{common.save.button}"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
67
src/main/resources/templates/order/index.html
Normal file
67
src/main/resources/templates/order/index.html
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{main}">
|
||||||
|
<head>
|
||||||
|
<title th:text="#{default.title}"></title>
|
||||||
|
|
||||||
|
<script th:inline="javascript">
|
||||||
|
function deleteOrderById(id) {
|
||||||
|
const confirmationResult = confirm("Are you sure to delete?");
|
||||||
|
if (confirmationResult) {
|
||||||
|
const url = /*[[@{/order/delete/}]]*/;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url + id,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function () {
|
||||||
|
$('#order-row-' + id).remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div layout:fragment="content">
|
||||||
|
<h1 th:text="#{order.title}"></h1>
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<a class="btn btn-success" th:href="@{/order/create}" th:text="#{common.create.button}"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{client.label}"></th>
|
||||||
|
<th th:text="#{mechanic.label}"></th>
|
||||||
|
<th th:text="#{description.label}"></th>
|
||||||
|
<th th:text="#{createdOn.label}"></th>
|
||||||
|
<th th:text="#{finishedOn.label}"></th>
|
||||||
|
<th th:text="#{status.label}"></th>
|
||||||
|
<th th:text="#{totalPrice.label}"></th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</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 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.orderStatus}}"></td>
|
||||||
|
<td th:text="${{order.totalPrice}}"></td>
|
||||||
|
<td style="break-inside: avoid">
|
||||||
|
<div class="btn-group pull-right">
|
||||||
|
<a th:href="@{/order/edit/{id}(id=${order.id})}" class="btn btn-default" th:text="#{common.edit.button}"></a>
|
||||||
|
<button type="button" class="btn btn-danger" th:onclick="'deleteOrderById(' + ${order.id} + ')'" th:text="#{common.delete.button}"></button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div th:replace="common::pagination(@{/order/}, ${page}, ${totalPages})"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user