From 1aa30673d859c62777548219ff0854e1825b9567 Mon Sep 17 00:00:00 2001 From: Robert van Dijk Date: Sat, 21 Sep 2024 22:16:24 +0200 Subject: [PATCH 1/2] Add max amount of tickets per customer for product families --- .../core/repository/TicketRepository.java | 10 +++++++ .../order/OrderValidationServiceImpl.java | 20 +++++++++++--- .../core/service/product/ProductService.java | 7 +++++ .../service/product/ProductServiceImpl.java | 26 ++++++++++++++++--- .../core/service/ticket/TicketService.java | 10 +++++++ .../service/ticket/TicketServiceImpl.java | 13 ++++++++++ 6 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/main/java/ch/wisv/events/core/repository/TicketRepository.java b/src/main/java/ch/wisv/events/core/repository/TicketRepository.java index de4d6cce..1a693319 100644 --- a/src/main/java/ch/wisv/events/core/repository/TicketRepository.java +++ b/src/main/java/ch/wisv/events/core/repository/TicketRepository.java @@ -23,6 +23,16 @@ public interface TicketRepository extends JpaRepository { */ List findAllByProductAndOwner(Product product, Customer owner); + /** + * Find all Ticket by Products and Customer. + * + * @param products of type List + * @param owner of type Customer + * + * @return List + */ + List findAllByProductInAndOwner(List products, Customer owner); + /** * Find all Ticket by Product. * diff --git a/src/main/java/ch/wisv/events/core/service/order/OrderValidationServiceImpl.java b/src/main/java/ch/wisv/events/core/service/order/OrderValidationServiceImpl.java index ba6601ba..bf77002c 100644 --- a/src/main/java/ch/wisv/events/core/service/order/OrderValidationServiceImpl.java +++ b/src/main/java/ch/wisv/events/core/service/order/OrderValidationServiceImpl.java @@ -13,6 +13,7 @@ import ch.wisv.events.core.model.product.Product; import ch.wisv.events.core.repository.OrderRepository; import ch.wisv.events.core.service.event.EventService; +import ch.wisv.events.core.service.product.ProductService; import ch.wisv.events.core.service.ticket.TicketService; import java.time.LocalDateTime; import java.util.List; @@ -31,6 +32,9 @@ public class OrderValidationServiceImpl implements OrderValidationService { /** TicketService. */ private final TicketService ticketService; + /** ProductService. */ + private final ProductService productService; + /** EventService. */ private final EventService eventService; @@ -42,9 +46,10 @@ public class OrderValidationServiceImpl implements OrderValidationService { * @param eventService of type EventService */ @Autowired - public OrderValidationServiceImpl(OrderRepository orderRepository, TicketService ticketService, EventService eventService) { + public OrderValidationServiceImpl(OrderRepository orderRepository, TicketService ticketService, ProductService productService, EventService eventService) { this.orderRepository = orderRepository; this.ticketService = ticketService; + this.productService = productService; this.eventService = eventService; } @@ -80,16 +85,23 @@ public void assertOrderIsValidForCustomer(Order order, Customer customer) throws continue; } - int ticketSold = ticketService.getAllByProductAndCustomer(orderProduct.getProduct(), customer).size(); + List relatedProducts = productService.getRelatedProducts(orderProduct.getProduct()); + + int ticketSold = ticketService.getAllByProductsAndCustomer(relatedProducts, customer).size(); ticketSold += reservationOrders.stream() .mapToInt(reservationOrder -> reservationOrder.getOrderProducts().stream() - .filter(reservationOrderProduct -> orderProduct.getProduct().equals(reservationOrderProduct.getProduct())) + .filter(reservationOrderProduct -> relatedProducts.contains(reservationOrderProduct.getProduct())) .mapToInt(reservationOrderProduct -> reservationOrderProduct.getAmount().intValue()) .sum() ).sum(); - if (ticketSold + orderProduct.getAmount() > maxSoldPerCustomer) { + int tryingToOrder = order.getOrderProducts().stream() + .filter(relatedOrderProduct -> relatedProducts.contains(relatedOrderProduct.getProduct())) + .mapToInt(relatedOrderProduct -> relatedOrderProduct.getAmount().intValue()) + .sum(); + + if (ticketSold + tryingToOrder > maxSoldPerCustomer) { throw new OrderExceedCustomerLimitException(maxSoldPerCustomer - ticketSold); } } diff --git a/src/main/java/ch/wisv/events/core/service/product/ProductService.java b/src/main/java/ch/wisv/events/core/service/product/ProductService.java index fa495f06..591e9673 100644 --- a/src/main/java/ch/wisv/events/core/service/product/ProductService.java +++ b/src/main/java/ch/wisv/events/core/service/product/ProductService.java @@ -33,6 +33,13 @@ public interface ProductService { */ List getPossibleParentProductsByProduct(Product product); + /** + * Get the parent, children, and sibling products, including the original product + * + * @return Collection of Products + */ + List getRelatedProducts(Product product); + /** * Get Product by Key. * diff --git a/src/main/java/ch/wisv/events/core/service/product/ProductServiceImpl.java b/src/main/java/ch/wisv/events/core/service/product/ProductServiceImpl.java index 57a4cbba..aa71e95f 100644 --- a/src/main/java/ch/wisv/events/core/service/product/ProductServiceImpl.java +++ b/src/main/java/ch/wisv/events/core/service/product/ProductServiceImpl.java @@ -8,9 +8,7 @@ import ch.wisv.events.core.model.product.Product; import ch.wisv.events.core.repository.ProductRepository; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -72,6 +70,28 @@ public List getPossibleParentProductsByProduct(Product product) { .collect(Collectors.toList()); } + /** + * Get the parent, children, and sibling products, including the original product + * + * @return Collection of Products + */ + @Override + public List getRelatedProducts(Product product) { + List result = new ArrayList<>(); + Product parent = product; + while (parent.getParentProduct() != null) { + parent = parent.getParentProduct(); + } + Queue q = new LinkedList<>(); + q.add(parent); + while (!q.isEmpty()) { + Product p = q.remove(); + result.add(p); + q.addAll(p.getChildProducts()); + } + return result; + } + /** * Get Product by Key. * diff --git a/src/main/java/ch/wisv/events/core/service/ticket/TicketService.java b/src/main/java/ch/wisv/events/core/service/ticket/TicketService.java index efb3cb54..42ef94bd 100644 --- a/src/main/java/ch/wisv/events/core/service/ticket/TicketService.java +++ b/src/main/java/ch/wisv/events/core/service/ticket/TicketService.java @@ -51,6 +51,16 @@ public interface TicketService { */ List getAllByProductAndCustomer(Product product, Customer customer); + /** + * Get all Ticket for one of multiple products and Customer. + * + * @param products of type List + * @param customer of type Customer + * + * @return List of Tickets + */ + List getAllByProductsAndCustomer(List products, Customer customer); + /** * Get all Ticket by a Product. * diff --git a/src/main/java/ch/wisv/events/core/service/ticket/TicketServiceImpl.java b/src/main/java/ch/wisv/events/core/service/ticket/TicketServiceImpl.java index 17da9240..adaadaf8 100644 --- a/src/main/java/ch/wisv/events/core/service/ticket/TicketServiceImpl.java +++ b/src/main/java/ch/wisv/events/core/service/ticket/TicketServiceImpl.java @@ -101,6 +101,19 @@ public List getAllByProductAndCustomer(Product product, Customer custome return ticketRepository.findAllByProductAndOwner(product, customer); } + /** + * Get all Ticket for one of multiple products and Customer. + * + * @param products of type List + * @param customer of type Customer + * + * @return List of Tickets + */ + @Override + public List getAllByProductsAndCustomer(List products, Customer customer) { + return ticketRepository.findAllByProductInAndOwner(products, customer); + } + /** * Get all Ticket by a Product. * From bfc732a39eac3efd26f3a1411d539025c5e87d06 Mon Sep 17 00:00:00 2001 From: Robert van Dijk Date: Sat, 21 Sep 2024 22:33:26 +0200 Subject: [PATCH 2/2] Fix tests --- .../service/OrderValidationServiceImplTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/java/ch/wisv/events/core/service/OrderValidationServiceImplTest.java b/src/test/java/ch/wisv/events/core/service/OrderValidationServiceImplTest.java index 8ba58b05..dac2d448 100644 --- a/src/test/java/ch/wisv/events/core/service/OrderValidationServiceImplTest.java +++ b/src/test/java/ch/wisv/events/core/service/OrderValidationServiceImplTest.java @@ -18,11 +18,14 @@ import ch.wisv.events.core.service.event.EventService; import ch.wisv.events.core.service.order.OrderValidationService; import ch.wisv.events.core.service.order.OrderValidationServiceImpl; +import ch.wisv.events.core.service.product.ProductService; import ch.wisv.events.core.service.ticket.TicketService; import ch.wisv.events.core.util.VatRate; import com.google.common.collect.ImmutableList; import java.time.LocalDateTime; import java.util.Collections; +import java.util.List; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -43,6 +46,10 @@ public class OrderValidationServiceImplTest extends ServiceTest { @Mock private TicketService ticketService; + /** ProductService. */ + @Mock + private ProductService productService; + /** EventService. */ @Mock private EventService eventService; @@ -56,7 +63,7 @@ public class OrderValidationServiceImplTest extends ServiceTest { @Before public void setUp() { - orderValidationService = new OrderValidationServiceImpl(orderRepository, ticketService, eventService); + orderValidationService = new OrderValidationServiceImpl(orderRepository, ticketService, productService, eventService); product = mock(Product.class); when(product.getVatRate()).thenReturn(VatRate.VAT_HIGH); @@ -229,8 +236,9 @@ public void assertOrderIsValidForCustomerExceedSold() throws Exception { Order prevOrder = mock(Order.class); when(product.getMaxSoldPerCustomer()).thenReturn(1); + when(productService.getRelatedProducts(product)).thenReturn(ImmutableList.of(product)); when(orderRepository.findAllByOwnerAndStatus(customer, OrderStatus.RESERVATION)).thenReturn(ImmutableList.of(prevOrder)); - when(ticketService.getAllByProductAndCustomer(product, customer)).thenReturn(ImmutableList.of(mock(Ticket.class))); + when(ticketService.getAllByProductsAndCustomer(List.of(product), customer)).thenReturn(ImmutableList.of(mock(Ticket.class))); thrown.expect(OrderExceedCustomerLimitException.class); thrown.expectMessage("Customer limit exceeded (max 0 tickets allowed)."); @@ -249,8 +257,9 @@ public void assertOrderIsValidForCustomerExceedReservation() throws Exception { when(prevOrder.getOrderProducts()).thenReturn(ImmutableList.of(prevOrderProduct)); when(product.getMaxSoldPerCustomer()).thenReturn(1); + when(productService.getRelatedProducts(product)).thenReturn(ImmutableList.of(product)); when(orderRepository.findAllByOwnerAndStatus(customer, OrderStatus.RESERVATION)).thenReturn(ImmutableList.of(prevOrder)); - when(ticketService.getAllByProductAndCustomer(product, customer)).thenReturn(ImmutableList.of()); + when(ticketService.getAllByProductsAndCustomer(List.of(product), customer)).thenReturn(ImmutableList.of()); thrown.expect(OrderExceedCustomerLimitException.class); thrown.expectMessage("Customer limit exceeded (max 0 tickets allowed).");