/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.acct; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; import org.compiere.model.MClientInfo; import org.compiere.model.MCurrency; import org.compiere.model.MOrder; import org.compiere.model.MOrderLine; import org.compiere.model.MRequisitionLine; import org.compiere.model.MTax; import org.compiere.model.ProductCost; import org.compiere.util.DB; import org.compiere.util.Env; /** * Post Order Documents. *
 *  Table:              C_Order (259)
 *  Document Types:     SOO, POO
 *  
* @author Jorg Janke * @version $Id: Doc_Order.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ */ public class Doc_Order extends Doc { /** * Constructor * @param as accounting schema * @param rs record * @param trxName trx */ public Doc_Order (MAcctSchema as, ResultSet rs, String trxName) { super (as, MOrder.class, rs, null, trxName); } // Doc_Order /** Contained Optional Tax Lines */ private DocTax[] m_taxes = null; /** Requisitions */ private DocLine[] m_requisitions = null; /** Order Currency Precision */ private int m_precision = -1; /** * Load Specific Document Details * @return error message or null */ @Override protected String loadDocumentDetails () { MOrder order = (MOrder)getPO(); setDateDoc(order.getDateOrdered()); setIsTaxIncluded(order.isTaxIncluded()); // Amounts setAmount(AMTTYPE_Gross, order.getGrandTotal()); setAmount(AMTTYPE_Net, order.getTotalLines()); setAmount(AMTTYPE_Charge, order.getChargeAmt()); // Contained Objects m_taxes = loadTaxes(); p_lines = loadLines(order); return null; } // loadDocumentDetails /** * Load order lines * @param order order * @return DocLine Array */ private DocLine[] loadLines(MOrder order) { ArrayList list = new ArrayList(); MOrderLine[] lines = order.getLines(); for (int i = 0; i < lines.length; i++) { MOrderLine line = lines[i]; DocLine docLine = new DocLine (line, this); BigDecimal Qty = line.getQtyOrdered(); docLine.setQty(Qty, order.isSOTrx()); // BigDecimal PriceCost = null; if (getDocumentType().equals(DOCTYPE_POrder)) // PO PriceCost = line.getPriceCost(); BigDecimal LineNetAmt = null; if (PriceCost != null && PriceCost.signum() != 0) LineNetAmt = Qty.multiply(PriceCost); else LineNetAmt = line.getLineNetAmt(); docLine.setAmount (LineNetAmt); // DR BigDecimal PriceList = line.getPriceList(); int C_Tax_ID = docLine.getC_Tax_ID(); // Correct included Tax if (isTaxIncluded() && C_Tax_ID != 0) { MTax tax = MTax.get(getCtx(), C_Tax_ID); if (!tax.isZeroTax()) { BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPrecision()); if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax); LineNetAmt = LineNetAmt.subtract(LineNetAmtTax); for (int t = 0; t < m_taxes.length; t++) { if (m_taxes[t].getC_Tax_ID() == C_Tax_ID) { m_taxes[t].addIncludedTax(LineNetAmtTax); break; } } BigDecimal PriceListTax = tax.calculateTax(PriceList, true, getStdPrecision()); PriceList = PriceList.subtract(PriceListTax); } } // correct included Tax docLine.setAmount (LineNetAmt, PriceList, Qty); list.add(docLine); } // Return Array DocLine[] dl = new DocLine[list.size()]; list.toArray(dl); return dl; } // loadLines /** * Load Requisitions * @return requisition lines of Order */ private DocLine[] loadRequisitions () { MOrder order = (MOrder)getPO(); MOrderLine[] oLines = order.getLines(); HashMap qtys = new HashMap(); for (int i = 0; i < oLines.length; i++) { MOrderLine line = oLines[i]; qtys.put(Integer.valueOf(line.getC_OrderLine_ID()), line.getQtyOrdered()); } // ArrayList list = new ArrayList(); String sql = "SELECT * FROM M_RequisitionLine rl " + "WHERE EXISTS (SELECT * FROM C_Order o " + " INNER JOIN C_OrderLine ol ON (o.C_Order_ID=ol.C_Order_ID) " + "WHERE ol.C_OrderLine_ID=rl.C_OrderLine_ID" + " AND o.C_Order_ID=?) " + "ORDER BY rl.C_OrderLine_ID"; PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement (sql, null); pstmt.setInt (1, order.getC_Order_ID()); rs = pstmt.executeQuery (); while (rs.next ()) { MRequisitionLine line = new MRequisitionLine (getCtx(), rs, null); DocLine docLine = new DocLine (line, this); // Quantity - not more then OrderLine // Issue: Split of Requisition to multiple POs & different price Integer key = Integer.valueOf(line.getC_OrderLine_ID()); BigDecimal maxQty = qtys.get(key); BigDecimal Qty = line.getQty().max(maxQty); if (Qty.signum() == 0) continue; docLine.setQty (Qty, false); qtys.put(key, maxQty.subtract(Qty)); // BigDecimal PriceActual = line.getPriceActual(); BigDecimal LineNetAmt = line.getLineNetAmt(); if (line.getQty().compareTo(Qty) != 0) LineNetAmt = PriceActual.multiply(Qty); docLine.setAmount (LineNetAmt); // DR list.add (docLine); } } catch (Exception e) { log.log (Level.SEVERE, sql, e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Return Array DocLine[] dls = new DocLine[list.size ()]; list.toArray (dls); return dls; } // loadRequisitions /** * Get Currency Precision * @return precision */ private int getStdPrecision() { if (m_precision == -1) m_precision = MCurrency.getStdPrecision(getCtx(), getC_Currency_ID()); return m_precision; } // getPrecision /** * Load Order Taxes * @return DocTax Array */ private DocTax[] loadTaxes() { ArrayList list = new ArrayList(); StringBuilder sql = new StringBuilder("SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax ") .append("FROM C_Tax t, C_OrderTax it ") .append("WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Order_ID=?"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql.toString(), getTrxName()); pstmt.setInt(1, get_ID()); rs = pstmt.executeQuery(); // while (rs.next()) { int C_Tax_ID = rs.getInt(1); String name = rs.getString(2); BigDecimal rate = rs.getBigDecimal(3); BigDecimal taxBaseAmt = rs.getBigDecimal(4); BigDecimal amount = rs.getBigDecimal(5); boolean salesTax = "Y".equals(rs.getString(6)); // DocTax taxLine = new DocTax(C_Tax_ID, name, rate, taxBaseAmt, amount, salesTax); list.add(taxLine); } } catch (SQLException e) { log.log(Level.SEVERE, sql.toString(), e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Return Array DocTax[] tl = new DocTax[list.size()]; list.toArray(tl); return tl; } // loadTaxes /** * Get Source Currency Balance - subtracts line and tax amounts from total - no rounding * @return positive amount, if total invoice is bigger than lines */ @Override public BigDecimal getBalance() { BigDecimal retValue = Env.ZERO; StringBuilder sb = new StringBuilder (" ["); // Total retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross)); sb.append(getAmount(Doc.AMTTYPE_Gross)); // - Header Charge retValue = retValue.subtract(getAmount(Doc.AMTTYPE_Charge)); sb.append("-").append(getAmount(Doc.AMTTYPE_Charge)); // - Tax if (m_taxes != null) { for (int i = 0; i < m_taxes.length; i++) { retValue = retValue.subtract(m_taxes[i].getAmount()); sb.append("-").append(m_taxes[i].getAmount()); } } // - Lines if (p_lines != null) { for (int i = 0; i < p_lines.length; i++) { retValue = retValue.subtract(p_lines[i].getAmtSource()); sb.append("-").append(p_lines[i].getAmtSource()); } sb.append("]"); } // if (retValue.signum() != 0 // Sum of Cost(vs. Price) in lines may not add up && getDocumentType().equals(DOCTYPE_POrder)) // PO { if (log.isLoggable(Level.FINE)) log.fine(toString() + " Balance=" + retValue + sb.toString() + " (ignored)"); retValue = Env.ZERO; } else if (log.isLoggable(Level.FINE)) log.fine(toString() + " Balance=" + retValue + sb.toString()); return retValue; } // getBalance /** * Create Facts (the accounting logic) for * SOO, POO. *
	 *  Reservation (release)
	 * 		Expense			DR
	 * 		Offset					CR
	 *  Commitment
	 *  (to be released by Invoice Matching)
	 * 		Expense					CR
	 * 		Offset			DR
	 *  
* @param as accounting schema * @return Fact */ @Override public ArrayList createFacts (MAcctSchema as) { ArrayList facts = new ArrayList(); // Purchase Order if (getDocumentType().equals(DOCTYPE_POrder)) { updateProductPO(as); // Commitment @SuppressWarnings("unused") FactLine fl = null; if (as.isCreatePOCommitment()) { Fact fact = new Fact(this, as, Fact.POST_Commitment); BigDecimal total = Env.ZERO; for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; BigDecimal cost = line.getAmtSource(); total = total.add(cost); // Account MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as); fl = fact.createLine (line, expense, getC_Currency_ID(), cost, null); } // Offset MAccount offset = getAccount(ACCTTYPE_CommitmentOffset, as); if (offset == null) { p_Error = "@NotFound@ @CommitmentOffset_Acct@"; log.log(Level.SEVERE, p_Error); return null; } fact.createLine (null, offset, getC_Currency_ID(), null, total); // facts.add(fact); } // Reverse Reservation if (as.isCreateReservation()) { Fact fact = new Fact(this, as, Fact.POST_Reservation); BigDecimal total = Env.ZERO; if (m_requisitions == null) m_requisitions = loadRequisitions(); for (int i = 0; i < m_requisitions.length; i++) { DocLine line = m_requisitions[i]; BigDecimal cost = line.getAmtSource(); total = total.add(cost); // Account MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as); fl = fact.createLine (line, expense, getC_Currency_ID(), null, cost); } // Offset if (m_requisitions.length > 0) { MAccount offset = getAccount(ACCTTYPE_CommitmentOffset, as); if (offset == null) { p_Error = "@NotFound@ @CommitmentOffset_Acct@"; log.log(Level.SEVERE, p_Error); return null; } fact.createLine (null, offset, getC_Currency_ID(), total, null); } // facts.add(fact); } // reservations } // SO else if (getDocumentType().equals(DOCTYPE_SOrder)) { // Commitment @SuppressWarnings("unused") FactLine fl = null; if (as.isCreateSOCommitment()) { Fact fact = new Fact(this, as, Fact.POST_Commitment); BigDecimal total = Env.ZERO; for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; BigDecimal cost = line.getAmtSource(); total = total.add(cost); // Account MAccount revenue = line.getAccount(ProductCost.ACCTTYPE_P_Revenue, as); fl = fact.createLine (line, revenue, getC_Currency_ID(), null, cost); } // Offset MAccount offset = getAccount(ACCTTYPE_CommitmentOffsetSales, as); if (offset == null) { p_Error = "@NotFound@ @CommitmentOffsetSales_Acct@"; log.log(Level.SEVERE, p_Error); return null; } fact.createLine (null, offset, getC_Currency_ID(), total, null); // facts.add(fact); } } return facts; } // createFact /** * Update ProductPO PriceLastPO * @param as accounting schema */ private void updateProductPO(MAcctSchema as) { MClientInfo ci = MClientInfo.get(getCtx(), as.getAD_Client_ID()); if (ci.getC_AcctSchema1_ID() != as.getC_AcctSchema_ID()) return; StringBuilder sql = new StringBuilder ( "UPDATE M_Product_PO po ") .append("SET PriceLastPO = (SELECT currencyConvert(ol.PriceActual,ol.C_Currency_ID,po.C_Currency_ID,o.DateOrdered,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) ") .append("FROM C_Order o, C_OrderLine ol ") .append("WHERE o.C_Order_ID=ol.C_Order_ID") .append(" AND po.M_Product_ID=ol.M_Product_ID AND po.C_BPartner_ID=o.C_BPartner_ID "); if (DB.isOracle()) //jz { sql.append(" AND ROWNUM=1 "); } else sql.append(" AND ol.C_OrderLine_ID = (SELECT MIN(ol1.C_OrderLine_ID) ") .append("FROM C_Order o1, C_OrderLine ol1 ") .append("WHERE o1.C_Order_ID=ol1.C_Order_ID") .append(" AND po.M_Product_ID=ol1.M_Product_ID AND po.C_BPartner_ID=o1.C_BPartner_ID") .append(" AND o1.C_Order_ID=").append(get_ID()).append(") "); sql.append(" AND o.C_Order_ID=").append(get_ID()).append(") ") .append("WHERE EXISTS (SELECT * ") .append("FROM C_Order o, C_OrderLine ol ") .append("WHERE o.C_Order_ID=ol.C_Order_ID") .append(" AND po.M_Product_ID=ol.M_Product_ID AND po.C_BPartner_ID=o.C_BPartner_ID") .append(" AND o.C_Order_ID=").append(get_ID()).append(")"); int no = DB.executeUpdate(sql.toString(), getTrxName()); if (log.isLoggable(Level.FINE)) log.fine("Updated=" + no); } // updateProductPO /** * Get Commitments * @param doc document * @param maxQty Qty invoiced/matched * @param C_InvoiceLine_ID invoice line * @return commitments (order lines) */ protected static DocLine[] getCommitments(Doc doc, BigDecimal maxQty, int C_InvoiceLine_ID) { int precision = -1; // ArrayList list = new ArrayList(); StringBuilder sql = new StringBuilder("SELECT * FROM C_OrderLine ol ") .append("WHERE EXISTS ") .append("(SELECT * FROM C_InvoiceLine il ") .append("WHERE il.C_OrderLine_ID=ol.C_OrderLine_ID") .append(" AND il.C_InvoiceLine_ID=?)") .append(" OR EXISTS ") .append("(SELECT * FROM M_MatchPO po ") .append("WHERE po.C_OrderLine_ID=ol.C_OrderLine_ID") .append(" AND po.C_InvoiceLine_ID=?)"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement (sql.toString(), null); pstmt.setInt (1, C_InvoiceLine_ID); pstmt.setInt (2, C_InvoiceLine_ID); rs = pstmt.executeQuery (); while (rs.next ()) { if (maxQty.signum() == 0) continue; MOrderLine line = new MOrderLine (doc.getCtx(), rs, null); DocLine docLine = new DocLine (line, doc); // Currency if (precision == -1) { doc.setC_Currency_ID(docLine.getC_Currency_ID()); precision = MCurrency.getStdPrecision(doc.getCtx(), docLine.getC_Currency_ID()); } // Qty BigDecimal Qty = line.getQtyOrdered().max(maxQty); docLine.setQty(Qty, false); // BigDecimal PriceActual = line.getPriceActual(); BigDecimal PriceCost = line.getPriceCost(); BigDecimal LineNetAmt = null; if (PriceCost != null && PriceCost.signum() != 0) LineNetAmt = Qty.multiply(PriceCost); else if (Qty.equals(maxQty)) LineNetAmt = line.getLineNetAmt(); else LineNetAmt = Qty.multiply(PriceActual); maxQty = maxQty.subtract(Qty); docLine.setAmount (LineNetAmt); // DR BigDecimal PriceList = line.getPriceList(); int C_Tax_ID = docLine.getC_Tax_ID(); // Correct included Tax if (C_Tax_ID != 0 && line.getParent().isTaxIncluded()) { MTax tax = MTax.get(doc.getCtx(), C_Tax_ID); if (!tax.isZeroTax()) { BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, precision); if (s_log.isLoggable(Level.FINE)) s_log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax); LineNetAmt = LineNetAmt.subtract(LineNetAmtTax); BigDecimal PriceListTax = tax.calculateTax(PriceList, true, precision); PriceList = PriceList.subtract(PriceListTax); } } // correct included Tax docLine.setAmount (LineNetAmt, PriceList, Qty); list.add(docLine); } } catch (Exception e) { s_log.log (Level.SEVERE, sql.toString(), e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Return Array DocLine[] dl = new DocLine[list.size()]; list.toArray(dl); return dl; } // getCommitments /** * Get Commitment Release.
* Called from MatchInv for accrual and Allocation for cash based accounting * @param as accounting schema * @param doc doc * @param Qty qty invoiced/matched * @param C_InvoiceLine_ID line * @param multiplier 1 for accrual * @return Fact */ protected static Fact getCommitmentRelease(MAcctSchema as, Doc doc, BigDecimal Qty, int C_InvoiceLine_ID, BigDecimal multiplier) { Fact fact = new Fact(doc, as, Fact.POST_Commitment); DocLine[] commitments = Doc_Order.getCommitments(doc, Qty, C_InvoiceLine_ID); BigDecimal total = Env.ZERO; @SuppressWarnings("unused") FactLine fl = null; int C_Currency_ID = -1; for (int i = 0; i < commitments.length; i++) { DocLine line = commitments[i]; if (C_Currency_ID == -1) C_Currency_ID = line.getC_Currency_ID(); else if (C_Currency_ID != line.getC_Currency_ID()) { doc.p_Error = "Different Currencies of Order Lines"; s_log.log(Level.SEVERE, doc.p_Error); return null; } BigDecimal cost = line.getAmtSource().multiply(multiplier); total = total.add(cost); // Account MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as); fl = fact.createLine (line, expense, C_Currency_ID, null, cost); } // Offset MAccount offset = doc.getAccount(ACCTTYPE_CommitmentOffset, as); if (offset == null) { doc.p_Error = "@NotFound@ @CommitmentOffset_Acct@"; s_log.log(Level.SEVERE, doc.p_Error); return null; } fact.createLine (null, offset, C_Currency_ID, total, null); return fact; } // getCommitmentRelease /** * Get Commitments Sales * @param doc document * @param maxQty Qty invoiced/matched * @param M_InOutLine_ID invoice line * @return commitments (order lines) */ protected static DocLine[] getCommitmentsSales(Doc doc, BigDecimal maxQty, int M_InOutLine_ID) { int precision = -1; // ArrayList list = new ArrayList(); StringBuilder sql = new StringBuilder("SELECT * FROM C_OrderLine ol ") .append("WHERE EXISTS ") .append("(SELECT * FROM M_InOutLine il ") .append("WHERE il.C_OrderLine_ID=ol.C_OrderLine_ID") .append(" AND il.M_InOutLine_ID=?)"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement (sql.toString(), null); pstmt.setInt (1, M_InOutLine_ID); rs = pstmt.executeQuery (); while (rs.next ()) { if (maxQty.signum() == 0) continue; MOrderLine line = new MOrderLine (doc.getCtx(), rs, null); DocLine docLine = new DocLine (line, doc); // Currency if (precision == -1) { doc.setC_Currency_ID(docLine.getC_Currency_ID()); precision = MCurrency.getStdPrecision(doc.getCtx(), docLine.getC_Currency_ID()); } // Qty BigDecimal Qty = line.getQtyOrdered().max(maxQty); docLine.setQty(Qty, false); // BigDecimal PriceActual = line.getPriceActual(); BigDecimal PriceCost = line.getPriceCost(); BigDecimal LineNetAmt = null; if (PriceCost != null && PriceCost.signum() != 0) LineNetAmt = Qty.multiply(PriceCost); else if (Qty.equals(maxQty)) LineNetAmt = line.getLineNetAmt(); else LineNetAmt = Qty.multiply(PriceActual); maxQty = maxQty.subtract(Qty); docLine.setAmount (LineNetAmt); // DR BigDecimal PriceList = line.getPriceList(); int C_Tax_ID = docLine.getC_Tax_ID(); // Correct included Tax if (C_Tax_ID != 0 && line.getParent().isTaxIncluded()) { MTax tax = MTax.get(doc.getCtx(), C_Tax_ID); if (!tax.isZeroTax()) { BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, precision); if (s_log.isLoggable(Level.FINE)) s_log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax); LineNetAmt = LineNetAmt.subtract(LineNetAmtTax); BigDecimal PriceListTax = tax.calculateTax(PriceList, true, precision); PriceList = PriceList.subtract(PriceListTax); } } // correct included Tax docLine.setAmount (LineNetAmt, PriceList, Qty); list.add(docLine); } } catch (Exception e) { s_log.log (Level.SEVERE, sql.toString(), e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // Return Array DocLine[] dl = new DocLine[list.size()]; list.toArray(dl); return dl; } // getCommitmentsSales /** * Get Commitment Sales Release. * Called from InOut * @param as accounting schema * @param doc doc * @param Qty qty invoiced/matched * @param M_InOutLine_ID line * @param multiplier 1 for accrual * @return Fact */ public static Fact getCommitmentSalesRelease(MAcctSchema as, Doc doc, BigDecimal Qty, int M_InOutLine_ID, BigDecimal multiplier) { Fact fact = new Fact(doc, as, Fact.POST_Commitment); DocLine[] commitments = Doc_Order.getCommitmentsSales(doc, Qty, M_InOutLine_ID); BigDecimal total = Env.ZERO; @SuppressWarnings("unused") FactLine fl = null; int C_Currency_ID = -1; for (int i = 0; i < commitments.length; i++) { DocLine line = commitments[i]; if (C_Currency_ID == -1) C_Currency_ID = line.getC_Currency_ID(); else if (C_Currency_ID != line.getC_Currency_ID()) { doc.p_Error = "Different Currencies of Order Lines"; s_log.log(Level.SEVERE, doc.p_Error); return null; } BigDecimal cost = line.getAmtSource().multiply(multiplier); total = total.add(cost); // Account MAccount revenue = line.getAccount(ProductCost.ACCTTYPE_P_Revenue, as); fl = fact.createLine (line, revenue, C_Currency_ID, cost, null); } // Offset MAccount offset = doc.getAccount(ACCTTYPE_CommitmentOffsetSales, as); if (offset == null) { doc.p_Error = "@NotFound@ @CommitmentOffsetSales_Acct@"; s_log.log(Level.SEVERE, doc.p_Error); return null; } fact.createLine (null, offset, C_Currency_ID, null, total); return fact; } // getCommitmentSalesRelease } // Doc_Order