Related To Issue 39888: Added junit test
authorAtul Gaware <atul.gaware@openbravo.com>
Tue, 19 Feb 2019 15:35:08 +0530
changeset 35510 2f46504e585b
parent 35509 46a06da3a17a
child 35511 8b497714669e
Related To Issue 39888: Added junit test
src-test/src/org/openbravo/test/costing/TestCosting.java
src-test/src/org/openbravo/test/costing/TestIssue39888.java
src-test/src/org/openbravo/test/costing/assertclass/ProductTransactionAssert.java
src-test/src/org/openbravo/test/costing/utils/TestCostingConstants.java
src-test/src/org/openbravo/test/costing/utils/TestCostingUtils.java
--- a/src-test/src/org/openbravo/test/costing/TestCosting.java	Fri Mar 01 13:37:14 2019 +0530
+++ b/src-test/src/org/openbravo/test/costing/TestCosting.java	Tue Feb 19 15:35:08 2019 +0530
@@ -34,8 +34,8 @@
     TestCostingLandedCost.class, //
     TestIssue37033.class, //
     TestIssue37279.class, //
-    TestIssue39616.class //
-
+    TestIssue39616.class, //
+    TestIssue39888.class //
 })
 public class TestCosting {
   // No content is required, this is just the definition of a test suite.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-test/src/org/openbravo/test/costing/TestIssue39888.java	Tue Feb 19 15:35:08 2019 +0530
@@ -0,0 +1,383 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License. 
+ * The Original Code is Openbravo ERP. 
+ * The Initial Developer of the Original Code is Openbravo SLU 
+ * All portions are Copyright (C) 2019 Openbravo SLU
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+package org.openbravo.test.costing;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.openbravo.base.exception.OBException;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.model.common.enterprise.Locator;
+import org.openbravo.model.common.plm.Product;
+import org.openbravo.model.materialmgmt.cost.LandedCost;
+import org.openbravo.model.materialmgmt.transaction.ProductionLine;
+import org.openbravo.model.materialmgmt.transaction.ProductionTransaction;
+import org.openbravo.model.materialmgmt.transaction.ShipmentInOut;
+import org.openbravo.model.materialmgmt.transaction.ShipmentInOutLine;
+import org.openbravo.test.costing.assertclass.ProductTransactionAssert;
+import org.openbravo.test.costing.utils.TestCostingConstants;
+import org.openbravo.test.costing.utils.TestCostingUtils;
+
+public class TestIssue39888 extends TestCostingBase {
+
+  private static final String UNDEF_OVERISSUE_STATUS = "0";
+
+  @Test
+  public void testIssue39888() throws Exception {
+
+    final int day0 = 0;
+    final BigDecimal salesPrice = new BigDecimal("10.00");
+    final BigDecimal purchasePrice = new BigDecimal("10.00");
+    final BigDecimal cost = new BigDecimal("10.00");
+    final BigDecimal bomQuantity = new BigDecimal("2.00");
+
+    final BigDecimal shipReceiveQuantity = new BigDecimal("1000.00");
+    final BigDecimal orginalPrice = new BigDecimal("10.00");
+    final BigDecimal bomProductionQty = BigDecimal.ONE;
+    final BigDecimal cost1 = new BigDecimal("20.00");
+    final BigDecimal cost2 = new BigDecimal("120.00");
+    final BigDecimal cost3 = new BigDecimal("180.00");
+
+    final BigDecimal totalCost = new BigDecimal("-9980.00");
+    final BigDecimal totalCostAfterLC1 = new BigDecimal("-109880.00");
+    final BigDecimal totalCostAfterLC2 = new BigDecimal("-169820.00");
+
+    final BigDecimal amount1 = new BigDecimal("50000.00");
+    final BigDecimal amount2 = new BigDecimal("30000.00");
+
+    ProductionLine productionLine1;
+    try {
+
+      OBContext.setOBContext(TestCostingConstants.OPENBRAVO_USER_ID,
+          TestCostingConstants.QATESTING_ROLE_ID, TestCostingConstants.QATESTING_CLIENT_ID,
+          TestCostingConstants.SPAIN_ORGANIZATION_ID);
+
+      OBContext.setAdminMode(true);
+
+      Product rawProduct = TestCostingUtils.addProductPriceCost("Raw Material", "I", purchasePrice,
+          null, cost, "AVA", 0, TestCostingConstants.EURO_ID);
+
+      List<Product> productList = new ArrayList<Product>();
+      List<BigDecimal> quantityList = new ArrayList<BigDecimal>();
+      Product finalProduct = TestCostingUtils.addProductPriceCost("Final Product", "I", null,
+          salesPrice, cost, "AVA", 0, TestCostingConstants.EURO_ID);
+      productList.add(rawProduct);
+      quantityList.add(bomQuantity);
+      finalProduct = TestCostingUtils.addBOMProducts(finalProduct, productList, quantityList);
+
+      Locator storageBin = OBDal.getInstance()
+          .get(Locator.class, TestCostingConstants.LOCATOR_M01_ID);
+      assertThat("Inventory Status of Storage Bin must be 'Undefined Over-Issue': ",
+          storageBin.getInventoryStatus().getId(), equalTo(UNDEF_OVERISSUE_STATUS));
+      // Goods Shipment
+      ShipmentInOut goodsShipment = TestCostingUtils.createGoodsShipment(finalProduct, salesPrice,
+          shipReceiveQuantity, TestCostingConstants.LOCATOR_M01_ID, day0);
+
+      List<ProductTransactionAssert> productTransactionAssertList = new ArrayList<ProductTransactionAssert>();
+      productTransactionAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
+          .get(ShipmentInOut.class, goodsShipment.getId())
+          .getMaterialMgmtShipmentInOutLineList()
+          .get(0), TestCostingConstants.EURO_ID, orginalPrice, orginalPrice));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Goods Receipt
+      ShipmentInOut goodsReceipt = TestCostingUtils.createGoodsReceipt(rawProduct, purchasePrice,
+          shipReceiveQuantity, TestCostingConstants.LOCATOR_M01_ID, day0);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      List<ProductTransactionAssert> productTransactionReceiptAssertList = new ArrayList<ProductTransactionAssert>();
+      productTransactionReceiptAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
+          .get(ShipmentInOut.class, goodsReceipt.getId())
+          .getMaterialMgmtShipmentInOutLineList()
+          .get(0), TestCostingConstants.EURO_ID, orginalPrice, orginalPrice));
+
+      TestCostingUtils.assertProductTransaction(rawProduct.getId(),
+          productTransactionReceiptAssertList);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Bills Of Material Production I
+      ProductionTransaction billOfMaterialsProduction = TestCostingUtils
+          .createBillOfMaterialsProduction(finalProduct, bomProductionQty,
+              TestCostingConstants.LOCATOR_M01_ID, day0, false, true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productionLine1 = OBDal.getInstance()
+          .get(ProductionTransaction.class, billOfMaterialsProduction.getId())
+          .getMaterialMgmtProductionPlanList()
+          .get(0)
+          .getManufacturingProductionLineList()
+          .get(0);
+
+      productTransactionAssertList
+          .add(new ProductTransactionAssert(productionLine1, cost1, totalCost, cost1));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Bills Of Material Production II
+      ProductionTransaction billOfMaterialsProduction2 = TestCostingUtils
+          .createBillOfMaterialsProduction(finalProduct, bomProductionQty,
+              TestCostingConstants.LOCATOR_M01_ID, day0, false, true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
+          .get(ProductionTransaction.class, billOfMaterialsProduction2.getId())
+          .getMaterialMgmtProductionPlanList()
+          .get(0)
+          .getManufacturingProductionLineList()
+          .get(0), cost1, cost1));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Bills Of Material Production III
+      ProductionTransaction billOfMaterialsProduction3 = TestCostingUtils
+          .createBillOfMaterialsProduction(finalProduct, bomProductionQty,
+              TestCostingConstants.LOCATOR_M01_ID, day0, false, true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.add(new ProductTransactionAssert(OBDal.getInstance()
+          .get(ProductionTransaction.class, billOfMaterialsProduction3.getId())
+          .getMaterialMgmtProductionPlanList()
+          .get(0)
+          .getManufacturingProductionLineList()
+          .get(0), cost1, cost1));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Create Landed Cost I
+      List<String> landedCostTypeIdList = new ArrayList<String>();
+      landedCostTypeIdList.add(TestCostingConstants.LANDEDCOSTTYPE_FEES_ID);
+      List<BigDecimal> amountList = new ArrayList<BigDecimal>();
+      amountList.add(amount1);
+      List<ShipmentInOut> receiptList = new ArrayList<ShipmentInOut>();
+      List<ShipmentInOutLine> receiptLineList = new ArrayList<ShipmentInOutLine>();
+      receiptList.add(goodsReceipt);
+      receiptLineList.add(goodsReceipt.getMaterialMgmtShipmentInOutLineList().get(0));
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      LandedCost landedCost1 = TestCostingUtils.createLandedCost(landedCostTypeIdList, amountList,
+          receiptList, receiptLineList, day0);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.remove(1);
+      productTransactionAssertList.add(1,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, totalCostAfterLC1, cost2));
+      productTransactionAssertList.remove(2);
+      productTransactionAssertList.add(2,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction2.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost2, cost2));
+      productTransactionAssertList.remove(3);
+      productTransactionAssertList.add(3,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction3.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost2, cost2));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Assert Transaction Cost after Landed Cost I
+      assertTrue(TestCostingUtils.existsProductTransactionCostByCostIsUnitCostCurrency(
+          TestCostingUtils.getProductTransactionsForProductionLine(productionLine1), true,
+          TestCostingConstants.EURO_ID, new BigDecimal(100)));
+      assertTrue(TestCostingUtils.existsProductTransactionCostByCostIsUnitCostCurrency(
+          TestCostingUtils.getProductTransactionsForProductionLine(productionLine1), false,
+          TestCostingConstants.EURO_ID, new BigDecimal(-100000)));
+
+      // Create Landed Cost II
+
+      amountList = new ArrayList<BigDecimal>();
+      amountList.add(amount2);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      LandedCost landedCost2 = TestCostingUtils.createLandedCost(landedCostTypeIdList, amountList,
+          receiptList, receiptLineList, day0);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.remove(1);
+      productTransactionAssertList.add(1,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, totalCostAfterLC2, cost3));
+      productTransactionAssertList.remove(2);
+      productTransactionAssertList.add(2,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction2.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost3, cost3));
+      productTransactionAssertList.remove(3);
+      productTransactionAssertList.add(3,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction3.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost3, cost3));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Assert Transaction Cost after Landed Cost I
+      assertTrue(TestCostingUtils.existsProductTransactionCostByCostIsUnitCostCurrency(
+          TestCostingUtils.getProductTransactionsForProductionLine(productionLine1), true,
+          TestCostingConstants.EURO_ID, new BigDecimal(60)));
+      assertTrue(TestCostingUtils.existsProductTransactionCostByCostIsUnitCostCurrency(
+          TestCostingUtils.getProductTransactionsForProductionLine(productionLine1), false,
+          TestCostingConstants.EURO_ID, new BigDecimal(-60000)));
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Reactivate Landed Cost II
+      TestCostingUtils.cancelLandedCost(landedCost2);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.remove(1);
+      productTransactionAssertList.add(1,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, totalCostAfterLC1, cost2));
+      productTransactionAssertList.remove(2);
+      productTransactionAssertList.add(2,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction2.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost2, cost2));
+      productTransactionAssertList.remove(3);
+      productTransactionAssertList.add(3,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction3.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost2, cost2));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      // Reactivate Landed Cost I
+      TestCostingUtils.cancelLandedCost(landedCost1);
+
+      // Add sleep to avoid assert errors
+      Thread.sleep(1000);
+
+      productTransactionAssertList.remove(1);
+      productTransactionAssertList.add(1,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, totalCost, cost1));
+      productTransactionAssertList.remove(2);
+      productTransactionAssertList.add(2,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction2.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost1, cost1));
+      productTransactionAssertList.remove(3);
+      productTransactionAssertList.add(3,
+          new ProductTransactionAssert(OBDal.getInstance()
+              .get(ProductionTransaction.class, billOfMaterialsProduction3.getId())
+              .getMaterialMgmtProductionPlanList()
+              .get(0)
+              .getManufacturingProductionLineList()
+              .get(0), cost1, cost1, cost1));
+
+      TestCostingUtils.assertProductTransaction(finalProduct.getId(), productTransactionAssertList,
+          true);
+
+      OBDal.getInstance().commitAndClose();
+
+    } catch (Exception e) {
+      System.out.println(e.getMessage());
+      throw new OBException(e);
+    }
+
+    finally {
+      OBContext.restorePreviousMode();
+    }
+  }
+
+}
--- a/src-test/src/org/openbravo/test/costing/assertclass/ProductTransactionAssert.java	Fri Mar 01 13:37:14 2019 +0530
+++ b/src-test/src/org/openbravo/test/costing/assertclass/ProductTransactionAssert.java	Tue Feb 19 15:35:08 2019 +0530
@@ -45,6 +45,12 @@
   final private boolean permanent;
 
   public ProductTransactionAssert(ShipmentInOutLine shipmentReceiptLine, BigDecimal originalPrice,
+      BigDecimal finalPrice, String costingStatus) {
+    this(shipmentReceiptLine, null, null, null, null, TestCostingConstants.EURO_ID, originalPrice,
+        finalPrice, finalPrice, false, false);
+  }
+
+  public ProductTransactionAssert(ShipmentInOutLine shipmentReceiptLine, BigDecimal originalPrice,
       BigDecimal finalPrice) {
     this(shipmentReceiptLine, null, null, null, null, TestCostingConstants.EURO_ID, originalPrice,
         finalPrice, finalPrice, false, false);
@@ -128,6 +134,12 @@
         finalPrice, finalPrice, false, false);
   }
 
+  public ProductTransactionAssert(ProductionLine productionLine, BigDecimal originalPrice,
+      BigDecimal totalCost, BigDecimal finalPrice) {
+    this(null, null, null, null, productionLine, TestCostingConstants.EURO_ID, originalPrice,
+        totalCost, finalPrice, false, false);
+  }
+
   public ProductTransactionAssert(ShipmentInOutLine shipmentReceiptLine,
       InventoryAmountUpdateLine inventoryLine, InternalMovementLine movementLine,
       InternalConsumptionLine consumptionLine, ProductionLine productionLine, String currencyId,
@@ -189,5 +201,4 @@
   public boolean isPermanent() {
     return permanent;
   }
-
 }
--- a/src-test/src/org/openbravo/test/costing/utils/TestCostingConstants.java	Fri Mar 01 13:37:14 2019 +0530
+++ b/src-test/src/org/openbravo/test/costing/utils/TestCostingConstants.java	Tue Feb 19 15:35:08 2019 +0530
@@ -114,6 +114,9 @@
   public static final String LOCATOR_M01_ID = "96DEDCC179504711A81497DE68900F49";
 
   public static final String ENABLE_AUTOMATIC_PRICE_CORRECTION_TRXS = "enableAutomaticPriceCorrectionTrxs";
+  // Negative Stock Correction Preference
+  public static final String ENABLE_NEGATIVE_STOCK_CORRECTION_PREFERENCE = "enableNegativeStockCorrections";
+
   public static final Organization ALL_ORGANIZATIONS = OBDal.getInstance()
       .get(Organization.class, "0");
 
--- a/src-test/src/org/openbravo/test/costing/utils/TestCostingUtils.java	Fri Mar 01 13:37:14 2019 +0530
+++ b/src-test/src/org/openbravo/test/costing/utils/TestCostingUtils.java	Tue Feb 19 15:35:08 2019 +0530
@@ -405,6 +405,128 @@
     }
   }
 
+  // Create a new product cloning costing Product 1
+  public static Product addProductPriceCost(String name, String productType,
+      BigDecimal purchasePrice, BigDecimal salesPrice, BigDecimal cost, String costType, int year,
+      String currencyId) {
+    try {
+      int num = TestCostingUtils.getNumberOfCostingProducts(name);
+      Product product = OBDal.getInstance()
+          .get(Product.class, TestCostingConstants.COSTING_PRODUCT_ID);
+      Product productClone = (Product) DalUtil.copy(product, false);
+      setGeneralData(productClone);
+
+      productClone.setSearchKey(name + "-" + num);
+      productClone.setName(name + "-" + num);
+      productClone.setMaterialMgmtMaterialTransactionList(null);
+      productClone.setProductType(productType);
+      OBDal.getInstance().save(productClone);
+
+      StringBuffer where = new StringBuffer();
+      where.append(" as pp ");
+      where.append(" join pp." + ProductPrice.PROPERTY_PRICELISTVERSION + " as plv");
+      where.append(" join plv." + PriceListVersion.PROPERTY_PRICELIST + " as pl");
+      where.append(" where pp." + ProductPrice.PROPERTY_PRODUCT + ".id = :productId");
+      where.append(" order by pl." + PriceList.PROPERTY_NAME);
+      OBQuery<ProductPrice> hql = OBDal.getInstance()
+          .createQuery(ProductPrice.class, where.toString());
+      hql.setNamedParameter("productId", TestCostingConstants.COSTING_PRODUCT_ID);
+
+      for (ProductPrice productPrice : hql.list()) {
+        if (productPrice.getPriceListVersion().getPriceList().isSalesPriceList()
+            && salesPrice != null) {
+          ProductPrice productPriceClone = (ProductPrice) DalUtil.copy(productPrice, false);
+          setGeneralData(productPriceClone);
+          productPriceClone.setStandardPrice(salesPrice);
+          productPriceClone.setListPrice(salesPrice);
+          productPriceClone.setProduct(productClone);
+          OBDal.getInstance().save(productPriceClone);
+          productClone.getPricingProductPriceList().add(productPriceClone);
+        } else if (!productPrice.getPriceListVersion().getPriceList().isSalesPriceList()
+            && purchasePrice != null) {
+          ProductPrice productPriceClone = (ProductPrice) DalUtil.copy(productPrice, false);
+          setGeneralData(productPriceClone);
+          productPriceClone.setStandardPrice(purchasePrice);
+          productPriceClone.setListPrice(purchasePrice);
+          productPriceClone.setProduct(productClone);
+          OBDal.getInstance().save(productPriceClone);
+          productClone.getPricingProductPriceList().add(productPriceClone);
+        }
+      }
+
+      if (cost != null) {
+        Costing productCosting = OBProvider.getInstance().get(Costing.class);
+        setGeneralData(productCosting);
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(2000, 01, 01);
+        productCosting.setStartingDate(calendar.getTime());
+        calendar = Calendar.getInstance();
+        calendar.set(9999, 11, 31);
+        productCosting.setEndingDate(calendar.getTime());
+        productCosting.setManual(true);
+        // productCosting.setPermanent(true);
+        productCosting.setCostType(costType);
+        productCosting.setCost(cost);
+        productCosting
+            .setCurrency(OBDal.getInstance().get(Currency.class, TestCostingConstants.EURO_ID));
+        productCosting.setProduct(productClone);
+        productCosting.setWarehouse(
+            OBDal.getInstance().get(Warehouse.class, TestCostingConstants.SPAIN_EAST_WAREHOUSE_ID));
+        productClone.getMaterialMgmtCostingList().add(productCosting);
+      }
+      OBDal.getInstance().save(productClone);
+      OBDal.getInstance().flush();
+      OBDal.getInstance().refresh(productClone);
+
+      return productClone;
+    } catch (
+
+    Exception e) {
+      throw new OBException(e);
+    }
+  }
+
+  public static Product addBOMProducts(Product product, List<Product> productList,
+      List<BigDecimal> quantityList) {
+    List<String> productIdList = new ArrayList<String>();
+    if (productList != null) {
+      for (Product raw_product : productList) {
+        productIdList.add(raw_product.getId());
+      }
+    }
+    Product productClone = product;
+    try {
+      productClone.setBillOfMaterials(true);
+      int i = 0;
+      for (String productBOMId : productIdList) {
+        ProductBOM productBOMClone = OBProvider.getInstance().get(ProductBOM.class);
+        setGeneralData(productBOMClone);
+        productBOMClone.setLineNo((i + 1) * 10L);
+        productBOMClone.setProduct(productClone);
+        productBOMClone.setBOMProduct(OBDal.getInstance().get(Product.class, productBOMId));
+        productBOMClone.setBOMQuantity(quantityList.get(i));
+        i++;
+
+        OBDal.getInstance().save(productBOMClone);
+        OBDal.getInstance().flush();
+        OBDal.getInstance().refresh(productBOMClone);
+      }
+      OBDal.getInstance().save(productClone);
+      OBDal.getInstance().flush();
+      OBDal.getInstance().refresh(productClone);
+
+      verifyBOM(productClone.getId());
+      productClone.setBOMVerified(true);
+
+      OBDal.getInstance().save(productClone);
+      OBDal.getInstance().flush();
+      OBDal.getInstance().refresh(productClone);
+    } catch (Exception e) {
+      throw new OBException(e);
+    }
+    return productClone;
+  }
+
   // Set common fields in all tables
   public static void setGeneralData(BaseOBObject document) {
     try {
@@ -880,7 +1002,7 @@
     }
   }
 
-  // Create a Goods Receipt from a purchase order, complete it and post it
+  // Create a Goods Shipment from a sales order, complete it and post it
   public static ShipmentInOut createGoodsShipment(Order salesOrder, BigDecimal price,
       BigDecimal quantity, int day) {
     try {
@@ -891,7 +1013,7 @@
     }
   }
 
-  // Create a Goods Receipt from a purchase order, complete it and post it
+  // Create a Goods Shipment from a sales order, complete it and post it
   private static ShipmentInOut createGoodsShipment(Order salesOrder, BigDecimal price,
       BigDecimal quantity, String locatorId, int day) {
     try {
@@ -1152,6 +1274,13 @@
   // Create a Inventory Amount Update and process it
   public static ProductionTransaction createBillOfMaterialsProduction(Product product,
       BigDecimal quantity, String locatorId, int day) {
+    return createBillOfMaterialsProduction(product, quantity, locatorId, day, true, false);
+  }
+
+  // Create a Inventory Amount Update and process it
+  public static ProductionTransaction createBillOfMaterialsProduction(Product product,
+      BigDecimal quantity, String locatorId, int day, boolean sortProductionLine,
+      boolean orderByLineNo) {
     try {
       ProductionTransaction billOfMaterialsProduction = createBillOfMaterialsProduction(
           product.getId(), quantity, locatorId, day);
@@ -1174,24 +1303,25 @@
       postDocument(bMaterialsProduction);
       List<DocumentPostAssert> documentPostAssertList1 = new ArrayList<DocumentPostAssert>();
       List<ProductionLine> productionLinesList = getProductionLines(
-          billOfMaterialsProduction.getId());
-      productionLinesList.add(0, productionLinesList.get(productionLinesList.size() - 1));
-      productionLinesList.remove(productionLinesList.size() - 1);
-
-      final OBCriteria<AccountingFact> criteria1 = OBDal.getInstance()
-          .createCriteria(AccountingFact.class);
-      criteria1.add(
-          Restrictions.eq(AccountingFact.PROPERTY_RECORDID, billOfMaterialsProduction.getId()));
-      criteria1.addOrderBy(AccountingFact.PROPERTY_SEQUENCENUMBER, true);
-
-      if (!criteria1.list()
-          .get(2)
-          .getQuantity()
-          .equals(productionLinesList.get(1).getMovementQuantity())) {
-        productionLinesList.add(1, productionLinesList.get(productionLinesList.size() - 1));
+          billOfMaterialsProduction.getId(), orderByLineNo);
+      if (sortProductionLine) {
+        productionLinesList.add(0, productionLinesList.get(productionLinesList.size() - 1));
         productionLinesList.remove(productionLinesList.size() - 1);
+
+        final OBCriteria<AccountingFact> criteria1 = OBDal.getInstance()
+            .createCriteria(AccountingFact.class);
+        criteria1.add(
+            Restrictions.eq(AccountingFact.PROPERTY_RECORDID, billOfMaterialsProduction.getId()));
+        criteria1.addOrderBy(AccountingFact.PROPERTY_SEQUENCENUMBER, true);
+
+        if (!criteria1.list()
+            .get(2)
+            .getQuantity()
+            .equals(productionLinesList.get(1).getMovementQuantity())) {
+          productionLinesList.add(1, productionLinesList.get(productionLinesList.size() - 1));
+          productionLinesList.remove(productionLinesList.size() - 1);
+        }
       }
-
       int i = 0;
       for (ProductionLine productionLine : productionLinesList) {
         BigDecimal amountTotal = BigDecimal.ZERO;
@@ -3847,20 +3977,44 @@
   }
 
   // Get Product Transaction list
-  public static List<MaterialTransaction> getProductTransactions(String productId) {
+  public static List<MaterialTransaction> getProductTransactions(String productId,
+      boolean orderByTransProcessDate) {
     try {
       OBCriteria<MaterialTransaction> criteria = OBDal.getInstance()
           .createCriteria(MaterialTransaction.class);
       criteria.add(Restrictions.eq(MaterialTransaction.PROPERTY_PRODUCT,
           OBDal.getInstance().get(Product.class, productId)));
-      criteria.addOrderBy(MaterialTransaction.PROPERTY_MOVEMENTDATE, true);
-      criteria.addOrderBy(MaterialTransaction.PROPERTY_MOVEMENTQUANTITY, true);
+      if (orderByTransProcessDate) {
+        criteria.addOrderBy(MaterialTransaction.PROPERTY_TRANSACTIONPROCESSDATE, true);
+      } else {
+        criteria.addOrderBy(MaterialTransaction.PROPERTY_MOVEMENTDATE, true);
+        criteria.addOrderBy(MaterialTransaction.PROPERTY_MOVEMENTQUANTITY, true);
+      }
       return criteria.list();
     } catch (Exception e) {
       throw new OBException(e);
     }
   }
 
+  // Get Product Transaction for Production Line
+  public static MaterialTransaction getProductTransactionsForProductionLine(
+      ProductionLine productionLine) {
+    try {
+      OBCriteria<MaterialTransaction> criteria = OBDal.getInstance()
+          .createCriteria(MaterialTransaction.class);
+      criteria.add(Restrictions.eq(MaterialTransaction.PROPERTY_PRODUCTIONLINE, productionLine));
+      criteria.setMaxResults(1);
+      return criteria.uniqueResult() != null ? (MaterialTransaction) criteria.uniqueResult() : null;
+    } catch (Exception e) {
+      throw new OBException(e);
+    }
+  }
+
+  // Get Product Transaction list
+  public static List<MaterialTransaction> getProductTransactions(String productId) {
+    return getProductTransactions(productId, false);
+  }
+
   // Get Product Transaction list
   public static List<TransactionCost> getProductTransactionCosts(String transactionId) {
     try {
@@ -3882,6 +4036,33 @@
     }
   }
 
+  public static Boolean existsProductTransactionCostByCostIsUnitCostCurrency(
+      MaterialTransaction transaction, Boolean isUnitCost, String currencyId, BigDecimal cost) {
+    if (transaction != null) {
+      try {
+        StringBuffer where = new StringBuffer();
+        where.append(" as t ");
+        where.append(
+            "\n where t." + TransactionCost.PROPERTY_INVENTORYTRANSACTION + " = :transaction");
+        where.append("\n and t." + TransactionCost.PROPERTY_UNITCOST + " = :unitcost");
+        where.append("\n and t." + TransactionCost.PROPERTY_CURRENCY + " = :currencyId");
+        where.append("\n and t." + TransactionCost.PROPERTY_COST + " = :cost");
+        OBQuery<TransactionCost> hql = OBDal.getInstance()
+            .createQuery(TransactionCost.class, where.toString());
+        hql.setNamedParameter("transaction", transaction);
+        hql.setNamedParameter("unitcost", isUnitCost);
+        hql.setNamedParameter("currencyId", OBDal.getInstance().get(Currency.class, currencyId));
+        hql.setNamedParameter("cost", cost);
+        hql.setMaxResult(1);
+        return hql.uniqueResult() != null;
+      } catch (Exception e) {
+        throw new OBException(e);
+      }
+    } else {
+      return false;
+    }
+  }
+
   // Get Product Costing list
   public static List<Costing> getProductCostings(String productId) {
     try {
@@ -3904,7 +4085,8 @@
   }
 
   // Get Production Line list
-  public static List<ProductionLine> getProductionLines(String productionTransactionId) {
+  public static List<ProductionLine> getProductionLines(String productionTransactionId,
+      boolean orderByLineNo) {
     try {
       StringBuffer where = new StringBuffer();
       where.append(" as t1 ");
@@ -3912,7 +4094,11 @@
       where.append("\n left join t1." + ProductionLine.PROPERTY_PRODUCT + " t3");
       where.append(
           "\n where t2." + ProductionPlan.PROPERTY_PRODUCTION + " = :productionTransaction");
-      where.append("\n order by t3." + Product.PROPERTY_NAME);
+      if (orderByLineNo) {
+        where.append("\n order by t1." + ProductionLine.PROPERTY_LINENO);
+      } else {
+        where.append("\n order by t3." + Product.PROPERTY_NAME);
+      }
       OBQuery<ProductionLine> hql = OBDal.getInstance()
           .createQuery(ProductionLine.class, where.toString());
       hql.setNamedParameter("productionTransaction",
@@ -3923,6 +4109,12 @@
     }
   }
 
+  // Get Production Line list Order by Line No
+  public static List<ProductionLine> getProductionLines(String productionTransactionId) {
+    return getProductionLines(productionTransactionId, false);
+
+  }
+
   // Get transaction amount
   public static BigDecimal getTransactionAmount(ShipmentInOut transaction,
       LandedCost actualLandedCost) {
@@ -4258,11 +4450,17 @@
     }
   }
 
+  public static void assertProductTransaction(String productId,
+      List<ProductTransactionAssert> productTransactionAssertList) {
+    assertProductTransaction(productId, productTransactionAssertList, false);
+  }
+
   // Assert Product Transactions
   public static void assertProductTransaction(String productId,
-      List<ProductTransactionAssert> productTransactionAssertList) {
+      List<ProductTransactionAssert> productTransactionAssertList, boolean orderByProcessDate) {
     try {
-      List<MaterialTransaction> materialTransactionList = getProductTransactions(productId);
+      List<MaterialTransaction> materialTransactionList = getProductTransactions(productId,
+          orderByProcessDate);
       assertEquals(materialTransactionList.size(), productTransactionAssertList.size());
 
       int i = 0;
@@ -4285,7 +4483,8 @@
         assertEquals(materialTransaction.isCostPermanent(), productTransactionAssert.isPermanent());
 
         if (productTransactionAssert.getOriginalPrice() != null) {
-          assertEquals(materialTransaction.getCurrency(), productTransactionAssert.getCurrency());
+          assertEquals(materialTransaction.getCurrency().getId(),
+              productTransactionAssert.getCurrency().getId());
           assertEquals(materialTransaction.getCostingAlgorithm().getName(), "Average Algorithm");
           assertTrue(materialTransaction.isCostCalculated());
           assertEquals(materialTransaction.getCostingStatus(), "CC");
@@ -4355,30 +4554,40 @@
                     .setScale(2, RoundingMode.HALF_UP));
           }
 
-          assertEquals(materialTransaction.getGoodsShipmentLine(),
-              productTransactionAssert.getShipmentReceiptLine());
-          assertEquals(materialTransaction.getPhysicalInventoryLine(),
-              productTransactionAssert.getInventoryLine());
-          assertEquals(materialTransaction.getMovementLine(),
-              productTransactionAssert.getMovementLine());
-          assertEquals(materialTransaction.getInternalConsumptionLine(),
-              productTransactionAssert.getConsumptionLine());
-          assertEquals(materialTransaction.getProductionLine(),
-              productTransactionAssert.getProductionLine());
+          if (materialTransaction.getGoodsShipmentLine() != null) {
+            assertEquals(materialTransaction.getGoodsShipmentLine().getId(),
+                productTransactionAssert.getShipmentReceiptLine().getId());
+          }
+          if (materialTransaction.getPhysicalInventoryLine() != null) {
+            assertEquals(materialTransaction.getPhysicalInventoryLine().getId(),
+                productTransactionAssert.getInventoryLine().getId());
+          }
+          if (materialTransaction.getMovementLine() != null) {
+            assertEquals(materialTransaction.getMovementLine().getId(),
+                productTransactionAssert.getMovementLine().getId());
+          }
+          if (materialTransaction.getInternalConsumptionLine() != null) {
+            assertEquals(materialTransaction.getInternalConsumptionLine().getId(),
+                productTransactionAssert.getConsumptionLine().getId());
+          }
+          if (materialTransaction.getProductionLine() != null) {
+            assertEquals(materialTransaction.getProductionLine().getId(),
+                productTransactionAssert.getProductionLine().getId());
+          }
           assertEquals(materialTransaction.getMovementType(),
               productTransactionAssert.getShipmentReceiptLine()
                   .getShipmentReceipt()
                   .getMovementType());
-          assertEquals(materialTransaction.getStorageBin(),
-              productTransactionAssert.getShipmentReceiptLine().getStorageBin());
-          assertEquals(materialTransaction.getProduct(),
-              productTransactionAssert.getShipmentReceiptLine().getProduct());
+          assertEquals(materialTransaction.getStorageBin().getId(),
+              productTransactionAssert.getShipmentReceiptLine().getStorageBin().getId());
+          assertEquals(materialTransaction.getProduct().getId(),
+              productTransactionAssert.getShipmentReceiptLine().getProduct().getId());
           assertEquals(formatDate(materialTransaction.getMovementDate()),
               formatDate(productTransactionAssert.getShipmentReceiptLine()
                   .getShipmentReceipt()
                   .getMovementDate()));
-          assertEquals(materialTransaction.getUOM(),
-              productTransactionAssert.getShipmentReceiptLine().getUOM());
+          assertEquals(materialTransaction.getUOM().getId(),
+              productTransactionAssert.getShipmentReceiptLine().getUOM().getId());
           assertTrue(materialTransaction.isCheckReservedQuantity());
         }
 
@@ -4536,8 +4745,8 @@
           assertEquals(materialTransaction.getMovementQuantity(),
               productTransactionAssert.getProductionLine().getMovementQuantity());
           assertEquals(materialTransaction.getMovementType(), "P+");
-          assertEquals(materialTransaction.getStorageBin(),
-              productTransactionAssert.getProductionLine().getStorageBin());
+          assertEquals(materialTransaction.getStorageBin().getId(),
+              productTransactionAssert.getProductionLine().getStorageBin().getId());
 
           assertEquals(materialTransaction.getGoodsShipmentLine(),
               productTransactionAssert.getShipmentReceiptLine());
@@ -4547,15 +4756,15 @@
               productTransactionAssert.getMovementLine());
           assertEquals(materialTransaction.getInternalConsumptionLine(),
               productTransactionAssert.getConsumptionLine());
-          assertEquals(materialTransaction.getProduct(),
-              productTransactionAssert.getProductionLine().getProduct());
+          assertEquals(materialTransaction.getProduct().getId(),
+              productTransactionAssert.getProductionLine().getProduct().getId());
           assertEquals(formatDate(materialTransaction.getMovementDate()),
               formatDate(productTransactionAssert.getProductionLine()
                   .getProductionPlan()
                   .getProduction()
                   .getMovementDate()));
-          assertEquals(materialTransaction.getUOM(),
-              productTransactionAssert.getProductionLine().getUOM());
+          assertEquals(materialTransaction.getUOM().getId(),
+              productTransactionAssert.getProductionLine().getUOM().getId());
           assertTrue(materialTransaction.isCheckReservedQuantity());
 
           j++;
@@ -4650,8 +4859,8 @@
           assertEquals(materialTransactionCost.getInventoryTransaction(), materialTransaction);
           assertEquals(formatDate(materialTransactionCost.getCostDate()),
               formatDate(materialTransaction.getTransactionProcessDate()));
-          assertEquals(materialTransactionCost.getCurrency(),
-              productTransactionAssert.getCurrency());
+          assertEquals(materialTransactionCost.getCurrency().getId(),
+              productTransactionAssert.getCurrency().getId());
 
           if (k == 0) {
             assertEquals(materialTransactionCost.getCost(),