/****************************************************************************** * 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.lang.reflect.Constructor; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; import java.util.logging.Level; import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.compiere.model.I_C_AllocationHdr; import org.compiere.model.I_C_Cash; import org.compiere.model.I_C_ProjectIssue; import org.compiere.model.I_M_MatchInv; import org.compiere.model.I_M_MatchPO; import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; import org.compiere.model.MConversionRate; import org.compiere.model.MDocType; import org.compiere.model.MInOut; import org.compiere.model.MInvoice; import org.compiere.model.MMatchInv; import org.compiere.model.MMatchPO; import org.compiere.model.MNote; import org.compiere.model.MPeriod; import org.compiere.model.MRefList; import org.compiere.model.ModelValidationEngine; import org.compiere.model.ModelValidator; import org.compiere.model.PO; import org.compiere.process.DocumentEngine; import org.compiere.util.AdempiereUserError; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Trx; import org.compiere.util.Util; /** * Abstract base class for posting of accounting document. * *
 *  Table               Base Document Types (C_DocType.DocBaseType and AD_Reference_ID=183)
 *      Class           AD_Table_ID
 *  ------------------  ------------------------------
 *  C_Invoice:          ARI, ARC, ARF, API, APC
 *      Doc_Invoice     318 - has C_DocType_ID
 *
 *  C_Payment:          ARP, APP
 *      Doc_Payment     335 - has C_DocType_ID
 *
 *  C_Order:            SOO, POO,  POR (Requisition)
 *      Doc_Order       259 - has C_DocType_ID
 *
 *  M_InOut:            MMS, MMR
 *      Doc_InOut       319 - DocType derived
 *
 *  M_Inventory:        MMI
 *      Doc_Inventory   321 - DocType fixed
 *
 *  M_Movement:         MMM
 *      Doc_Movement    323 - DocType fixed
 *
 *  M_Production:       MMP
 *      Doc_Production  325 - DocType fixed
 *
 * M_Production:        MMO
 *      Doc_CostCollector  330 - DocType fixed
 *
 *  C_BankStatement:    CMB
 *      Doc_Bank        392 - DocType fixed
 *
 *  C_Cash:             CMC
 *      Doc_Cash        407 - DocType fixed
 *
 *  C_Allocation:       CMA
 *      Doc_Allocation  390 - DocType fixed
 *
 *  GL_Journal:         GLJ
 *      Doc_GLJournal   224 = has C_DocType_ID
 *
 *  Matching Invoice    MXI
 *      M_MatchInv      472 - DocType fixed
 *
 *  Matching PO         MXP
 *      M_MatchPO       473 - DocType fixed
 *
 *	Project Issue		PJI
 *		C_ProjectIssue	623 - DocType fixed
 *
 *  
* @author Jorg Janke * @author victor.perez@e-evolution.com, e-Evolution http://www.e-evolution.com *
  • FR [ 2520591 ] Support multiples calendar for Org * @see https://sourceforge.net/p/adempiere/feature-requests/631/ * @version $Id: Doc.java,v 1.6 2006/07/30 00:53:33 jjanke Exp $ */ public abstract class Doc { /************************************************************************** * Document Types * -------------- * C_DocType.DocBaseType and AD_Reference_ID=183 * C_Invoice: ARI, ARC, ARF, API, APC * C_Payment: ARP, APP * C_Order: SOO, POO * M_Transaction: MMI, MMM, MMS, MMR * C_BankStatement: CMB * C_Cash: CMC * C_Allocation: CMA * GL_Journal: GLJ * C_ProjectIssue PJI * M_Requisition POR **************************************************************************/ public static final String DOC_TYPE_BY_DOC_BASE_TYPE_SQL = "SELECT C_DocType_ID FROM C_DocType WHERE AD_Client_ID=? AND DocBaseType=? AND IsActive='Y' ORDER BY IsDefault DESC, C_DocType_ID"; /** AR Invoices - ARI */ public static final String DOCTYPE_ARInvoice = MDocType.DOCBASETYPE_ARInvoice; /** AR Credit Memo */ public static final String DOCTYPE_ARCredit = "ARC"; /** AR Receipt */ public static final String DOCTYPE_ARReceipt = "ARR"; /** AR ProForma */ public static final String DOCTYPE_ARProForma = "ARF"; /** AP Invoices */ public static final String DOCTYPE_APInvoice = "API"; /** AP Credit Memo */ public static final String DOCTYPE_APCredit = "APC"; /** AP Payment */ public static final String DOCTYPE_APPayment = "APP"; /** CashManagement Bank Statement */ public static final String DOCTYPE_BankStatement = "CMB"; /** CashManagement Cash Journals */ public static final String DOCTYPE_CashJournal = "CMC"; /** CashManagement Allocations */ public static final String DOCTYPE_Allocation = "CMA"; /** Material Shipment */ public static final String DOCTYPE_MatShipment = "MMS"; /** Material Receipt */ public static final String DOCTYPE_MatReceipt = "MMR"; /** Material Inventory */ public static final String DOCTYPE_MatInventory = "MMI"; /** Material Movement */ public static final String DOCTYPE_MatMovement = "MMM"; /** Material Production */ public static final String DOCTYPE_MatProduction = "MMP"; /** Match Invoice */ public static final String DOCTYPE_MatMatchInv = "MXI"; /** Match PO */ public static final String DOCTYPE_MatMatchPO = "MXP"; /** GL Journal */ public static final String DOCTYPE_GLJournal = "GLJ"; /** Purchase Order */ public static final String DOCTYPE_POrder = "POO"; /** Sales Order */ public static final String DOCTYPE_SOrder = "SOO"; /** Project Issue */ public static final String DOCTYPE_ProjectIssue = "PJI"; /** Purchase Requisition */ public static final String DOCTYPE_PurchaseRequisition = "POR"; // Posting Status - AD_Reference_ID=234 // /** Document Status */ public static final String STATUS_NotPosted = "N"; /** Document Status */ public static final String STATUS_NotBalanced = "b"; /** Document Status */ public static final String STATUS_NotConvertible = "c"; /** Document Status */ public static final String STATUS_PeriodClosed = "p"; /** Document Status */ public static final String STATUS_InvalidAccount = "i"; /** Document Status */ public static final String STATUS_PostPrepared = "y"; /** Document Status */ public static final String STATUS_Posted = "Y"; /** Document Status */ public static final String STATUS_Error = "E"; /** Document Status */ public static final String STATUS_Deferred = "d"; /** * Create Posting document * @param as accounting schema * @param AD_Table_ID Table ID of Documents * @param Record_ID record ID to load * @param trxName transaction name * @return new Posting Document instance or null */ public static Doc get (MAcctSchema as, int AD_Table_ID, int Record_ID, String trxName) { return DocManager.getDocument(as, AD_Table_ID, Record_ID, trxName); } // get /** * Create Posting document * @param as accounting schema * @param AD_Table_ID Table ID of Documents * @param rs ResultSet * @param trxName transaction name * @return new Posting Document instance or null * @throws AdempiereUserError */ public static Doc get (MAcctSchema as, int AD_Table_ID, ResultSet rs, String trxName) { return DocManager.getDocument(as, AD_Table_ID, rs, trxName); } // get /** * Post document immediately * @param ass accounting schema * @param AD_Table_ID Transaction table * @param Record_ID Record ID of this document * @param force force posting * @param trxName transaction * @return null if the document was posted or error message */ public static String postImmediate (MAcctSchema[] ass, int AD_Table_ID, int Record_ID, boolean force, String trxName) { return DocManager.postDocument(ass, AD_Table_ID, Record_ID, force, true, trxName); } // post /** * Manual posting by user * @param WindowNo * @param AD_Client_ID * @param AD_Table_ID * @param Record_ID * @param force * @return error message ( if any ) */ public static String manualPosting (int WindowNo, int AD_Client_ID, int AD_Table_ID, int Record_ID, boolean force) { String error = null; MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(Env.getCtx(), AD_Client_ID); Trx trx = Trx.get(Trx.createTrxName("ManulPosting"), true); trx.setDisplayName(Doc.class.getName()+"_manualPosting"); try { //Costing: Post MatchPO before MR if (AD_Table_ID == MInOut.Table_ID) { MMatchPO[] matchPos = MMatchPO.getInOut(Env.getCtx(), Record_ID, trx.getTrxName()); for (MMatchPO matchPo : matchPos) { if (!matchPo.isPosted()) { error = postImmediate(ass, matchPo.get_Table_ID(), matchPo.get_ID(), force, matchPo.get_TrxName()); if (!Util.isEmpty(error)) break; } } } if (Util.isEmpty(error)) { error = postImmediate(ass, AD_Table_ID, Record_ID, force, trx.getTrxName()); } //Costing: Post MatchInv after Invoice if (Util.isEmpty(error)) { if (AD_Table_ID == MInvoice.Table_ID) { MMatchInv[] matchInvs = MMatchInv.getInvoice(Env.getCtx(), Record_ID, trx.getTrxName()); for (MMatchInv matchInv : matchInvs) { if (!matchInv.isPosted()) { error = postImmediate(ass, matchInv.get_Table_ID(), matchInv.get_ID(), force, matchInv.get_TrxName()); if (!Util.isEmpty(error)) break; } } } } if (Util.isEmpty(error)) { trx.commit(true); } else { trx.rollback(); } } catch (Throwable t) { trx.rollback(); if(t instanceof SQLException sqlEx) { String messageError = DBException.getDefaultDBExceptionMessage(sqlEx); if (messageError != null) return Msg.getMsg(Env.getCtx(), messageError); } return "@Error@ " + t.getLocalizedMessage(); } finally { trx.close(); } return error; } /** Static Log */ protected static final CLogger s_log = CLogger.getCLogger(Doc.class); /** Log per Document */ protected transient CLogger log = CLogger.getCLogger(getClass()); /* If the transaction must be managed locally (false if it's managed externally by the caller) */ private boolean m_manageLocalTrx; /** * Constructor * @param as accounting schema * @param clazz Document Class * @param rs result set * @param defaultDocumentType default document type or null * @param trxName trx */ public Doc (MAcctSchema as, Class clazz, ResultSet rs, String defaultDocumentType, String trxName) { p_Status = STATUS_Error; m_as = as; m_ctx = new Properties(m_as.getCtx()); m_ctx.setProperty(Env.AD_CLIENT_ID, String.valueOf(m_as.getAD_Client_ID())); String className = clazz.getName(); className = className.substring(className.lastIndexOf('.')+1); try { Constructor constructor = clazz.getConstructor(new Class[]{Properties.class, ResultSet.class, String.class}); p_po = (PO)constructor.newInstance(new Object[]{m_ctx, rs, trxName}); } catch (Exception e) { String msg = className + ": " + e.getLocalizedMessage(); log.severe(msg); throw new IllegalArgumentException(msg); } p_po.load(p_po.get_TrxName()); // reload the PO to get any virtual column that was not obtained using the rs (IDEMPIERE-775) // DocStatus int index = p_po.get_ColumnIndex("DocStatus"); if (index != -1) m_DocStatus = (String)p_po.get_Value(index); // Document Type setDocumentType (defaultDocumentType); m_trxName = trxName; m_manageLocalTrx = false; if (m_trxName == null) { m_trxName = "Post" + m_DocumentType + p_po.get_ID(); m_manageLocalTrx = true; } p_po.set_TrxName(m_trxName); // Amounts for(int i = 0; i < m_Amounts.length; i++) { m_Amounts[i] = Env.ZERO; } } // Doc /** Accounting Schema */ private MAcctSchema m_as = null; /** Properties */ private Properties m_ctx = null; /** Transaction Name */ private String m_trxName = null; /** The Document */ protected PO p_po = null; /** Document Type */ private String m_DocumentType = null; /** Document Status */ private String m_DocStatus = null; /** Document No */ private String m_DocumentNo = null; /** Description */ private String m_Description = null; /** GL Category */ private int m_GL_Category_ID = 0; /** GL Period */ private MPeriod m_period = null; /** Period ID */ private int m_C_Period_ID = 0; /** Location From */ private int m_C_LocFrom_ID = 0; /** Location To */ private int m_C_LocTo_ID = 0; /** Accounting Date */ private Timestamp m_DateAcct = null; /** Document Date */ private Timestamp m_DateDoc = null; /** Tax Included */ private boolean m_TaxIncluded = false; /** Is (Source) Multi-Currency Document - i.e. the document has different currencies * (if true, the document will not be source balanced) */ private boolean m_MultiCurrency = false; /** BP Sales Region */ private int m_BP_C_SalesRegion_ID = -1; /** B Partner */ private int m_C_BPartner_ID = -1; /** Bank Account */ private int m_C_BankAccount_ID = -1; /** Cach Book */ private int m_C_CashBook_ID = -1; /** Currency */ private int m_C_Currency_ID = -1; /** Contained Doc Lines */ protected DocLine[] p_lines; /** Facts */ private ArrayList m_fact = null; /** No Currency in Document Indicator (-1) */ protected static final int NO_CURRENCY = -2; /** Actual Document Status */ protected String p_Status = null; public String getPostStatus() { return p_Status; } /** Error Message */ protected String p_Error = null; /** * Get Context * @return context */ public Properties getCtx() { return m_ctx; } // getCtx /** * Get Table Name * @return table name */ public String get_TableName() { return p_po.get_TableName(); } // get_TableName /** * Get Table ID * @return table id */ public int get_Table_ID() { return p_po.get_Table_ID(); } // get_Table_ID /** * Get Record_ID * @return record id */ public int get_ID() { return p_po.get_ID(); } // get_ID /** * Get Persistent Object * @return po */ public PO getPO() { return p_po; } // getPO /** * Post Document. *
    	 *  - try to lock document (Processed='Y' (AND Processing='N' AND Posted='N'))
    	 *       - if not ok - return false
    	 *          - postlogic (for all Accounting Schema)
    	 *              - create Fact lines
    	 *          - postCommit
    	 *              - commits Fact lines and Document and sets Processing = 'N'
    	 *              - if error - create Note
    	 *  
    * @param force if true ignore that locked * @param repost if true ignore that already posted * @return error message or null */ public final String post (boolean force, boolean repost) { if (m_DocStatus == null) ; // return "No DocStatus for DocumentNo=" + getDocumentNo(); else if (m_DocStatus.equals(DocumentEngine.STATUS_Completed) || m_DocStatus.equals(DocumentEngine.STATUS_Closed) || m_DocStatus.equals(DocumentEngine.STATUS_Voided) || m_DocStatus.equals(DocumentEngine.STATUS_Reversed)) ; else{ StringBuilder msgreturn = new StringBuilder("Invalid DocStatus='").append(m_DocStatus).append("' for DocumentNo=").append(getDocumentNo()); return msgreturn.toString(); } // if (p_po.getAD_Client_ID() != m_as.getAD_Client_ID()) { StringBuilder error = new StringBuilder("AD_Client_ID Conflict - Document=").append(p_po.getAD_Client_ID()) .append(", AcctSchema=").append(m_as.getAD_Client_ID()); log.severe(error.toString()); return error.toString(); } // Lock Record ---- String trxName = null; // outside trx if on server if (! m_manageLocalTrx) trxName = getTrxName(); // on trx if it's in client StringBuilder sql = new StringBuilder ("UPDATE "); sql.append(get_TableName()).append( " SET Processing='Y' WHERE ") .append(get_TableName()).append("_ID=").append(get_ID()) .append(" AND Processed='Y' AND IsActive='Y'"); if (!force) sql.append(" AND (Processing='N' OR Processing IS NULL)"); if (!repost) sql.append(" AND Posted IN ('N','d')"); if (DB.executeUpdate(sql.toString(), trxName) == 1) { if (log.isLoggable(Level.INFO)) log.info("Locked: " + get_TableName() + "_ID=" + get_ID()); } else { log.log(Level.SEVERE, "Resubmit - Cannot lock " + get_TableName() + "_ID=" + get_ID() + ", Force=" + force + ",RePost=" + repost); if (!p_po.isActive()) return Msg.translate(getCtx(), "CannotPostInactiveDocument"); if (force) return Msg.translate(getCtx(), "CannotLockReSubmit"); return Msg.translate(getCtx(), "CannotLockReSubmitOrRePostWithForce"); } p_Error = loadDocumentDetails(); if (p_Error != null) return p_Error; if (isDeferPosting()) { unlock(); p_Status = STATUS_Deferred; return null; } Trx trx = Trx.get(getTrxName(), true); // Delete existing Accounting if (repost) { if (isPosted() && !isPeriodOpen()) // already posted - don't delete if period closed { log.log(Level.SEVERE, toString() + " - Period Closed for already posed document"); unlock(); trx.commit(); trx.close(); return "PeriodClosed"; } // delete it deleteAcct(); } else if (isPosted()) { log.log(Level.SEVERE, toString() + " - Document already posted"); unlock(); trx.commit(); trx.close(); return "AlreadyPosted"; } p_Status = STATUS_NotPosted; // Create Fact per AcctSchema m_fact = new ArrayList(); getPO().setDoc(this); try { // if acct schema has "only" org, skip boolean skip = false; if (m_as.getAD_OrgOnly_ID() != 0) { // Header Level Org skip = m_as.isSkipOrg(getAD_Org_ID()); // Line Level Org if (p_lines != null) { for (int line = 0; skip && line < p_lines.length; line++) { skip = m_as.isSkipOrg(p_lines[line].getAD_Org_ID()); if (!skip) break; } } } if (!skip) { // post p_Status = postLogic (); } else { p_Status = STATUS_Posted; // skipped is OK } } catch (Exception e) { log.log(Level.SEVERE, "", e); p_Status = STATUS_Error; p_Error = e.toString(); } String validatorMsg = null; // Call validator on before post if (p_Status.equals(STATUS_Posted)) { validatorMsg = ModelValidationEngine.get().fireDocValidate(getPO(), ModelValidator.TIMING_BEFORE_POST); if (validatorMsg != null) { p_Status = STATUS_Error; p_Error = validatorMsg; } } // commitFact p_Status = postCommit (p_Status); if (p_Status.equals(STATUS_Posted)) { validatorMsg = ModelValidationEngine.get().fireDocValidate(getPO(), ModelValidator.TIMING_AFTER_POST); if (validatorMsg != null) { p_Status = STATUS_Error; p_Error = validatorMsg; } } // Create Note if (!p_Status.equals(STATUS_Posted) && !p_Status.equals(STATUS_Deferred)) { // Insert Note SimpleDateFormat dateFormat = DisplayType.getDateFormat(DisplayType.Date); DecimalFormat numberFormat = DisplayType.getNumberFormat(DisplayType.Amount); String AD_MessageValue = "PostingError-" + p_Status; int AD_User_ID = p_po.getUpdatedBy(); MNote note = new MNote (getCtx(), AD_MessageValue, AD_User_ID, getAD_Client_ID(), getAD_Org_ID(), null); note.setRecord(p_po.get_Table_ID(), p_po.get_ID()); // Reference note.setReference(toString()); // Document // Text StringBuilder Text = new StringBuilder (Msg.getMsg(Env.getCtx(), AD_MessageValue)); if (p_Error != null) Text.append(" (").append(p_Error).append(")"); String cn = getClass().getName(); Text.append(" - ").append(cn.substring(cn.lastIndexOf('.'))) .append(" (").append(getDocumentType()) .append(" - " + Msg.getElement(Env.getCtx(),"DocumentNo") + "=").append(getDocumentNo()) .append(" - " + Msg.getElement(Env.getCtx(),"DateAcct") + "=").append(dateFormat.format(getDateAcct())) .append(" - " + Msg.getMsg(Env.getCtx(),"Amount") + "=").append(numberFormat.format(getAmount())) .append(" - " + Msg.getElement(Env.getCtx(),"DocStatus") + "=").append(MRefList.getListName(getCtx(), 131, m_DocStatus)) .append(" - " + Msg.getMsg(Env.getCtx(),"PeriodOpen") + "=").append(Msg.getMsg(Env.getCtx(), String.valueOf(isPeriodOpen()))) .append(" - " + Msg.getElement(Env.getCtx(),"IsBalanced") + "=").append( Msg.getMsg(Env.getCtx(), String.valueOf(isBalanced()))) .append(" - " + Msg.getElement(Env.getCtx(),"C_AcctSchema_ID") + "=").append(m_as.getName()); note.setTextMsg(Text.toString()); try { note.saveEx(); } catch (AdempiereException e) { if (e.getMessage() != null && e.getMessage().startsWith("Foreign ID " + p_po.get_ID() + " not found in ")) { ; //ignore, in unit test } else { throw e; } } p_Error = Text.toString(); } // dispose facts for (int i = 0; i < m_fact.size(); i++) { Fact fact = m_fact.get(i); if (fact != null) fact.dispose(); } p_lines = null; if (p_Status.equals(STATUS_Posted)) return null; return p_Error; } // post /** * Delete fact records * @return number of records deleted */ protected int deleteAcct() { StringBuilder sql = new StringBuilder ("DELETE FROM Fact_Acct WHERE AD_Table_ID=") .append(get_Table_ID()) .append(" AND Record_ID=").append(p_po.get_ID()) .append(" AND C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); int no = DB.executeUpdate(sql.toString(), getTrxName()); if (no != 0) if (log.isLoggable(Level.INFO)) log.info("deleted=" + no); return no; } // deleteAcct /** * Posting logic for Accounting Schema * @return posting status/error code */ private final String postLogic () { // rejectUnbalanced if (!m_as.isSuspenseBalancing() && !isBalanced()) return STATUS_NotBalanced; // rejectUnconvertible if (!isConvertible(m_as)) return STATUS_NotConvertible; // rejectPeriodClosed if (!isPeriodOpen()) return STATUS_PeriodClosed; // createFacts ArrayList facts = createFacts (m_as); if (facts == null) return STATUS_Error; // call modelValidator String validatorMsg = ModelValidationEngine.get().fireFactsValidate(m_as, facts, getPO()); if (validatorMsg != null) { p_Error = validatorMsg; return STATUS_Error; } for (int f = 0; f < facts.size(); f++) { Fact fact = facts.get(f); if (fact == null) return STATUS_Error; m_fact.add(fact); // p_Status = STATUS_PostPrepared; // check accounts if (!fact.checkAccounts()) return STATUS_InvalidAccount; // distribute if (!fact.distribute()) return STATUS_Error; // balanceSource if (!fact.isSourceBalanced()) { fact.balanceSource(); if (!fact.isSourceBalanced()) return STATUS_NotBalanced; } // balanceSegments if (!fact.isSegmentBalanced()) { fact.balanceSegments(); if (!fact.isSegmentBalanced()) return STATUS_NotBalanced; } // balanceAccounting if (!fact.isAcctBalanced()) { fact.balanceAccounting(); if (!fact.isAcctBalanced()) return STATUS_NotBalanced; } } // for all facts return STATUS_Posted; } // postLogic /** * Post Commit.
    * Save Facts & Document * @param status status * @return Posting Status */ private final String postCommit (String status) { if (log.isLoggable(Level.INFO)) log.info("Sta=" + status + " DT=" + getDocumentType() + " ID=" + p_po.get_ID()); p_Status = status; Trx trx = Trx.get(getTrxName(), true); try { // *** Transaction Start *** // Commit Facts if (status.equals(STATUS_Posted)) { for (int i = 0; i < m_fact.size(); i++) { Fact fact = m_fact.get(i); if (fact == null) ; else if (fact.save(getTrxName())) ; else { log.log(Level.SEVERE, "(fact not saved) ... rolling back"); if (m_manageLocalTrx) { trx.rollback(); trx.close(); } unlock(); return STATUS_Error; } } } unlock(); // Success if (m_manageLocalTrx) { trx.commit(true); trx.close(); trx = null; } // *** Transaction End *** } catch (Exception e) { log.log(Level.SEVERE, "... rolling back", e); status = STATUS_Error; if (m_manageLocalTrx) { try { if (trx != null) trx.rollback(); } catch (Exception e2) {} try { if (trx != null) trx.close(); trx = null; } catch (Exception e3) {} } unlock(); } p_Status = status; return status; } // postCommit /** * Get Trx Name * @return Trx Name */ public String getTrxName() { return m_trxName; } // getTrxName /** * Unlock Document */ private void unlock() { String trxName = null; // outside trx if on server if (! m_manageLocalTrx) trxName = getTrxName(); // on trx if it's in client StringBuilder sql = new StringBuilder ("UPDATE "); sql.append(get_TableName()).append( " SET Processing='N' WHERE ") .append(get_TableName()).append("_ID=").append(p_po.get_ID()); DB.executeUpdate(sql.toString(), trxName); } // unlock /** * Load Document Type and GL Info. * Set p_DocumentType and p_GL_Category_ID * @return document type (i.e. C_DocType.DocBaseType) */ public String getDocumentType() { if (m_DocumentType == null) setDocumentType(null); return m_DocumentType; } // getDocumentType /** * Load Document Type and GL Info. * Set p_DocumentType and p_GL_Category_ID * @param DocumentType */ public void setDocumentType (String DocumentType) { if (DocumentType != null) m_DocumentType = DocumentType; // IDEMPIERE-3342 - prefer the category defined for the doctype if there is such column in the table if (p_po.get_ColumnIndex("C_DocType_ID") >= 0 && getC_DocType_ID() != 0) { String sql = "SELECT DocBaseType, GL_Category_ID FROM C_DocType WHERE C_DocType_ID=?"; PreparedStatement pstmt = null; ResultSet rsDT = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, getC_DocType_ID()); rsDT = pstmt.executeQuery(); if (rsDT.next()) { m_DocumentType = rsDT.getString(1); m_GL_Category_ID = rsDT.getInt(2); } } catch (SQLException e) { log.log(Level.SEVERE, sql, e); } finally { DB.close(rsDT, pstmt); rsDT = null; pstmt = null; } } if (m_DocumentType == null) { log.log(Level.SEVERE, "No DocBaseType for C_DocType_ID=" + getC_DocType_ID() + ", DocumentNo=" + getDocumentNo()); } // We have a document Type, but no GL info - search for DocType if (m_GL_Category_ID == 0) { String sql = "SELECT GL_Category_ID FROM C_DocType " + "WHERE AD_Client_ID=? AND DocBaseType=?"; PreparedStatement pstmt = null; ResultSet rsDT = null; try { pstmt = DB.prepareStatement(sql.toString(), null); pstmt.setInt(1, getAD_Client_ID()); pstmt.setString(2, m_DocumentType); rsDT = pstmt.executeQuery(); if (rsDT.next()) m_GL_Category_ID = rsDT.getInt(1); } catch (SQLException e) { log.log(Level.SEVERE, sql, e); } finally { DB.close(rsDT, pstmt); rsDT = null; pstmt = null; } } // Still no GL_Category - get Default GL Category if (m_GL_Category_ID == 0) { String sql = "SELECT GL_Category_ID FROM GL_Category " + "WHERE AD_Client_ID=? " + "ORDER BY IsDefault DESC"; PreparedStatement pstmt = null; ResultSet rsDT = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, getAD_Client_ID()); rsDT = pstmt.executeQuery(); if (rsDT.next()) m_GL_Category_ID = rsDT.getInt(1); } catch (SQLException e) { log.log(Level.SEVERE, sql, e); } finally { DB.close(rsDT, pstmt); rsDT = null; pstmt = null; } } // if (m_GL_Category_ID == 0) log.log(Level.SEVERE, "No default GL_Category - " + toString()); if (m_DocumentType == null) throw new IllegalStateException("Document Type not found"); } // setDocumentType /** * Is the Source Document Balanced * @return true if (source) balanced */ public boolean isBalanced() { // Multi-Currency documents are source balanced by definition if (isMultiCurrency()) return true; // boolean retValue = getBalance().signum() == 0; if (retValue) { if (log.isLoggable(Level.FINE)) log.fine("Yes " + toString()); } else { log.warning("NO - " + toString()); } return retValue; } // isBalanced /** * Is Document convertible to currency and Conversion Type * @param acctSchema accounting schema * @return true, if convertible to accounting currency */ public boolean isConvertible (MAcctSchema acctSchema) { // No Currency in document if (getC_Currency_ID() == NO_CURRENCY) { if (log.isLoggable(Level.FINE)) log.fine("(none) - " + toString()); return true; } // Journal from a different acct schema if (this instanceof Doc_GLJournal) { int glj_as = ((Integer) p_po.get_Value("C_AcctSchema_ID")).intValue(); if (acctSchema.getC_AcctSchema_ID() != glj_as) return true; } // Get All Currencies HashSet set = new HashSet(); set.add(Integer.valueOf(getC_Currency_ID())); for (int i = 0; p_lines != null && i < p_lines.length; i++) { int C_Currency_ID = p_lines[i].getC_Currency_ID(); if (C_Currency_ID != NO_CURRENCY) set.add(Integer.valueOf(C_Currency_ID)); } // just one and the same if (set.size() == 1 && acctSchema.getC_Currency_ID() == getC_Currency_ID()) { if (log.isLoggable(Level.FINE)) log.fine("(same) Cur=" + getC_Currency_ID() + " - " + toString()); return true; } boolean convertible = true; Iterator it = set.iterator(); while (it.hasNext() && convertible) { int C_Currency_ID = it.next().intValue(); if (C_Currency_ID != acctSchema.getC_Currency_ID()) { BigDecimal amt = MConversionRate.getRate (C_Currency_ID, acctSchema.getC_Currency_ID(), getDateAcct(), getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID()); if (amt == null) { convertible = false; log.warning ("NOT from C_Currency_ID=" + C_Currency_ID + " to " + acctSchema.getC_Currency_ID() + " - " + toString()); } else if (log.isLoggable(Level.FINE)) log.fine("From C_Currency_ID=" + C_Currency_ID); } } if (log.isLoggable(Level.FINE)) log.fine("Convertible=" + convertible + ", AcctSchema C_Currency_ID=" + acctSchema.getC_Currency_ID() + " - " + toString()); return convertible; } // isConvertible /** * Calculate Period from DateAcct. * m_C_Period_ID is set to -1 if not open, to 0 if not found */ public void setPeriod() { if (m_period != null) return; // Period defined in GL Journal (e.g. adjustment period) int index = p_po.get_ColumnIndex("C_Period_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_period = MPeriod.get(getCtx(), ii.intValue()); } if (m_period == null) m_period = MPeriod.get(getCtx(), getDateAcct(), getAD_Org_ID(), (String)null); // Is Period Open? if (m_period != null && m_period.isOpen(getDocumentType(), getDateAcct(), true)) m_C_Period_ID = m_period.getC_Period_ID(); else m_C_Period_ID = -1; // if (log.isLoggable(Level.FINE)) log.fine( // + AD_Client_ID + " - " getDateAcct() + " - " + getDocumentType() + " => " + m_C_Period_ID); } // setC_Period_ID /** * Get C_Period_ID * @return C_Period_ID */ public int getC_Period_ID() { if (m_period == null) setPeriod(); return m_C_Period_ID; } // getC_Period_ID /** * Is Period Open * @return true if period is open */ public boolean isPeriodOpen() { setPeriod(); boolean open = m_C_Period_ID > 0; if (open) { if (log.isLoggable(Level.FINE)) log.fine("Yes - " + toString()); } else { log.warning("NO - " + toString()); } return open; } // isPeriodOpen /*************************************************************************/ /** Amount Type - Invoice - Gross */ public static final int AMTTYPE_Gross = 0; /** Amount Type - Invoice - Net */ public static final int AMTTYPE_Net = 1; /** Amount Type - Invoice - Charge */ public static final int AMTTYPE_Charge = 2; /** Source Amounts (may not all be used) */ private BigDecimal[] m_Amounts = new BigDecimal[4]; /** Quantity */ private BigDecimal m_qty = null; /** * Get the Amount * (loaded in loadDocumentDetails) * * @param AmtType see AMTTYPE_* * @return Amount */ public BigDecimal getAmount(int AmtType) { if (AmtType < 0 || AmtType >= m_Amounts.length) return null; return m_Amounts[AmtType]; } // getAmount /** * Set the Amount * @param AmtType see AMTTYPE_* * @param amt Amount */ public void setAmount(int AmtType, BigDecimal amt) { if (AmtType < 0 || AmtType >= m_Amounts.length) return; if (amt == null) m_Amounts[AmtType] = Env.ZERO; else m_Amounts[AmtType] = amt; } // setAmount /** * Get Amount with index 0 * @return Amount (primary document amount) */ public BigDecimal getAmount() { return m_Amounts[0]; } // getAmount /** * Set Quantity * @param qty Quantity */ public void setQty (BigDecimal qty) { m_qty = qty; } // setQty /** * Get Quantity * @return Quantity */ public BigDecimal getQty() { if (m_qty == null) { int index = p_po.get_ColumnIndex("Qty"); if (index != -1) m_qty = (BigDecimal)p_po.get_Value(index); else m_qty = Env.ZERO; } return m_qty; } // getQty /*************************************************************************/ /** Account Type - Invoice - Charge */ public static final int ACCTTYPE_Charge = 0; /** Account Type - Invoice - AR */ public static final int ACCTTYPE_C_Receivable = 1; /** Account Type - Invoice - AP */ public static final int ACCTTYPE_V_Liability = 2; /** Account Type - Invoice - AP Service */ public static final int ACCTTYPE_V_Liability_Services = 3; // Deprecated IDEMPIERE-362 /** Account Type - Invoice - AR Service */ public static final int ACCTTYPE_C_Receivable_Services = 4; // Deprecated IDEMPIERE-362 /** Account Type - Payment - Unallocated */ public static final int ACCTTYPE_UnallocatedCash = 10; /** Account Type - Payment - Transfer */ public static final int ACCTTYPE_BankInTransit = 11; /** Account Type - Payment - Selection */ public static final int ACCTTYPE_PaymentSelect = 12; /** Account Type - Payment - Prepayment */ public static final int ACCTTYPE_C_Prepayment = 13; /** Account Type - Payment - Prepayment */ public static final int ACCTTYPE_V_Prepayment = 14; /** Account Type - Cash - Asset */ public static final int ACCTTYPE_CashAsset = 20; /** Account Type - Cash - Transfer */ public static final int ACCTTYPE_CashTransfer = 21; /** Account Type - Cash - Expense */ public static final int ACCTTYPE_CashExpense = 22; /** Account Type - Cash - Receipt */ public static final int ACCTTYPE_CashReceipt = 23; /** Account Type - Cash - Difference */ public static final int ACCTTYPE_CashDifference = 24; /** Account Type - Allocation - Discount Expense (AR) */ public static final int ACCTTYPE_DiscountExp = 30; /** Account Type - Allocation - Discount Revenue (AP) */ public static final int ACCTTYPE_DiscountRev = 31; /** Account Type - Allocation - Write Off */ public static final int ACCTTYPE_WriteOff = 32; /** Account Type - Bank Statement - Asset */ public static final int ACCTTYPE_BankAsset = 40; /** Account Type - Bank Statement - Interest Revenue */ public static final int ACCTTYPE_InterestRev = 41; /** Account Type - Bank Statement - Interest Exp */ public static final int ACCTTYPE_InterestExp = 42; /** Inventory Accounts - Differences */ public static final int ACCTTYPE_InvDifferences = 50; /** Inventory Accounts - NIR */ public static final int ACCTTYPE_NotInvoicedReceipts = 51; /** Project Accounts - Assets */ public static final int ACCTTYPE_ProjectAsset = 61; /** Project Accounts - WIP */ public static final int ACCTTYPE_ProjectWIP = 62; /** GL Accounts - PPV Offset */ public static final int ACCTTYPE_PPVOffset = 101; /** GL Accounts - Commitment Offset */ public static final int ACCTTYPE_CommitmentOffset = 111; /** GL Accounts - Commitment Offset Sales */ public static final int ACCTTYPE_CommitmentOffsetSales = 112; /** * Get valid combination id by account type and accounting schema * @param AcctType see ACCTTYPE_* * @param as accounting schema * @return C_ValidCombination_ID */ public int getValidCombination_ID (int AcctType, MAcctSchema as) { int para_1 = 0; // first parameter (second is always AcctSchema) String sql = null; /** Account Type - Invoice */ if (AcctType == ACCTTYPE_Charge) // see getChargeAccount in DocLine { int cmp = getAmount(AMTTYPE_Charge).compareTo(Env.ZERO); if (cmp == 0) return 0; else sql = "SELECT CH_Expense_Acct FROM C_Charge_Acct WHERE C_Charge_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_Charge_ID(); } else if (AcctType == ACCTTYPE_V_Liability) { sql = "SELECT V_Liability_Acct FROM C_BP_Vendor_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_V_Liability_Services) // Deprecated IDEMPIERE-362 { sql = "SELECT V_Liability_Services_Acct FROM C_BP_Vendor_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_C_Receivable) { sql = "SELECT C_Receivable_Acct FROM C_BP_Customer_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_C_Receivable_Services) // Deprecated IDEMPIERE-362 { sql = "SELECT C_Receivable_Services_Acct FROM C_BP_Customer_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_V_Prepayment) { sql = "SELECT V_Prepayment_Acct FROM C_BP_Vendor_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_C_Prepayment) { sql = "SELECT C_Prepayment_Acct FROM C_BP_Customer_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } /** Account Type - Payment */ else if (AcctType == ACCTTYPE_UnallocatedCash) { sql = "SELECT B_UnallocatedCash_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } else if (AcctType == ACCTTYPE_BankInTransit) { sql = "SELECT B_InTransit_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } else if (AcctType == ACCTTYPE_PaymentSelect) { sql = "SELECT B_PaymentSelect_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } /** Account Type - Allocation */ else if (AcctType == ACCTTYPE_DiscountExp) { sql = "SELECT a.PayDiscount_Exp_Acct FROM C_BP_Group_Acct a, C_BPartner bp " + "WHERE a.C_BP_Group_ID=bp.C_BP_Group_ID AND bp.C_BPartner_ID=? AND a.C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_DiscountRev) { sql = "SELECT PayDiscount_Rev_Acct FROM C_BP_Group_Acct a, C_BPartner bp " + "WHERE a.C_BP_Group_ID=bp.C_BP_Group_ID AND bp.C_BPartner_ID=? AND a.C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } else if (AcctType == ACCTTYPE_WriteOff) { sql = "SELECT WriteOff_Acct FROM C_BP_Group_Acct a, C_BPartner bp " + "WHERE a.C_BP_Group_ID=bp.C_BP_Group_ID AND bp.C_BPartner_ID=? AND a.C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } /** Account Type - Bank Statement */ else if (AcctType == ACCTTYPE_BankAsset) { sql = "SELECT B_Asset_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } else if (AcctType == ACCTTYPE_InterestRev) { sql = "SELECT B_InterestRev_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } else if (AcctType == ACCTTYPE_InterestExp) { sql = "SELECT B_InterestExp_Acct FROM C_BankAccount_Acct WHERE C_BankAccount_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_BankAccount_ID(); } /** Account Type - Cash */ else if (AcctType == ACCTTYPE_CashAsset) { sql = "SELECT CB_Asset_Acct FROM C_CashBook_Acct WHERE C_CashBook_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_CashBook_ID(); } else if (AcctType == ACCTTYPE_CashTransfer) { sql = "SELECT CB_CashTransfer_Acct FROM C_CashBook_Acct WHERE C_CashBook_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_CashBook_ID(); } else if (AcctType == ACCTTYPE_CashExpense) { sql = "SELECT CB_Expense_Acct FROM C_CashBook_Acct WHERE C_CashBook_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_CashBook_ID(); } else if (AcctType == ACCTTYPE_CashReceipt) { sql = "SELECT CB_Receipt_Acct FROM C_CashBook_Acct WHERE C_CashBook_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_CashBook_ID(); } else if (AcctType == ACCTTYPE_CashDifference) { sql = "SELECT CB_Differences_Acct FROM C_CashBook_Acct WHERE C_CashBook_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_CashBook_ID(); } /** Inventory Accounts */ else if (AcctType == ACCTTYPE_InvDifferences) { sql = "SELECT W_Differences_Acct FROM M_Warehouse_Acct WHERE M_Warehouse_ID=? AND C_AcctSchema_ID=?"; // "SELECT W_Inventory_Acct, W_Revaluation_Acct, W_InvActualAdjust_Acct FROM M_Warehouse_Acct WHERE M_Warehouse_ID=? AND C_AcctSchema_ID=?"; para_1 = getM_Warehouse_ID(); } else if (AcctType == ACCTTYPE_NotInvoicedReceipts) { sql = "SELECT NotInvoicedReceipts_Acct FROM C_BP_Group_Acct a, C_BPartner bp " + "WHERE a.C_BP_Group_ID=bp.C_BP_Group_ID AND bp.C_BPartner_ID=? AND a.C_AcctSchema_ID=?"; para_1 = getC_BPartner_ID(); } /** Project Accounts */ else if (AcctType == ACCTTYPE_ProjectAsset) { sql = "SELECT PJ_Asset_Acct FROM C_Project_Acct WHERE C_Project_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_Project_ID(); } else if (AcctType == ACCTTYPE_ProjectWIP) { sql = "SELECT PJ_WIP_Acct FROM C_Project_Acct WHERE C_Project_ID=? AND C_AcctSchema_ID=?"; para_1 = getC_Project_ID(); } /** GL Accounts */ else if (AcctType == ACCTTYPE_PPVOffset) { sql = "SELECT PPVOffset_Acct FROM C_AcctSchema_GL WHERE C_AcctSchema_ID=?"; para_1 = -1; } else if (AcctType == ACCTTYPE_CommitmentOffset) { sql = "SELECT CommitmentOffset_Acct FROM C_AcctSchema_GL WHERE C_AcctSchema_ID=?"; para_1 = -1; } else if (AcctType == ACCTTYPE_CommitmentOffsetSales) { sql = "SELECT CommitmentOffsetSales_Acct FROM C_AcctSchema_GL WHERE C_AcctSchema_ID=?"; para_1 = -1; } else { log.warning("Not found AcctType=" + AcctType); return 0; } // Do we have sql & Parameter if (sql == null || para_1 == 0) { log.warning("No Parameter for AcctType=" + AcctType + " - SQL=" + sql); return 0; } // Get Acct int Account_ID = 0; PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, getTrxName()); if (para_1 == -1) // GL Accounts pstmt.setInt (1, as.getC_AcctSchema_ID()); else { pstmt.setInt (1, para_1); pstmt.setInt (2, as.getC_AcctSchema_ID()); } rs = pstmt.executeQuery(); if (rs.next()) Account_ID = rs.getInt(1); } catch (SQLException e) { log.log(Level.SEVERE, "AcctType=" + AcctType + " - SQL=" + sql, e); return 0; } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // No account if (Account_ID == 0) { log.warning("NO account Type=" + AcctType + ", Record=" + p_po.get_ID()); return 0; } return Account_ID; } // getAccount_ID /** * Get account record by accounting schema and account type * @param AcctType see ACCTTYPE_* * @param as accounting schema * @return MAccount */ public final MAccount getAccount (int AcctType, MAcctSchema as) { int C_ValidCombination_ID = getValidCombination_ID(AcctType, as); if (C_ValidCombination_ID == 0) return null; // Return Account MAccount acct = MAccount.get (as.getCtx(), C_ValidCombination_ID); return acct; } // getAccount /** * Get DocLine with ID * @param Record_ID Record ID * @return DocLine */ public DocLine getDocLine (int Record_ID) { if (p_lines == null || p_lines.length == 0 || Record_ID == 0) return null; for (int i = 0; i < p_lines.length; i++) { if (p_lines[i].get_ID() == Record_ID) return p_lines[i]; } return null; } // getDocLine /** * String Representation * @return String */ public String toString() { return p_po.toString(); } // toString /** * Get AD_Client_ID * @return AD_Client_ID */ public int getAD_Client_ID() { return p_po.getAD_Client_ID(); } // getAD_Client_ID /** * Get AD_Org_ID * @return AD_Org_ID */ public int getAD_Org_ID() { return p_po.getAD_Org_ID(); } // getAD_Org_ID /** * Get Document No * @return document No */ public String getDocumentNo() { if (m_DocumentNo != null) return m_DocumentNo; int index = p_po.get_ColumnIndex("DocumentNo"); if (index == -1) index = p_po.get_ColumnIndex("Name"); if (index == -1) throw new UnsupportedOperationException("No DocumentNo"); m_DocumentNo = (String)p_po.get_Value(index); return m_DocumentNo; } // getDocumentNo /** * Get Description * @return Description */ public String getDescription() { if (m_Description == null) { int index = p_po.get_ColumnIndex("Description"); if (index != -1) m_Description = (String)p_po.get_Value(index); else m_Description = ""; } return m_Description; } // getDescription /** * Get C_Currency_ID * @return C_Currency_ID */ public int getC_Currency_ID() { if (m_C_Currency_ID == -1) { int index = p_po.get_ColumnIndex("C_Currency_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_C_Currency_ID = ii.intValue(); } if (m_C_Currency_ID == -1) m_C_Currency_ID = NO_CURRENCY; } return m_C_Currency_ID; } // getC_Currency_ID /** * Set C_Currency_ID * @param C_Currency_ID id */ public void setC_Currency_ID (int C_Currency_ID) { m_C_Currency_ID = C_Currency_ID; } // setC_Currency_ID /** * Is Multi Currency * @return mc */ public boolean isMultiCurrency() { return m_MultiCurrency; } // isMultiCurrency /** * Set Multi Currency * @param mc multi currency */ public void setIsMultiCurrency (boolean mc) { m_MultiCurrency = mc; } // setIsMultiCurrency /** * Is Tax Included * @return tax incl */ public boolean isTaxIncluded() { return m_TaxIncluded; } // isTaxIncluded /** * Set Tax Included * @param ti Tax Included */ public void setIsTaxIncluded (boolean ti) { m_TaxIncluded = ti; } // setIsTaxIncluded /** * Get C_ConversionType_ID * @return C_ConversionType_ID */ public int getC_ConversionType_ID() { int index = p_po.get_ColumnIndex("C_ConversionType_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_ConversionType_ID /** * @return currency rate or null */ public BigDecimal getCurrencyRate() { return null; } /** * Get GL_Category_ID * @return GL_Category_ID */ public int getGL_Category_ID() { int index = p_po.get_ColumnIndex("GL_Category_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return m_GL_Category_ID; } // getGL_Category_ID /** * Get getGL_Budget_ID * @return GL_Budget_ID or 0 */ public int getGL_Budget_ID() { int index = p_po.get_ColumnIndex("GL_Budget_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getGL_Budget_ID /** * Get Accounting Date * @return DateAcct or null */ public Timestamp getDateAcct() { if (m_DateAcct != null) return m_DateAcct; int index = p_po.get_ColumnIndex("DateAcct"); if (index != -1) { m_DateAcct = (Timestamp)p_po.get_Value(index); if (m_DateAcct != null) return m_DateAcct; } throw new IllegalStateException("No DateAcct"); } // getDateAcct /** * Set Date Acct * @param da accounting date */ public void setDateAcct (Timestamp da) { m_DateAcct = da; } // setDateAcct /** * Get Document Date * @return document date */ public Timestamp getDateDoc() { if (m_DateDoc != null) return m_DateDoc; int index = p_po.get_ColumnIndex("DateDoc"); if (index == -1) index = p_po.get_ColumnIndex("MovementDate"); if (index != -1) { m_DateDoc = (Timestamp)p_po.get_Value(index); if (m_DateDoc != null) return m_DateDoc; } throw new IllegalStateException("No DateDoc"); } // getDateDoc /** * Set Date Doc * @param dd document date */ public void setDateDoc (Timestamp dd) { m_DateDoc = dd; } // setDateDoc /** * Is Document Posted * @return true if posted */ public boolean isPosted() { int index = p_po.get_ColumnIndex("Posted"); if (index != -1) { Object posted = p_po.get_Value(index); if (posted instanceof Boolean) return ((Boolean)posted).booleanValue(); if (posted instanceof String) return "Y".equals(posted); } throw new IllegalStateException("No Posted"); } // isPosted /** * Is Sales Trx * @return true if it is sales trx */ public boolean isSOTrx() { int index = p_po.get_ColumnIndex("IsSOTrx"); if (index == -1) index = p_po.get_ColumnIndex("IsReceipt"); if (index != -1) { Object posted = p_po.get_Value(index); if (posted instanceof Boolean) return ((Boolean)posted).booleanValue(); if (posted instanceof String) return "Y".equals(posted); } return false; } // isSOTrx /** * Get C_DocType_ID * @return C_DocType_ID or 0 */ public int getC_DocType_ID() { int index = p_po.get_ColumnIndex("C_DocType_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); // DocType does not exist - get DocTypeTarget if (ii != null && ii.intValue() == 0) { index = p_po.get_ColumnIndex("C_DocTypeTarget_ID"); if (index != -1) ii = (Integer)p_po.get_Value(index); } if (ii != null) return ii.intValue(); } else { if (p_po.get_TableName().equals(I_M_MatchPO.Table_Name)) { int docTypeId = DB.getSQLValue((String)null, DOC_TYPE_BY_DOC_BASE_TYPE_SQL, p_po.getAD_Client_ID(), Doc.DOCTYPE_MatMatchPO); if (docTypeId > 0) return docTypeId; } else if (p_po.get_TableName().equals(I_M_MatchInv.Table_Name)) { int docTypeId = DB.getSQLValue((String)null, DOC_TYPE_BY_DOC_BASE_TYPE_SQL, p_po.getAD_Client_ID(), Doc.DOCTYPE_MatMatchInv); if (docTypeId > 0) return docTypeId; } else if (p_po.get_TableName().equals(I_C_AllocationHdr.Table_Name)) { int docTypeId = DB.getSQLValue((String)null, DOC_TYPE_BY_DOC_BASE_TYPE_SQL, p_po.getAD_Client_ID(), Doc.DOCTYPE_Allocation); if (docTypeId > 0) return docTypeId; } else if (p_po.get_TableName().equals(I_C_Cash.Table_Name)) { int docTypeId = DB.getSQLValue((String)null, DOC_TYPE_BY_DOC_BASE_TYPE_SQL, p_po.getAD_Client_ID(), Doc.DOCTYPE_CashJournal); if (docTypeId > 0) return docTypeId; } else if (p_po.get_TableName().equals(I_C_ProjectIssue.Table_Name)) { int docTypeId = DB.getSQLValue((String)null, DOC_TYPE_BY_DOC_BASE_TYPE_SQL, p_po.getAD_Client_ID(), Doc.DOCTYPE_ProjectIssue); if (docTypeId > 0) return docTypeId; } } return 0; } // getC_DocType_ID /** * Get header level C_Charge_ID * @return C_Charge_ID or 0 */ public int getC_Charge_ID() { int index = p_po.get_ColumnIndex("C_Charge_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_Charge_ID /** * Get SalesRep_ID * @return SalesRep_ID or 0 */ public int getSalesRep_ID() { int index = p_po.get_ColumnIndex("SalesRep_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getSalesRep_ID /** * Get C_BankAccount_ID * @return C_BankAccount_ID or 0 */ public int getC_BankAccount_ID() { if (m_C_BankAccount_ID == -1) { int index = p_po.get_ColumnIndex("C_BankAccount_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_C_BankAccount_ID = ii.intValue(); } if (m_C_BankAccount_ID == -1) m_C_BankAccount_ID = 0; } return m_C_BankAccount_ID; } // getC_BankAccount_ID /** * Set C_BankAccount_ID * @param C_BankAccount_ID bank acct */ public void setC_BankAccount_ID (int C_BankAccount_ID) { m_C_BankAccount_ID = C_BankAccount_ID; } // setC_BankAccount_ID /** * Get C_CashBook_ID * @return C_CashBook_ID or 0 */ public int getC_CashBook_ID() { if (m_C_CashBook_ID == -1) { int index = p_po.get_ColumnIndex("C_CashBook_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_C_CashBook_ID = ii.intValue(); } if (m_C_CashBook_ID == -1) m_C_CashBook_ID = 0; } return m_C_CashBook_ID; } // getC_CashBook_ID /** * Set C_CashBook_ID * @param C_CashBook_ID cash book */ public void setC_CashBook_ID (int C_CashBook_ID) { m_C_CashBook_ID = C_CashBook_ID; } // setC_CashBook_ID /** * Get M_Warehouse_ID * @return M_Warehouse_ID or 0 */ public int getM_Warehouse_ID() { int index = p_po.get_ColumnIndex("M_Warehouse_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getM_Warehouse_ID /** * Get C_BPartner_ID * @return C_BPartner_ID or 0 */ public int getC_BPartner_ID() { if (m_C_BPartner_ID == -1) { int index = p_po.get_ColumnIndex("C_BPartner_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_C_BPartner_ID = ii.intValue(); } if (m_C_BPartner_ID == -1) m_C_BPartner_ID = 0; } return m_C_BPartner_ID; } // getC_BPartner_ID /** * Set C_BPartner_ID * @param C_BPartner_ID bp */ public void setC_BPartner_ID (int C_BPartner_ID) { m_C_BPartner_ID = C_BPartner_ID; } // setC_BPartner_ID /** * Get C_BPartner_Location_ID * @return C_BPartner_Location_ID or 0 */ public int getC_BPartner_Location_ID() { int index = p_po.get_ColumnIndex("C_BPartner_Location_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_BPartner_Location_ID /** * Get C_Project_ID * @return C_Project_ID or 0 */ public int getC_Project_ID() { int index = p_po.get_ColumnIndex("C_Project_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_Project_ID /** * Get C_ProjectPhase_ID * @return C_ProjectPhase_ID or 0 */ public int getC_ProjectPhase_ID() { int index = p_po.get_ColumnIndex("C_ProjectPhase_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_ProjectPhase_ID /** * Get C_ProjectTask_ID * @return C_ProjectTask_ID or 0 */ public int getC_ProjectTask_ID() { int index = p_po.get_ColumnIndex("C_ProjectTask_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_ProjectTask_ID /** * Get C_SalesRegion_ID * @return C_SalesRegion_ID or 0 */ public int getC_SalesRegion_ID() { int index = p_po.get_ColumnIndex("C_SalesRegion_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_SalesRegion_ID /** * Get C_SalesRegion_ID * @return C_SalesRegion_ID or 0 */ public int getBP_C_SalesRegion_ID() { if (m_BP_C_SalesRegion_ID == -1) { int index = p_po.get_ColumnIndex("C_SalesRegion_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) m_BP_C_SalesRegion_ID = ii.intValue(); } if (m_BP_C_SalesRegion_ID == -1) m_BP_C_SalesRegion_ID = 0; } return m_BP_C_SalesRegion_ID; } // getBP_C_SalesRegion_ID /** * Set C_SalesRegion_ID * @param C_SalesRegion_ID id */ public void setBP_C_SalesRegion_ID (int C_SalesRegion_ID) { m_BP_C_SalesRegion_ID = C_SalesRegion_ID; } // setBP_C_SalesRegion_ID /** * Get C_Activity_ID * @return C_Activity_ID or 0 */ public int getC_Activity_ID() { int index = p_po.get_ColumnIndex("C_Activity_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_Activity_ID /** * Get C_Campaign_ID * @return C_Campaign_ID or 0 */ public int getC_Campaign_ID() { int index = p_po.get_ColumnIndex("C_Campaign_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getC_Campaign_ID /** * Get M_Product_ID * @return M_Product_ID or 0 */ public int getM_Product_ID() { int index = p_po.get_ColumnIndex("M_Product_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getM_Product_ID /** * Get AD_OrgTrx_ID * @return AD_OrgTrx_ID or 0 */ public int getAD_OrgTrx_ID() { int index = p_po.get_ColumnIndex("AD_OrgTrx_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getAD_OrgTrx_ID /** * Get C_LocFrom_ID * @return from C_Location_ID or 0 */ public int getC_LocFrom_ID() { return m_C_LocFrom_ID; } // getC_LocFrom_ID /** * Set C_LocFrom_ID * @param C_LocFrom_ID loc from */ public void setC_LocFrom_ID(int C_LocFrom_ID) { m_C_LocFrom_ID = C_LocFrom_ID; } // setC_LocFrom_ID /** * Get C_LocTo_ID * @return to C_Location_ID or 0 */ public int getC_LocTo_ID() { return m_C_LocTo_ID; } // getC_LocTo_ID /** * Set C_LocTo_ID * @param C_LocTo_ID loc to */ public void setC_LocTo_ID(int C_LocTo_ID) { m_C_LocTo_ID = C_LocTo_ID; } // setC_LocTo_ID /** * Get User1_ID * @return User1_ID or 0 */ public int getUser1_ID() { int index = p_po.get_ColumnIndex("User1_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getUser1_ID /** * Get User2_ID * @return User2_ID or 0 */ public int getUser2_ID() { int index = p_po.get_ColumnIndex("User2_ID"); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getUser2_ID /** * Get value by column name * @param ColumnName * @return column value or 0 (if column doesn't exists) */ public int getValue (String ColumnName) { int index = p_po.get_ColumnIndex(ColumnName); if (index != -1) { Integer ii = (Integer)p_po.get_Value(index); if (ii != null) return ii.intValue(); } return 0; } // getValue /*************************************************************************/ // To be overwritten by Subclasses /** * Load Document Details * @return error message or null */ protected abstract String loadDocumentDetails (); /** * Get Source Currency Balance - subtracts line (and tax) amounts from total - no rounding * @return positive amount, if total header is bigger than lines */ public abstract BigDecimal getBalance(); /** * Create Facts (the accounting logic) * @param as accounting schema * @return Facts */ public abstract ArrayList createFacts (MAcctSchema as); /** * Get Facts (the accounting logic) * @return Facts */ public ArrayList getFacts() { return m_fact; } /** * @return MAcctSchema */ protected MAcctSchema getAcctSchema() { return m_as; } /** * @return true if posting of document should be deferred to next run of accounting posting */ public boolean isDeferPosting() { return false; } } // Doc