/**
  * Get PO Costs in Currency of AcctSchema
  *
  * @param as Account Schema
  * @return Unit PO Cost
  */
 private BigDecimal getPOCost(MAcctSchema as) {
   BigDecimal retValue = null;
   //	Uses PO Date
   String sql =
       "SELECT currencyConvert(ol.PriceActual, o.C_Currency_ID, ?, o.DateOrdered, o.C_ConversionType_ID, ?, ?) "
           + "FROM C_OrderLine ol"
           + " INNER JOIN M_InOutLine iol ON (iol.C_OrderLine_ID=ol.C_OrderLine_ID)"
           + " INNER JOIN C_Order o ON (o.C_Order_ID=ol.C_Order_ID) "
           + "WHERE iol.M_InOutLine_ID=?";
   PreparedStatement pstmt = null;
   ResultSet rs = null;
   try {
     pstmt = DB.prepareStatement(sql, getTrxName());
     pstmt.setInt(1, as.getC_Currency_ID());
     pstmt.setInt(2, getAD_Client_ID());
     pstmt.setInt(3, getAD_Org_ID());
     pstmt.setInt(4, m_issue.getM_InOutLine_ID());
     rs = pstmt.executeQuery();
     if (rs.next()) {
       retValue = rs.getBigDecimal(1);
       log.fine("POCost = " + retValue);
     } else log.warning("Not found for M_InOutLine_ID=" + m_issue.getM_InOutLine_ID());
   } catch (Exception e) {
     log.log(Level.SEVERE, sql, e);
   } finally {
     DB.close(rs, pstmt);
     pstmt = null;
     rs = null;
   }
   return retValue;
 } //	getPOCost();
  /**
   * Get Labor Cost from Expense Report
   *
   * @param as Account Schema
   * @return Unit Labor Cost
   */
  private BigDecimal getLaborCost(MAcctSchema as) {
    // Todor Lulov 30.01.2008
    BigDecimal retValue = Env.ZERO;
    BigDecimal qty = Env.ZERO;

    String sql =
        "SELECT ConvertedAmt, Qty FROM S_TimeExpenseLine "
            + " WHERE S_TimeExpenseLine.S_TimeExpenseLine_ID = ?";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql.toString(), getTrxName());
      pstmt.setInt(1, m_issue.getS_TimeExpenseLine_ID());
      rs = pstmt.executeQuery();
      if (rs.next()) {
        retValue = rs.getBigDecimal(1);
        qty = rs.getBigDecimal(2);
        retValue = retValue.multiply(qty);
        log.fine("ExpLineCost = " + retValue);
      } else log.warning("Not found for S_TimeExpenseLine_ID=" + m_issue.getS_TimeExpenseLine_ID());
    } catch (Exception e) {
      log.log(Level.SEVERE, sql.toString(), e);
    } finally {
      DB.close(rs, pstmt);
      pstmt = null;
      rs = null;
    }
    return retValue;
  } //	getLaborCost
  /**
   * Create Facts (the accounting logic) for PJI
   *
   * <pre>
   *  Issue
   *      ProjectWIP      DR
   *      Inventory               CR
   *  </pre>
   *
   * Project Account is either Asset or WIP depending on Project Type
   *
   * @param as accounting schema
   * @return Fact
   */
  public ArrayList<Fact> createFacts(MAcctSchema as) {
    //  create Fact Header
    Fact fact = new Fact(this, as, Fact.POST_Actual);
    setC_Currency_ID(as.getC_Currency_ID());

    MProject project = new MProject(getCtx(), m_issue.getC_Project_ID(), getTrxName());
    String ProjectCategory = project.getProjectCategory();
    MProduct product = MProduct.get(getCtx(), m_issue.getM_Product_ID());

    //  Line pointers
    FactLine dr = null;
    FactLine cr = null;

    //  Issue Cost
    BigDecimal costs = null;
    BigDecimal total = Env.ZERO;
    if (m_issue.getM_InOutLine_ID() != 0) costs = getPOCost(as);
    else if (m_issue.getS_TimeExpenseLine_ID() != 0) costs = getLaborCost(as);
    if (costs == null) // 	standard Product Costs
    {
      for (MCostDetail cost : m_line.getCostDetail(as)) {
        if (!MCostDetail.existsCost(cost)) continue;

        costs = MCostDetail.getTotalCost(cost, as);
        total = total.add(costs);
      }
    }

    if (total == null || total.signum() == 0) {
      p_Error = "Resubmit - No Costs for " + product.getName();
      log.log(Level.WARNING, p_Error);
      return null;
    }

    //  Project         DR
    int acctType = ACCTTYPE_ProjectWIP;
    if (MProject.PROJECTCATEGORY_AssetProject.equals(ProjectCategory))
      acctType = ACCTTYPE_ProjectAsset;
    dr = fact.createLine(m_line, getAccount(acctType, as), as.getC_Currency_ID(), costs, null);
    dr.setQty(m_line.getQty().negate());

    //  Inventory               CR
    acctType = ProductCost.ACCTTYPE_P_Asset;
    if (product.isService()) acctType = ProductCost.ACCTTYPE_P_Expense;
    cr =
        fact.createLine(
            m_line, m_line.getAccount(acctType, as), as.getC_Currency_ID(), null, costs);
    cr.setM_Locator_ID(m_line.getM_Locator_ID());
    cr.setLocationFromLocator(m_line.getM_Locator_ID(), true); // from Loc
    //
    ArrayList<Fact> facts = new ArrayList<Fact>();
    facts.add(fact);
    return facts;
  } //  createFact
  /**
   * Load Document Details
   *
   * @return error message or null
   */
  protected String loadDocumentDetails() {
    setC_Currency_ID(NO_CURRENCY);
    m_issue = (MProjectIssue) getPO();
    setDateDoc(m_issue.getMovementDate());
    setDateAcct(m_issue.getMovementDate());

    //	Pseudo Line
    m_line = new DocLine(m_issue, this);
    m_line.setQty(m_issue.getMovementQty(), true); //  sets Trx and Storage Qty

    //	Pseudo Line Check
    if (m_line.getM_Product_ID() == 0) log.warning(m_line.toString() + " - No Product");
    log.fine(m_line.toString());
    return null;
  } //  loadDocumentDetails
 /**
  * Get DocumentNo
  *
  * @return document no
  */
 public String getDocumentNo() {
   MProject p = m_issue.getParent();
   if (p != null) return p.getValue() + " #" + m_issue.getLine();
   return "(" + m_issue.get_ID() + ")";
 } //	getDocumentNo