/**
   * get Material transaction for Reversal Document
   *
   * @param trx MTransaction
   * @return
   */
  public static MTransaction getByDocumentLine(MTransaction trx) {
    IDocumentLine reversal = trx.getDocumentLine().getReversalDocumentLine();
    List<Object> parameters = new ArrayList();
    String columnName = reversal.get_TableName() + "_ID";
    StringBuffer whereClause = new StringBuffer(I_M_Transaction.COLUMNNAME_M_Product_ID);
    whereClause.append("=? AND ");
    parameters.add(reversal.getM_Product_ID());
    whereClause.append(columnName).append("=? AND ");
    parameters.add(reversal.get_ID());

    if (trx.getM_AttributeSetInstance_ID() > 0) {
      whereClause.append(I_M_Transaction.COLUMNNAME_M_AttributeSetInstance_ID).append("=? AND ");
      parameters.add(trx.getM_AttributeSetInstance_ID());
    }

    whereClause.append(I_M_Transaction.COLUMNNAME_MovementType).append("=? AND ");
    if (MTransaction.MOVEMENTTYPE_InventoryIn.equals(trx.getMovementType()))
      parameters.add(MTransaction.MOVEMENTTYPE_InventoryOut);
    else if (MTransaction.MOVEMENTTYPE_InventoryOut.equals(trx.getMovementType()))
      parameters.add(MTransaction.MOVEMENTTYPE_InventoryIn);
    else parameters.add(trx.getMovementType());

    whereClause.append(I_M_Transaction.COLUMNNAME_M_Transaction_ID).append("<>?");
    parameters.add(trx.getM_Transaction_ID());
    return new Query(trx.getCtx(), Table_Name, whereClause.toString(), trx.get_TrxName())
        .setClient_ID()
        .setParameters(parameters)
        .first();
  }
  /**
   * get all material transaction for MInOutLine
   *
   * @param line MInOutLine
   * @return List the MTransaction
   */
  public static List<MTransaction> getByInOutLine(MInOutLine line) {
    ArrayList<MTransaction> transactions = new ArrayList();

    List<MInOutLineMA> lines =
        MInOutLineMA.get(line.getCtx(), line.getM_InOutLine_ID(), line.get_TrxName());
    if (lines != null && lines.size() == 0) {
      MTransaction transaction = get(line, line.getM_AttributeSetInstance_ID());
      if (transaction != null && transaction.get_ID() > 0) transactions.add(transaction);

      return transactions;
    }
    for (MInOutLineMA ma : lines) {
      MTransaction trx = get(line, ma.getM_AttributeSetInstance_ID());
      transactions.add(trx);
    }
    return transactions;
  }
  /**
   * get the Material Transaction after Date Account
   *
   * @param ctx Context
   * @param M_Product_ID Product ID
   * @param dateAcct Date Account
   * @param trxName Transaction name
   * @return List with the MTransaction after date account
   */
  public static List<MTransaction> getAfterDateAcct(
      Properties ctx, int M_Product_ID, Timestamp dateAcct, String trxName) {
    ArrayList<MTransaction> list = new ArrayList();
    final String whereClause = I_M_Transaction.COLUMNNAME_M_Product_ID + "=?";
    List<MTransaction> trxs =
        new Query(ctx, Table_Name, whereClause, trxName)
            .setClient_ID()
            .setParameters(M_Product_ID)
            .list();

    for (MTransaction trx : trxs) {
      IDocumentLine model = trx.getDocumentLine();
      if (model.getDateAcct().compareTo(dateAcct) > 0) {
        list.add(trx);
      }
    }
    return list;
  }
 /**
  * Get Cost Detail
  *
  * @param model Model Inventory Line
  * @param as Account Schema
  * @param M_CostElement_ID Cost Element
  * @param M_AttributeSetInstance_ID
  * @return MCostDetail
  */
 private MCostDetail getCostDetail(
     IDocumentLine model, MTransaction mtrx, I_C_AcctSchema as, int M_CostElement_ID) {
   final String whereClause =
       "AD_Client_ID=? AND AD_Org_ID=?"
           + " AND "
           + model.get_TableName()
           + "_ID=?"
           + " AND "
           + MCostDetail.COLUMNNAME_M_Product_ID
           + "=?"
           + " AND "
           + MCostDetail.COLUMNNAME_M_AttributeSetInstance_ID
           + "=?"
           + " AND "
           + MCostDetail.COLUMNNAME_C_AcctSchema_ID
           + "=?"
           // +" AND "+MCostDetail.COLUMNNAME_M_CostType_ID+"=?"
           + " AND "
           + MCostDetail.COLUMNNAME_M_CostElement_ID
           + "=?";
   final Object[] params =
       new Object[] {
         mtrx.getAD_Client_ID(),
         mtrx.getAD_Org_ID(),
         model.get_ID(),
         mtrx.getM_Product_ID(),
         mtrx.getM_AttributeSetInstance_ID(),
         as.getC_AcctSchema_ID(),
         // as.getM_CostType_ID(),
         M_CostElement_ID,
       };
   return new Query(mtrx.getCtx(), MCostDetail.Table_Name, whereClause, mtrx.get_TrxName())
       .setParameters(params)
       .firstOnly();
 }
  /**
   * Create Cost Detail (Material Issue, Material Receipt)
   *
   * @param model
   * @param mtrx Material Transaction
   */
  public void createCostDetail(IDocumentLine model, MTransaction mtrx) {
    final I_PP_Cost_Collector cc =
        (model instanceof MPPCostCollector ? (MPPCostCollector) model : null);

    final Properties ctx = mtrx.getCtx();

    for (I_C_AcctSchema as : getAcctSchema(mtrx)) {
      // Cost Detail
      final I_M_Product product = MProduct.get(ctx, mtrx.getM_Product_ID());
      final String costingMethod = Services.get(IProductBL.class).getCostingMethod(product, as);
      // Check costing method
      if (!getCostingMethod().equals(costingMethod)) {
        throw new LiberoException("Costing method not supported - " + costingMethod);
      }
      //
      for (I_M_CostElement element : getCostElements(ctx)) {
        //
        // Delete Unprocessed zero Differences
        deleteCostDetail(
            model, as, element.getM_CostElement_ID(), mtrx.getM_AttributeSetInstance_ID());
        //
        // Get Costs
        final BigDecimal qty = mtrx.getMovementQty();
        final BigDecimal price =
            getProductActualCostPriceOrZero(cc, product, as, element, mtrx.get_TrxName());
        final BigDecimal amt = roundCost(price.multiply(qty), as.getC_AcctSchema_ID());
        //
        // Create / Update Cost Detail
        MCostDetail cd = getCostDetail(model, mtrx, as, element.getM_CostElement_ID());
        if (cd == null) // createNew
        {
          cd =
              new MCostDetail(
                  as,
                  mtrx.getAD_Org_ID(),
                  mtrx.getM_Product_ID(),
                  mtrx.getM_AttributeSetInstance_ID(),
                  element.getM_CostElement_ID(),
                  amt,
                  qty,
                  model.getDescription(),
                  mtrx.get_TrxName());
          // cd.setMovementDate(mtrx.getMovementDate());
          // if (cost != null)
          // {
          // cd.setCurrentCostPrice(cost.getCurrentCostPrice());
          // cd.setCurrentCostPriceLL(cost.getCurrentCostPriceLL());
          // }
          // else
          // {
          // cd.setCurrentCostPrice(Env.ZERO);
          // cd.setCurrentCostPriceLL(Env.ZERO);
          // }
          // cd.setM_CostType_ID(as.getM_CostType_ID());
          // //cd.setCostingMethod(element.getCostingMethod());
          // cd.setM_Transaction_ID(mtrx.get_ID());
          if (cc != null) {
            cd.setPP_Cost_Collector_ID(cc.getPP_Cost_Collector_ID());
          }
        } else {
          cd.setDeltaAmt(amt.subtract(cd.getAmt()));
          cd.setDeltaQty(mtrx.getMovementQty().subtract(cd.getQty()));
          if (cd.isDelta()) {
            cd.setProcessed(false);
            cd.setAmt(amt);
            cd.setQty(mtrx.getMovementQty());
          }
        }
        cd.saveEx();
        processCostDetail(cd);
        log.info("" + cd);
      } // for ELements
    } // Account Schema
  }