From c877bf3d287351a2672d6fd065c49546eb6a27e2 Mon Sep 17 00:00:00 2001 From: Teo Sarca Date: Thu, 19 Sep 2019 21:14:41 +0300 Subject: [PATCH] ProductsToPickRowsDataFactoryTest https://github.com/metasfresh/metasfresh/issues/5544 --- pom.xml | 68 ++--- .../productsToPick/PickingV2TestHelper.java | 182 +++++++++++++ .../ProductsToPickRowsDataFactoryTest.java | 252 ++++++++++++++++++ 3 files changed, 472 insertions(+), 30 deletions(-) create mode 100644 src/test/java/de/metas/ui/web/pickingV2/productsToPick/PickingV2TestHelper.java create mode 100644 src/test/java/de/metas/ui/web/pickingV2/productsToPick/ProductsToPickRowsDataFactoryTest.java diff --git a/pom.xml b/pom.xml index a9e55b86e..60e060869 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 @@ -8,7 +10,8 @@ [1,10.0.0] - + 10.0.0 de.metas.ui.web @@ -18,9 +21,8 @@ 1.5.3.RELEASE - + [1,10.0.0] @@ -49,20 +51,15 @@ org.springframework.boot spring-boot-starter-websocket - - - - + + + + - + de.codecentric spring-boot-admin-starter-client @@ -105,7 +102,8 @@ de.metas.fresh.base ${metasfresh.version} - + de.metas.adempiere.adempiere de.metas.adempiere.adempiere.serverRoot.base @@ -125,7 +123,7 @@ ${metasfresh.version} - de.metas.vertical.pharma @@ -161,6 +159,15 @@ ${metasfresh.version} + + de.metas.handlingunits + de.metas.handlingunits.base + ${metasfresh.version} + tests + test + + + de.metas.elasticsearch @@ -235,7 +242,7 @@ - + org.jmockit jmockit @@ -248,7 +255,8 @@ spring-boot-starter-test test - + org.ow2.asm asm @@ -268,10 +276,9 @@ metasfresh-webui-api - + org.codehaus.mojo versions-maven-plugin @@ -288,7 +295,8 @@ - + org.apache.maven.plugins maven-jar-plugin @@ -353,8 +361,8 @@ true + Note that the ${docker.build.directory} property is set by the prepare-docker + profile that is activated by the presence of the scr/main/docker folder --> ${docker.build.directory} diff --git a/src/test/java/de/metas/ui/web/pickingV2/productsToPick/PickingV2TestHelper.java b/src/test/java/de/metas/ui/web/pickingV2/productsToPick/PickingV2TestHelper.java new file mode 100644 index 000000000..9a7cfdef1 --- /dev/null +++ b/src/test/java/de/metas/ui/web/pickingV2/productsToPick/PickingV2TestHelper.java @@ -0,0 +1,182 @@ +package de.metas.ui.web.pickingV2.productsToPick; + +import static org.adempiere.model.InterfaceWrapperHelper.newInstance; +import static org.adempiere.model.InterfaceWrapperHelper.saveRecord; + +import java.time.LocalDate; + +import javax.annotation.Nullable; + +import org.adempiere.mm.attributes.AttributeId; +import org.adempiere.mm.attributes.api.AttributeConstants; +import org.adempiere.model.InterfaceWrapperHelper; +import org.adempiere.warehouse.LocatorId; +import org.adempiere.warehouse.WarehouseId; +import org.compiere.model.I_C_UOM; +import org.compiere.model.I_M_Attribute; +import org.compiere.model.X_M_Attribute; +import org.compiere.util.TimeUtil; + +import de.metas.adempiere.model.I_M_Product; +import de.metas.handlingunits.HuId; +import de.metas.handlingunits.HuPackingInstructionsId; +import de.metas.handlingunits.HuPackingInstructionsVersionId; +import de.metas.handlingunits.model.I_M_HU; +import de.metas.handlingunits.model.I_M_HU_Attribute; +import de.metas.handlingunits.model.I_M_HU_PI; +import de.metas.handlingunits.model.I_M_HU_PI_Attribute; +import de.metas.handlingunits.model.I_M_HU_PI_Version; +import de.metas.handlingunits.model.I_M_HU_Storage; +import de.metas.handlingunits.model.I_M_Locator; +import de.metas.handlingunits.model.I_M_Warehouse; +import de.metas.handlingunits.model.X_M_HU; +import de.metas.handlingunits.model.X_M_HU_PI_Version; +import de.metas.handlingunits.test.misc.builders.HUPIAttributeBuilder; +import de.metas.product.ProductId; +import de.metas.quantity.Quantity; +import de.metas.ui.web.window.datatypes.LookupValue.IntegerLookupValue; +import de.metas.util.NumberUtils; +import lombok.Builder; +import lombok.NonNull; + +/* + * #%L + * metasfresh-webui-api + * %% + * Copyright (C) 2019 metas GmbH + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +final class PickingV2TestHelper +{ + public final I_C_UOM uomKg; + public final AttributeId bestBeforeDateAttributeId; + private int huPIAttributeId_VHU_BestBeforeDate; + + public PickingV2TestHelper() + { + uomKg = createUOM("Kg"); + bestBeforeDateAttributeId = createAttribute(AttributeConstants.ATTR_BestBeforeDate, X_M_Attribute.ATTRIBUTEVALUETYPE_Date); + createVirtualPI(); + } + + public AttributeId createAttribute( + @NonNull final String code, + @NonNull final String valueType) + { + I_M_Attribute attribute = newInstance(I_M_Attribute.class); + attribute.setValue(code); + attribute.setName(code); + attribute.setAttributeValueType(valueType); + saveRecord(attribute); + return AttributeId.ofRepoId(attribute.getM_Attribute_ID()); + } + + public I_C_UOM createUOM(final String symbol) + { + I_C_UOM record = newInstance(I_C_UOM.class); + record.setUOMSymbol(symbol); + saveRecord(record); + return record; + } + + public ProductId createProduct(final String code) + { + I_M_Product record = newInstance(I_M_Product.class); + record.setValue(code); + record.setName(code); + saveRecord(record); + return ProductId.ofRepoId(record.getM_Product_ID()); + } + + public WarehouseId createWarehouse() + { + I_M_Warehouse record = newInstance(I_M_Warehouse.class); + saveRecord(record); + return WarehouseId.ofRepoId(record.getM_Warehouse_ID()); + } + + public LocatorId createLocator(final WarehouseId warehouseId) + { + I_M_Locator record = newInstance(I_M_Locator.class); + record.setM_Warehouse_ID(warehouseId.getRepoId()); + saveRecord(record); + return LocatorId.ofRecord(record); + } + + @Builder(builderMethodName = "prepareExistingHU", builderClassName = "ExistingHUBuilder") + private HuId createExistingHU( + @NonNull final LocatorId locatorId, + @Nullable final LocalDate bestBeforeDate, + @NonNull final ProductId productId, + @NonNull final Quantity qty) + { + final I_M_HU hu = newInstance(I_M_HU.class); + hu.setM_HU_PI_Version_ID(HuPackingInstructionsVersionId.VIRTUAL.getRepoId()); + hu.setHUStatus(X_M_HU.HUSTATUS_Active); + hu.setM_Locator_ID(locatorId.getRepoId()); + saveRecord(hu); + + final I_M_HU_Attribute huAttribute = newInstance(I_M_HU_Attribute.class); + huAttribute.setM_HU_ID(hu.getM_HU_ID()); + huAttribute.setM_HU_PI_Attribute_ID(huPIAttributeId_VHU_BestBeforeDate); + huAttribute.setM_Attribute_ID(bestBeforeDateAttributeId.getRepoId()); + huAttribute.setValueDate(TimeUtil.asTimestamp(bestBeforeDate)); + saveRecord(huAttribute); + + final I_M_HU_Storage huStorage = newInstance(I_M_HU_Storage.class); + huStorage.setM_HU_ID(hu.getM_HU_ID()); + huStorage.setM_Product_ID(productId.getRepoId()); + huStorage.setQty(qty.toBigDecimal()); + huStorage.setC_UOM_ID(qty.getUomId().getRepoId()); + saveRecord(huStorage); + + return HuId.ofRepoId(hu.getM_HU_ID()); + } + + public void createVirtualPI() + { + final I_M_HU_PI pi = InterfaceWrapperHelper.newInstance(I_M_HU_PI.class); + pi.setName("VirtualPI"); + pi.setM_HU_PI_ID(HuPackingInstructionsId.VIRTUAL.getRepoId()); + saveRecord(pi); + + final I_M_HU_PI_Version version = InterfaceWrapperHelper.newInstance(I_M_HU_PI_Version.class); + version.setName(pi.getName()); + version.setM_HU_PI_ID(pi.getM_HU_PI_ID()); + version.setIsCurrent(true); + version.setHU_UnitType(X_M_HU_PI_Version.HU_UNITTYPE_VirtualPI); + version.setM_HU_PI_Version_ID(HuPackingInstructionsVersionId.VIRTUAL.getRepoId()); + saveRecord(version); + + final I_M_HU_PI_Attribute huPIAttribute = HUPIAttributeBuilder.newInstance(bestBeforeDateAttributeId) + .setM_HU_PI_Version(HuPackingInstructionsVersionId.VIRTUAL) + .create(); + huPIAttributeId_VHU_BestBeforeDate = huPIAttribute.getM_HU_PI_Attribute_ID(); + } + + public IntegerLookupValue locatorLookupById(final Object idObj) + { + if (idObj == null) + { + return null; + } + final int id = NumberUtils.asIntegerOrNull(idObj); + return IntegerLookupValue.of(id, "locator-" + id); + } + +} diff --git a/src/test/java/de/metas/ui/web/pickingV2/productsToPick/ProductsToPickRowsDataFactoryTest.java b/src/test/java/de/metas/ui/web/pickingV2/productsToPick/ProductsToPickRowsDataFactoryTest.java new file mode 100644 index 000000000..c1b0339d4 --- /dev/null +++ b/src/test/java/de/metas/ui/web/pickingV2/productsToPick/ProductsToPickRowsDataFactoryTest.java @@ -0,0 +1,252 @@ +package de.metas.ui.web.pickingV2.productsToPick; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; +import java.time.Month; +import java.util.Optional; + +import javax.annotation.Nullable; + +import org.adempiere.mm.attributes.AttributeSetInstanceId; +import org.adempiere.test.AdempiereTestHelper; +import org.adempiere.warehouse.LocatorId; +import org.adempiere.warehouse.WarehouseId; +import org.compiere.model.I_C_UOM; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +import de.metas.bpartner.BPartnerId; +import de.metas.bpartner.BPartnerLocationId; +import de.metas.bpartner.ShipmentAllocationBestBeforePolicy; +import de.metas.handlingunits.HuId; +import de.metas.handlingunits.picking.PickingCandidateRepository; +import de.metas.handlingunits.picking.PickingCandidateService; +import de.metas.handlingunits.reservation.HUReservationRepository; +import de.metas.handlingunits.reservation.HUReservationService; +import de.metas.handlingunits.sourcehu.HuId2SourceHUsService; +import de.metas.handlingunits.trace.HUTraceRepository; +import de.metas.inoutcandidate.api.Packageable; +import de.metas.inoutcandidate.api.ShipmentScheduleId; +import de.metas.order.OrderId; +import de.metas.product.ProductId; +import de.metas.quantity.Quantity; +import de.metas.ui.web.pickingV2.packageable.PackageableRow; +import de.metas.ui.web.window.datatypes.LookupValue.IntegerLookupValue; +import lombok.Builder; +import lombok.NonNull; + +/* + * #%L + * metasfresh-webui-api + * %% + * Copyright (C) 2019 metas GmbH + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +public class ProductsToPickRowsDataFactoryTest +{ + private PickingV2TestHelper testHelper; + + // + // Master data + private BPartnerLocationId customerAndLocationId; + private ProductId productId; + private I_C_UOM uomKg; + private LocatorId locatorId; + + @BeforeEach + public void beforeEachTest() + { + AdempiereTestHelper.get().init(); + testHelper = new PickingV2TestHelper(); + + customerAndLocationId = BPartnerLocationId.ofRepoId(BPartnerId.ofRepoId(2), 3); + productId = testHelper.createProduct("product"); + uomKg = testHelper.uomKg; + final WarehouseId warehouseId = testHelper.createWarehouse(); + locatorId = testHelper.createLocator(warehouseId); + } + + private ProductsToPickRowsDataFactory createProductsToPickRowsDataFactory() + { + final HUReservationRepository huReservationRepository = new HUReservationRepository(); + final HUReservationService huReservationService = new HUReservationService(huReservationRepository); + + final PickingCandidateRepository pickingCandidateRepository = new PickingCandidateRepository(); + + final HUTraceRepository huTraceRepository = new HUTraceRepository(); + final HuId2SourceHUsService sourceHUsRepository = new HuId2SourceHUsService(huTraceRepository); + + final PickingCandidateService pickingCandidateService = new PickingCandidateService(pickingCandidateRepository, sourceHUsRepository); + + return ProductsToPickRowsDataFactory.builder() + .huReservationService(huReservationService) + .pickingCandidateService(pickingCandidateService) + .locatorLookup(testHelper::locatorLookupById) + .build(); + } + + @Test + public void testRowsOrder_BestBeforePolicy_Expiring_First() + { + final HuId huId1 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(LocalDate.of(2019, Month.SEPTEMBER, 1)) + .productId(productId) + .qty(Quantity.of(10, uomKg)) + .build(); + + final HuId huId2 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(LocalDate.of(2019, Month.SEPTEMBER, 2)) + .productId(productId) + .qty(Quantity.of(11, uomKg)) + .build(); + + final HuId huId3 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(null) + .productId(productId) + .qty(Quantity.of(12, uomKg)) + .build(); + + final PackageableRow packageableRow = preparePackageableRow() + .qtyOrdered(Quantity.of(100, uomKg)) + .bestBeforePolicy(ShipmentAllocationBestBeforePolicy.Expiring_First) + .build(); + + final ProductsToPickRowsDataFactory productsToPickRowsDataFactory = createProductsToPickRowsDataFactory(); + final ProductsToPickRowsData rowsData = productsToPickRowsDataFactory.create(packageableRow); + + final ImmutableList rows = ImmutableList.copyOf(rowsData.getTopLevelRows()); + rows.forEach(row -> System.out.println("hu=" + row.getHuId() + ", exp=" + row.getExpiringDate() + ", qty=" + row.getQty() + " -- " + row)); + assertThat(rows).hasSize(4); + + final ProductsToPickRow row1 = rows.get(0); + assertThat(row1.getHuId()).isEqualTo(huId1); + assertThat(row1.getQty()).isEqualTo(Quantity.of(10, uomKg)); + assertThat(row1.getExpiringDate()).isEqualTo(LocalDate.of(2019, Month.SEPTEMBER, 1)); + + final ProductsToPickRow row2 = rows.get(1); + assertThat(row2.getHuId()).isEqualTo(huId2); + assertThat(row2.getQty()).isEqualTo(Quantity.of(11, uomKg)); + assertThat(row2.getExpiringDate()).isEqualTo(LocalDate.of(2019, Month.SEPTEMBER, 2)); + + final ProductsToPickRow row3 = rows.get(2); + assertThat(row3.getHuId()).isEqualTo(huId3); + assertThat(row3.getQty()).isEqualTo(Quantity.of(12, uomKg)); + assertThat(row3.getExpiringDate()).isNull(); + + final ProductsToPickRow row4 = rows.get(3); + assertThat(row4.getHuId()).isNull(); + assertThat(row4.getQty()).isEqualTo(Quantity.of(100 - 10 - 11 - 12, uomKg)); + assertThat(row4.getExpiringDate()).isNull(); + } + + @Test + public void testRowsOrder_BestBeforePolicy_Expiring_Last() + { + final HuId huId1 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(LocalDate.of(2019, Month.SEPTEMBER, 1)) + .productId(productId) + .qty(Quantity.of(10, uomKg)) + .build(); + + final HuId huId2 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(LocalDate.of(2019, Month.SEPTEMBER, 2)) + .productId(productId) + .qty(Quantity.of(11, uomKg)) + .build(); + + final HuId huId3 = testHelper.prepareExistingHU() + .locatorId(locatorId) + .bestBeforeDate(null) + .productId(productId) + .qty(Quantity.of(12, uomKg)) + .build(); + + final PackageableRow packageableRow = preparePackageableRow() + .qtyOrdered(Quantity.of(100, uomKg)) + .bestBeforePolicy(ShipmentAllocationBestBeforePolicy.Newest_First) + .build(); + + final ProductsToPickRowsDataFactory productsToPickRowsDataFactory = createProductsToPickRowsDataFactory(); + final ProductsToPickRowsData rowsData = productsToPickRowsDataFactory.create(packageableRow); + + final ImmutableList rows = ImmutableList.copyOf(rowsData.getTopLevelRows()); + rows.forEach(row -> System.out.println("hu=" + row.getHuId() + ", exp=" + row.getExpiringDate() + ", qty=" + row.getQty() + " -- " + row)); + assertThat(rows).hasSize(4); + + final ProductsToPickRow row1 = rows.get(0); + assertThat(row1.getHuId()).isEqualTo(huId2); + assertThat(row1.getQty()).isEqualTo(Quantity.of(11, uomKg)); + assertThat(row1.getExpiringDate()).isEqualTo(LocalDate.of(2019, Month.SEPTEMBER, 2)); + + final ProductsToPickRow row2 = rows.get(1); + assertThat(row2.getHuId()).isEqualTo(huId1); + assertThat(row2.getQty()).isEqualTo(Quantity.of(10, uomKg)); + assertThat(row2.getExpiringDate()).isEqualTo(LocalDate.of(2019, Month.SEPTEMBER, 1)); + + final ProductsToPickRow row3 = rows.get(2); + assertThat(row3.getHuId()).isEqualTo(huId3); + assertThat(row3.getQty()).isEqualTo(Quantity.of(12, uomKg)); + assertThat(row3.getExpiringDate()).isNull(); + + final ProductsToPickRow row4 = rows.get(3); + assertThat(row4.getHuId()).isNull(); + assertThat(row4.getQty()).isEqualTo(Quantity.of(100 - 10 - 11 - 12, uomKg)); + assertThat(row4.getExpiringDate()).isNull(); + } + + @Builder(builderMethodName = "preparePackageableRow", builderClassName = "PackageableRowBuilder") + private PackageableRow createPackageableRow( + @NonNull final Quantity qtyOrdered, + @Nullable final ShipmentAllocationBestBeforePolicy bestBeforePolicy) + { + return PackageableRow.builder() + .orderId(OrderId.ofRepoId(1)) + .orderDocumentNo("1234") + .customer(IntegerLookupValue.of(customerAndLocationId.getBpartnerId().getRepoId(), "customer")) + .packageable(Packageable.builder() + .shipmentScheduleId(ShipmentScheduleId.ofRepoId(3)) + // + .qtyOrdered(qtyOrdered) + .qtyToDeliver(qtyOrdered) + .qtyDelivered(Quantity.of(0, uomKg)) + .qtyPickedNotDelivered(Quantity.of(0, uomKg)) + .qtyPickedPlanned(Quantity.of(0, uomKg)) + .qtyPickedAndDelivered(Quantity.of(0, uomKg)) + // + .customerId(customerAndLocationId.getBpartnerId()) + .customerLocationId(customerAndLocationId) + // + .warehouseId(locatorId.getWarehouseId()) + // + .bestBeforePolicy(Optional.ofNullable(bestBeforePolicy)) + // + .productId(productId) + .asiId(AttributeSetInstanceId.NONE) + // + .build()) + .build(); + } +}