diff --git a/api-java/src/main/java/javaclasses/mealorder/c/BoundedContexts.java b/api-java/src/main/java/javaclasses/mealorder/c/BoundedContexts.java index 74684f35..6e1663b8 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/BoundedContexts.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/BoundedContexts.java @@ -26,6 +26,15 @@ import javaclasses.mealorder.c.order.OrderRepository; import javaclasses.mealorder.c.po.PurchaseOrderRepository; import javaclasses.mealorder.c.vendor.VendorRepository; +import javaclasses.mealorder.q.repository.FullMenuViewRepository; +import javaclasses.mealorder.q.repository.MenuCalendarViewRepository; +import javaclasses.mealorder.q.repository.MenuListViewRepository; +import javaclasses.mealorder.q.repository.MonthlySpendingsReportViewRepository; +import javaclasses.mealorder.q.repository.OrderListViewRepository; +import javaclasses.mealorder.q.repository.PurchaseOrderDetailsByDishViewRepository; +import javaclasses.mealorder.q.repository.PurchaseOrderDetailsByUserViewRepository; +import javaclasses.mealorder.q.repository.PurchaseOrderItemViewRepository; +import javaclasses.mealorder.q.repository.VendorListViewRepository; import static com.google.common.base.Preconditions.checkNotNull; @@ -71,16 +80,36 @@ public static BoundedContext create() { */ public static BoundedContext create(StorageFactory storageFactory) { checkNotNull(storageFactory); - final VendorRepository vendorRepository = VendorRepository.getRepository(); - + final VendorRepository vendorRepository = VendorRepository.createRepository(); final OrderRepository orderRepository = new OrderRepository(); final PurchaseOrderRepository purchaseOrderRepository = new PurchaseOrderRepository(); + final FullMenuViewRepository fullMenuViewRepository = new FullMenuViewRepository(); + final MenuCalendarViewRepository menuCalendarViewRepository = new MenuCalendarViewRepository(); + final MenuListViewRepository menuListViewRepository = new MenuListViewRepository(); + final MonthlySpendingsReportViewRepository monthlySpendingsReportViewRepository = new MonthlySpendingsReportViewRepository(); + final OrderListViewRepository orderListViewRepository = new OrderListViewRepository(); + final PurchaseOrderDetailsByDishViewRepository poDetailsByDishViewRepository = new PurchaseOrderDetailsByDishViewRepository(); + final PurchaseOrderDetailsByUserViewRepository poDetailsByUserViewRepository = new PurchaseOrderDetailsByUserViewRepository(); + final PurchaseOrderItemViewRepository poItemViewRepository = new PurchaseOrderItemViewRepository(); + final VendorListViewRepository vendorListViewRepository = new VendorListViewRepository(); + final BoundedContext boundedContext = createBoundedContext(storageFactory); boundedContext.register(vendorRepository); boundedContext.register(orderRepository); boundedContext.register(purchaseOrderRepository); + + boundedContext.register(fullMenuViewRepository); + boundedContext.register(menuCalendarViewRepository); + boundedContext.register(menuListViewRepository); + boundedContext.register(monthlySpendingsReportViewRepository); + boundedContext.register(orderListViewRepository); + boundedContext.register(poDetailsByDishViewRepository); + boundedContext.register(poDetailsByUserViewRepository); + boundedContext.register(poItemViewRepository); + boundedContext.register(vendorListViewRepository); + return boundedContext; } diff --git a/api-java/src/main/java/javaclasses/mealorder/c/order/OrderAggregate.java b/api-java/src/main/java/javaclasses/mealorder/c/order/OrderAggregate.java index 5e801181..1a3b44a9 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/order/OrderAggregate.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/order/OrderAggregate.java @@ -99,6 +99,7 @@ OrderCreated handle(CreateOrder cmd) throws OrderAlreadyExists, MenuNotAvailable final OrderCreated result = OrderCreated.newBuilder() .setOrderId(orderId) .setMenuId(menuId) + .setWhenCreated(getCurrentTime()) .build(); return result; } @@ -125,6 +126,7 @@ DishAddedToOrder handle(AddDishToOrder cmd) throws DishVendorMismatch, final DishAddedToOrder result = DishAddedToOrder.newBuilder() .setOrderId(orderId) .setDish(dish) + .setWhenAdded(getCurrentTime()) .build(); return result; } @@ -145,6 +147,7 @@ DishRemovedFromOrder handle(RemoveDishFromOrder cmd) throws CannotRemoveMissingD DishRemovedFromOrder result = DishRemovedFromOrder.newBuilder() .setOrderId(orderId) .setDish(dish) + .setWhenRemoved(getCurrentTime()) .build(); return result; } diff --git a/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrderAggregate.java b/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrderAggregate.java index 25406707..af056a22 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrderAggregate.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrderAggregate.java @@ -221,7 +221,7 @@ void purchaseOrderCanceled(PurchaseOrderCanceled event) { } @Apply - void purchaseOrderCanceled(PurchaseOrderDelivered event) { + void purchaseOrderDelivered(PurchaseOrderDelivered event) { getBuilder().setStatus(DELIVERED); } diff --git a/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrders.java b/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrders.java index 63db91c6..d07935bd 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrders.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/po/PurchaseOrders.java @@ -221,7 +221,7 @@ static PurchaseOrderDelivered createPOMarkedAsDeliveredEvent(MarkPurchaseOrderAs .newBuilder() .setId(id) .setWhoMarkedAsDelivered(whoMarksAsDelivered) - .setWhenDelievered(getCurrentTime()) + .setWhenDelivered(getCurrentTime()) .build(); return result; @@ -277,6 +277,7 @@ static PurchaseOrderSent createPOSentEvent(PurchaseOrder purchaseOrder, .setPurchaseOrder(purchaseOrder) .setSenderEmail(senderEmail) .setVendorEmail(vendorEmail) + .setWhenSent(getCurrentTime()) .build(); return result; } diff --git a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregate.java b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregate.java index 352c65fb..e1dad124 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregate.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregate.java @@ -25,7 +25,6 @@ import io.spine.server.command.Assign; import javaclasses.mealorder.Menu; import javaclasses.mealorder.MenuDateRange; -import javaclasses.mealorder.MenuId; import javaclasses.mealorder.Vendor; import javaclasses.mealorder.VendorChange; import javaclasses.mealorder.VendorId; @@ -33,18 +32,13 @@ import javaclasses.mealorder.VendorVBuilder; import javaclasses.mealorder.c.command.AddVendor; import javaclasses.mealorder.c.command.ImportMenu; -import javaclasses.mealorder.c.command.SetDateRangeForMenu; import javaclasses.mealorder.c.command.UpdateVendor; -import javaclasses.mealorder.c.event.DateRangeForMenuSet; import javaclasses.mealorder.c.event.MenuImported; import javaclasses.mealorder.c.event.VendorAdded; import javaclasses.mealorder.c.event.VendorUpdated; import javaclasses.mealorder.c.rejection.CannotSetDateRange; import javaclasses.mealorder.c.rejection.VendorAlreadyExists; -import java.util.List; -import java.util.stream.IntStream; - import static io.spine.time.Time.getCurrentTime; import static javaclasses.mealorder.c.vendor.VendorAggregateRejections.cannotSetDateRange; import static javaclasses.mealorder.c.vendor.VendorAggregateRejections.vendorAlreadyExists; @@ -79,6 +73,7 @@ VendorAdded handle(AddVendor cmd) throws VendorAlreadyExists { .setEmail(cmd.getEmail()) .addAllPhoneNumber(cmd.getPhoneNumberList()) .setPoDailyDeadline(cmd.getPoDailyDeadline()) + .setWhenAdded(getCurrentTime()) .build(); return vendorAdded; } @@ -95,36 +90,23 @@ VendorUpdated handle(UpdateVendor cmd) { } @Assign - MenuImported handle(ImportMenu cmd) { + MenuImported handle(ImportMenu cmd) throws CannotSetDateRange { + final MenuDateRange range = cmd.getMenuDateRange(); + final Vendor vendor = getState(); + if (!isValidDateRange(range) || isThereMenuForThisDateRange(vendor, range)) { + throw cannotSetDateRange(cmd); + } final MenuImported menuImported = MenuImported.newBuilder() .setVendorId(cmd.getVendorId()) .setMenuId(cmd.getMenuId()) .setWhoImported(cmd.getUserId()) .setWhenImported(getCurrentTime()) .addAllDish(cmd.getDishList()) + .setMenuDateRange(cmd.getMenuDateRange()) .build(); return menuImported; } - @Assign - DateRangeForMenuSet handle(SetDateRangeForMenu cmd) throws CannotSetDateRange { - final MenuDateRange range = cmd.getMenuDateRange(); - final Vendor vendor = getState(); - - if (!isValidDateRange(range) || isThereMenuForThisDateRange(vendor, range)) { - throw cannotSetDateRange(cmd); - } - final DateRangeForMenuSet dateRangeForMenuSet = - DateRangeForMenuSet.newBuilder() - .setVendorId(cmd.getVendorId()) - .setMenuId(cmd.getMenuId()) - .setWhoSet(cmd.getUserId()) - .setWhenSet(getCurrentTime()) - .setMenuDateRange(cmd.getMenuDateRange()) - .build(); - return dateRangeForMenuSet; - } - @Apply void vendorAdded(VendorAdded event) { getBuilder().setId(event.getVendorId()) @@ -149,24 +131,7 @@ void menuImported(MenuImported event) { getBuilder().addMenu(Menu.newBuilder() .setId(event.getMenuId()) .addAllDish(event.getDishList()) + .setMenuDateRange(event.getMenuDateRange()) .build()); } - - @Apply - void dateRangeForMenuSet(DateRangeForMenuSet event) { - final List menus = getBuilder().getMenu(); - final MenuId menuId = event.getMenuId(); - - final int index = IntStream.range(0, menus.size()) - .filter(i -> menus.get(i) - .getId() - .equals(menuId)) - .findFirst() - .getAsInt(); - - final Menu menu = menus.get(index); - getBuilder().setMenu(index, Menu.newBuilder(menu) - .setMenuDateRange(event.getMenuDateRange()) - .build()); - } } diff --git a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregateRejections.java b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregateRejections.java index 7f06f1a2..f38feb09 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregateRejections.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorAggregateRejections.java @@ -21,7 +21,7 @@ package javaclasses.mealorder.c.vendor; import javaclasses.mealorder.c.command.AddVendor; -import javaclasses.mealorder.c.command.SetDateRangeForMenu; +import javaclasses.mealorder.c.command.ImportMenu; import javaclasses.mealorder.c.rejection.CannotSetDateRange; import javaclasses.mealorder.c.rejection.VendorAlreadyExists; @@ -62,7 +62,7 @@ static VendorAlreadyExists vendorAlreadyExists(AddVendor cmd) throws * @param cmd the {@code SetDateRangeForMenu} command which thrown the rejection * @throws CannotSetDateRange the rejection to throw */ - static CannotSetDateRange cannotSetDateRange(SetDateRangeForMenu cmd) throws + static CannotSetDateRange cannotSetDateRange(ImportMenu cmd) throws CannotSetDateRange { checkNotNull(cmd); final CannotSetDateRange cannotSetDateRange = new CannotSetDateRange(cmd.getVendorId(), diff --git a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorRepository.java b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorRepository.java index 53e1f1f6..8865bdbf 100644 --- a/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorRepository.java +++ b/api-java/src/main/java/javaclasses/mealorder/c/vendor/VendorRepository.java @@ -40,8 +40,12 @@ public static VendorRepository getRepository() { return VendorRepositorySingleton.INSTANCE.value; } + public static VendorRepository createRepository() { + VendorRepositorySingleton.INSTANCE.value = new VendorRepository(); + return VendorRepositorySingleton.INSTANCE.value; + } private enum VendorRepositorySingleton { INSTANCE; - public final VendorRepository value = new VendorRepository(); + public VendorRepository value = new VendorRepository(); } } diff --git a/api-java/src/main/java/javaclasses/mealorder/q/FullMenuViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/FullMenuViewProjection.java new file mode 100644 index 00000000..4bad7142 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/FullMenuViewProjection.java @@ -0,0 +1,62 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.MenuId; +import javaclasses.mealorder.VendorName; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.q.projection.FullMenuView; +import javaclasses.mealorder.q.projection.FullMenuViewVBuilder; + +import java.util.List; + +import static javaclasses.mealorder.q.Projections.getAllDishesByCategories; + +public class FullMenuViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public FullMenuViewProjection(MenuId id) { + super(id); + } + + @Subscribe + public void on(MenuImported event) { + final VendorName vendorName = VendorName.newBuilder() + .setValue(event.getVendorId() + .getValue()) + .build(); + + final List allDishesByCategories = getAllDishesByCategories( + event.getDishList()); + + getBuilder().addAllDishesByCategory(allDishesByCategories); + getBuilder().setVendorName(vendorName); + getBuilder().setMenuId(event.getMenuId()); + getBuilder().setMenuDateRange(event.getMenuDateRange()); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/MenuCalendarViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/MenuCalendarViewProjection.java new file mode 100644 index 00000000..284a9725 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/MenuCalendarViewProjection.java @@ -0,0 +1,73 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.MenuCalendarId; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.q.projection.MenuCalendarView; +import javaclasses.mealorder.q.projection.MenuCalendarViewVBuilder; + +import java.time.LocalDate; +import java.util.List; + +import static javaclasses.mealorder.q.Projections.getDatesBetween; +import static javaclasses.mealorder.q.Projections.toLocalDate; + +public class MenuCalendarViewProjection extends Projection { + + /** + * {@link MenuCalendarViewProjection} is a singleton. + * + *

The {@code ID} value should be the same for all JVMs + * to support work with the same projection from execution to execution. + */ + public static final MenuCalendarId ID = MenuCalendarId.newBuilder() + .setValue( + "MenuCalendarViewProjectionSingleton") + .build(); + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public MenuCalendarViewProjection(MenuCalendarId id) { + super(id); + } + + @Subscribe + public void on(MenuImported event) { + final List datesBetween = getDatesBetween(event.getMenuDateRange() + .getRangeStart(), + event.getMenuDateRange() + .getRangeEnd()); + + datesBetween.forEach(date -> { + getBuilder().addCalendarItem(MenuCalendarItem.newBuilder() + .setDate(toLocalDate(date)) + .setHasMenu(true) + .build()); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/MenuListViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/MenuListViewProjection.java new file mode 100644 index 00000000..6dbfcac5 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/MenuListViewProjection.java @@ -0,0 +1,108 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import io.spine.time.LocalDate; +import javaclasses.mealorder.MenuDateRange; +import javaclasses.mealorder.MenuListId; +import javaclasses.mealorder.VendorName; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.q.projection.MenuListView; +import javaclasses.mealorder.q.projection.MenuListViewVBuilder; + +import java.util.List; + +import static javaclasses.mealorder.q.Projections.getAllDishesByCategories; +import static javaclasses.mealorder.q.Projections.getDatesBetween; + +public class MenuListViewProjection extends Projection { + /** + * {@link MenuListViewProjection} is a singleton. + * + *

The {@code ID} value should be the same for all JVMs + * to support work with the same projection from execution to execution. + */ + public static final MenuListId ID = MenuListId.newBuilder() + .setDate(LocalDate.newBuilder() + .setDay(2) + .setMonthValue(3) + .setYear(2018) + .build()) + .build(); + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public MenuListViewProjection(MenuListId id) { + super(id); + } + + @Subscribe + public void on(MenuImported event) { + final VendorName vendorName = VendorName.newBuilder() + .setValue(event.getVendorId() + .getValue()) + .build(); + final List allDishesByCategories = getAllDishesByCategories( + event.getDishList()); + + final MenuDateRange menuDateRange = event.getMenuDateRange(); + final List datesBetween = getDatesBetween( + menuDateRange.getRangeStart(), menuDateRange.getRangeEnd()); + datesBetween.forEach(date -> { + final LocalDate localDate = LocalDate.newBuilder() + .setDay(date.getDayOfMonth()) + .setMonthValue(date.getMonthValue()) + .setYear(date.getYear()) + .build(); + final MenuItem menuItem = MenuItem.newBuilder() + .setVendorName(vendorName) + .addAllDishesByCategory(allDishesByCategories) + .setMenuDate(localDate) + .setIsAvilable(true) + .build(); + getBuilder().addMenu(menuItem); + }); + } + + @Subscribe + public void on(PurchaseOrderCreated event) { + final LocalDate poDate = event.getId() + .getPoDate(); + getBuilder().getMenu() + .forEach(menuItem -> { + if (menuItem.getMenuDate() + .equals(poDate)) { + final MenuItem newMenuItem = MenuItem.newBuilder(menuItem) + .setIsAvilable(false) + .build(); + final int index = getBuilder().getMenu() + .indexOf(menuItem); + getBuilder().setMenu(index, newMenuItem); + } + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/MonthlySpendingsReportViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/MonthlySpendingsReportViewProjection.java new file mode 100644 index 00000000..31ab0848 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/MonthlySpendingsReportViewProjection.java @@ -0,0 +1,154 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.money.Money; +import io.spine.server.projection.Projection; +import io.spine.time.MonthOfYear; +import javaclasses.mealorder.Dish; +import javaclasses.mealorder.LocalMonth; +import javaclasses.mealorder.MonthlySpendingsReportId; +import javaclasses.mealorder.PurchaseOrder; +import javaclasses.mealorder.UserId; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.q.projection.MonthlySpendingsReportView; +import javaclasses.mealorder.q.projection.MonthlySpendingsReportViewVBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalInt; +import java.util.stream.IntStream; + +public class MonthlySpendingsReportViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public MonthlySpendingsReportViewProjection(MonthlySpendingsReportId id) { + super(id); + } + + @Subscribe + public void on(PurchaseOrderSent event) { + final List userOrderDetailsList = new ArrayList<>(); + + final PurchaseOrder purchaseOrder = event.getPurchaseOrder(); + purchaseOrder.getOrderList() + .forEach(order -> { + final List dishItemList = new ArrayList<>(); + final List dishList = order.getDishList(); + dishList.forEach(dish -> { + final DishItem dishItem = DishItem.newBuilder() + .setId(dish.getId()) + .setPrice(dish.getPrice()) + .setName(dish.getName()) + .build(); + dishItemList.add(dishItem); + }); + final UserId userId = order.getId() + .getUserId(); + final UserOrderDetails userOrderDetails = UserOrderDetails.newBuilder() + .setId(userId) + .addAllDish(dishItemList) + .setPurchaseOrderId( + event.getPurchaseOrder() + .getId()) + .build(); + userOrderDetailsList.add(userOrderDetails); + }); + getBuilder().addAllOrder(userOrderDetailsList); + final int year = event.getPurchaseOrder() + .getId() + .getPoDate() + .getYear(); + final MonthOfYear month = event.getPurchaseOrder() + .getId() + .getPoDate() + .getMonth(); + final LocalMonth localMonth = LocalMonth.newBuilder() + .setYear(year) + .setMonth(month) + .build(); + final MonthlySpendingsReportId monthlySpendingsReportId = MonthlySpendingsReportId.newBuilder() + .setMonth( + localMonth) + .build(); + getBuilder().setReportId(monthlySpendingsReportId); + } + + @Subscribe + public void on(PurchaseOrderDelivered event) { + final List orderDetailsList = getBuilder().getOrder(); + orderDetailsList.forEach(userOrderDetails -> { + if (userOrderDetails.getPurchaseOrderId() + .equals(event.getId())) { + long money = 0; + for (DishItem dishItem : userOrderDetails.getDishList()) { + money += dishItem.getPrice() + .getAmount(); + } + final int index = getUserSpendingsIndex(userOrderDetails.getId()); + if (index == -1) { + final Money cost = Money.newBuilder() + .setAmount(money) + .build(); + final UserSpendings spendings = UserSpendings.newBuilder() + .setAmount(cost) + .setId(userOrderDetails.getId()) + .build(); + getBuilder().addUserSpending(spendings); + getBuilder().removeOrder(getBuilder().getOrder() + .indexOf(userOrderDetails)); + } else { + final Money cost = Money.newBuilder() + .setAmount(getBuilder().getUserSpending() + .get(index) + .getAmount() + .getAmount() + money) + .build(); + final UserSpendings spendings = UserSpendings.newBuilder( + getBuilder().getUserSpending() + .get(index)) + .setAmount(cost) + .build(); + getBuilder().setUserSpending(index, spendings); + getBuilder().removeOrder(getBuilder().getOrder() + .indexOf(userOrderDetails)); + } + } + }); + } + + private int getUserSpendingsIndex(UserId id) { + final List userSpendingsList = getBuilder().getUserSpending(); + final OptionalInt optionalInt = IntStream.range(0, userSpendingsList.size()) + .filter(i -> userSpendingsList.get(i) + .getId() + .equals(id)) + .findFirst(); + return optionalInt.isPresent() ? optionalInt.getAsInt() : -1; + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/OrderListViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/OrderListViewProjection.java new file mode 100644 index 00000000..d529a756 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/OrderListViewProjection.java @@ -0,0 +1,130 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import com.google.common.collect.Iterables; +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.DishId; +import javaclasses.mealorder.OrderId; +import javaclasses.mealorder.OrderListId; +import javaclasses.mealorder.c.event.DishAddedToOrder; +import javaclasses.mealorder.c.event.DishRemovedFromOrder; +import javaclasses.mealorder.c.event.OrderCanceled; +import javaclasses.mealorder.c.event.OrderProcessed; +import javaclasses.mealorder.q.projection.OrderListView; +import javaclasses.mealorder.q.projection.OrderListViewVBuilder; + +import java.util.List; +import java.util.Optional; + +/** + * @author Alexander Karpets + */ +public class OrderListViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public OrderListViewProjection(OrderListId id) { + super(id); + } + + @Subscribe + public void on(DishAddedToOrder event) { + final OrderId orderId = event.getOrderId(); + final DishItem dish = DishItem.newBuilder() + .setName(event.getDish() + .getName()) + .setPrice(event.getDish() + .getPrice()) + .setId(event.getDish() + .getId()) + .build(); + if (getOrderById(orderId).isPresent()) { + getBuilder().setOrder(getBuilder().getOrder() + .indexOf(getOrderById(orderId).get()), + OrderItem.newBuilder(getOrderById(orderId).get()) + .addDish(dish) + .build()); + } else { + final OrderListId listId = OrderListId.newBuilder() + .setUserId(event.getOrderId() + .getUserId()) + .setOrderDate(event.getOrderId() + .getOrderDate()) + .build(); + getBuilder().addOrder(OrderItem.newBuilder() + .addDish(dish) + .setId(event.getOrderId()) + .build()); + getBuilder().setListId(listId); + } + } + + @Subscribe + public void on(DishRemovedFromOrder event) { + final List orderItems = getBuilder().getOrder(); + final int removeIndex = getDishIndexFromOrder(event.getDish() + .getId(), + getOrderById(event.getOrderId()).get()); + final OrderItem newOrder = OrderItem.newBuilder(getOrderById(event.getOrderId()).get()) + .removeDish(removeIndex) + .build(); + getBuilder().setOrder(orderItems.indexOf(getOrderById(event.getOrderId()).get()), newOrder); + } + + @Subscribe + public void on(OrderCanceled event) { + final OrderItem order = getOrderById(event.getOrderId()).get(); + getBuilder().removeOrder(getBuilder().getOrder() + .indexOf(order)); + } + + @Subscribe + public void on(OrderProcessed event) { + final OrderItem order = getOrderById(event.getOrder() + .getId()).get(); + getBuilder().setOrder(getBuilder().getOrder() + .indexOf(order), OrderItem.newBuilder(order) + .setIsProcessed(true) + .build()); + } + + private Optional getOrderById(OrderId orderId) { + final List orderItems = getBuilder().getOrder(); + final Optional inventoryItem = + orderItems.stream() + .filter(item -> item.getId() + .equals(orderId)) + .findFirst(); + return inventoryItem; + } + + private int getDishIndexFromOrder(DishId dishId, OrderItem order) { + final int index = Iterables.indexOf(order.getDishList(), dish -> dish.getId() + .equals(dishId)); + return index; + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/Projections.java b/api-java/src/main/java/javaclasses/mealorder/q/Projections.java new file mode 100644 index 00000000..422d8a6c --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/Projections.java @@ -0,0 +1,105 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.time.LocalDate; +import javaclasses.mealorder.CategoryName; +import javaclasses.mealorder.Dish; + +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalInt; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public final class Projections { + + /** + * The {@code private} constructor prevents the utility class instantiation. + */ + private Projections() { + } + + public static List getDatesBetween( + LocalDate startDate, LocalDate endDate) { + java.time.LocalDate start = java.time.LocalDate.of(startDate.getYear(), + startDate.getMonthValue(), + startDate.getDay()); + java.time.LocalDate end = java.time.LocalDate.of(endDate.getYear(), endDate.getMonthValue(), + endDate.getDay()); + long numOfDaysBetween = ChronoUnit.DAYS.between(start, end); + final List collect = IntStream.iterate(0, i -> i + 1) + .limit(numOfDaysBetween) + .mapToObj(i -> start.plusDays(i)) + .collect(Collectors.toList()); + return collect; + } + + public static LocalDate toLocalDate(java.time.LocalDate date) { + return LocalDate.newBuilder() + .setDay(date.getDayOfMonth()) + .setMonthValue(date.getMonthValue()) + .setYear(date.getYear()) + .build(); + } + + public static List getAllDishesByCategories( + List dishList) { + final List dishesByCategoryList = new ArrayList<>(); + dishList.forEach(dish -> { + final int index = categoryIndex(dishesByCategoryList, dish.getCategory()); + final DishItem newDish = DishItem.newBuilder() + .setId(dish.getId()) + .setName(dish.getName()) + .setPrice(dish.getPrice()) + .build(); + if (index == -1) { + final CategoryName category = CategoryName.newBuilder() + .setValue(dish.getCategory()) + .build(); + + final DishesByCategory dishesByCategory = DishesByCategory.newBuilder() + .setCategory(category) + .addDishes(newDish) + .build(); + dishesByCategoryList.add(dishesByCategory); + } else { + final DishesByCategory newDishesByCategory = DishesByCategory.newBuilder( + dishesByCategoryList.get(index)) + .addDishes(newDish) + .build(); + dishesByCategoryList.set(index, newDishesByCategory); + } + }); + return dishesByCategoryList; + } + + public static int categoryIndex(List dishByCategory, String category) { + final OptionalInt optionalInt = IntStream.range(0, dishByCategory.size()) + .filter(i -> dishByCategory.get(i) + .getCategory() + .getValue() + .equals(category)) + .findFirst(); + return optionalInt.isPresent() ? optionalInt.getAsInt() : -1; + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByDishViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByDishViewProjection.java new file mode 100644 index 00000000..cbe860fb --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByDishViewProjection.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.Order; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByDishView; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByDishViewVBuilder; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Alexander Karpets + */ +public class PurchaseOrderDetailsByDishViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public PurchaseOrderDetailsByDishViewProjection(PurchaseOrderId id) { + super(id); + } + + @Subscribe + public void on(PurchaseOrderCreated event) { + final List dishItems = getDishItems(event.getOrderList()); + getBuilder().addAllDish(dishItems); + getBuilder().setId(event.getId()); + } + + @Subscribe + public void on(PurchaseOrderDelivered event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.DELIVERED); + } + + @Subscribe + public void on(PurchaseOrderSent event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.SENT); + } + + @Subscribe + public void on(PurchaseOrderValidationFailed event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.INVALID); + } + + private List getDishItems(List orderList) { + final List dishItems = new ArrayList<>(); + orderList.forEach(order -> + order.getDishList() + .forEach(dish -> { + dishItems.add(DishItem.newBuilder() + .setName(dish.getName()) + .setPrice(dish.getPrice()) + .setId(dish.getId()) + .build()); + }) + ); + return dishItems; + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByUserViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByUserViewProjection.java new file mode 100644 index 00000000..381b6d92 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderDetailsByUserViewProjection.java @@ -0,0 +1,152 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.Order; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.UserId; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByUserView; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByUserViewVBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public class PurchaseOrderDetailsByUserViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public PurchaseOrderDetailsByUserViewProjection(PurchaseOrderId id) { + super(id); + } + + @Subscribe + public void on(PurchaseOrderCreated event) { + final List usersOrders = getUserOrders(event); + getBuilder().addAllOrder(usersOrders); + getBuilder().setId(event.getId()); + } + + @Subscribe + public void on(PurchaseOrderDelivered event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.DELIVERED); + } + + @Subscribe + public void on(PurchaseOrderSent event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.SENT); + } + + @Subscribe + public void on(PurchaseOrderValidationFailed event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.INVALID); + event.getFailureOrderList() + .forEach(order -> { + final UserId userId = order.getId() + .getUserId(); + final int index = getOrderIndexByUserId(userId); + final UserOrderDetails newOrder = UserOrderDetails.newBuilder( + getBuilder().getOrder() + .get(index)) + .setIsValid(false) + .build(); + getBuilder().setOrder(index, newOrder); + }); + } + + + private List getUserOrders(PurchaseOrderCreated event) { + final List dishes = new ArrayList<>(); + for (int i = 0; i < event.getOrderList() + .size(); i++) { + if (!userOrderDetailsHasUser(dishes, event.getOrderList() + .get(i) + .getId() + .getUserId())) { + final UserId user = event.getOrderList() + .get(i) + .getId() + .getUserId(); + final List dishItems = getDishItemsForUser(user, event.getOrderList()); + final UserOrderDetails dish = UserOrderDetails.newBuilder() + .setId(event.getOrderList() + .get(i) + .getId() + .getUserId()) + .addAllDish(dishItems) + .setIsValid(true) + .build(); + dishes.add(dish); + } + } + return dishes; + } + + private boolean userOrderDetailsHasUser(List dishes, + UserId userId) { + return dishes.stream() + .anyMatch(dish -> + dish.getId() + .equals(userId)); + } + + private List getDishItemsForUser(UserId user, List orderList) { + final List dishItems = new ArrayList<>(); + orderList.forEach(order -> { + if (order.getId() + .getUserId() + .equals(user)) { + order.getDishList() + .forEach(dish -> { + final DishItem dishItem = DishItem.newBuilder() + .setId(dish.getId()) + .setName(dish.getName()) + .setPrice(dish.getPrice()) + .build(); + dishItems.add(dishItem); + }); + } + }); + return dishItems; + } + + private int getOrderIndexByUserId(UserId userId) { + final List orders = getState().getOrderList(); + final int index = IntStream.range(0, orders.size()) + .filter(i -> orders.get(i) + .getId() + .equals(userId)) + .findFirst() + .getAsInt(); + return index; + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderItemViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderItemViewProjection.java new file mode 100644 index 00000000..5ddc70d1 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/PurchaseOrderItemViewProjection.java @@ -0,0 +1,77 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.entity.storage.Column; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.projection.PurchaseOrderItemView; +import javaclasses.mealorder.q.projection.PurchaseOrderItemViewVBuilder; + +import javax.annotation.Nullable; + +public class PurchaseOrderItemViewProjection extends Projection { + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public PurchaseOrderItemViewProjection(PurchaseOrderId id) { + super(id); + } + + @Column + @Nullable + public PurchaseOrderId getPurchaseOrderId() { + return getState().getId(); + } + + @Column + @Nullable + public PurchaseOrderStatus getPurchaseOrderStatus() { + return getState().getPurchaseOrderStatus(); + } + + @Subscribe + public void on(PurchaseOrderSent event) { + getBuilder().setId(event.getPurchaseOrder() + .getId()); + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.SENT); + } + + @Subscribe + public void on(PurchaseOrderDelivered event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.DELIVERED); + + } + + @Subscribe + public void on(PurchaseOrderValidationFailed event) { + getBuilder().setPurchaseOrderStatus(PurchaseOrderStatus.INVALID); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/VendorListViewProjection.java b/api-java/src/main/java/javaclasses/mealorder/q/VendorListViewProjection.java new file mode 100644 index 00000000..b21179b1 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/VendorListViewProjection.java @@ -0,0 +1,99 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q; + +import io.spine.core.Subscribe; +import io.spine.server.projection.Projection; +import javaclasses.mealorder.VendorId; +import javaclasses.mealorder.VendorListId; +import javaclasses.mealorder.c.event.VendorAdded; +import javaclasses.mealorder.c.event.VendorUpdated; +import javaclasses.mealorder.q.projection.VendorListView; +import javaclasses.mealorder.q.projection.VendorListViewVBuilder; + +import java.util.List; +import java.util.stream.IntStream; + +/** + * @author Alexander Karpets + */ +public class VendorListViewProjection extends Projection { + + /** + * {@link VendorListViewProjection} is a singleton. + * + *

The {@code ID} value should be the same for all JVMs + * to support work with the same projection from execution to execution. + */ + public static final VendorListId ID = VendorListId.newBuilder() + .setValue("VendorListViewProjectionSingleton") + .build(); + + /** + * Creates a new instance. + * + * @param id the ID for the new instance + * @throws IllegalArgumentException if the ID is not of one of the supported types + */ + public VendorListViewProjection(VendorListId id) { + super(id); + } + + @Subscribe + public void on(VendorAdded event) { + final VendorItem vendorItem = VendorItem.newBuilder() + .setId(event.getVendorId()) + .setEmail(event.getEmail()) + .setVendorName(event.getVendorName()) + .addAllPhoneNumber(event.getPhoneNumberList()) + .setPoDailyDeadline(event.getPoDailyDeadline()) + .build(); + getBuilder().addVendor(vendorItem); + } + + @Subscribe + public void on(VendorUpdated event) { + final VendorItem vendorItem = VendorItem.newBuilder() + .setId(event.getVendorId()) + .setEmail(event.getVendorChange() + .getNewEmail()) + .setVendorName(event.getVendorChange() + .getNewVendorName()) + .addAllPhoneNumber(event.getVendorChange() + .getNewPhoneNumberList()) + .setPoDailyDeadline(event.getVendorChange() + .getNewPoDailyDeadline()) + .build(); + getBuilder().setVendor(getVendorById(event.getVendorId()), vendorItem); + } + + private int getVendorById(VendorId vendorId) { + final List vendorList = getBuilder().getVendor(); + int index = IntStream.range(0, vendorList.size()) + .filter(i -> vendorList.get(i) + .getId() + .equals(vendorId)) + .findFirst() + .getAsInt(); + return index; + } +} + diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/FullMenuViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/FullMenuViewRepository.java new file mode 100644 index 00000000..c76e0465 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/FullMenuViewRepository.java @@ -0,0 +1,53 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.MenuId; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.q.FullMenuViewProjection; +import javaclasses.mealorder.q.projection.FullMenuView; + +import static java.util.Collections.singleton; + +public class FullMenuViewRepository extends ProjectionRepository { + + public FullMenuViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + final EventRouting routing = getEventRouting(); + routing.route(MenuImported.class, + (message, context) -> { + final MenuImported menuImported = (MenuImported) message; + return singleton(menuImported.getMenuId()); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuCalendarViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuCalendarViewRepository.java new file mode 100644 index 00000000..8e7abba3 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuCalendarViewRepository.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import javaclasses.mealorder.MenuCalendarId; +import javaclasses.mealorder.q.MenuCalendarViewProjection; +import javaclasses.mealorder.q.projection.MenuCalendarView; + +import static java.util.Collections.singleton; + +public class MenuCalendarViewRepository extends ProjectionRepository { + + public MenuCalendarViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + getEventRouting().replaceDefault( + ((message, context) -> singleton(MenuCalendarViewProjection.ID))); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuListViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuListViewRepository.java new file mode 100644 index 00000000..8307d902 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/MenuListViewRepository.java @@ -0,0 +1,53 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.MenuListId; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.q.MenuListViewProjection; +import javaclasses.mealorder.q.projection.MenuListView; + +import static java.util.Collections.singleton; + +public class MenuListViewRepository extends ProjectionRepository { + + public MenuListViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + final EventRouting routing = getEventRouting(); + routing.route(MenuImported.class, + (message, context) -> singleton(MenuListViewProjection.ID)); + routing.route(PurchaseOrderCreated.class, + (message, context) -> singleton(MenuListViewProjection.ID)); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/MonthlySpendingsReportViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/MonthlySpendingsReportViewRepository.java new file mode 100644 index 00000000..d574e791 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/MonthlySpendingsReportViewRepository.java @@ -0,0 +1,72 @@ +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import io.spine.time.MonthOfYear; +import javaclasses.mealorder.LocalMonth; +import javaclasses.mealorder.MonthlySpendingsReportId; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.q.MonthlySpendingsReportViewProjection; +import javaclasses.mealorder.q.projection.MonthlySpendingsReportView; + +import static java.util.Collections.singleton; + +public class MonthlySpendingsReportViewRepository extends ProjectionRepository { + + public MonthlySpendingsReportViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(PurchaseOrderSent.class, + (message, context) -> { + final PurchaseOrderSent purchaseOrderSent = (PurchaseOrderSent) message; + final int year = purchaseOrderSent.getPurchaseOrder() + .getId() + .getPoDate() + .getYear(); + final MonthOfYear month = purchaseOrderSent.getPurchaseOrder() + .getId() + .getPoDate() + .getMonth(); + final LocalMonth localMonth = LocalMonth.newBuilder() + .setYear(year) + .setMonth(month) + .build(); + final MonthlySpendingsReportId monthlySpendingsReportId = MonthlySpendingsReportId.newBuilder() + .setMonth( + localMonth) + .build(); + return singleton(monthlySpendingsReportId); + }); + routing.route(PurchaseOrderDelivered.class, + (message, context) -> { + final PurchaseOrderDelivered purchaseOrderDelivered = (PurchaseOrderDelivered) message; + final int year = purchaseOrderDelivered.getId() + .getPoDate() + .getYear(); + final MonthOfYear month = purchaseOrderDelivered.getId() + .getPoDate() + .getMonth(); + final LocalMonth localMonth = LocalMonth.newBuilder() + .setYear(year) + .setMonth(month) + .build(); + final MonthlySpendingsReportId monthlySpendingsReportId = MonthlySpendingsReportId.newBuilder() + .setMonth( + localMonth) + .build(); + return singleton(monthlySpendingsReportId); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/OrderListViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/OrderListViewRepository.java new file mode 100644 index 00000000..dfac8f4c --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/OrderListViewRepository.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import io.spine.time.LocalDate; +import javaclasses.mealorder.OrderListId; +import javaclasses.mealorder.UserId; +import javaclasses.mealorder.c.event.DishAddedToOrder; +import javaclasses.mealorder.c.event.DishRemovedFromOrder; +import javaclasses.mealorder.c.event.OrderCanceled; +import javaclasses.mealorder.c.event.OrderProcessed; +import javaclasses.mealorder.q.OrderListViewProjection; +import javaclasses.mealorder.q.projection.OrderListView; + +import static java.util.Collections.singleton; + +public class OrderListViewRepository extends ProjectionRepository { + + public OrderListViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(DishAddedToOrder.class, + (message, context) -> { + final LocalDate date = message.getOrderId() + .getOrderDate(); + final UserId userId = message.getOrderId() + .getUserId(); + final OrderListId orderListId = OrderListId.newBuilder() + .setOrderDate(date) + .setUserId(userId) + .build(); + return singleton(orderListId); + }); + routing.route(DishRemovedFromOrder.class, + (message, context) -> { + final LocalDate date = message.getOrderId() + .getOrderDate(); + final UserId userId = message.getOrderId() + .getUserId(); + final OrderListId orderListId = OrderListId.newBuilder() + .setOrderDate(date) + .setUserId(userId) + .build(); + return singleton(orderListId); + }); + routing.route(OrderCanceled.class, + (message, context) -> { + final LocalDate date = message.getOrderId() + .getOrderDate(); + final UserId userId = message.getOrderId() + .getUserId(); + final OrderListId orderListId = OrderListId.newBuilder() + .setOrderDate(date) + .setUserId(userId) + .build(); + return singleton(orderListId); + }); + routing.route(OrderProcessed.class, + (message, context) -> { + final LocalDate date = message.getOrder() + .getId() + .getOrderDate(); + final UserId userId = message.getOrder() + .getId() + .getUserId(); + final OrderListId orderListId = OrderListId.newBuilder() + .setOrderDate(date) + .setUserId(userId) + .build(); + return singleton(orderListId); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByDishViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByDishViewRepository.java new file mode 100644 index 00000000..66411924 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByDishViewRepository.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.PurchaseOrderDetailsByDishViewProjection; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByDishView; + +import static java.util.Collections.singleton; + +@SuppressWarnings("Duplicates") /* Has the same logic for routing as + PurchaseOrderDetailsByUserViewRepository*/ +public class PurchaseOrderDetailsByDishViewRepository extends ProjectionRepository { + + public PurchaseOrderDetailsByDishViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(PurchaseOrderCreated.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderDelivered.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderSent.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getPurchaseOrder() + .getId() + .getVendorId()) + .setPoDate( + message.getPurchaseOrder() + .getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderValidationFailed.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByUserViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByUserViewRepository.java new file mode 100644 index 00000000..0f558a9e --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderDetailsByUserViewRepository.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.PurchaseOrderDetailsByUserViewProjection; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByUserView; + +import static java.util.Collections.singleton; + +@SuppressWarnings("Duplicates") /* Has the same logic for routing as + PurchaseOrderDetailsByDishViewRepository*/ +public class PurchaseOrderDetailsByUserViewRepository extends ProjectionRepository { + + public PurchaseOrderDetailsByUserViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(PurchaseOrderCreated.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderDelivered.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderSent.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getPurchaseOrder() + .getId() + .getVendorId()) + .setPoDate( + message.getPurchaseOrder() + .getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderValidationFailed.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderItemViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderItemViewRepository.java new file mode 100644 index 00000000..67b7386b --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/PurchaseOrderItemViewRepository.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.PurchaseOrderItemViewProjection; +import javaclasses.mealorder.q.projection.PurchaseOrderItemView; + +import static java.util.Collections.singleton; + +public class PurchaseOrderItemViewRepository extends ProjectionRepository { + + public PurchaseOrderItemViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(PurchaseOrderSent.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getPurchaseOrder() + .getId() + .getVendorId()) + .setPoDate( + message.getPurchaseOrder() + .getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderDelivered.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + routing.route(PurchaseOrderValidationFailed.class, + (message, context) -> { + final PurchaseOrderId purchaseOrderId = PurchaseOrderId.newBuilder() + .setVendorId( + message.getId() + .getVendorId()) + .setPoDate( + message.getId() + .getPoDate()) + .build(); + return singleton(purchaseOrderId); + }); + } +} diff --git a/api-java/src/main/java/javaclasses/mealorder/q/repository/VendorListViewRepository.java b/api-java/src/main/java/javaclasses/mealorder/q/repository/VendorListViewRepository.java new file mode 100644 index 00000000..75fd36a6 --- /dev/null +++ b/api-java/src/main/java/javaclasses/mealorder/q/repository/VendorListViewRepository.java @@ -0,0 +1,54 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.repository; + +import io.spine.server.projection.ProjectionRepository; +import io.spine.server.route.EventRouting; +import javaclasses.mealorder.VendorListId; +import javaclasses.mealorder.c.event.VendorAdded; +import javaclasses.mealorder.c.event.VendorUpdated; +import javaclasses.mealorder.q.VendorListViewProjection; +import javaclasses.mealorder.q.projection.VendorListView; + +import static java.util.Collections.singleton; + +public class VendorListViewRepository extends ProjectionRepository { + + public VendorListViewRepository() { + super(); + setUpEventRoute(); + } + + /** + * Adds the {@link io.spine.server.route.EventRoute EventRoute}s to the repository. + * + *

Override this method in successor classes, otherwise all successors will use + * {@code MyListViewProjection.ID}. + */ + protected void setUpEventRoute() { + + final EventRouting routing = getEventRouting(); + routing.route(VendorAdded.class, + (message, context) -> singleton(VendorListViewProjection.ID)); + routing.route(VendorUpdated.class, + (message, context) -> singleton(VendorListViewProjection.ID)); + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/c/MealOrderTest.java b/api-java/src/test/java/javaclasses/mealorder/c/MealOrderTest.java index 56fcd878..f1c7cfde 100644 --- a/api-java/src/test/java/javaclasses/mealorder/c/MealOrderTest.java +++ b/api-java/src/test/java/javaclasses/mealorder/c/MealOrderTest.java @@ -30,63 +30,99 @@ import io.spine.server.BoundedContext; import io.spine.server.commandbus.CommandBus; import io.spine.server.entity.Repository; +import io.spine.time.MonthOfYear; +import javaclasses.mealorder.LocalMonth; +import javaclasses.mealorder.MonthlySpendingsReportId; +import javaclasses.mealorder.OrderListId; import javaclasses.mealorder.PurchaseOrder; import javaclasses.mealorder.PurchaseOrderSender; +import javaclasses.mealorder.PurchaseOrderStatus; import javaclasses.mealorder.ServiceFactory; +import javaclasses.mealorder.VendorListId; import javaclasses.mealorder.c.po.PurchaseOrderAggregate; +import javaclasses.mealorder.q.FullMenuViewProjection; +import javaclasses.mealorder.q.MenuCalendarItem; +import javaclasses.mealorder.q.MenuCalendarViewProjection; +import javaclasses.mealorder.q.MenuListViewProjection; +import javaclasses.mealorder.q.MonthlySpendingsReportViewProjection; +import javaclasses.mealorder.q.OrderListViewProjection; +import javaclasses.mealorder.q.PurchaseOrderDetailsByDishViewProjection; +import javaclasses.mealorder.q.PurchaseOrderDetailsByUserViewProjection; +import javaclasses.mealorder.q.PurchaseOrderItemViewProjection; +import javaclasses.mealorder.q.VendorListViewProjection; +import javaclasses.mealorder.q.projection.FullMenuView; +import javaclasses.mealorder.q.projection.MenuCalendarView; +import javaclasses.mealorder.q.projection.MenuListView; +import javaclasses.mealorder.q.projection.MonthlySpendingsReportView; +import javaclasses.mealorder.q.projection.OrderListView; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByDishView; +import javaclasses.mealorder.q.projection.PurchaseOrderDetailsByUserView; +import javaclasses.mealorder.q.projection.PurchaseOrderItemView; +import javaclasses.mealorder.q.projection.VendorListView; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Iterator; +import java.util.List; + import static io.spine.protobuf.TypeConverter.toMessage; import static javaclasses.mealorder.PurchaseOrderStatus.DELIVERED; +import static javaclasses.mealorder.PurchaseOrderStatus.INVALID; import static javaclasses.mealorder.testdata.TestOrderCommandFactory.addDishToOrderInstance; import static javaclasses.mealorder.testdata.TestOrderCommandFactory.createOrderInstance; import static javaclasses.mealorder.testdata.TestPurchaseOrderCommandFactory.createPurchaseOrderInstance; +import static javaclasses.mealorder.testdata.TestPurchaseOrderCommandFactory.createPurchaseOrderWithInvalidOrdersInstance; import static javaclasses.mealorder.testdata.TestPurchaseOrderCommandFactory.markPurchaseOrderAsDeliveredInstance; +import static javaclasses.mealorder.testdata.TestValues.DATE; +import static javaclasses.mealorder.testdata.TestValues.MENU_ID; +import static javaclasses.mealorder.testdata.TestValues.MENU_ID2; +import static javaclasses.mealorder.testdata.TestValues.NEW_VENDOR_NAME; import static javaclasses.mealorder.testdata.TestValues.PURCHASE_ORDER_ID; +import static javaclasses.mealorder.testdata.TestValues.USER_ID; import static javaclasses.mealorder.testdata.TestVendorCommandFactory.addVendorInstance; -import static javaclasses.mealorder.testdata.TestVendorCommandFactory.importMenuInstance; -import static javaclasses.mealorder.testdata.TestVendorCommandFactory.setDateRangeForMenuInstance; +import static javaclasses.mealorder.testdata.TestVendorCommandFactory.importMenuInstance2; +import static javaclasses.mealorder.testdata.TestVendorCommandFactory.importMenuInstance3; +import static javaclasses.mealorder.testdata.TestVendorCommandFactory.updateVendorInstance; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; @DisplayName("MealOrder Integration Test") class MealOrderTest { - private final ActorRequestFactory requestFactory = - TestActorRequestFactory.newInstance(getClass()); - - private final BoundedContext boundedContext = BoundedContexts.create(); - private final CommandBus commandBus = boundedContext.getCommandBus(); + private ActorRequestFactory requestFactory; + private CommandBus commandBus; + private BoundedContext boundedContext; + private MemoizingObserver observer; private Command createCommand(GeneratedMessageV3 message) { return getRequestFactory().command() .create(toMessage(message)); } + @DisplayName("Add vendor -> Import menu -> Set date range for menu ->" + + " Create order -> Add dish to order -> Create purchase order ->" + + " Mark purchase order as delivered ") @BeforeEach public void setUp() { + requestFactory = + TestActorRequestFactory.newInstance(getClass()); + observer = MemoizingObserver.newInstance(); + boundedContext = BoundedContexts.create(); + commandBus = boundedContext.getCommandBus(); + final PurchaseOrderSender purchaseOrderSenderMock = mock(PurchaseOrderSender.class); ServiceFactory.setPoSenderInstance(purchaseOrderSenderMock); - } - - @Test - @DisplayName("Add vendor -> Import menu -> Set date range for menu ->" + - " Create order -> Add dish to order -> Create purchase order ->" + - " Mark purchase order as delivered ") - void firstFlow() { - final MemoizingObserver observer = MemoizingObserver.newInstance(); final Command addVendor = createCommand(addVendorInstance()); commandBus.post(addVendor, observer); - final Command importMenu = createCommand(importMenuInstance()); + final Command importMenu = createCommand(importMenuInstance2()); commandBus.post(importMenu, observer); - - final Command setDateRangeForMenu = createCommand(setDateRangeForMenuInstance()); - commandBus.post(setDateRangeForMenu, observer); + final Command importMenu3 = createCommand(importMenuInstance3()); + commandBus.post(importMenu3, observer); final Command createOrderCommand = createCommand(createOrderInstance()); commandBus.post(createOrderCommand, observer); @@ -100,7 +136,11 @@ void firstFlow() { final Command markAsDeliveredCommand = createCommand( markPurchaseOrderAsDeliveredInstance()); commandBus.post(markAsDeliveredCommand, observer); + } + @Test + @DisplayName("Should change aggregates") + void checkAggregate() { assertNull(observer.getError()); final Optional purchaseOrderRepository = boundedContext.findRepository( @@ -116,6 +156,229 @@ void firstFlow() { .getStatus()); } + @Test + @DisplayName("Should change full menu projections") + void checkFullMenu() { + final Repository fullMenuRepository = boundedContext.findRepository(FullMenuView.class) + .get(); + + final FullMenuViewProjection fullMenu1 = (FullMenuViewProjection) fullMenuRepository.find( + MENU_ID) + .get(); + final FullMenuViewProjection fullMenu2 = (FullMenuViewProjection) fullMenuRepository.find( + MENU_ID2) + .get(); + assertNotEquals(fullMenu1.getState() + .getMenuId(), fullMenu2.getState() + .getMenuId()); + assertEquals(fullMenu1.getState() + .getDishesByCategoryList(), fullMenu2.getState() + .getDishesByCategoryList()); + } + + @Test + @DisplayName("Should change calendar repository") + void checkMenuCalendar() { + final Repository menuCalendarViewRepository = boundedContext.findRepository( + MenuCalendarView.class) + .get(); + final MenuCalendarViewProjection menuCalendarViewProjection = (MenuCalendarViewProjection) menuCalendarViewRepository.find( + MenuCalendarViewProjection.ID) + .get(); + final List calendarItemList = menuCalendarViewProjection.getState() + .getCalendarItemList(); + assertEquals(33, calendarItemList.size()); + assertEquals(13, calendarItemList.get(0) + .getDate() + .getDay()); + } + + @Test + @DisplayName("Should change menu list") + void checkMenuList() { + final Repository menuListViewRepository = boundedContext.findRepository( + MenuListView.class) + .get(); + + final MenuListViewProjection menuListViewProjection = (MenuListViewProjection) menuListViewRepository.find( + MenuListViewProjection.ID) + .get(); + assertEquals(33, menuListViewProjection.getState() + .getMenuList() + .size()); + } + + @Test + @DisplayName("Should change monthly spendings") + void checkMonthlySpendings() { + final Repository monthlySpendingsRepository = boundedContext.findRepository( + MonthlySpendingsReportView.class) + .get(); + + final LocalMonth localMonth = LocalMonth.newBuilder() + .setYear(2019) + .setMonth(MonthOfYear.FEBRUARY) + .build(); + final MonthlySpendingsReportViewProjection spendingsProjection = (MonthlySpendingsReportViewProjection) monthlySpendingsRepository.find( + MonthlySpendingsReportId.newBuilder() + .setMonth(localMonth) + .build()) + .get(); + spendingsProjection.getId(); + assertEquals("user@example.com", spendingsProjection.getState() + .getUserSpending(0) + .getId() + .getEmail() + .getValue()); + assertEquals(56, spendingsProjection.getState() + .getUserSpending(0) + .getAmount() + .getAmount()); + } + + @Test + @DisplayName("Should change order view") + void checkOrderView() { + final Repository orderListViewRepository = boundedContext.findRepository( + OrderListView.class) + .get(); + + final OrderListViewProjection orderListViewProjection = (OrderListViewProjection) orderListViewRepository.find( + OrderListId.newBuilder() + .setUserId(USER_ID) + .setOrderDate(DATE) + .build()) + .get(); + assertEquals("dishName1", orderListViewProjection.getState() + .getOrder(0) + .getDish(0) + .getName()); + } + + @Test + @DisplayName("Should change po by dish view") + void checkPoByDish() { + final Repository poDetailsByDishViewRepository = boundedContext.findRepository( + PurchaseOrderDetailsByDishView.class) + .get(); + final Iterator iterator = poDetailsByDishViewRepository.iterator(input -> true); + for (Iterator it = iterator; it.hasNext(); ) { + final Object o = it.next(); + } + final PurchaseOrderDetailsByDishViewProjection poDetailsByDishViewProjection = (PurchaseOrderDetailsByDishViewProjection) poDetailsByDishViewRepository.find( + PURCHASE_ORDER_ID) + .get(); + assertEquals(PurchaseOrderStatus.DELIVERED, poDetailsByDishViewProjection.getState() + .getPurchaseOrderStatus()); + assertEquals("dishName1", poDetailsByDishViewProjection.getState() + .getDishList() + .get(0) + .getName()); + } + + @Test + @DisplayName("Should change po by user view") + void checkPoByUser() { + final Repository poDetailsByUserViewRepository = boundedContext.findRepository( + PurchaseOrderDetailsByUserView.class) + .get(); + final PurchaseOrderDetailsByUserViewProjection poDetailsByUserViewProjection = (PurchaseOrderDetailsByUserViewProjection) poDetailsByUserViewRepository.find( + PURCHASE_ORDER_ID) + .get(); + assertEquals(1, poDetailsByUserViewProjection.getState() + .getOrderList() + .size()); + assertEquals("user@example.com", poDetailsByUserViewProjection.getState() + .getOrderList() + .get(0) + .getId() + .getEmail() + .getValue()); + assertEquals(1, poDetailsByUserViewProjection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + } + + @Test + @DisplayName("Should change po item view") + void checkPoItemView() { + final Repository poItemViewRepository = boundedContext.findRepository( + PurchaseOrderItemView.class) + .get(); + final PurchaseOrderItemViewProjection poItemViewProjection = (PurchaseOrderItemViewProjection) poItemViewRepository.find( + PURCHASE_ORDER_ID) + .get(); + assertEquals(DELIVERED, poItemViewProjection.getState() + .getPurchaseOrderStatus()); + assertEquals("vendor:value: \"VendorName1\"", poItemViewProjection.getState() + .getId() + .getVendorId() + .getValue() + .trim()); + } + + @Test + @DisplayName("Should change vendor list view") + void checkVendorList() { + final Repository vendorListViewRepository = boundedContext.findRepository( + VendorListView.class) + .get(); + final VendorListId vendorListId = VendorListViewProjection.ID; + final VendorListViewProjection vendorListViewProjection = (VendorListViewProjection) vendorListViewRepository.find( + vendorListId) + .get(); + assertEquals("VendorListViewProjectionSingleton", vendorListViewProjection.getId() + .getValue()); + assertEquals(2, vendorListViewProjection.getState() + .getVendorList() + .get(0) + .getPhoneNumberList() + .size()); + } + + @Test + @DisplayName("Should create invalid po") + void checkInvalidPo() { + final Command createInvalidPOCommand = createCommand( + createPurchaseOrderWithInvalidOrdersInstance()); + commandBus.post(createInvalidPOCommand, observer); + final Repository poItemViewRepository = boundedContext.findRepository( + PurchaseOrderItemView.class) + .get(); + final PurchaseOrderItemViewProjection poItemViewProjection = (PurchaseOrderItemViewProjection) poItemViewRepository.find( + PURCHASE_ORDER_ID) + .get(); + assertEquals(INVALID, poItemViewProjection.getState() + .getPurchaseOrderStatus()); + final Repository poDetailsByUserViewRepository = boundedContext.findRepository( + PurchaseOrderDetailsByUserView.class) + .get(); + final PurchaseOrderDetailsByUserViewProjection poDetailsByUserViewProjection = (PurchaseOrderDetailsByUserViewProjection) poDetailsByUserViewRepository.find( + PURCHASE_ORDER_ID) + .get(); + assertEquals(INVALID, poDetailsByUserViewProjection.getState() + .getPurchaseOrderStatus()); + } + + @Test + @DisplayName("Should updates vendor") + void checkUpdateVendor() { + final Command updateVendor = createCommand(updateVendorInstance()); + commandBus.post(updateVendor, observer); + final Repository vendorListViewRepository = boundedContext.findRepository( + VendorListView.class) + .get(); + final VendorListId vendorListId = VendorListViewProjection.ID; + final VendorListViewProjection vendorListViewProjection = (VendorListViewProjection) vendorListViewRepository.find( + vendorListId) + .get(); + assertEquals(NEW_VENDOR_NAME, vendorListViewProjection.getState() + .getVendorList() + .get(0) + .getVendorName()); + } private ActorRequestFactory getRequestFactory() { return requestFactory; } diff --git a/api-java/src/test/java/javaclasses/mealorder/c/order/OrderCommandTest.java b/api-java/src/test/java/javaclasses/mealorder/c/order/OrderCommandTest.java index 613802f7..d98507da 100644 --- a/api-java/src/test/java/javaclasses/mealorder/c/order/OrderCommandTest.java +++ b/api-java/src/test/java/javaclasses/mealorder/c/order/OrderCommandTest.java @@ -23,7 +23,6 @@ import io.spine.client.ActorRequestFactory; import io.spine.client.TestActorRequestFactory; import io.spine.core.Command; -import io.spine.grpc.StreamObservers; import io.spine.server.BoundedContext; import io.spine.server.commandbus.CommandBus; import io.spine.server.event.EventBus; @@ -62,10 +61,5 @@ private void executeVendorCommands(ActorRequestFactory requestFactory, CommandBu requestFactory.command() .create(TestVendorCommandFactory.importMenuInstance()); commandBus.post(importMenu, noOpObserver()); - - final Command setDateRangeForMenu = - requestFactory.command() - .create(TestVendorCommandFactory.setDateRangeForMenuInstance()); - commandBus.post(setDateRangeForMenu, noOpObserver()); } } diff --git a/api-java/src/test/java/javaclasses/mealorder/c/vendor/ImportMenuTest.java b/api-java/src/test/java/javaclasses/mealorder/c/vendor/ImportMenuTest.java index f638b8be..166faf55 100644 --- a/api-java/src/test/java/javaclasses/mealorder/c/vendor/ImportMenuTest.java +++ b/api-java/src/test/java/javaclasses/mealorder/c/vendor/ImportMenuTest.java @@ -20,12 +20,17 @@ package javaclasses.mealorder.c.vendor; +import com.google.common.base.Throwables; import com.google.protobuf.Message; import javaclasses.mealorder.Dish; +import javaclasses.mealorder.Menu; import javaclasses.mealorder.Vendor; import javaclasses.mealorder.c.command.AddVendor; import javaclasses.mealorder.c.command.ImportMenu; import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.c.rejection.CannotSetDateRange; +import javaclasses.mealorder.c.rejection.Rejections; +import javaclasses.mealorder.testdata.TestValues; import javaclasses.mealorder.testdata.TestVendorCommandFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -36,11 +41,19 @@ import static io.spine.server.aggregate.AggregateMessageDispatcher.dispatchCommand; import static javaclasses.mealorder.testdata.TestValues.DISH1; import static javaclasses.mealorder.testdata.TestValues.DISH2; +import static javaclasses.mealorder.testdata.TestValues.INVALID_MENU_DATE_RANGE; +import static javaclasses.mealorder.testdata.TestValues.MENU; +import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE; +import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE_FROM_PAST; import static javaclasses.mealorder.testdata.TestValues.MENU_ID; import static javaclasses.mealorder.testdata.TestValues.USER_ID; import static javaclasses.mealorder.testdata.TestValues.VENDOR_ID; +import static javaclasses.mealorder.testdata.TestVendorCommandFactory.importMenuInstance; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author Yurii Haidamaka @@ -60,14 +73,15 @@ void produceEvent() { final AddVendor addVendorCmd = TestVendorCommandFactory.addVendorInstance(); dispatchCommand(aggregate, envelopeOf(addVendorCmd)); - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); + final ImportMenu importMenu = importMenuInstance(); final List messageList = dispatchCommand(aggregate, envelopeOf(importMenu)); assertNotNull(aggregate.getId()); assertEquals(1, messageList.size()); - assertEquals(MenuImported.class, messageList.get(0).getClass()); + assertEquals(MenuImported.class, messageList.get(0) + .getClass()); final MenuImported menuImported = (MenuImported) messageList.get(0); @@ -86,10 +100,133 @@ void importMenu() { final AddVendor addVendorCmd = TestVendorCommandFactory.addVendorInstance(); dispatchCommand(aggregate, envelopeOf(addVendorCmd)); - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); + final ImportMenu importMenu = importMenuInstance(); dispatchCommand(aggregate, envelopeOf(importMenu)); final Vendor state = aggregate.getState(); assertEquals(state.getId(), importMenu.getVendorId()); } + + @Test + @DisplayName("create correct date range") + void createEvent() { + final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); + dispatchCommand(aggregate, envelopeOf(addVendor)); + final ImportMenu importMenu = importMenuInstance(); + final List messageList = + dispatchCommand(aggregate, envelopeOf(importMenu)); + + assertNotNull(aggregate.getId()); + assertEquals(1, messageList.size()); + assertEquals(MenuImported.class, messageList.get(0) + .getClass()); + + final MenuImported menuImported = (MenuImported) messageList.get(0); + + assertEquals(VENDOR_ID, menuImported.getVendorId()); + assertEquals(MENU_ID, menuImported.getMenuId()); + assertEquals(USER_ID, menuImported.getWhoImported()); + assertEquals(MENU_DATE_RANGE, menuImported.getMenuDateRange()); + } + + @Test + @DisplayName("set date range for menu") + void setDateRange() { + final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); + dispatchCommand(aggregate, envelopeOf(addVendor)); + + final ImportMenu importMenu = importMenuInstance(); + dispatchCommand(aggregate, envelopeOf(importMenu)); + + final Vendor state = aggregate.getState(); + assertEquals(state.getId(), importMenu.getVendorId()); + + final Menu menu = state.getMenuList() + .stream() + .filter(m -> m.getId() + .equals(importMenu.getMenuId())) + .findFirst() + .get(); + + assertEquals(VENDOR_ID, importMenu.getVendorId()); + assertEquals(MENU_ID, importMenu.getMenuId()); + assertEquals(USER_ID, importMenu.getUserId()); + assertEquals(menu.getMenuDateRange(), importMenu.getMenuDateRange()); + assertEquals(importMenu.getMenuDateRange(), state.getMenuList() + .get(0) + .getMenuDateRange()); + } + + @Test + @DisplayName("produce `CannotSetDateRange` rejection if date range is not valid") + void produceRejection() { + final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); + dispatchCommand(aggregate, envelopeOf(addVendor)); + + final ImportMenu invalidImportMenu = + importMenuInstance(VENDOR_ID, USER_ID, MENU_ID, INVALID_MENU_DATE_RANGE, + TestValues.MENU); + + final Throwable t = assertThrows(Throwable.class, + () -> dispatchCommand(aggregate, + envelopeOf( + invalidImportMenu))); + final Throwable cause = Throwables.getRootCause(t); + assertThat(cause, instanceOf(CannotSetDateRange.class)); + + @SuppressWarnings("ConstantConditions") // Instance type checked before. + final Rejections.CannotSetDateRange rejection = + ((CannotSetDateRange) cause).getMessageThrown(); + + assertEquals(invalidImportMenu.getVendorId(), rejection.getVendorId()); + assertEquals(invalidImportMenu.getMenuId(), rejection.getMenuId()); + assertEquals(invalidImportMenu.getMenuDateRange(), rejection.getMenuDateRange()); + } + + @Test + @DisplayName("produce `CannotSetDateRange` rejection if the order date is from the past") + void produceCannotSetDateRangeRejection() { + final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); + dispatchCommand(aggregate, envelopeOf(addVendor)); + final ImportMenu importMenu = importMenuInstance(); + dispatchCommand(aggregate, envelopeOf(importMenu)); + final ImportMenu importMenuFromPast = + importMenuInstance(VENDOR_ID, USER_ID, MENU_ID, MENU_DATE_RANGE_FROM_PAST, MENU); + + final Throwable t = + assertThrows(Throwable.class, () -> dispatchCommand(aggregate, + envelopeOf( + importMenuFromPast))); + final Throwable cause = Throwables.getRootCause(t); + + @SuppressWarnings("ConstantConditions") // Instance type checked before. + final Rejections.CannotSetDateRange rejection = + ((CannotSetDateRange) cause).getMessageThrown(); + + assertEquals(importMenuFromPast.getVendorId(), rejection.getVendorId()); + assertEquals(importMenuFromPast.getMenuId(), rejection.getMenuId()); + assertEquals(importMenuFromPast.getMenuDateRange(), rejection.getMenuDateRange()); + } + + @Test + @DisplayName("produce `CannotSetDateRange` rejection if vendor already has menu on this date range") + void produceRejectionIfMenuExists() { + final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); + dispatchCommand(aggregate, envelopeOf(addVendor)); + final ImportMenu importMenu = importMenuInstance(); + dispatchCommand(aggregate, envelopeOf(importMenu)); + + final Throwable t = assertThrows(Throwable.class, + () -> dispatchCommand(aggregate, envelopeOf(importMenu))); + final Throwable cause = Throwables.getRootCause(t); + assertThat(cause, instanceOf(CannotSetDateRange.class)); + + @SuppressWarnings("ConstantConditions") // Instance type checked before. + final Rejections.CannotSetDateRange rejection = + ((CannotSetDateRange) cause).getMessageThrown(); + + assertEquals(importMenu.getVendorId(), rejection.getVendorId()); + assertEquals(importMenu.getMenuId(), rejection.getMenuId()); + assertEquals(importMenu.getMenuDateRange(), rejection.getMenuDateRange()); + } } diff --git a/api-java/src/test/java/javaclasses/mealorder/c/vendor/SetDateRangeForMenuTest.java b/api-java/src/test/java/javaclasses/mealorder/c/vendor/SetDateRangeForMenuTest.java deleted file mode 100644 index 4a3e4a34..00000000 --- a/api-java/src/test/java/javaclasses/mealorder/c/vendor/SetDateRangeForMenuTest.java +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright 2018, TeamDev Ltd. All rights reserved. -// -// Redistribution and use in source and/or binary gorms, with or without -// modification, must retain the above copyright notice and the following -// disclaimer. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -package javaclasses.mealorder.c.vendor; - -import com.google.common.base.Throwables; -import com.google.protobuf.Message; -import javaclasses.mealorder.Menu; -import javaclasses.mealorder.Vendor; -import javaclasses.mealorder.c.command.AddVendor; -import javaclasses.mealorder.c.command.ImportMenu; -import javaclasses.mealorder.c.command.SetDateRangeForMenu; -import javaclasses.mealorder.c.event.DateRangeForMenuSet; -import javaclasses.mealorder.c.rejection.CannotSetDateRange; -import javaclasses.mealorder.c.rejection.Rejections; -import javaclasses.mealorder.testdata.TestVendorCommandFactory; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static io.spine.server.aggregate.AggregateMessageDispatcher.dispatchCommand; -import static javaclasses.mealorder.testdata.TestValues.INVALID_MENU_DATE_RANGE; -import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE; -import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE_FROM_PAST; -import static javaclasses.mealorder.testdata.TestValues.MENU_ID; -import static javaclasses.mealorder.testdata.TestValues.USER_ID; -import static javaclasses.mealorder.testdata.TestValues.VENDOR_ID; -import static javaclasses.mealorder.testdata.TestVendorCommandFactory.setDateRangeForMenuInstance; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -/** - * @author Yurii Haidamaka - */ -@DisplayName("`SetDateRangeForMenu` command should be interpreted by `VendorAggregate` and") -public class SetDateRangeForMenuTest extends VendorCommandTest { - - @Override - @BeforeEach - public void setUp() { - super.setUp(); - } - - @Test - @DisplayName("produce `DateRangeForMenuSet` event") - void produceEvent() { - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); - dispatchCommand(aggregate, envelopeOf(importMenu)); - - final SetDateRangeForMenu setDateRangeForMenuCmd = - TestVendorCommandFactory.setDateRangeForMenuInstance(); - - final List messageList = - dispatchCommand(aggregate, envelopeOf(setDateRangeForMenuCmd)); - - assertNotNull(aggregate.getId()); - assertEquals(1, messageList.size()); - assertEquals(DateRangeForMenuSet.class, messageList.get(0) - .getClass()); - - final DateRangeForMenuSet dateRangeForMenuSet = (DateRangeForMenuSet) messageList.get(0); - - assertEquals(VENDOR_ID, dateRangeForMenuSet.getVendorId()); - assertEquals(MENU_ID, dateRangeForMenuSet.getMenuId()); - assertEquals(USER_ID, dateRangeForMenuSet.getWhoSet()); - assertEquals(MENU_DATE_RANGE, dateRangeForMenuSet.getMenuDateRange()); - } - - @Test - @DisplayName("set date range for menu") - void setDateRange() { - final AddVendor addVendor = TestVendorCommandFactory.addVendorInstance(); - dispatchCommand(aggregate, envelopeOf(addVendor)); - - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); - dispatchCommand(aggregate, envelopeOf(importMenu)); - - final SetDateRangeForMenu setDateRangeForMenu = TestVendorCommandFactory.setDateRangeForMenuInstance(); - dispatchCommand(aggregate, envelopeOf(setDateRangeForMenu)); - - final Vendor state = aggregate.getState(); - assertEquals(state.getId(), setDateRangeForMenu.getVendorId()); - - final Menu menu = state.getMenuList() - .stream() - .filter(m -> m.getId() - .equals(setDateRangeForMenu.getMenuId())) - .findFirst() - .get(); - - assertEquals(VENDOR_ID, setDateRangeForMenu.getVendorId()); - assertEquals(MENU_ID, setDateRangeForMenu.getMenuId()); - assertEquals(USER_ID, setDateRangeForMenu.getUserId()); - assertEquals(menu.getMenuDateRange(), setDateRangeForMenu.getMenuDateRange()); - } - - @Test - @DisplayName("produce `CannotSetDateRange` rejection if date range is not valid") - void produceRejection() { - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); - dispatchCommand(aggregate, envelopeOf(importMenu)); - - final SetDateRangeForMenu setInvalidDateRangeForMenu = - setDateRangeForMenuInstance(VENDOR_ID, MENU_ID, USER_ID, INVALID_MENU_DATE_RANGE); - - final Throwable t = assertThrows(Throwable.class, - () -> dispatchCommand(aggregate, - envelopeOf( - setInvalidDateRangeForMenu))); - final Throwable cause = Throwables.getRootCause(t); - assertThat(cause, instanceOf(CannotSetDateRange.class)); - - @SuppressWarnings("ConstantConditions") // Instance type checked before. - final Rejections.CannotSetDateRange rejection = - ((CannotSetDateRange) cause).getMessageThrown(); - - assertEquals(setInvalidDateRangeForMenu.getVendorId(), rejection.getVendorId()); - assertEquals(setInvalidDateRangeForMenu.getMenuId(), rejection.getMenuId()); - assertEquals(setInvalidDateRangeForMenu.getMenuDateRange(), rejection.getMenuDateRange()); - } - - @Test - @DisplayName("produce `CannotSetDateRange` rejection if the order date is from the past") - void produceCannotSetDateRangeRejection() { - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); - dispatchCommand(aggregate, envelopeOf(importMenu)); - - final SetDateRangeForMenu setRangeFromPast = - setDateRangeForMenuInstance(VENDOR_ID, MENU_ID, USER_ID, MENU_DATE_RANGE_FROM_PAST); - - final Throwable t = - assertThrows(Throwable.class, () -> dispatchCommand(aggregate, - envelopeOf(setRangeFromPast))); - final Throwable cause = Throwables.getRootCause(t); - - @SuppressWarnings("ConstantConditions") // Instance type checked before. - final Rejections.CannotSetDateRange rejection = - ((CannotSetDateRange) cause).getMessageThrown(); - - assertEquals(setRangeFromPast.getVendorId(), rejection.getVendorId()); - assertEquals(setRangeFromPast.getMenuId(), rejection.getMenuId()); - assertEquals(setRangeFromPast.getMenuDateRange(), rejection.getMenuDateRange()); - } - - @Test - @DisplayName("produce `CannotSetDateRange` rejection if vendor already has menu on this date range") - void produceRejectionIfMenuExists() { - final ImportMenu importMenu = TestVendorCommandFactory.importMenuInstance(); - dispatchCommand(aggregate, envelopeOf(importMenu)); - - final SetDateRangeForMenu setRange = TestVendorCommandFactory.setDateRangeForMenuInstance(); - dispatchCommand(aggregate, envelopeOf(setRange)); - - final Throwable t = assertThrows(Throwable.class, - () -> dispatchCommand(aggregate, envelopeOf(setRange))); - final Throwable cause = Throwables.getRootCause(t); - assertThat(cause, instanceOf(CannotSetDateRange.class)); - - @SuppressWarnings("ConstantConditions") // Instance type checked before. - final Rejections.CannotSetDateRange rejection = - ((CannotSetDateRange) cause).getMessageThrown(); - - assertEquals(setRange.getVendorId(), rejection.getVendorId()); - assertEquals(setRange.getMenuId(), rejection.getMenuId()); - assertEquals(setRange.getMenuDateRange(), rejection.getMenuDateRange()); - } -} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/FullMenuViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/FullMenuViewProjectionTest.java new file mode 100644 index 00000000..968b11f6 --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/FullMenuViewProjectionTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.q.FullMenuViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.VendorEvents.menuImportedInstance; +import static javaclasses.mealorder.testdata.TestValues.MENU_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FullMenuViewProjectionTest extends ProjectionTest { + private FullMenuViewProjection projection; + + @BeforeEach + void setUp() { + projection = new FullMenuViewProjection(MENU_ID); + } + + @Nested + @DisplayName("MenuImported event should be interpreted by FullMenuViewProjection") + class MenuImportedEvent { + + @Test + @DisplayName("Should set dates with menus") + void addView() { + final MenuImported menuImported = menuImportedInstance(); + dispatch(projection, createEvent(menuImported)); + + assertEquals(menuImported.getMenuId(), projection.getState() + .getMenuId()); + assertEquals(menuImported.getMenuDateRange(), projection.getState() + .getMenuDateRange()); + assertEquals(3, projection.getState() + .getDishesByCategoryList() + .size()); + + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuCalendarViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuCalendarViewProjectionTest.java new file mode 100644 index 00000000..2b7dd324 --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuCalendarViewProjectionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.q.MenuCalendarItem; +import javaclasses.mealorder.q.MenuCalendarViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.VendorEvents.menuImportedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MenuCalendarViewProjectionTest extends ProjectionTest { + private MenuCalendarViewProjection projection; + + @BeforeEach + void setUp() { + projection = new MenuCalendarViewProjection(MenuCalendarViewProjection.ID); + } + + @Nested + @DisplayName("MenuImported event should be interpreted by MenuCalendarViewProjection") + class MenuImportedEvent { + + @Test + @DisplayName("Should set dates with menus") + void addView() { + final MenuImported menuImported = menuImportedInstance(); + dispatch(projection, createEvent(menuImported)); + final List calendarItems = projection.getState() + .getCalendarItemList(); + assertEquals(25, calendarItems.size()); + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuListViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuListViewProjectionTest.java new file mode 100644 index 00000000..1f6e14ef --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/MenuListViewProjectionTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.q.MenuItem; +import javaclasses.mealorder.q.MenuListViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderCreatedInstance2; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.VendorEvents.menuImportedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MenuListViewProjectionTest extends ProjectionTest { + private MenuListViewProjection projection; + + @BeforeEach + void setUp() { + projection = new MenuListViewProjection(MenuListViewProjection.ID); + } + + @Nested + @DisplayName("MenuImported event should be interpreted by MenuListViewProjection") + class MenuImportedEvent { + @Test + @DisplayName("Should import menu") + void addView() { + final MenuImported menuImported = menuImportedInstance(); + dispatch(projection, createEvent(menuImported)); + final List menuList = projection.getState() + .getMenuList(); + assertEquals(menuList.get(1) + .getDishesByCategoryList(), menuList.get(0) + .getDishesByCategoryList()); + assertEquals(25, menuList.size()); + assertEquals(27, menuList.get(5) + .getMenuDate() + .getDay()); + assertEquals(2020, menuList.get(5) + .getMenuDate() + .getYear()); + assertEquals(2, menuList.get(5) + .getMenuDate() + .getMonthValue()); + assertEquals(true, menuList.get(5) + .getIsAvilable()); + } + + @Test + @DisplayName("Should disable menu") + void addView2() { + final MenuImported menuImported = menuImportedInstance(); + dispatch(projection, createEvent(menuImported)); + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance2(); + dispatch(projection, createEvent(purchaseOrderCreated)); + assertFalse(projection.getState() + .getMenuList() + .get(10) + .getIsAvilable()); + assertTrue(projection.getState() + .getMenuList() + .get(19) + .getIsAvilable()); + } + } +} + diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/MonthlySpendingsReportViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/MonthlySpendingsReportViewProjectionTest.java new file mode 100644 index 00000000..3bc37aba --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/MonthlySpendingsReportViewProjectionTest.java @@ -0,0 +1,147 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.LocalMonth; +import javaclasses.mealorder.MonthlySpendingsReportId; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.q.MonthlySpendingsReportViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderDeliveredInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderDeliveredInstance2; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderSentInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderSentInstance2; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MonthlySpendingsReportViewProjectionTest extends ProjectionTest { + + private MonthlySpendingsReportViewProjection projection; + + @BeforeEach + void setUp() { + final LocalMonth localMonth = LocalMonth.newBuilder() + .setMonthValue(2) + .setYear(2019) + .build(); + + projection = new MonthlySpendingsReportViewProjection(MonthlySpendingsReportId.newBuilder() + .setMonth( + localMonth) + .build()); + } + + @Nested + @DisplayName("PurchaseOrderSent event should be interpreted by MonthlySpendingsReportViewProjection") + class PurchaseOrderSentEvent { + @Test + @DisplayName("Should add orders for a projection") + void addView() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + assertEquals(1 , projection.getState().getOrderCount()); + assertEquals(1, projection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + assertEquals(0, projection.getState() + .getUserSpendingList() + .size()); + } + + @Test + @DisplayName("Should add compicated orders for a projection") + void addView2() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + final PurchaseOrderSent purchaseOrderSent2 = purchaseOrderSentInstance2(); + dispatch(projection, createEvent(purchaseOrderSent2)); + assertEquals(5, projection.getState() + .getOrderCount()); + assertEquals(1, projection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + assertEquals(0, projection.getState() + .getUserSpendingList() + .size()); + assertEquals(2, projection.getState() + .getOrderList() + .get(3) + .getDishList() + .size()); + } + } + + @Nested + @DisplayName("PurchaseOrderDelivered event should be interpreted by MonthlySpendingsReportViewProjection") + class PurchaseOrderDeliveredEvent { + @Test + @DisplayName("Should add user's spendings for a projection") + void addView() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + final PurchaseOrderSent purchaseOrderSent2 = purchaseOrderSentInstance2(); + dispatch(projection, createEvent(purchaseOrderSent2)); + final PurchaseOrderDelivered purchaseOrderDelivered = purchaseOrderDeliveredInstance(); + final PurchaseOrderDelivered purchaseOrderDelivered2 = purchaseOrderDeliveredInstance2(); + + dispatch(projection, createEvent(purchaseOrderDelivered)); + assertEquals("user@example.com", projection.getState() + .getUserSpendingList() + .get(0) + .getId() + .getEmail() + .getValue()); + assertEquals(56, projection.getState() + .getUserSpendingList() + .get(0) + .getAmount() + .getAmount()); + assertEquals(1, projection.getState() + .getUserSpendingList() + .size()); + + dispatch(projection, createEvent(purchaseOrderDelivered2)); + assertEquals(336, projection.getState() + .getUserSpendingList() + .get(0) + .getAmount() + .getAmount()); + assertEquals(2, projection.getState() + .getUserSpendingList() + .size()); + assertEquals(448, projection.getState() + .getUserSpendingList() + .get(1) + .getAmount() + .getAmount()); + } + } + +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/OrderListViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/OrderListViewProjectionTest.java new file mode 100644 index 00000000..f73bfe93 --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/OrderListViewProjectionTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.OrderListId; +import javaclasses.mealorder.c.event.DishAddedToOrder; +import javaclasses.mealorder.c.event.DishRemovedFromOrder; +import javaclasses.mealorder.c.event.OrderCanceled; +import javaclasses.mealorder.c.event.OrderProcessed; +import javaclasses.mealorder.q.OrderListViewProjection; +import javaclasses.mealorder.testdata.TestValues; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.OrderEvents.dishAddedToOrderInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.OrderEvents.dishAddedToOrderInstance2; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.OrderEvents.dishRemovedFromOrderInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.OrderEvents.orderCanceledInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.OrderEvents.orderProcessedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class OrderListViewProjectionTest extends ProjectionTest { + private OrderListViewProjection projection; + + @BeforeEach + void setUp() { + projection = new OrderListViewProjection(OrderListId.newBuilder() + .setUserId(TestValues.USER_ID) + .setOrderDate(TestValues.DATE) + .build()); + } + + @Nested + @DisplayName("DishAddedToOrder event should be interpreted by OrderListViewProjection") + class DishAddedToOrderEvent { + + @Test + @DisplayName("Should add dish to the order") + void addDish() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + + assertEquals(1, projection.getState() + .getOrderList() + .size()); + assertEquals("dishName1", projection.getState() + .getOrderList() + .get(0) + .getDishList() + .get(0) + .getName()); + } + + @Test + @DisplayName("Should add 3 dishes to the order") + void addThreeDishes() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + dispatch(projection, createEvent(dishAddedToOrder)); + dispatch(projection, createEvent(dishAddedToOrder)); + + assertEquals(3, projection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + assertEquals("dishName1", projection.getState() + .getOrderList() + .get(0) + .getDishList() + .get(2) + .getName()); + } + + @Test + @DisplayName("Should add 2 dishes to different orders") + void addTwoDishes() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + final DishAddedToOrder dishAddedToOrder2 = dishAddedToOrderInstance2(); + dispatch(projection, createEvent(dishAddedToOrder2)); + + assertEquals(2, projection.getState() + .getOrderList() + .size()); + assertEquals(1, projection.getState() + .getOrderList() + .get(1) + .getDishList() + .size()); + assertEquals("dishName1", projection.getState() + .getOrderList() + .get(0) + .getDish(0) + .getName()); + assertEquals("dishName2", projection.getState() + .getOrderList() + .get(1) + .getDish(0) + .getName()); + } + } + + @Nested + @DisplayName("DishAddedToOrder event should be interpreted by OrderListViewProjection") + class DishRemovedFromOrderEvent { + @Test + @DisplayName("Should remove 1 dish from the correct order") + void remove() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + dispatch(projection, createEvent(dishAddedToOrder)); + final DishAddedToOrder dishAddedToOrder2 = dishAddedToOrderInstance2(); + dispatch(projection, createEvent(dishAddedToOrder2)); + assertEquals(2, projection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + final DishRemovedFromOrder dishRemovedFromOrder = dishRemovedFromOrderInstance(); + dispatch(projection, createEvent(dishRemovedFromOrder)); + assertEquals(1, projection.getState() + .getOrderList() + .get(0) + .getDishList() + .size()); + assertEquals(1, projection.getState() + .getOrderList() + .get(1) + .getDishList() + .size()); + } + } + + @Nested + @DisplayName("OrderCanceled event should be interpreted by OrderListViewProjection") + class OrderCanceledEvent { + @Test + @DisplayName("Should remove correct order ") + void remove() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + final OrderCanceled orderCanceled = orderCanceledInstance(); + dispatch(projection, createEvent(orderCanceled)); + assertEquals(0, projection.getState() + .getOrderList() + .size()); + } + } + + @Nested + @DisplayName("OrderProcessed event should be interpreted by OrderListViewProjection") + class OrderProcessedEvent { + @Test + @DisplayName("Should process correct order") + void remove() { + final DishAddedToOrder dishAddedToOrder = dishAddedToOrderInstance(); + dispatch(projection, createEvent(dishAddedToOrder)); + final OrderProcessed orderProcessed = orderProcessedInstance(); + dispatch(projection, createEvent(orderProcessed)); + assertEquals(true, projection.getState() + .getOrderList() + .get(0) + .getIsProcessed()); + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionTest.java new file mode 100644 index 00000000..b315216a --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import com.google.protobuf.Message; +import io.spine.core.Event; +import io.spine.server.command.TestEventFactory; +import io.spine.server.event.EventFactory; + +abstract class ProjectionTest { + + private final EventFactory eventFactory = TestEventFactory.newInstance(getClass()); + + Event createEvent(Message messageOrAny) { + final Event event = eventFactory.createEvent(messageOrAny, null); + return event; + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionsTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionsTest.java new file mode 100644 index 00000000..e86a3d4b --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/ProjectionsTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.q.Projections; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static io.spine.test.Tests.assertHasPrivateParameterlessCtor; + +@DisplayName("Projections should") +public class ProjectionsTest { + @Test + @DisplayName("have the private constructor") + void havePrivateConstructor() { + assertHasPrivateParameterlessCtor(Projections.class); + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByDishViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByDishViewProjectionTest.java new file mode 100644 index 00000000..00b24924 --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByDishViewProjectionTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import io.spine.time.LocalDate; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.VendorId; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.DishItem; +import javaclasses.mealorder.q.PurchaseOrderDetailsByDishViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderCreatedInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderDeliveredInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderSentInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderValidationFailedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PurchaseOrderDetailsByDishViewProjectionTest extends ProjectionTest { + private PurchaseOrderDetailsByDishViewProjection projection; + + @BeforeEach + void setUp() { + projection = new PurchaseOrderDetailsByDishViewProjection(PurchaseOrderId.newBuilder() + .setPoDate( + LocalDate.newBuilder() + .setDay(14) + .build()) + .setVendorId( + VendorId.newBuilder() + .setValue( + "Пюре") + .build()) + .build()); + } + + @Nested + @DisplayName("PurchaseOrderCreated event should be interpreted by PurchaseOrderDetailsByDishViewProjection") + class PurchaseOrderCreatedEvent { + + @Test + @DisplayName("Should set order for a projection") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final List dishes = projection.getState() + .getDishList(); + assertEquals(13, dishes.size()); + assertEquals("vendor:value: \"VendorName1\"\n", projection.getState() + .getId() + .getVendorId() + .getValue()); + } + } + + @Nested + @DisplayName("PurchaseOrderSent event should be interpreted by PurchaseOrderDetailsByDishViewProjection") + class PurchaseOrderValidationFailedEvent { + + @Test + @DisplayName("Should change status for a projection") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderValidationFailed poValidationFailed = purchaseOrderValidationFailedInstance(); + dispatch(projection, createEvent(poValidationFailed)); + assertEquals(PurchaseOrderStatus.INVALID, projection.getState() + .getPurchaseOrderStatus()); + } + } + + @Nested + @DisplayName("PurchaseOrderSent event should be interpreted by PurchaseOrderDetailsByDishViewProjection") + class PurchaseOrderSentEvent { + + @Test + @DisplayName("Should set status for a projection") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + assertEquals(PurchaseOrderStatus.SENT, projection.getState() + .getPurchaseOrderStatus()); + } + } + @Nested + @DisplayName("PurchaseOrderDelivered event should be interpreted by PurchaseOrderDetailsByDishViewProjection") + class PurchaseOrderDeliveredEvent { + + @Test + @DisplayName("Should change existing status for a projection") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + assertEquals(PurchaseOrderStatus.SENT, projection.getState() + .getPurchaseOrderStatus()); + + final PurchaseOrderDelivered purchaseOrderDelivered = purchaseOrderDeliveredInstance(); + dispatch(projection, createEvent(purchaseOrderDelivered)); + assertEquals(PurchaseOrderStatus.DELIVERED, projection.getState() + .getPurchaseOrderStatus()); + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByUserViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByUserViewProjectionTest.java new file mode 100644 index 00000000..e6afc0a3 --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderDetailsByUserViewProjectionTest.java @@ -0,0 +1,166 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import io.spine.time.LocalDate; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.VendorId; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.PurchaseOrderDetailsByUserViewProjection; +import javaclasses.mealorder.q.UserOrderDetails; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderCreatedInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderDeliveredInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderSentInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderValidationFailedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class PurchaseOrderDetailsByUserViewProjectionTest extends ProjectionTest { + private PurchaseOrderDetailsByUserViewProjection projection; + + @BeforeEach + void setUp() { + projection = new PurchaseOrderDetailsByUserViewProjection(PurchaseOrderId.newBuilder() + .setPoDate( + LocalDate.newBuilder() + .setDay(14) + .build()) + .setVendorId( + VendorId.newBuilder() + .setValue( + "Пюре") + .build()) + .build()); + } + + @Nested + @DisplayName("PurchaseOrderCreated event should be interpreted by PurchaseOrderItemViewProjection") + class PurchaseOrderCreatedEvent { + + @Test + @DisplayName("Should set order for a projection") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final List orderList = projection.getState() + .getOrderList(); + assertEquals(2, orderList.size()); + assertEquals("user@example.com", orderList.get(0) + .getId() + .getEmail() + .getValue()); + assertEquals("petr@example.com", orderList.get(1) + .getId() + .getEmail() + .getValue()); + assertEquals(true, orderList.get(0) + .getIsValid()); + assertEquals(5, orderList.get(0) + .getDishList() + .size()); + assertEquals(8, orderList.get(1) + .getDishList() + .size()); + } + } + + @Nested + @DisplayName("PurchaseOrderDelivered event should be interpreted") + class PurchaseOrderDeliveredEvent { + + @Test + @DisplayName("Should change status") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderDelivered purchaseOrderDelivered = purchaseOrderDeliveredInstance(); + dispatch(projection, createEvent(purchaseOrderDelivered)); + assertEquals(PurchaseOrderStatus.DELIVERED, projection.getState() + .getPurchaseOrderStatus()); + } + } + + @Nested + @DisplayName("PurchaseOrderSent event should be interpreted") + class PurchaseOrderSentEvent { + + @Test + @DisplayName("Should change status") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + + assertEquals(PurchaseOrderStatus.SENT, projection.getState() + .getPurchaseOrderStatus()); + } + } + + @Nested + @DisplayName("PurchaseOrderValidationFailed event should be interpreted") + class PurchaseOrderValidationFailedEvent { + + @Test + @DisplayName("Should set invalid for correct user") + void addView() { + final PurchaseOrderCreated purchaseOrderCreated = purchaseOrderCreatedInstance(); + dispatch(projection, createEvent(purchaseOrderCreated)); + final PurchaseOrderValidationFailed poValidationFailed = purchaseOrderValidationFailedInstance(); + dispatch(projection, createEvent(poValidationFailed)); + + assertEquals(false, projection.getState() + .getOrderList() + .get(0) + .getIsValid()); + assertEquals(poValidationFailed.getFailureOrder(0) + .getId() + .getUserId(), projection.getState() + .getOrderList() + .get(0) + .getId()); + + assertEquals(true, projection.getState() + .getOrderList() + .get(1) + .getIsValid()); + assertNotEquals(poValidationFailed.getFailureOrder(0) + .getId() + .getUserId(), projection.getState() + .getOrderList() + .get(1) + .getId()); + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderItemViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderItemViewProjectionTest.java new file mode 100644 index 00000000..bb694b4b --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/PurchaseOrderItemViewProjectionTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.q.PurchaseOrderItemViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderDeliveredInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderSentInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.PurchaseOrderEvents.purchaseOrderValidationFailedInstance; +import static javaclasses.mealorder.testdata.TestValues.DATE; +import static javaclasses.mealorder.testdata.TestValues.VENDOR_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PurchaseOrderItemViewProjectionTest extends ProjectionTest { + private PurchaseOrderItemViewProjection projection; + + @BeforeEach + void setUp() { + projection = new PurchaseOrderItemViewProjection(PurchaseOrderId.newBuilder() + .setVendorId( + VENDOR_ID) + .setPoDate(DATE) + .build()); + } + + @Nested + @DisplayName("PurchaseOrderSent event should be interpreted by PurchaseOrderItemViewProjection") + class PurchaseOrderSentEvent { + + @Test + @DisplayName("Should set order for a projection") + void addView() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + + assertEquals("vendor:value: \"VendorName1\"", projection.getState() + .getId() + .getVendorId() + .getValue() + .trim()); + assertEquals(15, projection.getState() + .getId() + .getPoDate() + .getDay()); + assertEquals(2019, projection.getState() + .getId() + .getPoDate() + .getYear()); + assertEquals(2, projection.getState() + .getId() + .getPoDate() + .getMonthValue()); + assertEquals(PurchaseOrderStatus.SENT, projection.getState() + .getPurchaseOrderStatus()); + } + } + + @Nested + @DisplayName("PurchaseOrderDelivered event should be interpreted by PurchaseOrderItemViewProjection") + class PurchaseOrderDeliveredEvent { + + @Test + @DisplayName("Should change status of the PO") + void addView() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + final PurchaseOrderDelivered purchaseOrderDelivered = purchaseOrderDeliveredInstance(); + dispatch(projection, createEvent(purchaseOrderDelivered)); + assertEquals(PurchaseOrderStatus.DELIVERED, projection.getState() + .getPurchaseOrderStatus()); + } + } + + @Nested + @DisplayName("PurchaseOrderValidationFailed event should be interpreted by PurchaseOrderItemViewProjection") + class PurchaseOrderValidationFailedEvent { + + @Test + @DisplayName("Should change status of the PO") + void addView() { + final PurchaseOrderSent purchaseOrderSent = purchaseOrderSentInstance(); + dispatch(projection, createEvent(purchaseOrderSent)); + final PurchaseOrderValidationFailed poValidationFailed = purchaseOrderValidationFailedInstance(); + dispatch(projection, createEvent(poValidationFailed)); + assertEquals(PurchaseOrderStatus.INVALID, projection.getState() + .getPurchaseOrderStatus()); + } + } +} diff --git a/api-java/src/test/java/javaclasses/mealorder/q/projection/VendorListViewProjectionTest.java b/api-java/src/test/java/javaclasses/mealorder/q/projection/VendorListViewProjectionTest.java new file mode 100644 index 00000000..bd53b1ec --- /dev/null +++ b/api-java/src/test/java/javaclasses/mealorder/q/projection/VendorListViewProjectionTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.q.projection; + +import javaclasses.mealorder.c.event.VendorAdded; +import javaclasses.mealorder.c.event.VendorUpdated; +import javaclasses.mealorder.q.VendorListViewProjection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.spine.server.projection.ProjectionEventDispatcher.dispatch; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.VendorEvents.vendorAddedInstance; +import static javaclasses.mealorder.testdata.TestMealOrderEventFactory.VendorEvents.vendorUpdatedInstance; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class VendorListViewProjectionTest extends ProjectionTest { + private VendorListViewProjection projection; + + @BeforeEach + void setUp() { + projection = new VendorListViewProjection(VendorListViewProjection.ID); + } + + @Nested + @DisplayName("VendorAdded event should be interpreted by VendorListViewProjection") + class VendorAddedEvent { + + @Test + @DisplayName("Should add new vendor") + void addView() { + final VendorAdded vendorAdded = vendorAddedInstance(); + dispatch(projection, createEvent(vendorAdded)); + assertEquals(1, projection.getState() + .getVendorList() + .size()); + assertEquals("vendor1@example.com", projection.getState() + .getVendorList() + .get(0) + .getEmail() + .getValue()); + assertEquals("vendor:value: \"VendorName1\"", projection.getState() + .getVendorList() + .get(0) + .getId() + .getValue() + .trim()); + } + } + + @Nested + @DisplayName("VendorUpdated event should be interpreted by VendorListViewProjection") + class VendorUpdatedEvent { + + @Test + @DisplayName("Should update vendor") + void addView() { + final VendorAdded vendorAdded = vendorAddedInstance(); + dispatch(projection, createEvent(vendorAdded)); + assertEquals("VendorName1", projection.getState() + .getVendorList() + .get(0) + .getVendorName() + .getValue()); + final VendorUpdated vendorUpdated = vendorUpdatedInstance(); + dispatch(projection, createEvent(vendorUpdated)); + assertEquals("VendorName2", projection.getState() + .getVendorList() + .get(0) + .getVendorName() + .getValue()); + } + } +} diff --git a/model/src/main/proto/javaclasses/mealorder/attributes.proto b/model/src/main/proto/javaclasses/mealorder/attributes.proto index 86fd7e87..37c6681b 100644 --- a/model/src/main/proto/javaclasses/mealorder/attributes.proto +++ b/model/src/main/proto/javaclasses/mealorder/attributes.proto @@ -37,8 +37,8 @@ import "spine/time/time.proto"; message LocalMonth { // The month value. - spine.time.MonthOfYear month = 1; + spine.time.MonthOfYear month = 1 [(required) = true]; // The year value. - int32 year = 2; + int32 year = 2 [(required) = true]; } diff --git a/model/src/main/proto/javaclasses/mealorder/c/commands.proto b/model/src/main/proto/javaclasses/mealorder/c/commands.proto index 07dc001a..398bbf4f 100644 --- a/model/src/main/proto/javaclasses/mealorder/c/commands.proto +++ b/model/src/main/proto/javaclasses/mealorder/c/commands.proto @@ -44,23 +44,23 @@ import "javaclasses/mealorder/model.proto"; message AddVendor { // The identifier of a vendor which should be added. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the user who adds a vendor. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // The name of a vendor. - VendorName vendor_name = 3; + VendorName vendor_name = 3 [(required) = true]; // The email adress of a vendor to send a purchase order. - spine.net.EmailAddress email = 4; + spine.net.EmailAddress email = 4 [(required) = true]; // Phone numbers of a vendor. - repeated PhoneNumber phone_number = 5; + repeated PhoneNumber phone_number = 5 [(required) = true]; // Time when orders for this vendor are closed for editing. // Purchase orders for a vendor will be created exactly at this time. - spine.time.LocalTime po_daily_deadline = 6; + spine.time.LocalTime po_daily_deadline = 6 [(required) = true]; } // Updates a vendor profile. @@ -68,13 +68,13 @@ message AddVendor { message UpdateVendor { // The identifier of a vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the user who updates vendor profile. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Changes in a vendor profile. - VendorChange vendor_change = 3; + VendorChange vendor_change = 3 [(required) = true]; } // Imports a menu. @@ -82,33 +82,19 @@ message UpdateVendor { message ImportMenu { // The identifier of a vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of a imported menu - MenuId menuId = 2; + MenuId menuId = 2 [(required) = true]; // The identifier of the user who imports a menu. - UserId user_id = 3; + UserId user_id = 3 [(required) = true]; // The collection of dishes. - repeated Dish dish = 4; -} - -// Sets a menu date range. -// -message SetDateRangeForMenu { - - // The identifier of a vendor. - VendorId vendor_id = 1; - - // The identifier of a menu. - MenuId menu_id = 2; - - // The identifier of the user who sets a menu date range. - UserId user_id = 3; + repeated Dish dish = 4 [(required) = true]; // A menu date range that should be set. - MenuDateRange menu_date_range = 4; + MenuDateRange menu_date_range = 5 [(required) = true]; } // Creates a new order. @@ -118,10 +104,10 @@ message SetDateRangeForMenu { message CreateOrder { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the menu. Dishes from only this menu can be added to an order. - MenuId menu_id = 2; + MenuId menu_id = 2 [(required) = true]; } // Adds a dish to an order. @@ -132,10 +118,10 @@ message CreateOrder { message AddDishToOrder { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // A dish that should be added to an order. - Dish dish = 2; + Dish dish = 2 [(required) = true]; } // Removes a dish from an order. @@ -146,10 +132,10 @@ message AddDishToOrder { message RemoveDishFromOrder { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of a dish that should be removed from an order. - DishId dish_id = 2; + DishId dish_id = 2 [(required) = true]; } // Cancels an order. @@ -162,10 +148,10 @@ message RemoveDishFromOrder { message CancelOrder { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the user who cancels an order. - UserId who_cancels = 2; + UserId who_cancels = 2 [(required) = true]; } // Creates a purchase order. @@ -173,16 +159,16 @@ message CancelOrder { message CreatePurchaseOrder { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The collection of all orders for this day for the specified vendor. repeated Order order = 2; // The identifier of the user who creates a purchase order. - UserId who_creates = 3; + UserId who_creates = 3 [(required) = true]; // The email adress of a vendor to send a purchase order. - spine.net.EmailAddress vendor_email = 4; + spine.net.EmailAddress vendor_email = 4 [(required) = true]; } // Marks a purchase order as delivered. @@ -192,10 +178,10 @@ message CreatePurchaseOrder { message MarkPurchaseOrderAsDelivered { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The identifier of the user who marks a purchase order as delivered. - UserId who_marks_as_delivered = 2; + UserId who_marks_as_delivered = 2 [(required) = true]; } // Overrules a purchase order validation. @@ -205,13 +191,13 @@ message MarkPurchaseOrderAsDelivered { message MarkPurchaseOrderAsValid { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The identifier of the user who marks a purchase order as valid. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // The reason why a purchase order should be marked as valid. - string reason = 3; + string reason = 3 [(required) = true]; // The email adress of a vendor to send a purchase order. spine.net.EmailAddress vendor_email = 4; @@ -224,7 +210,7 @@ message MarkPurchaseOrderAsValid { message CancelPurchaseOrder { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The reason of cancelation. oneof reason { @@ -237,5 +223,5 @@ message CancelPurchaseOrder { } // The identifier of the user who cancels a purchase order. - UserId user_id = 4; + UserId user_id = 4 [(required) = true]; } diff --git a/model/src/main/proto/javaclasses/mealorder/c/events.proto b/model/src/main/proto/javaclasses/mealorder/c/events.proto index 29d9ffde..02f71063 100644 --- a/model/src/main/proto/javaclasses/mealorder/c/events.proto +++ b/model/src/main/proto/javaclasses/mealorder/c/events.proto @@ -42,25 +42,25 @@ import "javaclasses/mealorder/values.proto"; message VendorAdded { // The identifier of a added vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the user who added a vendor. - UserId who_added = 2; + UserId who_added = 2 [(required) = true]; // Was added at this time. - google.protobuf.Timestamp when_added = 3; + google.protobuf.Timestamp when_added = 3 [(required) = true]; // The name of a vendor. - VendorName vendor_name = 4; + VendorName vendor_name = 4 [(required) = true]; // The email adress to send a purchase order. - spine.net.EmailAddress email = 5; + spine.net.EmailAddress email = 5 [(required) = true]; // Phone numbers of a vendor. - repeated PhoneNumber phone_number = 6; + repeated PhoneNumber phone_number = 6 [(required) = true]; // Time to which all orders to this vendor must be made. - spine.time.LocalTime po_daily_deadline = 7; + spine.time.LocalTime po_daily_deadline = 7 [(required) = true]; } // The event fired upon a vendor profile update. @@ -68,16 +68,16 @@ message VendorAdded { message VendorUpdated { // The identifier of an updated vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the user who updated a vendor profile. - UserId who_uploaded = 2; + UserId who_uploaded = 2 [(required) = true]; // Was updated at this time. - google.protobuf.Timestamp when_updated = 3; + google.protobuf.Timestamp when_updated = 3 [(required) = true]; // Changes in a vendor profile. - VendorChange vendor_change = 4; + VendorChange vendor_change = 4 [(required) = true]; } // The event signalizing about the successful import of a menu. @@ -88,39 +88,22 @@ message VendorUpdated { message MenuImported { // The identifier of the vendor that provided a menu. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of an imported menu. - MenuId menu_id = 2; + MenuId menu_id = 2 [(required) = true]; // The identifier of the user who imported a menu. - UserId who_imported = 3; + UserId who_imported = 3 [(required) = true]; // Was imported at this time. - google.protobuf.Timestamp when_imported = 4; + google.protobuf.Timestamp when_imported = 4 [(required) = true]; // The collection of menu dishes. - repeated Dish dish = 5; -} - -// The event reflecting a menu active date range set. -// -message DateRangeForMenuSet { - - // The identifier of a vendor. - VendorId vendor_id = 1; - - // The identifier of a menu. - MenuId menu_id = 2; - - // The identifier of the user who set date range. - UserId who_set = 3; - - // Was set at this time. - google.protobuf.Timestamp when_set = 4; + repeated Dish dish = 5 [(required) = true]; // Date range that has been set. - MenuDateRange menu_date_range = 5; + MenuDateRange menu_date_range = 6 [(required) = true]; } // The event signalizing about the successful creation of an order. @@ -130,13 +113,13 @@ message DateRangeForMenuSet { message OrderCreated { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the menu which contains dishes that can be added to an order. - MenuId menu_id = 2; + MenuId menu_id = 2 [(required) = true]; // Was created at this time. - google.protobuf.Timestamp when_created = 3; + google.protobuf.Timestamp when_created = 3 [(required) = true]; } // The event signalizing about a dish addition to the order. @@ -144,13 +127,13 @@ message OrderCreated { message DishAddedToOrder { // The identifier of the order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // A dish that added to an order. - Dish dish = 2; + Dish dish = 2 [(required) = true]; // Was added at this time. - google.protobuf.Timestamp when_added = 3; + google.protobuf.Timestamp when_added = 3 [(required) = true]; } // The event signalizing about the successful removing of a dish from the order. @@ -158,13 +141,13 @@ message DishAddedToOrder { message DishRemovedFromOrder { // The identifier of the order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // A dish removed from an order. - Dish dish = 2; + Dish dish = 2 [(required) = true]; // Was removed at this time. - google.protobuf.Timestamp when_removed = 3; + google.protobuf.Timestamp when_removed = 3 [(required) = true]; } // The event signalizing about the successful order cancellation. @@ -172,13 +155,13 @@ message DishRemovedFromOrder { message OrderCanceled { // The identifier of an order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the user who canceled an order. - UserId who_canceled = 2; + UserId who_canceled = 2 [(required) = true]; // Was canceled at this time. - google.protobuf.Timestamp when_canceled = 3; + google.protobuf.Timestamp when_canceled = 3 [(required) = true]; } // The event signalizing about the successful addition of an order to the purchase order. @@ -186,10 +169,10 @@ message OrderCanceled { message OrderProcessed { // An order that was added to the purchase order. - Order order = 1; + Order order = 1 [(required) = true]; // Was added to the purchase order at this time. - google.protobuf.Timestamp when_processed = 2; + google.protobuf.Timestamp when_processed = 2 [(required) = true]; } // The event signalizing about the successful creation of a purchase order. @@ -197,16 +180,16 @@ message OrderProcessed { message PurchaseOrderCreated { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // Was created at this time. - google.protobuf.Timestamp when_created = 2; + google.protobuf.Timestamp when_created = 2 [(required) = true]; // The identifier of the user who created a purchase order. - UserId who_created = 3; + UserId who_created = 3 [(required) = true]; // The collection of all orders for this day. - repeated Order order = 4; + repeated Order order = 4 [(required) = true]; } // The event signalizing about the successful delivering of a purchase order. @@ -214,30 +197,30 @@ message PurchaseOrderCreated { message PurchaseOrderDelivered { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The identifier of the user who marked a purchase order as delivered. - UserId who_marked_as_delivered = 2; + UserId who_marked_as_delivered = 2 [(required) = true]; // Was delivered at this time. - google.protobuf.Timestamp when_delievered = 3; + google.protobuf.Timestamp when_delivered = 3 [(required) = true]; } // The event signalizing about the successful sending of a purchase order. // message PurchaseOrderSent { - // The identifier of a purchase order. - PurchaseOrder purchase_order = 1; + // Purchase order. + PurchaseOrder purchase_order = 1 [(required) = true]; // Was sent at this time. - google.protobuf.Timestamp when_sent = 2; + google.protobuf.Timestamp when_sent = 2 [(required) = true]; // The email address of the sender. - spine.net.EmailAddress sender_email = 3; + spine.net.EmailAddress sender_email = 3 [(required) = true]; // The email address of the recipient. - spine.net.EmailAddress vendor_email = 4; + spine.net.EmailAddress vendor_email = 4 [(required) = true]; } // The event signalizing about failed purchase order validation. @@ -251,13 +234,13 @@ message PurchaseOrderSent { message PurchaseOrderValidationFailed { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The collection of orders that caused a failure of validation. - repeated Order failure_order = 2; + repeated Order failure_order = 2 [(required) = true]; // Validation failed at this time. - google.protobuf.Timestamp when_failed = 3; + google.protobuf.Timestamp when_failed = 3 [(required) = true]; } // The event signalizing that purchase order validation is overruled successfully. @@ -265,13 +248,13 @@ message PurchaseOrderValidationFailed { message PurchaseOrderValidationOverruled { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The identifier of the user who overruled validation. - UserId who_overruled = 2; + UserId who_overruled = 2 [(required) = true]; // The reason why validation is overruled. - string reason = 3; + string reason = 3 [(required) = true]; // Validation was overruled at this time. google.protobuf.Timestamp when_overruled = 4; @@ -282,10 +265,10 @@ message PurchaseOrderValidationOverruled { message PurchaseOrderValidationPassed { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // Validation completed successfully at this time. - google.protobuf.Timestamp when_passed = 2; + google.protobuf.Timestamp when_passed = 2 [(required) = true]; } // The event signalizing about the successful order cancellation. @@ -293,13 +276,13 @@ message PurchaseOrderValidationPassed { message PurchaseOrderCanceled { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The identifier of the user who cancelled a purchase order. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Was canceled at this time. - google.protobuf.Timestamp when_canceled = 3; + google.protobuf.Timestamp when_canceled = 3 [(required) = true]; // The reason of cancellation. // diff --git a/model/src/main/proto/javaclasses/mealorder/c/rejections.proto b/model/src/main/proto/javaclasses/mealorder/c/rejections.proto index 91841117..574a9355 100644 --- a/model/src/main/proto/javaclasses/mealorder/c/rejections.proto +++ b/model/src/main/proto/javaclasses/mealorder/c/rejections.proto @@ -43,13 +43,13 @@ import "javaclasses/mealorder/values.proto"; message VendorAlreadyExists { // The identifier of the existing vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The name of the existing vendor. - VendorName vendor_name = 2; + VendorName vendor_name = 2 [(required) = true]; // Addition was rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } // The rejection to set date range for a menu. @@ -59,16 +59,16 @@ message VendorAlreadyExists { message CannotSetDateRange { // The identifier of the vendor of this menu. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the menu which date range wasn't set. - MenuId menu_id = 2; + MenuId menu_id = 2 [(required) = true]; // Date range that was been attempted to set. - MenuDateRange menu_date_range = 3; + MenuDateRange menu_date_range = 3 [(required) = true]; // Setting was rejected at this time. - google.protobuf.Timestamp when_rejected = 4; + google.protobuf.Timestamp when_rejected = 4 [(required) = true]; } // The rejection to create an order. @@ -78,10 +78,10 @@ message CannotSetDateRange { message OrderAlreadyExists { // The identifier of the existing order. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // Creation was rejected at this time. - google.protobuf.Timestamp when_rejected = 2; + google.protobuf.Timestamp when_rejected = 2 [(required) = true]; } // The rejection to create an order. @@ -91,16 +91,16 @@ message OrderAlreadyExists { message MenuNotAvailable { // The identifier of the user who tried to create an order. - UserId user_id = 1; + UserId user_id = 1 [(required) = true]; // The identifier of the vendor from who the user tried to order. - VendorId vendor_id = 2; + VendorId vendor_id = 2 [(required) = true]; // The date on which the user attempted to create an order. - spine.time.LocalDate order_date = 3; + spine.time.LocalDate order_date = 3 [(required) = true]; // Creation was rejected at this time. - google.protobuf.Timestamp when_rejected = 4; + google.protobuf.Timestamp when_rejected = 4 [(required) = true]; } @@ -111,19 +111,19 @@ message MenuNotAvailable { message DishVendorMismatch { // The identifier of the order in which the user tried to add a dish. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of a dish which the user tried to add to the order. - DishId dish_id = 2; + DishId dish_id = 2 [(required) = true]; // The identifier of the user who tried to add a dish. - UserId user_id = 3; + UserId user_id = 3 [(required) = true]; // The mismatching vendor value. - VendorMismatch vendor_mismatch = 4; + VendorMismatch vendor_mismatch = 4 [(required) = true]; // Addition was rejected at this time. - google.protobuf.Timestamp when_rejected = 5; + google.protobuf.Timestamp when_rejected = 5 [(required) = true]; } // The rejection to add a dish to the order. @@ -133,19 +133,19 @@ message DishVendorMismatch { message CannotAddDishToNotActiveOrder { // The identifier of the order in which the user tried to add a dish. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of a dish which the user tried to add to the order. - DishId dish_id = 2; + DishId dish_id = 2 [(required) = true]; // The identifier of the user who tried to add a dish. - UserId user_id = 3; + UserId user_id = 3 [(required) = true]; // The status of the order. - OrderStatus order_status = 4; + OrderStatus order_status = 4 [(required) = true]; // Addition was rejected at this time. - google.protobuf.Timestamp when_rejected = 5; + google.protobuf.Timestamp when_rejected = 5 [(required) = true]; } // The rejection to remove a dish from the order. @@ -155,19 +155,19 @@ message CannotAddDishToNotActiveOrder { message CannotRemoveDishFromNotActiveOrder { // The identifier of the order in which the user tried to add a dish. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of a dish which the user tried to add to the order. - DishId dish_id = 2; + DishId dish_id = 2 [(required) = true]; // The identifier of the user who tried to add a dish. - UserId user_id = 3; + UserId user_id = 3 [(required) = true]; // The status of the order. - OrderStatus order_status = 4; + OrderStatus order_status = 4 [(required) = true]; // Addition was rejected at this time. - google.protobuf.Timestamp when_rejected = 5; + google.protobuf.Timestamp when_rejected = 5 [(required) = true]; } // The rejection to remove a dish from the order. @@ -177,16 +177,16 @@ message CannotRemoveDishFromNotActiveOrder { message CannotRemoveMissingDish { // The identifier of the order from which the user tried to remove a dish. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the user who tried to remove a dish. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // The identifier of a dish which the user tried to remove from the order. - DishId dish_id = 3; + DishId dish_id = 3 [(required) = true]; // Removing was rejected at this time. - google.protobuf.Timestamp when_rejected = 4; + google.protobuf.Timestamp when_rejected = 4 [(required) = true]; } // The rejection to cancel an order. @@ -196,13 +196,13 @@ message CannotRemoveMissingDish { message CannotCancelProcessedOrder { // The identifier of an order which the user tried to cancel. - OrderId order_id = 1; + OrderId order_id = 1 [(required) = true]; // The identifier of the user who tried to cancel an order. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Cancellation was rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } // The rejection to create a purchase order. @@ -212,13 +212,13 @@ message CannotCancelProcessedOrder { message CannotCreatePurchaseOrder { // The identifier of the vendor for which a purchase order wasn't created. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The date on which a purchase order creation was rejected. - spine.time.LocalDate purchase_order_date = 2; + spine.time.LocalDate purchase_order_date = 2 [(required) = true]; // Creation was rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } // The rejection to mark a purchase order as delivered. @@ -228,13 +228,13 @@ message CannotCreatePurchaseOrder { message CannotMarkPurchaseOrderAsDelivered { // The identifier of a purchase order which the user tried to mark as delivered. - PurchaseOrderId po_id = 1; + PurchaseOrderId po_id = 1 [(required) = true]; // The identifier of the user who tried to mark a purchase ordser as delivered. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } // The rejection to cancel a purchase order. @@ -244,13 +244,13 @@ message CannotMarkPurchaseOrderAsDelivered { message CannotCancelDeliveredPurchaseOrder { // The identifier of a purchase order which the user tried to cancel. - PurchaseOrderId po_id = 1; + PurchaseOrderId po_id = 1 [(required) = true]; // The identifier of the user who tried to cancel a purchase order. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Cancellation was rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } // The rejection to overrule a purchase order validation. @@ -260,11 +260,11 @@ message CannotCancelDeliveredPurchaseOrder { message CannotOverruleValidationOfNotInvalidPO { // The identifier of a purchase order which validation the user tried to overrule. - PurchaseOrderId po_id = 1; + PurchaseOrderId po_id = 1 [(required) = true]; // The identifier of the user who tried to overrule validation. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // Rejected at this time. - google.protobuf.Timestamp when_rejected = 3; + google.protobuf.Timestamp when_rejected = 3 [(required) = true]; } diff --git a/model/src/main/proto/javaclasses/mealorder/identifiers.proto b/model/src/main/proto/javaclasses/mealorder/identifiers.proto index c802ed99..2e69ede5 100644 --- a/model/src/main/proto/javaclasses/mealorder/identifiers.proto +++ b/model/src/main/proto/javaclasses/mealorder/identifiers.proto @@ -35,6 +35,22 @@ import "spine/net/email_address.proto"; import "spine/time/time.proto"; import "javaclasses/mealorder/attributes.proto"; +// The ID of the vendor list. +// +message VendorListId { + + // The ID of the vendor list. + string value = 1 [(required) = true]; +} + +// The ID of the calendar. +// +message MenuCalendarId { + + // The ID of the calendar. + string value = 1 [(required) = true]; +} + // The ID of a user. // // Represented by the user's email address. @@ -42,7 +58,7 @@ import "javaclasses/mealorder/attributes.proto"; message UserId { // The user's email. - spine.net.EmailAddress email = 1; + spine.net.EmailAddress email = 1 [(required) = true]; } // The ID of a vendor. @@ -50,7 +66,7 @@ message UserId { message VendorId { // Represented by the vendor name value in the next form 'vendor:<`VendorName`>'. - string value = 1; + string value = 1 [(required) = true]; } // The ID of a order. @@ -60,13 +76,13 @@ message VendorId { message OrderId { // The identifier of the vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The identifier of the user who makes an order. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; // The date of an order. - spine.time.LocalDate order_date = 3; + spine.time.LocalDate order_date = 3 [(required) = true]; } // The ID of a menu. @@ -76,10 +92,10 @@ message OrderId { message MenuId { // The identifier of the vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // Was imported at this time. - google.protobuf.Timestamp when_imported = 2; + google.protobuf.Timestamp when_imported = 2 [(required) = true]; } // The ID of a dish. @@ -89,10 +105,10 @@ message MenuId { message DishId { // The sequence number of a dish in the menu. - int32 sequential_number = 1; + int32 sequential_number = 1 [(required) = true]; // The identifier of the menu. - MenuId menu_id = 2; + MenuId menu_id = 2 [(required) = true]; } // The ID of a purchase order. @@ -102,10 +118,10 @@ message DishId { message PurchaseOrderId { // The identifier of the vendor. - VendorId vendor_id = 1; + VendorId vendor_id = 1 [(required) = true]; // The date on which a purchase order is formed. - spine.time.LocalDate po_date = 2; + spine.time.LocalDate po_date = 2 [(required) = true]; } // The ID of a menu list projection for UI role User. @@ -113,7 +129,7 @@ message PurchaseOrderId { message MenuListId { // The date on which the a list is formed. - spine.time.LocalDate date = 1; + spine.time.LocalDate date = 1 [(required) = true]; } // The ID of an order list projection for UI role User. @@ -121,10 +137,10 @@ message MenuListId { message OrderListId { // The date on which an order list is formed. - spine.time.LocalDate order_date = 1; + spine.time.LocalDate order_date = 1 [(required) = true]; // The identifier of the user who made orders. - UserId user_id = 2; + UserId user_id = 2 [(required) = true]; } // The ID of a monthly spendings report projection for UI role Admin. @@ -132,5 +148,5 @@ message OrderListId { message MonthlySpendingsReportId { // The month on which spendings are calculated. - LocalMonth month = 1; + LocalMonth month = 1 [(required) = true]; } diff --git a/model/src/main/proto/javaclasses/mealorder/model.proto b/model/src/main/proto/javaclasses/mealorder/model.proto index ca1e5ce9..89316f0f 100644 --- a/model/src/main/proto/javaclasses/mealorder/model.proto +++ b/model/src/main/proto/javaclasses/mealorder/model.proto @@ -43,16 +43,16 @@ import "spine/net/email_address.proto"; message Dish { // The identifier of a dish. - DishId id = 1; + DishId id = 1 [(required) = true]; // The name of a dish. - string name = 2; + string name = 2 [(required) = true]; // A dish category. - string category = 3; + string category = 3 [(required) = true]; // A dish price. - spine.money.Money price = 4; + spine.money.Money price = 4 [(required) = true]; } // The model of a menu. @@ -62,13 +62,13 @@ message Dish { message Menu { // The identifier of a menu. - MenuId id = 1; + MenuId id = 1 [(required) = true]; // The date range when available. - MenuDateRange menu_date_range = 2; + MenuDateRange menu_date_range = 2 [(required) = true]; // The collection of dishes. - repeated Dish dish = 3; + repeated Dish dish = 3 [(required) = true]; } // The model representing the `Order` aggregate. @@ -87,13 +87,13 @@ message Menu { message Order { // The identifier of an order. - OrderId id = 1; + OrderId id = 1 [(required) = true]; // The collection of dishes. repeated Dish dish = 2; // The status of an order. - OrderStatus status = 3; + OrderStatus status = 3 [(required) = true]; } // The model representing the `PurchaseOrder` aggregate. @@ -127,13 +127,13 @@ message Order { message PurchaseOrder { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The collection of orders. - repeated Order order = 2; + repeated Order order = 2 [(required) = true]; // The status of a purchase order. - PurchaseOrderStatus status = 3; + PurchaseOrderStatus status = 3 [(required) = true]; } // The model representing the `Vendor` aggregate. @@ -141,22 +141,22 @@ message PurchaseOrder { message Vendor { // The identifier of a vendor. - VendorId id = 1; + VendorId id = 1 [(required) = true]; // The name of a vendor - VendorName vendor_name = 2; + VendorName vendor_name = 2 [(required) = true]; // The email address to send a purchase order. - spine.net.EmailAddress email = 3; + spine.net.EmailAddress email = 3 [(required) = true]; // The phone numbers of a vendor. - repeated PhoneNumber phone_number = 4; + repeated PhoneNumber phone_number = 4 [(required) = true]; // Daily deadline time. // // Time when orders for this vendor are closed for editing. // The purchase order for the specified vendor will be created exactly at this time. - spine.time.LocalTime po_daily_deadline = 5; + spine.time.LocalTime po_daily_deadline = 5 [(required) = true]; // The collection of menus. repeated Menu menu = 6; diff --git a/model/src/main/proto/javaclasses/mealorder/q/projections.proto b/model/src/main/proto/javaclasses/mealorder/q/projections.proto index d15bcc39..e602e82c 100644 --- a/model/src/main/proto/javaclasses/mealorder/q/projections.proto +++ b/model/src/main/proto/javaclasses/mealorder/q/projections.proto @@ -52,10 +52,7 @@ import "javaclasses/mealorder/values.proto"; // this date. This time is defined in a menu vendor aggregate. See `Vendor` // for more details. // -// Subscribes following events: -// 1. `DateRangeForMenuSet` -// 2. `PurchaseOrderCreated` -// 3. `MenuImported` +//Singleton, because menu list is global. // message MenuListView { @@ -72,13 +69,15 @@ message MenuListView { // today to the same day next week. (8 elements) // The each date contains information about the menus availability for it. // -// Subscribes following events: -// 1. `DateRangeForMenuSet` +// Singleton, because the calendar is global. // message MenuCalendarView { + // The identifier of the calendar. + MenuCalendarId menu_calendar_id = 1; + // The collection of calendar items (dates). - repeated MenuCalendarItem calendar_item = 1; + repeated MenuCalendarItem calendar_item = 2 [(required) = true]; } // The projection state of an order list. @@ -88,16 +87,11 @@ message MenuCalendarView { // // The order date and the user ID are specified by `OrderListId` value. // -// Subscribes following events: -// 1. `DishAddedToOrder` -// 2. `DishRemovedFromOrder` -// 3. `OrderCanceled` -// 4. `OrderProcessed` -// + message OrderListView { // The identifier of an order list. - OrderListId list_id = 1; + OrderListId list_id = 1 [(required) = true]; // The collection of user's orders. repeated OrderItem order = 2; @@ -105,31 +99,36 @@ message OrderListView { // **** Projections for UI role Admin. **** -// The projection state of the vendor list. +// The projection state of the full menu item. // -// Subscribes following events: -// 1. `VendorAdded` -// 2. `VendorUpdated` +// This view has menu with date range. // -message VendorListView { +message FullMenuView { - // The collection of all vendors. - repeated VendorItem vendor = 1; + // // The identifier of a full menu. + MenuId menu_id = 1 [(required) = true]; + + // The vendor name. + VendorName vendor_name = 2 [(required) = true]; + + // The collection of categories. + repeated DishesByCategory dishesByCategory = 3; + + // A date range for a menu. + MenuDateRange menu_date_range = 4 [(required) = true]; } -// The projection state of the full menu list. -// -// This view includes the list of all menus, -// sorted by menu date range. +// The projection state of the vendor list. // -// Subscribes following events: -// 1. `DateRangeForMenuSet` -// 2. `MenuImported` +// Singleton, because there is only one list of vendors. // -message FullMenuListView { +message VendorListView { - // The collection of all menus. - repeated FullMenuItem menu = 1; + // The identifier of the vendor list singleton. + VendorListId vendor_list_id = 1; + + // The collection of all vendors. + repeated VendorItem vendor = 2; } // The projection state of the purchase order list. @@ -137,43 +136,28 @@ message FullMenuListView { // This view includes the list of all purchase orders, // sorted by date. // -// Subscribes following events: -// 1. `PurchaseOrderCreated` -// 2. `PurchaseOrderDelivered` -// 3. `PurchaseOrderSent` -// 4. `PurchaseOrderValidationFailed` -// 5. `PurchaseOrderValidationOverruled` -// 6. `PurchaseOrderValidationPassed` -// 7. `PurchaseOrderCanceled` -// -message PurchaseOrderListView { +message PurchaseOrderItemView { - // The collection of all purchase orders. - repeated PurchaseOrderItem purchase_order = 1; + // The identifier of a purchase order. + PurchaseOrderId id = 1 [(required) = true]; + + // The purchase order status. + PurchaseOrderStatus purchase_order_status = 2 [(required) = true]; } // The projection state of a purchase order details view // grouped by dish. // -// Subscribes following events: -// 1. `PurchaseOrderCreated` -// 2. `PurchaseOrderDelivered` -// 3. `PurchaseOrderSent` -// 4. `PurchaseOrderValidationFailed` -// 5. `PurchaseOrderValidationOverruled` -// 6. `PurchaseOrderValidationPassed` -// 7. `PurchaseOrderCanceled` -// message PurchaseOrderDetailsByDishView { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The purchase order status. PurchaseOrderStatus purchase_order_status = 2; // The collection of dishes. - repeated DishItem dish = 3; + repeated DishItem dish = 3 [(required) = true]; } // The projection state of a purchase order details view @@ -182,25 +166,16 @@ message PurchaseOrderDetailsByDishView { // When a purchase order is created its validation may complete with failure. // Those orders which caused that failure are marked as invalid. // -// Subscribes following events: -// 1. `PurchaseOrderCreated` -// 2. `PurchaseOrderDelivered` -// 3. `PurchaseOrderSent` -// 4. `PurchaseOrderValidationFailed` -// 5. `PurchaseOrderValidationOverruled` -// 6. `PurchaseOrderValidationPassed` -// 7. `PurchaseOrderCanceled` -// message PurchaseOrderDetailsByUserView { // The identifier of a purchase order. - PurchaseOrderId id = 1; + PurchaseOrderId id = 1 [(required) = true]; // The purchase order status. PurchaseOrderStatus purchase_order_status = 2; // The collection of orders. - repeated UserOrderDetails order = 3; + repeated UserOrderDetails order = 3 [(required) = true]; } // The projection state of a monthly spendings report view. @@ -212,15 +187,17 @@ message PurchaseOrderDetailsByUserView { // It contains users spendings for period from month first // date till today if a report is formed for the current month. // -// Subscribes following events: -// 1. `PurchaseOrderDelivered` -// 2. `PurchaseOrderSent` -// message MonthlySpendingsReportView { // The identifier of a monthly spendings report. - MonthlySpendingsReportId report_id = 1; + MonthlySpendingsReportId report_id = 1 [(required) = true]; // The collection of users spendings for the specified month. repeated UserSpendings user_spending = 2; + + // List of orders. + // + // Created on `PurchaseOrderSent` and on `PurchaseOrderDelivered` + // users spendings will be added to the users' monthly spendings. + repeated UserOrderDetails order = 3; } diff --git a/model/src/main/proto/javaclasses/mealorder/q/values.proto b/model/src/main/proto/javaclasses/mealorder/q/values.proto index 6d348320..e18e0b9e 100644 --- a/model/src/main/proto/javaclasses/mealorder/q/values.proto +++ b/model/src/main/proto/javaclasses/mealorder/q/values.proto @@ -45,29 +45,40 @@ import "javaclasses/mealorder/values.proto"; message MenuItem { // The vendor name. - VendorName vendor_name = 1; + VendorName vendor_name = 1 [(required) = true]; - // The collection of dishes. - repeated DishItem dish = 2; + // The collection of categories. + repeated DishesByCategory dishesByCategory = 2 [(required) = true]; + + // A date on which a menu is intended. + spine.time.LocalDate menu_date = 3 [(required) = true]; + + // Indicates if a menu is available for user. + bool is_avilable = 4 [(required) = true]; } -// The single dish item of a menu. +// Dishes grouped by category. // -// The dish category is used in UI to group dishes. +message DishesByCategory { + + // Category of dishes. + CategoryName category = 1 [(required) = true]; + + // The collection of dishes. + repeated DishItem dishes = 2; +} +// The single dish item of a menu. // message DishItem { // The identifier of a dish. - DishId id = 1; + DishId id = 1 [(required) = true]; // The name of a dish. - string name = 2; - - // The dish category. - string category = 3; + string name = 2 [(required) = true]; // The dish price. - spine.money.Money price = 4; + spine.money.Money price = 3 [(required) = true]; } // The item of the menu calendar. @@ -78,10 +89,10 @@ message DishItem { message MenuCalendarItem { // A date in the menu calendar. - spine.time.LocalDate date = 1; + spine.time.LocalDate date = 1 [(required) = true]; // Indicates presence of attached menus on a specified date. - bool has_menu = 2; + bool has_menu = 2 [(required) = true]; } // The item of an order list. @@ -99,7 +110,7 @@ message MenuCalendarItem { message OrderItem { // The identifier of an order. - OrderId id = 1; + OrderId id = 1 [(required) = true]; // The collection of ordered dishes. repeated DishItem dish = 2; @@ -113,44 +124,19 @@ message OrderItem { message VendorItem { // The identifier of a vendor. - VendorId id = 1; + VendorId id = 1 [(required) = true]; // The vendor name. - VendorName vendor_name = 2; + VendorName vendor_name = 2 [(required) = true]; // The vendor email address. - spine.net.EmailAddress email = 3; + spine.net.EmailAddress email = 3 [(required) = true]; - // Phone numbers of the vendor. + // Phone numbers of a vendor. repeated PhoneNumber phone_number = 4; // Daily purchase order creation deadline time. - spine.time.LocalTime po_daily_deadline = 5; -} - -// The item of the full menu list. -// -message FullMenuItem { - - // The identifier of a menu. - MenuId menu_id = 1; - - // Date range when a menu is available. - MenuDateRange menu_date_range = 2; - - // The collection of dishes. - repeated DishItem dish = 3; -} - -// The item of the purchase order list. -// -message PurchaseOrderItem { - - // The identifier of a purchase order. - PurchaseOrderId id = 1; - - // The purchase order status. - PurchaseOrderStatus purchase_order_status = 2; + spine.time.LocalTime po_daily_deadline = 5 [(required) = true]; } // The item of an order list. @@ -163,13 +149,16 @@ message PurchaseOrderItem { message UserOrderDetails { // The identifier of the user. - UserId id = 1; + UserId id = 1 [(required) = true]; // The collection of dishes. repeated DishItem dish = 2; // An order validation status. bool is_valid = 3; + + // The identifier of a purchase order. + PurchaseOrderId purchase_order_id = 4; } // The item of a monthly spendings report view. @@ -179,8 +168,8 @@ message UserOrderDetails { message UserSpendings { // The identifier of a user. - UserId id = 1; + UserId id = 1 [(required) = true]; // Amount of spendings. - spine.money.Money amount = 2; + spine.money.Money amount = 2 [(required) = true]; } diff --git a/model/src/main/proto/javaclasses/mealorder/values.proto b/model/src/main/proto/javaclasses/mealorder/values.proto index f823dc2e..150f5ca3 100644 --- a/model/src/main/proto/javaclasses/mealorder/values.proto +++ b/model/src/main/proto/javaclasses/mealorder/values.proto @@ -36,15 +36,24 @@ import "spine/change/change.proto"; import "spine/net/email_address.proto"; import "spine/time/time.proto"; +// Name of a category. +// +// Probably it has fixed values. +message CategoryName { + + // Category of a dish. + string value = 1 [(required) = true]; +} + // The model representing a date range. // message MenuDateRange { // The range start date. - spine.time.LocalDate range_start = 1; + spine.time.LocalDate range_start = 1 [(required) = true]; // The range end date. - spine.time.LocalDate range_end = 2; + spine.time.LocalDate range_end = 2 [(required) = true]; } // The model representing a phone number. @@ -52,7 +61,7 @@ message MenuDateRange { message PhoneNumber { // String representation of a phone number. - string value = 1; + string value = 1 [(required) = true]; } // The model representing a vendor name. @@ -60,7 +69,7 @@ message PhoneNumber { message VendorName { // The name of a vendor, unique for each vendor. - string value = 1; + string value = 1 [(required) = true]; } // The representation of changes in a vendor profile. @@ -68,28 +77,28 @@ message VendorName { message VendorChange { // The name that's changing. - VendorName previous_vendor_name = 1; + VendorName previous_vendor_name = 1 [(required) = true]; // The email address that's changing. - spine.net.EmailAddress previous_email = 2; + spine.net.EmailAddress previous_email = 2 [(required) = true]; // Phone numbers that are changing. - repeated PhoneNumber previous_phone_number = 3; + repeated PhoneNumber previous_phone_number = 3 [(required) = true]; // Daily deadline time that's changing. - spine.time.LocalTime previous_po_daily_deadline = 4; + spine.time.LocalTime previous_po_daily_deadline = 4 [(required) = true]; // The new name. - VendorName new_vendor_name = 5; + VendorName new_vendor_name = 5 [(required) = true]; // The new email adress. - spine.net.EmailAddress new_email = 6; + spine.net.EmailAddress new_email = 6 [(required) = true]; // New phone numbers. - repeated PhoneNumber new_phone_number = 7; + repeated PhoneNumber new_phone_number = 7 [(required) = true]; // The new daily deadline time. - spine.time.LocalTime new_po_daily_deadline = 8; + spine.time.LocalTime new_po_daily_deadline = 8 [(required) = true]; } // A purchase order status values. @@ -136,8 +145,8 @@ enum OrderStatus { message VendorMismatch { // The vendor id in an order. - VendorId target = 1; + VendorId target = 1 [(required) = true]; // The vendor id in a dish. - VendorId actual = 2; + VendorId actual = 2 [(required) = true]; } diff --git a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestMealOrderEventFactory.java b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestMealOrderEventFactory.java new file mode 100644 index 00000000..93953bb0 --- /dev/null +++ b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestMealOrderEventFactory.java @@ -0,0 +1,306 @@ +/* + * Copyright 2018, TeamDev Ltd. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javaclasses.mealorder.testdata; + +import com.google.protobuf.Timestamp; +import io.spine.net.EmailAddress; +import io.spine.time.LocalTime; +import javaclasses.mealorder.Dish; +import javaclasses.mealorder.MenuDateRange; +import javaclasses.mealorder.MenuId; +import javaclasses.mealorder.Order; +import javaclasses.mealorder.OrderId; +import javaclasses.mealorder.PhoneNumber; +import javaclasses.mealorder.PurchaseOrder; +import javaclasses.mealorder.PurchaseOrderId; +import javaclasses.mealorder.PurchaseOrderStatus; +import javaclasses.mealorder.UserId; +import javaclasses.mealorder.VendorChange; +import javaclasses.mealorder.VendorId; +import javaclasses.mealorder.VendorName; +import javaclasses.mealorder.c.event.DishAddedToOrder; +import javaclasses.mealorder.c.event.DishRemovedFromOrder; +import javaclasses.mealorder.c.event.MenuImported; +import javaclasses.mealorder.c.event.OrderCanceled; +import javaclasses.mealorder.c.event.OrderProcessed; +import javaclasses.mealorder.c.event.PurchaseOrderCreated; +import javaclasses.mealorder.c.event.PurchaseOrderDelivered; +import javaclasses.mealorder.c.event.PurchaseOrderSent; +import javaclasses.mealorder.c.event.PurchaseOrderValidationFailed; +import javaclasses.mealorder.c.event.VendorAdded; +import javaclasses.mealorder.c.event.VendorUpdated; + +import java.util.List; + +import static io.spine.time.Time.getCurrentTime; + +public class TestMealOrderEventFactory { + + private static final Order ORDER = TestValues.ORDER; + private static final PurchaseOrderId ID = TestValues.PURCHASE_ORDER_ID; + private static final PurchaseOrder PURCHASE_ORDER = PurchaseOrder.newBuilder() + .addOrder(ORDER) + .setId(ID) + .setStatus( + PurchaseOrderStatus.CREATED) + .build(); + private static final PurchaseOrder PURCHASE_ORDER2 = PurchaseOrder.newBuilder() + .addAllOrder( + TestValues.BIG_ORDER) + .setId(TestValues.PURCHASE_ORDER_ID2) + .setStatus( + PurchaseOrderStatus.CREATED) + .build(); + + private TestMealOrderEventFactory() { + } + + public static class PurchaseOrderEvents { + private PurchaseOrderEvents() { + } + + public static PurchaseOrderValidationFailed purchaseOrderValidationFailedInstance() { + return purchaseOrderValidationFailedInstance(TestValues.PURCHASE_ORDER_ID, + TestValues.ORDER); + } + + public static PurchaseOrderValidationFailed purchaseOrderValidationFailedInstance( + PurchaseOrderId purchaseOrderId, Order order) { + final Timestamp currentTime = getCurrentTime(); + final PurchaseOrderValidationFailed result = + PurchaseOrderValidationFailed.newBuilder() + .setId(purchaseOrderId) + .addFailureOrder(order) + .setWhenFailed(currentTime) + .build(); + return result; + } + + public static PurchaseOrderSent purchaseOrderSentInstance() { + return purchaseOrderSentInstance(PURCHASE_ORDER, TestValues.USER_ID.getEmail(), + TestValues.EMAIL); + } + + public static PurchaseOrderSent purchaseOrderSentInstance2() { + return purchaseOrderSentInstance(PURCHASE_ORDER2, TestValues.USER_ID3.getEmail(), + TestValues.EMAIL); + } + + public static PurchaseOrderSent purchaseOrderSentInstance(PurchaseOrder po, + EmailAddress senderEmail, + EmailAddress vendorEmail) { + final Timestamp currentTime = getCurrentTime(); + final PurchaseOrderSent result = + PurchaseOrderSent.newBuilder() + .setPurchaseOrder(po) + .setSenderEmail(senderEmail) + .setVendorEmail(vendorEmail) + .setWhenSent(currentTime) + .build(); + return result; + } + + public static PurchaseOrderDelivered purchaseOrderDeliveredInstance() { + return purchaseOrderDeliveredInstance(TestValues.PURCHASE_ORDER_ID, TestValues.USER_ID); + } + + public static PurchaseOrderDelivered purchaseOrderDeliveredInstance2() { + return purchaseOrderDeliveredInstance(TestValues.PURCHASE_ORDER_ID2, + TestValues.USER_ID); + } + + private static PurchaseOrderDelivered purchaseOrderDeliveredInstance( + PurchaseOrderId purchaseOrderId, + UserId userId) { + final Timestamp currentTime = getCurrentTime(); + final PurchaseOrderDelivered result = + PurchaseOrderDelivered.newBuilder() + .setId(purchaseOrderId) + .setWhoMarkedAsDelivered(userId) + .setWhenDelivered(currentTime) + .build(); + return result; + } + + public static PurchaseOrderCreated purchaseOrderCreatedInstance() { + return purchaseOrderCreatedInstance(TestValues.PURCHASE_ORDER_ID, TestValues.USER_ID, + TestValues.BIG_ORDER); + } + + public static PurchaseOrderCreated purchaseOrderCreatedInstance2() { + return purchaseOrderCreatedInstance(TestValues.PURCHASE_ORDER_ID2, TestValues.USER_ID, + TestValues.BIG_ORDER); + } + + public static PurchaseOrderCreated purchaseOrderCreatedInstance( + PurchaseOrderId purchaseOrderId, UserId userId, + List orders) { + final Timestamp currentTime = getCurrentTime(); + final PurchaseOrderCreated result = + PurchaseOrderCreated.newBuilder() + .setId(purchaseOrderId) + .setWhenCreated(currentTime) + .setWhoCreated(userId) + .addAllOrder(orders) + .build(); + return result; + } + } + + public static class VendorEvents { + private VendorEvents() { + } + + public static MenuImported menuImportedInstance() { + return menuImportedInstance(TestValues.VENDOR_ID, TestValues.MENU_ID, + TestValues.USER_ID, TestValues.BIG_MENU, + TestValues.MENU_DATE_RANGE2); + } + + private static MenuImported menuImportedInstance(VendorId vendorId, MenuId menuId, + UserId whoImported, List dishes, + MenuDateRange menuDateRange) { + final Timestamp currentTime = getCurrentTime(); + final MenuImported result = + MenuImported.newBuilder() + .setVendorId(vendorId) + .setMenuId(menuId) + .setWhoImported(whoImported) + .setWhenImported(currentTime) + .addAllDish(dishes) + .setMenuDateRange(menuDateRange) + .build(); + return result; + } + + public static VendorAdded vendorAddedInstance() { + return vendorAddedInstance(TestValues.VENDOR_ID, TestValues.USER_ID, + TestValues.VENDOR_NAME, TestValues.EMAIL, + TestValues.PHONE_NUMBERS, TestValues.PO_DAILY_DEADLINE); + } + + private static VendorAdded vendorAddedInstance(VendorId vendorId, UserId userId, + VendorName vendorName, EmailAddress email, + List numbers, + LocalTime deadline) { + final Timestamp currentTime = getCurrentTime(); + final VendorAdded result = + VendorAdded.newBuilder() + .setVendorId(vendorId) + .setWhoAdded(userId) + .setWhenAdded(currentTime) + .setVendorName(vendorName) + .addAllPhoneNumber(numbers) + .setEmail(email) + .setPoDailyDeadline(deadline) + .build(); + return result; + } + + public static VendorUpdated vendorUpdatedInstance() { + return vendorUpdatedInstance(TestValues.VENDOR_ID, TestValues.USER_ID, + TestValues.VENDOR_CHANGE); + } + + private static VendorUpdated vendorUpdatedInstance(VendorId vendorId, UserId userId, + VendorChange vendorChange) { + final Timestamp currentTime = getCurrentTime(); + final VendorUpdated result = + VendorUpdated.newBuilder() + .setVendorId(vendorId) + .setWhoUploaded(userId) + .setVendorChange(vendorChange) + .setWhenUpdated(currentTime) + .build(); + return result; + } + + } + + public static class OrderEvents { + private OrderEvents() { + } + + public static DishAddedToOrder dishAddedToOrderInstance() { + return dishAddedToOrderInstance(TestValues.ORDER_ID, TestValues.DISH1); + } + + public static DishAddedToOrder dishAddedToOrderInstance2() { + return dishAddedToOrderInstance(TestValues.ORDER_ID2, TestValues.DISH2); + } + + private static DishAddedToOrder dishAddedToOrderInstance(OrderId orderId, Dish dish) { + final Timestamp currentTime = getCurrentTime(); + final DishAddedToOrder result = + DishAddedToOrder.newBuilder() + .setOrderId(orderId) + .setDish(dish) + .setWhenAdded(currentTime) + .build(); + return result; + } + + public static OrderCanceled orderCanceledInstance() { + return orderCanceledInstance(TestValues.ORDER_ID, TestValues.USER_ID); + } + + private static OrderCanceled orderCanceledInstance(OrderId orderId, UserId userId) { + final Timestamp currentTime = getCurrentTime(); + final OrderCanceled result = + OrderCanceled.newBuilder() + .setOrderId(orderId) + .setWhoCanceled(userId) + .setWhenCanceled(currentTime) + .build(); + return result; + } + + public static OrderProcessed orderProcessedInstance() { + return orderProcessedInstance(TestValues.ORDER); + } + + private static OrderProcessed orderProcessedInstance(Order order) { + final Timestamp currentTime = getCurrentTime(); + final OrderProcessed result = + OrderProcessed.newBuilder() + .setOrder(order) + .setWhenProcessed(currentTime) + .build(); + return result; + } + + public static DishRemovedFromOrder dishRemovedFromOrderInstance() { + return dishRemovedFromOrderInstance(TestValues.ORDER_ID, TestValues.DISH1); + } + + private static DishRemovedFromOrder dishRemovedFromOrderInstance(OrderId orderId, + Dish dish) { + final Timestamp currentTime = getCurrentTime(); + final DishRemovedFromOrder result = + DishRemovedFromOrder.newBuilder() + .setOrderId(orderId) + .setDish(dish) + .setWhenRemoved(currentTime) + .build(); + return result; + } + } +} diff --git a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestOrderCommandFactory.java b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestOrderCommandFactory.java index 6bd62875..a8daa065 100644 --- a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestOrderCommandFactory.java +++ b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestOrderCommandFactory.java @@ -35,6 +35,7 @@ import static javaclasses.mealorder.testdata.TestValues.ORDER_ID; import static javaclasses.mealorder.testdata.TestValues.ORDER_ID_WITH_INVALID_DATE; import static javaclasses.mealorder.testdata.TestValues.ORDER_ID_WITH_INVALID_VENDOR; +import static javaclasses.mealorder.testdata.TestValues.USER_ID2; /** * @author Vlad Kozachenko @@ -72,6 +73,7 @@ public static CancelOrder cancelOrderInstance() { public static CancelOrder cancelOrderInstance(OrderId orderId) { return CancelOrder.newBuilder() .setOrderId(orderId) + .setWhoCancels(USER_ID2) .build(); } diff --git a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestPurchaseOrderCommandFactory.java b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestPurchaseOrderCommandFactory.java index 4be24826..67a9fc6c 100644 --- a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestPurchaseOrderCommandFactory.java +++ b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestPurchaseOrderCommandFactory.java @@ -37,9 +37,11 @@ import java.util.List; import static javaclasses.mealorder.OrderStatus.ORDER_CANCELED; +import static javaclasses.mealorder.testdata.TestValues.EMAIL; import static javaclasses.mealorder.testdata.TestValues.ORDER; import static javaclasses.mealorder.testdata.TestValues.PURCHASE_ORDER_ID; import static javaclasses.mealorder.testdata.TestValues.USER_ID; +import static javaclasses.mealorder.testdata.TestValues.USER_ID2; /** * A factory of the purchase order commands for the test needs. @@ -61,10 +63,20 @@ public static CreatePurchaseOrder createPurchaseOrderInstance() { .setId(PURCHASE_ORDER_ID) .setWhoCreates(USER_ID) .addOrder(ORDER) + .setVendorEmail(EMAIL) .build(); return result; } + public static CreatePurchaseOrder createPurchaseOrderInstance(List order) { + final CreatePurchaseOrder result = CreatePurchaseOrder.newBuilder() + .setId(PURCHASE_ORDER_ID) + .setWhoCreates(USER_ID) + .addAllOrder(order) + .setVendorEmail(EMAIL) + .build(); + return result; + } /** * Provides a pre-configured {@link CreatePurchaseOrder} instance * with mismatch vendor identifier of purchase order and one of @@ -158,6 +170,8 @@ public static CreatePurchaseOrder createPurchaseOrderWithEmptyListInstance() { final PurchaseOrderId id = validCmd.getId(); final CreatePurchaseOrder result = CreatePurchaseOrder.newBuilder() .setId(id) + .setVendorEmail(EMAIL) + .setWhoCreates(USER_ID2) .build(); return result; } @@ -197,6 +211,7 @@ public static MarkPurchaseOrderAsValid markPurchaseOrderAsValidInstance() { .setId(PURCHASE_ORDER_ID) .setReason("Because I can.") .setUserId(USER_ID) + .setVendorEmail(EMAIL) .build(); return result; } diff --git a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestValues.java b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestValues.java index e0520521..1746853f 100644 --- a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestValues.java +++ b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestValues.java @@ -38,7 +38,11 @@ import javaclasses.mealorder.VendorId; import javaclasses.mealorder.VendorName; +import java.util.ArrayList; +import java.util.List; + import static io.spine.time.MonthOfYear.FEBRUARY; +import static io.spine.time.MonthOfYear.MARCH; import static io.spine.time.Time.getCurrentTime; import static javaclasses.mealorder.OrderStatus.ORDER_ACTIVE; @@ -55,10 +59,18 @@ public class TestValues { .setValue("VendorName1") .build(); + public static final VendorName VENDOR_NAME2 = VendorName.newBuilder() + .setValue("Позитив") + .build(); + public static final VendorId VENDOR_ID = VendorId.newBuilder() .setValue("vendor:" + VENDOR_NAME) .build(); + public static final VendorId VENDOR_ID2 = VendorId.newBuilder() + .setValue("vendor:" + VENDOR_NAME2) + .build(); + public static final VendorName NEW_VENDOR_NAME = VendorName.newBuilder() .setValue("VendorName2") .build(); @@ -74,6 +86,18 @@ public class TestValues { .build()) .build(); + public static final UserId USER_ID2 = UserId.newBuilder() + .setEmail(EmailAddress.newBuilder() + .setValue( + "petr@example.com") + .build()) + .build(); + public static final UserId USER_ID3 = UserId.newBuilder() + .setEmail(EmailAddress.newBuilder() + .setValue( + "sasha@mail.com") + .build()) + .build(); public static final LocalTime PO_DAILY_DEADLINE = LocalTime.newBuilder() .setHours(10) .setMinutes(0) @@ -86,6 +110,7 @@ public class TestValues { public static final PhoneNumber PHONE_NUMBER2 = PhoneNumber.newBuilder() .setValue("0987654321") .build(); + public static final List PHONE_NUMBERS = getPhoneNumbers(); public static final VendorChange VENDOR_CHANGE = VendorChange.newBuilder() .setPreviousVendorName(VENDOR_NAME) @@ -100,7 +125,7 @@ public class TestValues { .setNewEmail(EMAIL) .addNewPhoneNumber(PHONE_NUMBER1) .addNewPhoneNumber(PHONE_NUMBER2) - .setPreviousPoDailyDeadline( + .setNewPoDailyDeadline( PO_DAILY_DEADLINE) .build(); @@ -109,6 +134,11 @@ public class TestValues { .setWhenImported(getCurrentTime()) .build(); + public static final MenuId MENU_ID2 = MenuId.newBuilder() + .setVendorId(VENDOR_ID2) + .setWhenImported(getCurrentTime()) + .build(); + public static final MenuId NONEXISTENT_MENU_ID = MenuId.newBuilder() .setVendorId(VENDOR_ID) .setWhenImported( @@ -120,18 +150,21 @@ public class TestValues { .setMonthValue(2) .setDay(13) .build(); - + public static final LocalDate START_DATE2 = LocalDate.newBuilder() + .setYear(2020) + .setMonthValue(2) + .setDay(22) + .build(); public static final LocalDate END_DATE = LocalDate.newBuilder() .setYear(2019) .setMonthValue(2) .setDay(21) .build(); - - public static final MenuDateRange MENU_DATE_RANGE = MenuDateRange.newBuilder() - .setRangeStart(START_DATE) - .setRangeEnd(END_DATE) - .build(); - + public static final LocalDate END_DATE2 = LocalDate.newBuilder() + .setYear(2020) + .setMonthValue(3) + .setDay(18) + .build(); public static final LocalDate START_DATE_FROM_PAST = LocalDate.newBuilder() .setYear(2017) .setMonthValue(2) @@ -144,6 +177,23 @@ public class TestValues { .setDay(19) .build(); + public static final LocalDate END_DATE_FROM_PAST2 = LocalDate.newBuilder() + .setYear(2017) + .setMonthValue(3) + .setDay(10) + .build(); + public static final MenuDateRange MENU_DATE_RANGE = MenuDateRange.newBuilder() + .setRangeStart(START_DATE) + .setRangeEnd(END_DATE) + .build(); + public static final MenuDateRange MENU_DATE_RANGE2 = MenuDateRange.newBuilder() + .setRangeStart( + START_DATE2) + .setRangeEnd( + END_DATE2) + .build(); + + public static final LocalDate INVALID_START_DATE = LocalDate.newBuilder() .setYear(2020) .setMonthValue(2) @@ -163,11 +213,12 @@ public class TestValues { INVALID_END_DATE) .build(); + public static final MenuDateRange MENU_DATE_RANGE_FROM_PAST = MenuDateRange.newBuilder() .setRangeStart( - START_DATE_FROM_PAST) + START_DATE_FROM_PAST) .setRangeEnd( - END_DATE_FROM_PAST) + END_DATE_FROM_PAST) .build(); public static final Dish DISH1 = Dish.newBuilder() @@ -177,7 +228,9 @@ public class TestValues { .build()) .setName("dishName1") .setCategory("category") - .setPrice(Money.getDefaultInstance()) + .setPrice(Money.newBuilder() + .setAmount(56) + .build()) .build(); public static final Dish DISH2 = Dish.newBuilder() @@ -187,7 +240,76 @@ public class TestValues { .build()) .setName("dishName2") .setCategory("category") - .setPrice(Money.getDefaultInstance()) + .setPrice(Money.newBuilder() + .setAmount(56) + .build()) + .build(); + + public static final Dish DISH3 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Картофель") + .setCategory("Второе блюдо") + .setPrice(Money.newBuilder() + .setAmount(56) + .build()) + .build(); + public static final Dish DISH4 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Борщ украинский") + .setCategory("Первое блюдо") + .setPrice(Money.newBuilder() + .setAmount(33) + .build()) + .build(); + public static final Dish DISH5 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Стейк из лосося") + .setCategory("Второе блюдо") + .setPrice(Money.newBuilder() + .setAmount(80) + .build()) + .build(); + public static final Dish DISH6 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Компот из сухофруктов") + .setCategory("Напитки") + .setPrice(Money.newBuilder() + .setAmount(10) + .build()) + .build(); + public static final Dish DISH7 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Скумбрия на гриле") + .setCategory("Второе блюдо") + .setPrice(Money.newBuilder() + .setAmount(10) + .build()) + .build(); + public static final Dish DISH8 = Dish.newBuilder() + .setId(DishId.newBuilder() + .setMenuId(MENU_ID2) + .setSequentialNumber(1) + .build()) + .setName("Суп гороховый") + .setCategory("Первое блюдо") + .setPrice(Money.newBuilder() + .setAmount(10) + .build()) .build(); public static final LocalDate DATE = LocalDate.newBuilder() @@ -198,11 +320,24 @@ public class TestValues { .setDay(15) .build(); + public static final LocalDate DATE2 = LocalDate.newBuilder() + .setYear( + 2020) + .setMonth( + MARCH) + .setDay(3) + .build(); + public static final OrderId ORDER_ID = OrderId.newBuilder() .setUserId(USER_ID) .setVendorId(VENDOR_ID) .setOrderDate(DATE) .build(); + public static final OrderId ORDER_ID2 = OrderId.newBuilder() + .setUserId(USER_ID2) + .setVendorId(VENDOR_ID2) + .setOrderDate(DATE) + .build(); public static final VendorId INVALID_VENDOR_ID = VendorId.newBuilder() .setValue("vendor:INVALID") @@ -239,10 +374,98 @@ public class TestValues { .setVendorId(VENDOR_ID) .setPoDate(DATE) .build(); - + public static final PurchaseOrderId PURCHASE_ORDER_ID2 = PurchaseOrderId + .newBuilder() + .setVendorId(VENDOR_ID2) + .setPoDate(DATE2) + .build(); public static final Order ORDER = Order.newBuilder() .setId(ORDER_ID) .addDish(DISH1) .setStatus(ORDER_ACTIVE) .build(); + public static final List BIG_ORDER = createOrder(); + public static final List MENU = createSmallMenu(); + + public static final List BIG_MENU = createMenu(); + + private static List createMenu() { + final List menu = new ArrayList<>(); + menu.add(DISH3); + menu.add(DISH4); + menu.add(DISH5); + menu.add(DISH6); + menu.add(DISH7); + menu.add(DISH8); + + return menu; + } + + private static List createSmallMenu() { + final List menu = new ArrayList<>(); + menu.add(DISH1); + menu.add(DISH2); + return menu; + } + + private static List getPhoneNumbers() { + final List numbers = new ArrayList<>(); + numbers.add(PHONE_NUMBER1); + numbers.add(PHONE_NUMBER2); + return numbers; + } + + private static List createOrder() { + List orders = new ArrayList<>(); + final Order order1 = Order.newBuilder() + .addDish(DISH1) + .addDish(DISH1) + .addDish(DISH1) + .setId( + OrderId.newBuilder() + .setUserId(USER_ID) + .setVendorId(VENDOR_ID) + .setOrderDate(END_DATE) + .build()) + .build(); + final Order order2 = Order.newBuilder() + .addDish(DISH1) + .addDish(DISH1) + .addDish(DISH2) + .addDish(DISH2) + .addDish(DISH2) + .setId( + OrderId.newBuilder() + .setUserId(USER_ID2) + .setVendorId(VENDOR_ID) + .setOrderDate(END_DATE) + .build()) + .build(); + final Order order3 = Order.newBuilder() + .addDish(DISH2) + .addDish(DISH2) + .setId( + OrderId.newBuilder() + .setUserId(USER_ID) + .setVendorId(VENDOR_ID2) + .setOrderDate(END_DATE) + .build()) + .build(); + final Order order4 = Order.newBuilder() + .addDish(DISH1) + .addDish(DISH1) + .addDish(DISH2) + .setId( + OrderId.newBuilder() + .setUserId(USER_ID2) + .setVendorId(VENDOR_ID2) + .setOrderDate(END_DATE) + .build()) + .build(); + orders.add(order1); + orders.add(order2); + orders.add(order3); + orders.add(order4); + return orders; + } } diff --git a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestVendorCommandFactory.java b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestVendorCommandFactory.java index 3f54889a..055bd930 100644 --- a/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestVendorCommandFactory.java +++ b/testutil-api/src/main/java/javaclasses/mealorder/testdata/TestVendorCommandFactory.java @@ -32,10 +32,25 @@ import javaclasses.mealorder.VendorName; import javaclasses.mealorder.c.command.AddVendor; import javaclasses.mealorder.c.command.ImportMenu; -import javaclasses.mealorder.c.command.SetDateRangeForMenu; import javaclasses.mealorder.c.command.UpdateVendor; -import static javaclasses.mealorder.testdata.TestValues.*; +import java.util.List; + +import static javaclasses.mealorder.testdata.TestValues.BIG_MENU; +import static javaclasses.mealorder.testdata.TestValues.EMAIL; +import static javaclasses.mealorder.testdata.TestValues.MENU; +import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE; +import static javaclasses.mealorder.testdata.TestValues.MENU_DATE_RANGE2; +import static javaclasses.mealorder.testdata.TestValues.MENU_ID; +import static javaclasses.mealorder.testdata.TestValues.MENU_ID2; +import static javaclasses.mealorder.testdata.TestValues.PHONE_NUMBER1; +import static javaclasses.mealorder.testdata.TestValues.PHONE_NUMBER2; +import static javaclasses.mealorder.testdata.TestValues.PO_DAILY_DEADLINE; +import static javaclasses.mealorder.testdata.TestValues.USER_ID; +import static javaclasses.mealorder.testdata.TestValues.USER_ID2; +import static javaclasses.mealorder.testdata.TestValues.VENDOR_CHANGE; +import static javaclasses.mealorder.testdata.TestValues.VENDOR_ID; +import static javaclasses.mealorder.testdata.TestValues.VENDOR_NAME; /** * A factory of the vendor commands for the test needs. @@ -119,10 +134,23 @@ public static UpdateVendor updateVendorInstance(VendorId vendorId, UserId userId * @return the {@code ImportMenu} instance */ public static ImportMenu importMenuInstance() { - final ImportMenu result = importMenuInstance(VENDOR_ID, USER_ID, MENU_ID, DISH1, DISH2); + final ImportMenu result = importMenuInstance(VENDOR_ID, USER_ID, MENU_ID, MENU_DATE_RANGE, + MENU); return result; } + public static ImportMenu importMenuInstance2() { + final ImportMenu result = importMenuInstance(VENDOR_ID, USER_ID, MENU_ID, MENU_DATE_RANGE, + BIG_MENU); + return result; + } + + public static ImportMenu importMenuInstance3() { + final ImportMenu result = importMenuInstance(VENDOR_ID, USER_ID2, MENU_ID2, + MENU_DATE_RANGE2, + BIG_MENU); + return result; + } /** * Provides a pre-configured {@link ImportMenu} instance. * @@ -133,48 +161,16 @@ public static ImportMenu importMenuInstance() { * @return the {@code CreateBasicTask} instance */ public static ImportMenu importMenuInstance(VendorId vendorId, UserId userId, MenuId menuId, - Dish... dishes) { + MenuDateRange menuDateRange, + List dishes) { final ImportMenu result = ImportMenu.newBuilder() .setVendorId(vendorId) .setUserId(userId) .setMenuId(menuId) - .addDish(dishes[0]) - .addDish(dishes[1]) + .addAllDish(dishes) + .setMenuDateRange(menuDateRange) .build(); return result; } - - /** - * Provides a pre-configured {@link SetDateRangeForMenu} instance. - * - * @return the {@code ImportMenu} instance - */ - public static SetDateRangeForMenu setDateRangeForMenuInstance() { - final SetDateRangeForMenu result = setDateRangeForMenuInstance(VENDOR_ID, MENU_ID, USER_ID, - MENU_DATE_RANGE); - return result; - } - - /** - * Provides a pre-configured {@link SetDateRangeForMenu} instance. - * - * @param vendorId the identifier of a created vendor - * @param userId the identifier of the user who updates vendor profile - * @param menuId the identifier of the imported menu - * @param menuDateRange a menu date range that should be set. - * @return the {@code CreateBasicTask} instance - */ - public static SetDateRangeForMenu setDateRangeForMenuInstance(VendorId vendorId, MenuId menuId, - UserId userId, - MenuDateRange menuDateRange) { - - final SetDateRangeForMenu result = SetDateRangeForMenu.newBuilder() - .setVendorId(vendorId) - .setUserId(userId) - .setMenuId(menuId) - .setMenuDateRange(menuDateRange) - .build(); - return result; - } }