Title: | + + + |
---|---|
Author: | + + + |
Company: | + + + |
Description: | + + + |
+ * Table Base Document Types (C_DocType.DocBaseType & 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 + * + * 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 + * @version $Id: Doc.java,v 1.6 2006/07/30 00:53:33 jjanke Exp $ + */ +public abstract class Doc +{ + /** AD_Table_ID's of documents */ + public static int[] documentsTableID = new int[] { + MInvoice.Table_ID, // C_Invoice + MAllocationHdr.Table_ID, // C_Allocation + MCash.Table_ID, // C_Cash + MBankStatement.Table_ID, // C_BankStatement + MOrder.Table_ID, // C_Order + MPayment.Table_ID, // C_Payment + MInOut.Table_ID, // M_InOut + MInventory.Table_ID, // M_Inventory + MMovement.Table_ID, // M_Movement + X_M_Production.Table_ID, // M_Production + MJournal.Table_ID, // GL_Journal + MMatchInv.Table_ID, // M_MatchInv + MMatchPO.Table_ID, // M_MatchPO + MProjectIssue.Table_ID, // C_ProjectIssue + MRequisition.Table_ID // M_Requisition + }; + + /** Table Names of documents */ + public static String[] documentsTableName = new String[] { + MInvoice.Table_Name, // C_Invoice + MAllocationHdr.Table_Name, // C_Allocation + MCash.Table_Name, // C_Cash + MBankStatement.Table_Name, // C_BankStatement + MOrder.Table_Name, // C_Order + MPayment.Table_Name, // C_Payment + MInOut.Table_Name, // M_InOut + MInventory.Table_Name, // M_Inventory + MMovement.Table_Name, // M_Movement + X_M_Production.Table_Name, // M_Production + MJournal.Table_Name, // GL_Journal + MMatchInv.Table_Name, // M_MatchInv + MMatchPO.Table_Name, // M_MatchPO + MProjectIssue.Table_Name, // C_ProjectIssue + MRequisition.Table_Name // M_Requisition + }; + + /************************************************************************** + * Document Types + * -------------- + * C_DocType.DocBaseType & 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 + **************************************************************************/ + + /** 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"; + + + /** + * Create Posting document + * @param ass accounting schema + * @param AD_Table_ID Table ID of Documents + * @param Record_ID record ID to load + * @param trxName transaction name + * @return Document or null + */ + public static Doc get (MAcctSchema[] ass, int AD_Table_ID, int Record_ID, String trxName) + { + String TableName = null; + for (int i = 0; i < documentsTableID.length; i++) + { + if (documentsTableID[i] == AD_Table_ID) + { + TableName = documentsTableName[i]; + break; + } + } + if (TableName == null) + { + s_log.severe("Not found AD_Table_ID=" + AD_Table_ID); + return null; + } + // + Doc doc = null; + StringBuffer sql = new StringBuffer("SELECT * FROM ") + .append(TableName) + .append(" WHERE ").append(TableName).append("_ID=? AND Processed='Y'"); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), trxName); + pstmt.setInt (1, Record_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + doc = get (ass, AD_Table_ID, rs, trxName); + } + else + s_log.severe("Not Found: " + TableName + "_ID=" + Record_ID); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return doc; + } // get + + /** + * Create Posting document + * @param ass accounting schema + * @param AD_Table_ID Table ID of Documents + * @param rs ResultSet + * @param trxName transaction name + * @return Document + */ + public static Doc get (MAcctSchema[] ass, int AD_Table_ID, ResultSet rs, String trxName) + { + Doc doc = null; + switch (AD_Table_ID) + { + case MInvoice.Table_ID: + doc = new Doc_Invoice (ass, rs, trxName); + break; + case MAllocationHdr.Table_ID: + doc = new Doc_Allocation (ass, rs, trxName); + break; + case MCash.Table_ID: + doc = new Doc_Cash (ass, rs, trxName); + break; + case MBankStatement.Table_ID: + doc = new Doc_Bank (ass, rs, trxName); + break; + case MOrder.Table_ID: + doc = new Doc_Order (ass, rs, trxName); + break; + case MPayment.Table_ID: + doc = new Doc_Payment (ass, rs, trxName); + break; + case MInOut.Table_ID: + doc = new Doc_InOut (ass, rs, trxName); + break; + case MInventory.Table_ID: + doc = new Doc_Inventory (ass, rs, trxName); + break; + case MMovement.Table_ID: + doc = new Doc_Movement (ass, rs, trxName); + break; + case X_M_Production.Table_ID: + doc = new Doc_Production (ass, rs, trxName); + break; + case MJournal.Table_ID: + doc = new Doc_GLJournal (ass, rs, trxName); + break; + case MMatchInv.Table_ID: + doc = new Doc_MatchInv (ass, rs, trxName); + break; + case MMatchPO.Table_ID: + doc = new Doc_MatchPO (ass, rs, trxName); + break; + case MProjectIssue.Table_ID: + doc = new Doc_ProjectIssue (ass, rs, trxName); + break; + case MRequisition.Table_ID: + doc = new Doc_Requisition (ass, rs, trxName); + break; + } + if (doc == null) + s_log.log(Level.SEVERE, "Unknown AD_Table_ID=" + AD_Table_ID); + return doc; + } // get + + /** + * Post Document + * @param ass accounting schemata + * @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) + { + Doc doc = get (ass, AD_Table_ID, Record_ID, trxName); + if (doc != null) + return doc.post (force, true); // repost + return "NoDoc"; + } // post + + /** Static Log */ + protected static CLogger s_log = CLogger.getCLogger(Doc.class); + /** Log per Document */ + protected CLogger log = CLogger.getCLogger(getClass()); + + + /************************************************************************** + * Constructor + * @param ass accounting schemata + * @param clazz Document Class + * @param rs result set + * @param defaultDocumentType default document type or null + * @param trxName trx + */ + Doc (MAcctSchema[] ass, Class clazz, ResultSet rs, String defaultDocumentType, String trxName) + { + p_Status = STATUS_Error; + m_ass = ass; + m_ctx = new Properties(m_ass[0].getCtx()); + m_ctx.setProperty("#AD_Client_ID", String.valueOf(m_ass[0].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); + } + + // 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; + if (m_trxName == null) + m_trxName = "Post" + m_DocumentType + p_po.get_ID(); + p_po.set_TrxName(m_trxName); + + // Amounts + m_Amounts[0] = Env.ZERO; + m_Amounts[1] = Env.ZERO; + m_Amounts[2] = Env.ZERO; + m_Amounts[3] = Env.ZERO; + } // Doc + + /** Accounting Schema Array */ + private MAcctSchema[] m_ass = 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
+ * - 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 & sets Processing = 'N' + * - if error - create Note + *+ * @param force if true ignore that locked + * @param repost if true ignore that already posted + * @return null if posted error otherwise + */ + 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 + return "Invalid DocStatus='" + m_DocStatus + "' for DocumentNo=" + getDocumentNo(); + // + if (p_po.getAD_Client_ID() != m_ass[0].getAD_Client_ID()) + { + String error = "AD_Client_ID Conflict - Document=" + p_po.getAD_Client_ID() + + ", AcctSchema=" + m_ass[0].getAD_Client_ID(); + log.severe(error); + return error; + } + + // Lock Record ---- + StringBuffer sql = new StringBuffer ("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='N'"); + if (DB.executeUpdate(sql.toString(), null) == 1) // outside trx + 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 (force) + return "Cannot Lock - ReSubmit"; + return "Cannot Lock - ReSubmit or RePost with Force"; + } + + p_Error = loadDocumentDetails(); + if (p_Error != null) + return p_Error; + + // 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(); + return "PeriodClosed"; + } + // delete it + deleteAcct(); + } + else if (isPosted()) + { + log.log(Level.SEVERE, toString() + " - Document already posted"); + unlock(); + return "AlreadyPosted"; + } + + p_Status = STATUS_NotPosted; + + // Create Fact per AcctSchema + m_fact = new ArrayList
+ * Table: C_AllocationHdr + * Document Types: CMA + *+ * @author Jorg Janke + * @version $Id: Doc_Allocation.java,v 1.6 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Allocation extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Allocation (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MAllocationHdr.class, rs, DOCTYPE_Allocation, trxName); + } // Doc_Allocation + + /** Tolearance G&L */ + private static final BigDecimal TOLERANCE = new BigDecimal (0.02); + /** Facts */ + private ArrayList
+ * AR_Invoice_Payment + * UnAllocatedCash DR + * or C_Prepayment + * DiscountExp DR + * WriteOff DR + * Receivables CR + * AR_Invoice_Cash + * CashTransfer DR + * DiscountExp DR + * WriteOff DR + * Receivables CR + * + * AP_Invoice_Payment + * Liability DR + * DiscountRev CR + * WriteOff CR + * PaymentSelect CR + * or V_Prepayment + * AP_Invoice_Cash + * Liability DR + * DiscountRev CR + * WriteOff CR + * CashTransfer CR + * CashBankTransfer + * - + * ============================== + * Realized Gain & Loss + * AR/AP DR CR + * Realized G/L DR CR + * + * + *+ * Tax needs to be corrected for discount & write-off; + * Currency gain & loss is realized here. + * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: C_BankStatement (392) + * Document Types: CMB + *+ * @author Jorg Janke + * @version $Id: Doc_Bank.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Bank extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Bank (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MBankStatement.class, rs, DOCTYPE_BankStatement, trxName); + } // Doc_Bank + + /** Bank Account */ + private int m_C_BankAccount_ID = 0; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + MBankStatement bs = (MBankStatement)getPO(); + setDateDoc(bs.getStatementDate()); + setDateAcct(bs.getStatementDate()); // Overwritten on Line Level + + m_C_BankAccount_ID = bs.getC_BankAccount_ID(); + // Amounts + setAmount(AMTTYPE_Gross, bs.getStatementDifference()); + + // Set Bank Account Info (Currency) + MBankAccount ba = MBankAccount.get (getCtx(), m_C_BankAccount_ID); + setC_Currency_ID (ba.getC_Currency_ID()); + + // Contained Objects + p_lines = loadLines(bs); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Line. + * @param bs bank statement + * 4 amounts + * AMTTYPE_Payment + * AMTTYPE_Statement2 + * AMTTYPE_Charge + * AMTTYPE_Interest + * @return DocLine Array + */ + private DocLine[] loadLines(MBankStatement bs) + { + ArrayList
+ * BankAsset DR CR (Statement) + * BankInTransit DR CR (Payment) + * Charge DR (Charge) + * Interest DR CR (Interest) + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: C_Cash (407) + * Document Types: CMC + *+ * @author Jorg Janke + * @version $Id: Doc_Cash.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Cash extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Cash (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super(ass, MCash.class, rs, DOCTYPE_CashJournal, trxName); + } // Doc_Cash + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + MCash cash = (MCash)getPO(); + setDateDoc(cash.getStatementDate()); + + // Amounts + setAmount(Doc.AMTTYPE_Gross, cash.getStatementDifference()); + + // Set CashBook Org & Currency + MCashBook cb = MCashBook.get(getCtx(), cash.getC_CashBook_ID()); + setC_CashBook_ID(cb.getC_CashBook_ID()); + setC_Currency_ID(cb.getC_Currency_ID()); + + // Contained Objects + p_lines = loadLines(cash, cb); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + + /** + * Load Cash Line + * @param cash journal + * @param cb cash book + * @return DocLine Array + */ + private DocLine[] loadLines(MCash cash, MCashBook cb) + { + ArrayList
+ * Expense + * CashExpense DR + * CashAsset CR + * Receipt + * CashAsset DR + * CashReceipt CR + * Charge + * Charge DR + * CashAsset CR + * Difference + * CashDifference DR + * CashAsset CR + * Invoice + * CashAsset DR + * CashTransfer CR + * Transfer + * BankInTransit DR + * CashAsset CR + *+ * @param as account schema + * @return Fact + */ + public ArrayList
+ * Table: GL_Journal (224) + * Document Types: GLJ + *+ * @author Jorg Janke + * @version $Id: Doc_GLJournal.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_GLJournal extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_GLJournal (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super(ass, MJournal.class, rs, null, trxName); + } // Foc_GL_Journal + + /** Posting Type */ + private String m_PostingType = null; + private int m_C_AcctSchema_ID = 0; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + MJournal journal = (MJournal)getPO(); + m_PostingType = journal.getPostingType(); + m_C_AcctSchema_ID = journal.getC_AcctSchema_ID(); + + // Contained Objects + p_lines = loadLines(journal); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + + /** + * Load Invoice Line + * @param journal journal + * @return DocLine Array + */ + private DocLine[] loadLines(MJournal journal) + { + ArrayList
+ * account DR CR + *+ * @param as acct schema + * @return Fact + */ + public ArrayList
+ * Table: M_InOut (319) + * Document Types: MMS, MMR + *+ * @author Jorg Janke + * @version $Id: Doc_InOut.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_InOut extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + public Doc_InOut (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MInOut.class, rs, null, trxName); + } // DocInOut + + /** + * Load Document Details + * @return error message or null + */ + protected String loadDocumentDetails() + { + setC_Currency_ID(NO_CURRENCY); + MInOut inout = (MInOut)getPO(); + setDateDoc (inout.getMovementDate()); + // Contained Objects + p_lines = loadLines(inout); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Line + * @param inout shipment/receipt + * @return DocLine Array + */ + private DocLine[] loadLines(MInOut inout) + { + ArrayList
+ * Shipment + * CoGS (RevOrg) DR + * Inventory CR + * Shipment of Project Issue + * CoGS DR + * Project CR + * Receipt + * Inventory DR + * NotInvoicedReceipt CR + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: M_Inventory (321) + * Document Types: MMI + *+ * @author Jorg Janke + * @version $Id: Doc_Inventory.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Inventory extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + public Doc_Inventory (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MInventory.class, rs, DOCTYPE_MatInventory, trxName); + } // Doc_Inventory + + /** + * Load Document Details + * @return error message or null + */ + protected String loadDocumentDetails() + { + setC_Currency_ID (NO_CURRENCY); + MInventory inventory = (MInventory)getPO(); + setDateDoc (inventory.getMovementDate()); + setDateAcct(inventory.getMovementDate()); + // Contained Objects + p_lines = loadLines(inventory); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Line + * @param inventory inventory + * @return DocLine Array + */ + private DocLine[] loadLines(MInventory inventory) + { + ArrayList
+ * Inventory + * Inventory DR CR + * InventoryDiff DR CR (or Charge) + *+ * @param as account schema + * @return Fact + */ + public ArrayList
+ * Table: C_Invoice (318) + * Document Types: ARI, ARC, ARF, API, APC + *+ * @author Jorg Janke + * @version $Id: Doc_Invoice.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Invoice extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Invoice(MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MInvoice.class, rs, null, trxName); + } // Doc_Invoice + + /** Contained Optional Tax Lines */ + private DocTax[] m_taxes = null; + /** Currency Precision */ + private int m_precision = -1; + /** All lines are Service */ + private boolean m_allLinesService = true; + /** All lines are product item */ + private boolean m_allLinesItem = true; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + MInvoice invoice = (MInvoice)getPO(); + setDateDoc(invoice.getDateInvoiced()); + setIsTaxIncluded(invoice.isTaxIncluded()); + // Amounts + setAmount(Doc.AMTTYPE_Gross, invoice.getGrandTotal()); + setAmount(Doc.AMTTYPE_Net, invoice.getTotalLines()); + setAmount(Doc.AMTTYPE_Charge, invoice.getChargeAmt()); + + // Contained Objects + m_taxes = loadTaxes(); + p_lines = loadLines(invoice); + log.fine("Lines=" + p_lines.length + ", Taxes=" + m_taxes.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Taxes + * @return DocTax Array + */ + private DocTax[] loadTaxes() + { + ArrayList
+ * ARI, ARF + * Receivables DR + * Charge CR + * TaxDue CR + * Revenue CR + * + * ARC + * Receivables CR + * Charge DR + * TaxDue DR + * Revenue RR + * + * API + * Payables CR + * Charge DR + * TaxCredit DR + * Expense DR + * + * APC + * Payables DR + * Charge CR + * TaxCredit CR + * Expense CR + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: M_MatchInv (472) + * Document Types: MXI + *+ * Update Costing Records + * @author Jorg Janke + * @version $Id: Doc_MatchInv.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_MatchInv extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_MatchInv (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super(ass, MMatchInv.class, rs, DOCTYPE_MatMatchInv, trxName); + } // Doc_MatchInv + + /** Invoice Line */ + private MInvoiceLine m_invoiceLine = null; + /** Material Receipt */ + private MInOutLine m_receiptLine = null; + + private ProductCost m_pc = null; + + /** Commitments */ + private DocLine[] m_commitments = null; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + setC_Currency_ID (Doc.NO_CURRENCY); + MMatchInv matchInv = (MMatchInv)getPO(); + setDateDoc(matchInv.getDateTrx()); + setQty (matchInv.getQty()); + // Invoice Info + int C_InvoiceLine_ID = matchInv.getC_InvoiceLine_ID(); + m_invoiceLine = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, null); + // BP for NotInvoicedReceipts + int C_BPartner_ID = m_invoiceLine.getParent().getC_BPartner_ID(); + setC_BPartner_ID(C_BPartner_ID); + // + int M_InOutLine_ID = matchInv.getM_InOutLine_ID(); + m_receiptLine = new MInOutLine (getCtx(), M_InOutLine_ID, null); + // + m_pc = new ProductCost (Env.getCtx(), + getM_Product_ID(), matchInv.getM_AttributeSetInstance_ID(), null); + m_pc.setQty(getQty()); + + return null; + } // loadDocumentDetails + + + /************************************************************************** + * Get Source Currency Balance - subtracts line and tax amounts from total - no rounding + * @return Zero (always balanced) + */ + public BigDecimal getBalance() + { + return Env.ZERO; + } // getBalance + + + /** + * Create Facts (the accounting logic) for + * MXI. + * (single line) + *
+ * NotInvoicedReceipts DR (Receipt Org) + * InventoryClearing CR + * InvoicePV DR CR (difference) + * Commitment + * Expense CR + * Offset DR + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: C_MatchPO (473) + * Document Types: MXP + *+ * @author Jorg Janke + * @version $Id: Doc_MatchPO.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_MatchPO extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_MatchPO (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super(ass, MMatchPO.class, rs, DOCTYPE_MatMatchPO, trxName); + } // Doc_MatchPO + + private int m_C_OrderLine_ID = 0; + private MOrderLine m_oLine = null; + // + private int m_M_InOutLine_ID = 0; + private int m_C_InvoiceLine_ID = 0; + private ProductCost m_pc; + private int m_M_AttributeSetInstance_ID = 0; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + setC_Currency_ID (Doc.NO_CURRENCY); + MMatchPO matchPO = (MMatchPO)getPO(); + setDateDoc(matchPO.getDateTrx()); + // + m_M_AttributeSetInstance_ID = matchPO.getM_AttributeSetInstance_ID(); + setQty (matchPO.getQty()); + // + m_C_OrderLine_ID = matchPO.getC_OrderLine_ID(); + m_oLine = new MOrderLine (getCtx(), m_C_OrderLine_ID, getTrxName()); + // + m_M_InOutLine_ID = matchPO.getM_InOutLine_ID(); + m_C_InvoiceLine_ID = matchPO.getC_InvoiceLine_ID(); + // + m_pc = new ProductCost (Env.getCtx(), + getM_Product_ID(), m_M_AttributeSetInstance_ID, getTrxName()); + m_pc.setQty(getQty()); + return null; + } // loadDocumentDetails + + + /************************************************************************** + * Get Source Currency Balance - subtracts line and tax amounts from total - no rounding + * @return Zero - always balanced + */ + public BigDecimal getBalance() + { + return Env.ZERO; + } // getBalance + + + /** + * Create Facts (the accounting logic) for + * MXP. + *
+ * Product PPV+ * @param as accounting schema + * @return Fact + */ + public ArrayList+ * PPV_Offset + *
+ * Table: M_Movement (323) + * Document Types: MMM + *+ * @author Jorg Janke + * @version $Id: Doc_Movement.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Movement extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + public Doc_Movement (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MMovement.class, rs, DOCTYPE_MatMovement, trxName); + } // Doc_Movement + + /** + * Load Document Details + * @return error message or null + */ + protected String loadDocumentDetails() + { + setC_Currency_ID(NO_CURRENCY); + MMovement move = (MMovement)getPO(); + setDateDoc (move.getMovementDate()); + setDateAcct(move.getMovementDate()); + // Contained Objects + p_lines = loadLines(move); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Line + * @param move move + * @return document lines (DocLine_Material) + */ + private DocLine[] loadLines(MMovement move) + { + ArrayList
+ * Movement + * Inventory DR CR + * InventoryTo DR CR + *+ * @param as account schema + * @return Fact + */ + public ArrayList
+ * 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 ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Order (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, 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 + */ + 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); + // log.fine( "Lines=" + p_lines.length + ", Taxes=" + m_taxes.length); + return null; + } // loadDocumentDetails + + + /** + * Load Invoice Line + * @param order order + * @return DocLine Array + */ + private DocLine[] loadLines(MOrder order) + { + ArrayList
+ * Reservation (release) + * Expense DR + * Offset CR + * Commitment + * (to be released by Invoice Matching) + * Expense CR + * Offset DR + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: C_Payment (335) + * Document Types ARP, APP + *+ * @author Jorg Janke + * @version $Id: Doc_Payment.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Payment extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Payment (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MPayment.class, rs, null, trxName); + } // Doc_Payment + + /** Tender Type */ + private String m_TenderType = null; + /** Prepayment */ + private boolean m_Prepayment = false; + /** Bank Account */ + private int m_C_BankAccount_ID = 0; + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + MPayment pay = (MPayment)getPO(); + setDateDoc(pay.getDateTrx()); + m_TenderType = pay.getTenderType(); + m_Prepayment = pay.isPrepayment(); + m_C_BankAccount_ID = pay.getC_BankAccount_ID(); + // Amount + setAmount(Doc.AMTTYPE_Gross, pay.getPayAmt()); + return null; + } // loadDocumentDetails + + + /************************************************************************** + * Get Source Currency Balance - always zero + * @return Zero (always balanced) + */ + public BigDecimal getBalance() + { + BigDecimal retValue = Env.ZERO; + // log.config( toString() + " Balance=" + retValue); + return retValue; + } // getBalance + + /** + * Create Facts (the accounting logic) for + * ARP, APP. + *
+ * ARP + * BankInTransit DR + * UnallocatedCash CR + * or Charge/C_Prepayment + * APP + * PaymentSelect DR + * or Charge/V_Prepayment + * BankInTransit CR + * CashBankTransfer + * - + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: M_Production (325) + * Document Types: MMP + *+ * @author Jorg Janke + * @version $Id: Doc_Production.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Production extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + public Doc_Production (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, X_M_Production.class, rs, DOCTYPE_MatProduction, trxName); + } // Doc_Production + + /** + * Load Document Details + * @return error message or null + */ + protected String loadDocumentDetails() + { + setC_Currency_ID (NO_CURRENCY); + X_M_Production prod = (X_M_Production)getPO(); + setDateDoc (prod.getMovementDate()); + setDateAcct(prod.getMovementDate()); + // Contained Objects + p_lines = loadLines(prod); + log.fine("Lines=" + p_lines.length); + return null; + } // loadDocumentDetails + + /** + * Load Invoice Line + * @param prod production + * @return DoaLine Array + */ + private DocLine[] loadLines(X_M_Production prod) + { + ArrayList
+ * Production + * Inventory DR CR + *+ * @param as account schema + * @return Fact + */ + public ArrayList
+ * Issue + * ProjectWIP DR + * Inventory CR + *+ * Project Account is either Asset or WIP depending on Project Type + * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Table: M_Requisition + * Document Types: POR (Requisition) + *+ * + * @author Jorg Janke + * @version $Id: Doc_Requisition.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Doc_Requisition extends Doc +{ + /** + * Constructor + * @param ass accounting schemata + * @param rs record + * @param trxName trx + */ + protected Doc_Requisition (MAcctSchema[] ass, ResultSet rs, String trxName) + { + super (ass, MRequisition.class, rs, DOCTYPE_PurchaseRequisition, trxName); + } // Doc_Requisition + + /** + * Load Specific Document Details + * @return error message or null + */ + protected String loadDocumentDetails () + { + setC_Currency_ID(NO_CURRENCY); + MRequisition req = (MRequisition)getPO(); + setDateDoc (req.getDateDoc()); + setDateAcct (req.getDateDoc()); + // Amounts + setAmount(AMTTYPE_Gross, req.getTotalLines()); + setAmount(AMTTYPE_Net, req.getTotalLines()); + // Contained Objects + p_lines = loadLines (req); + // log.fine( "Lines=" + p_lines.length + ", Taxes=" + m_taxes.length); + return null; + } // loadDocumentDetails + + /** + * Load Requisition Lines + * @param req requisition + * @return DocLine Array + */ + private DocLine[] loadLines (MRequisition req) + { + ArrayList
+ * Reservation + * Expense CR + * Offset DR + *+ * @param as accounting schema + * @return Fact + */ + public ArrayList
+ * Example: 1 -1 1 -1 + * Old 100/0 100/0 0/100 0/100 + * New 99/0 101/0 0/99 0/101 + *+ * @param deltaAmount delta amount + */ + public void currencyCorrect (BigDecimal deltaAmount) + { + boolean negative = deltaAmount.compareTo(Env.ZERO) < 0; + boolean adjustDr = getAmtAcctDr().abs().compareTo(getAmtAcctCr().abs()) > 0; + + log.fine(deltaAmount.toString() + + "; Old-AcctDr=" + getAmtAcctDr() + ",AcctCr=" + getAmtAcctCr() + + "; Negative=" + negative + "; AdjustDr=" + adjustDr); + + if (adjustDr) + if (negative) + setAmtAcctDr (getAmtAcctDr().subtract(deltaAmount)); + else + setAmtAcctDr (getAmtAcctDr().subtract(deltaAmount)); + else + if (negative) + setAmtAcctCr (getAmtAcctCr().add(deltaAmount)); + else + setAmtAcctCr (getAmtAcctCr().add(deltaAmount)); + + log.fine("New-AcctDr=" + getAmtAcctDr() + ",AcctCr=" + getAmtAcctCr()); + } // currencyCorrect + + /** + * Convert to Accounted Currency + * @return true if converted + */ + public boolean convert () + { + // Document has no currency + if (getC_Currency_ID() == Doc.NO_CURRENCY) + setC_Currency_ID (m_acctSchema.getC_Currency_ID()); + + if (m_acctSchema.getC_Currency_ID() == getC_Currency_ID()) + { + setAmtAcctDr (getAmtSourceDr()); + setAmtAcctCr (getAmtSourceCr()); + return true; + } + // Get Conversion Type from Line or Header + int C_ConversionType_ID = 0; + int AD_Org_ID = 0; + if (m_docLine != null) // get from line + { + C_ConversionType_ID = m_docLine.getC_ConversionType_ID(); + AD_Org_ID = m_docLine.getAD_Org_ID(); + } + if (C_ConversionType_ID == 0) // get from header + { + if (m_doc == null) + { + log.severe ("No Document VO"); + return false; + } + C_ConversionType_ID = m_doc.getC_ConversionType_ID(); + if (AD_Org_ID == 0) + AD_Org_ID = m_doc.getAD_Org_ID(); + } + setAmtAcctDr (MConversionRate.convert (getCtx(), + getAmtSourceDr(), getC_Currency_ID(), m_acctSchema.getC_Currency_ID(), + getDateAcct(), C_ConversionType_ID, m_doc.getAD_Client_ID(), AD_Org_ID)); + if (getAmtAcctDr() == null) + return false; + setAmtAcctCr (MConversionRate.convert (getCtx(), + getAmtSourceCr(), getC_Currency_ID(), m_acctSchema.getC_Currency_ID(), + getDateAcct(), C_ConversionType_ID, m_doc.getAD_Client_ID(), AD_Org_ID)); + return true; + } // convert + + /** + * Get Account + * @return account + */ + public MAccount getAccount() + { + return m_acct; + } // getAccount + + /** + * To String + * @return String + */ + public String toString() + { + StringBuffer sb = new StringBuffer("FactLine=["); + sb.append(getAD_Table_ID()).append(":").append(getRecord_ID()) + .append(",").append(m_acct) + .append(",Cur=").append(getC_Currency_ID()) + .append(", DR=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr()) + .append(", CR=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr()) + .append("]"); + return sb.toString(); + } // toString + + + /** + * Get AD_Org_ID (balancing segment). + * (if not set directly - from document line, document, account, locator) + *
+ * Note that Locator needs to be set before - otherwise + * segment balancing might produce the wrong results + * @return AD_Org_ID + */ + public int getAD_Org_ID() + { + if (super.getAD_Org_ID() != 0) // set earlier + return super.getAD_Org_ID(); + // Prio 1 - get from locator - if exist + if (getM_Locator_ID() != 0) + { + String sql = "SELECT AD_Org_ID FROM M_Locator WHERE M_Locator_ID=? AND AD_Client_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getM_Locator_ID()); + pstmt.setInt(2, getAD_Client_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + setAD_Org_ID (rs.getInt(1)); + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (1 from M_Locator_ID=" + getM_Locator_ID() + ")"); + } + else + log.log(Level.SEVERE, "AD_Org_ID - Did not find M_Locator_ID=" + getM_Locator_ID()); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // M_Locator_ID != 0 + + // Prio 2 - get from doc line - if exists (document context overwrites) + if (m_docLine != null && super.getAD_Org_ID() == 0) + { + setAD_Org_ID (m_docLine.getAD_Org_ID()); + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (2 from DocumentLine)"); + } + // Prio 3 - get from doc - if not GL + if (m_doc != null && super.getAD_Org_ID() == 0) + { + if (Doc.DOCTYPE_GLJournal.equals (m_doc.getDocumentType())) + { + setAD_Org_ID (m_acct.getAD_Org_ID()); // inter-company GL + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (3 from Acct)"); + } + else + { + setAD_Org_ID (m_doc.getAD_Org_ID()); + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (3 from Document)"); + } + } + // Prio 4 - get from account - if not GL + if (m_doc != null && super.getAD_Org_ID() == 0) + { + if (Doc.DOCTYPE_GLJournal.equals (m_doc.getDocumentType())) + { + setAD_Org_ID (m_doc.getAD_Org_ID()); + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (4 from Document)"); + } + else + { + setAD_Org_ID (m_acct.getAD_Org_ID()); + log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (4 from Acct)"); + } + } + return super.getAD_Org_ID(); + } // setAD_Org_ID + + + /** + * Get/derive Sales Region + * @return Sales Region + */ + public int getC_SalesRegion_ID () + { + if (super.getC_SalesRegion_ID() != 0) + return super.getC_SalesRegion_ID(); + // + if (m_docLine != null) + setC_SalesRegion_ID (m_docLine.getC_SalesRegion_ID()); + if (m_doc != null) + { + if (super.getC_SalesRegion_ID() == 0) + setC_SalesRegion_ID (m_doc.getC_SalesRegion_ID()); + if (super.getC_SalesRegion_ID() == 0 && m_doc.getBP_C_SalesRegion_ID() > 0) + setC_SalesRegion_ID (m_doc.getBP_C_SalesRegion_ID()); + // derive SalesRegion if AcctSegment + if (super.getC_SalesRegion_ID() == 0 + && m_doc.getC_BPartner_Location_ID() != 0 + && m_doc.getBP_C_SalesRegion_ID() == -1) // never tried + // && m_acctSchema.isAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_SalesRegion)) + { + String sql = "SELECT COALESCE(C_SalesRegion_ID,0) FROM C_BPartner_Location WHERE C_BPartner_Location_ID=?"; + setC_SalesRegion_ID (DB.getSQLValue(null, + sql, m_doc.getC_BPartner_Location_ID())); + if (super.getC_SalesRegion_ID() != 0) // save in VO + { + m_doc.setBP_C_SalesRegion_ID(super.getC_SalesRegion_ID()); + log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID() + " (from BPL)" ); + } + else // From Sales Rep of Document -> Sales Region + { + sql = "SELECT COALESCE(MAX(C_SalesRegion_ID),0) FROM C_SalesRegion WHERE SalesRep_ID=?"; + setC_SalesRegion_ID (DB.getSQLValue(null, + sql, m_doc.getSalesRep_ID())); + if (super.getC_SalesRegion_ID() != 0) // save in VO + { + m_doc.setBP_C_SalesRegion_ID(super.getC_SalesRegion_ID()); + log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID() + " (from SR)" ); + } + else + m_doc.setBP_C_SalesRegion_ID(-2); // don't try again + } + } + if (m_acct != null && super.getC_SalesRegion_ID() == 0) + setC_SalesRegion_ID (m_acct.getC_SalesRegion_ID()); + } + // + // log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID() + // + ", C_BPartner_Location_ID=" + m_docVO.C_BPartner_Location_ID + // + ", BP_C_SalesRegion_ID=" + m_docVO.BP_C_SalesRegion_ID + // + ", SR=" + m_acctSchema.isAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_SalesRegion)); + return super.getC_SalesRegion_ID(); + } // getC_SalesRegion_ID + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord) + { + log.fine(toString()); + // + getAD_Org_ID(); + getC_SalesRegion_ID(); + // Set Default Account Info + if (getM_Product_ID() == 0) + setM_Product_ID (m_acct.getM_Product_ID()); + if (getC_LocFrom_ID() == 0) + setC_LocFrom_ID (m_acct.getC_LocFrom_ID()); + if (getC_LocTo_ID() == 0) + setC_LocTo_ID (m_acct.getC_LocTo_ID()); + if (getC_BPartner_ID() == 0) + setC_BPartner_ID (m_acct.getC_BPartner_ID()); + if (getAD_OrgTrx_ID() == 0) + setAD_OrgTrx_ID (m_acct.getAD_OrgTrx_ID()); + if (getC_Project_ID() == 0) + setC_Project_ID (m_acct.getC_Project_ID()); + if (getC_Campaign_ID() == 0) + setC_Campaign_ID (m_acct.getC_Campaign_ID()); + if (getC_Activity_ID() == 0) + setC_Activity_ID (m_acct.getC_Activity_ID()); + if (getUser1_ID() == 0) + setUser1_ID (m_acct.getUser1_ID()); + if (getUser2_ID() == 0) + setUser2_ID (m_acct.getUser2_ID()); + + // Revenue Recognition for AR Invoices + if (m_doc.getDocumentType().equals(Doc.DOCTYPE_ARInvoice) + && m_docLine != null + && m_docLine.getC_RevenueRecognition_ID() != 0) + { + int AD_User_ID = 0; + setAccount_ID ( + createRevenueRecognition ( + m_docLine.getC_RevenueRecognition_ID(), m_docLine.get_ID(), + getAD_Client_ID(), getAD_Org_ID(), AD_User_ID, + getAccount_ID(), getC_SubAcct_ID(), + getM_Product_ID(), getC_BPartner_ID(), getAD_OrgTrx_ID(), + getC_LocFrom_ID(), getC_LocTo_ID(), + getC_SalesRegion_ID(), getC_Project_ID(), + getC_Campaign_ID(), getC_Activity_ID(), + getUser1_ID(), getUser2_ID(), + getUserElement1_ID(), getUserElement2_ID()) + ); + } + } + return true; + } // beforeSave + + + /************************************************************************** + * Revenue Recognition. + * Called from FactLine.save + *
+ * Create Revenue recognition plan and return Unearned Revenue account + * to be used instead of Revenue Account. If not found, it returns + * the revenue account. + * + * @param C_RevenueRecognition_ID revenue recognition + * @param C_InvoiceLine_ID invoice line + * @param AD_Client_ID client + * @param AD_Org_ID org + * @param AD_User_ID user + * @param Account_ID of Revenue Account + * @param C_SubAcct_ID sub account + * @param M_Product_ID product + * @param C_BPartner_ID bpartner + * @param AD_OrgTrx_ID trx org + * @param C_LocFrom_ID loc from + * @param C_LocTo_ID loc to + * @param C_SRegion_ID sales region + * @param C_Project_ID project + * @param C_Campaign_ID campaign + * @param C_Activity_ID activity + * @param User1_ID user1 + * @param User2_ID user2 + * @param UserElement1_ID user element 1 + * @param UserElement2_ID user element 2 + * @return Account_ID for Unearned Revenue or Revenue Account if not found + */ + private int createRevenueRecognition ( + int C_RevenueRecognition_ID, int C_InvoiceLine_ID, + int AD_Client_ID, int AD_Org_ID, int AD_User_ID, + int Account_ID, int C_SubAcct_ID, + int M_Product_ID, int C_BPartner_ID, int AD_OrgTrx_ID, + int C_LocFrom_ID, int C_LocTo_ID, int C_SRegion_ID, int C_Project_ID, + int C_Campaign_ID, int C_Activity_ID, + int User1_ID, int User2_ID, int UserElement1_ID, int UserElement2_ID) + { + log.fine("From Accout_ID=" + Account_ID); + // get VC for P_Revenue (from Product) + MAccount revenue = MAccount.get(getCtx(), + AD_Client_ID, AD_Org_ID, getC_AcctSchema_ID(), Account_ID, C_SubAcct_ID, + M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID, C_LocTo_ID, C_SRegion_ID, + C_Project_ID, C_Campaign_ID, C_Activity_ID, + User1_ID, User2_ID, UserElement1_ID, UserElement2_ID); + if (revenue != null && revenue.get_ID() == 0) + revenue.save(); + if (revenue == null || revenue.get_ID() == 0) + { + log.severe ("Revenue_Acct not found"); + return Account_ID; + } + int P_Revenue_Acct = revenue.get_ID(); + + // get Unearned Revenue Acct from BPartner Group + int UnearnedRevenue_Acct = 0; + int new_Account_ID = 0; + String sql = "SELECT ga.UnearnedRevenue_Acct, vc.Account_ID " + + "FROM C_BP_Group_Acct ga, C_BPartner p, C_ValidCombination vc " + + "WHERE ga.C_BP_Group_ID=p.C_BP_Group_ID" + + " AND ga.UnearnedRevenue_Acct=vc.C_ValidCombination_ID" + + " AND ga.C_AcctSchema_ID=? AND p.C_BPartner_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_AcctSchema_ID()); + pstmt.setInt(2, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + UnearnedRevenue_Acct = rs.getInt(1); + new_Account_ID = rs.getInt(2); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + if (new_Account_ID == 0) + { + log.severe ("UnearnedRevenue_Acct not found"); + return Account_ID; + } + + MRevenueRecognitionPlan plan = new MRevenueRecognitionPlan(getCtx(), 0, null); + plan.setC_RevenueRecognition_ID (C_RevenueRecognition_ID); + plan.setC_AcctSchema_ID (getC_AcctSchema_ID()); + plan.setC_InvoiceLine_ID (C_InvoiceLine_ID); + plan.setUnEarnedRevenue_Acct (UnearnedRevenue_Acct); + plan.setP_Revenue_Acct (P_Revenue_Acct); + plan.setC_Currency_ID (getC_Currency_ID()); + plan.setTotalAmt (getAcctBalance()); + if (!plan.save(get_TrxName())) + { + log.severe ("Plan NOT created"); + return Account_ID; + } + log.fine("From Acctount_ID=" + Account_ID + " to " + new_Account_ID + + " - Plan from UnearnedRevenue_Acct=" + UnearnedRevenue_Acct + " to Revenue_Acct=" + P_Revenue_Acct); + return new_Account_ID; + } // createRevenueRecognition + + + /************************************************************************** + * Update Line with reversed Original Amount in Accounting Currency. + * Also copies original dimensions like Project, etc. + * Called from Doc_MatchInv + * @param AD_Table_ID table + * @param Record_ID record + * @param Line_ID line + * @param multiplier targetQty/documentQty + * @return true if success + */ + public boolean updateReverseLine (int AD_Table_ID, int Record_ID, int Line_ID, + BigDecimal multiplier) + { + boolean success = false; + + String sql = "SELECT * " + + "FROM Fact_Acct " + + "WHERE C_AcctSchema_ID=? AND AD_Table_ID=? AND Record_ID=?" + + " AND Line_ID=? AND Account_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_AcctSchema_ID()); + pstmt.setInt(2, AD_Table_ID); + pstmt.setInt(3, Record_ID); + pstmt.setInt(4, Line_ID); + pstmt.setInt(5, m_acct.getAccount_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + MFactAcct fact = new MFactAcct(getCtx(), rs, get_TrxName()); + // Accounted Amounts - reverse + BigDecimal dr = fact.getAmtAcctDr(); + BigDecimal cr = fact.getAmtAcctCr(); + setAmtAcctDr (cr.multiply(multiplier)); + setAmtAcctCr (dr.multiply(multiplier)); + // Source Amounts + setAmtSourceDr (getAmtAcctDr()); + setAmtSourceCr (getAmtAcctCr()); + // + success = true; + log.fine(new StringBuffer("(Table=").append(AD_Table_ID) + .append(",Record_ID=").append(Record_ID) + .append(",Line=").append(Record_ID) + .append(", Account=").append(m_acct) + .append(",dr=").append(dr).append(",cr=").append(cr) + .append(") - DR=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr()) + .append(", CR=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr()) + .toString()); + // Dimensions + setAD_OrgTrx_ID(fact.getAD_OrgTrx_ID()); + setC_Project_ID (fact.getC_Project_ID()); + setC_Activity_ID(fact.getC_Activity_ID()); + setC_Campaign_ID(fact.getC_Campaign_ID()); + setC_SalesRegion_ID(fact.getC_SalesRegion_ID()); + setC_LocFrom_ID(fact.getC_LocFrom_ID()); + setC_LocTo_ID(fact.getC_LocTo_ID()); + setM_Product_ID(fact.getM_Product_ID()); + setM_Locator_ID(fact.getM_Locator_ID()); + setUser1_ID(fact.getUser1_ID()); + setUser2_ID(fact.getUser2_ID()); + setC_UOM_ID(fact.getC_UOM_ID()); + setC_Tax_ID(fact.getC_Tax_ID()); + // Org for cross charge + setAD_Org_ID (fact.getAD_Org_ID()); + } + else + log.warning(new StringBuffer("Not Found (try later) ") + .append(",C_AcctSchema_ID=").append(getC_AcctSchema_ID()) + .append(", AD_Table_ID=").append(AD_Table_ID) + .append(",Record_ID=").append(Record_ID) + .append(",Line_ID=").append(Line_ID) + .append(", Account_ID=").append(m_acct.getAccount_ID()).toString()); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + return success; + } // updateReverseLine + +} // FactLine diff --git a/serverRoot/src/main/server/org/compiere/acct/Matcher.java b/serverRoot/src/main/server/org/compiere/acct/Matcher.java new file mode 100644 index 0000000000..0a7e8886b3 --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/acct/Matcher.java @@ -0,0 +1,165 @@ +/****************************************************************************** + * 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.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Automatic Matching. + * Inv + * + * @author Jorg Janke + * @version $Id: Matcher.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $ + */ +public class Matcher +{ + /** + * Constructor + * @param AD_Client_ID Client + * @param trxName transaction + */ + public Matcher (int AD_Client_ID, String trxName) + { + m_AD_Client_ID = AD_Client_ID; + m_trxName = trxName; + } // Matcher + + /** Client */ + private int m_AD_Client_ID; + /** Transaction */ + private String m_trxName = null; + /** Logger */ + protected CLogger log = CLogger.getCLogger (getClass()); + + /** + * Matching + *
+ * Derive Invoice-Receipt Match from PO-Invoice and PO-Receipt + * Purchase Order (20) + * - Invoice1 (10) + * - Invoice2 (10) + * - Receipt1 (5) + * - Receipt2 (15) + * + * (a) Creates Directs + * - Invoice1 - Receipt1 (5) + * - Invoice2 - Receipt2 (10) + * + * (b) Creates Indirects + * - Invoice1 - Receipt2 (5) + * (Not imlemented) + * + * + *+ * @return number of records created + */ + public int match() + { + int counter = 0; + // (a) Direct Matches + String sql = "SELECT m1.AD_Client_ID,m2.AD_Org_ID, " // 1..2 + + "m1.C_InvoiceLine_ID,m2.M_InOutLine_ID,m1.M_Product_ID, " // 3..5 + + "m1.DateTrx,m2.DateTrx, m1.Qty, m2.Qty " // 6..9 + + "FROM M_MatchPO m1, M_MatchPO m2 " + + "WHERE m1.C_OrderLine_ID=m2.C_OrderLine_ID" + + " AND m1.M_InOutLine_ID IS NULL" + + " AND m2.C_InvoiceLine_ID IS NULL" + + " AND m1.M_Product_ID=m2.M_Product_ID" + + " AND m1.AD_Client_ID=?" // #1 + // Not existing Inv Matches + + " AND NOT EXISTS (SELECT * FROM M_MatchInv mi " + + "WHERE mi.C_InvoiceLine_ID=m1.C_InvoiceLine_ID AND mi.M_InOutLine_ID=m2.M_InOutLine_ID)"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + BigDecimal qty1 = rs.getBigDecimal(8); + BigDecimal qty2 = rs.getBigDecimal(9); + BigDecimal Qty = qty1.min(qty2); + if (Qty.equals(Env.ZERO)) + continue; + Timestamp dateTrx1 = rs.getTimestamp(6); + Timestamp dateTrx2 = rs.getTimestamp(7); + Timestamp DateTrx = dateTrx1; + if (dateTrx1.before(dateTrx2)) + DateTrx = dateTrx2; + // + int AD_Client_ID = rs.getInt(1); + int AD_Org_ID = rs.getInt(2); + int C_InvoiceLine_ID = rs.getInt(3); + int M_InOutLine_ID = rs.getInt(4); + int M_Product_ID = rs.getInt(5); + // + if (createMatchInv(AD_Client_ID, AD_Org_ID, + M_InOutLine_ID, C_InvoiceLine_ID, + M_Product_ID, DateTrx, Qty)) + counter++; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "match", e); + } + log.fine("Matcher.match - Client_ID=" + m_AD_Client_ID + + ", Records created=" + counter); + return counter; + } // match + + /** + * Create MatchInv record + * @param AD_Client_ID Client + * @param AD_Org_ID Org + * @param M_InOutLine_ID Receipt + * @param C_InvoiceLine_ID Invoice + * @param M_Product_ID Product + * @param DateTrx Date + * @param Qty Qty + * @return true if record created + */ + private boolean createMatchInv (int AD_Client_ID, int AD_Org_ID, + int M_InOutLine_ID, int C_InvoiceLine_ID, + int M_Product_ID, Timestamp DateTrx, BigDecimal Qty) + { + log.fine("InvLine=" + C_InvoiceLine_ID + ",Rec=" + M_InOutLine_ID + ", Qty=" + Qty + ", " + DateTrx); + + // MMatchInv inv = new MMatchInv (); + int M_MatchInv_ID = DB.getNextID (AD_Client_ID, "M_MatchInv", m_trxName); + // + StringBuffer sql = new StringBuffer("INSERT INTO M_MatchInv (" + + "M_MatchInv_ID, " + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "M_InOutLine_ID,C_InvoiceLine_ID, " + + "M_Product_ID,DateTrx,Qty, " + + "Processing,Processed,Posted) VALUES (") + .append(M_MatchInv_ID).append(", ") + .append(AD_Client_ID).append(",").append(AD_Org_ID).append(",'Y',SysDate,0,SysDate,0, ") + .append(M_InOutLine_ID).append(",").append(C_InvoiceLine_ID).append(", ") + .append(M_Product_ID).append(",").append(DB.TO_DATE(DateTrx,true)).append(",").append(Qty) + .append(", 'N','Y','N')"); + int no = DB.executeUpdate(sql.toString(), m_trxName); + return no == 1; + } // createMatchInv + +} // Matcher diff --git a/serverRoot/src/main/server/org/compiere/acct/ProductInfo.java b/serverRoot/src/main/server/org/compiere/acct/ProductInfo.java new file mode 100644 index 0000000000..fd744a3644 --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/acct/ProductInfo.java @@ -0,0 +1,390 @@ +/****************************************************************************** + * 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.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Product Costing Information. + * + * @author Jorg Janke + * @version $Id: ProductInfo.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $ + */ +public class ProductInfo +{ + /** + * Constructor + * @param M_Product_ID Product + * @param trxName transcation + */ + public ProductInfo (int M_Product_ID, String trxName) + { + m_trxName = trxName; + init (M_Product_ID); + } // ProductInfo + + /** The Product Key */ + private int m_M_Product_ID = 0; + /** Transaction */ + private String m_trxName = null; + + // Product Info + private int m_AD_Client_ID = 0; + private int m_AD_Org_ID = 0; + + private String m_productType = null; + private String m_ProductCategory = null; + + private boolean m_isBOM = false; + private boolean m_isStocked = true; + + private int m_C_RevenueRecognition_ID = 0; + + private int m_C_UOM_ID = 0; + private BigDecimal m_qty = Env.ZERO; + + /** Logger */ + protected CLogger log = CLogger.getCLogger (getClass()); + + /** + * Get Product Info (Service, Revenue Recognition). + * automatically called by constructor + * @param M_Product_ID Product + */ + private void init (int M_Product_ID) + { + m_M_Product_ID = M_Product_ID; + if (m_M_Product_ID == 0) + return; + + String sql = "SELECT p.ProductType, pc.Value, " // 1..2 + + "p.C_RevenueRecognition_ID,p.C_UOM_ID, " // 3..4 + + "p.AD_Client_ID,p.AD_Org_ID, " // 5..6 + + "p.IsBOM, p.IsStocked " // 7..8 + + "FROM M_Product_Category pc" + + " INNER JOIN M_Product p ON (pc.M_Product_Category_ID=p.M_Product_Category_ID) " + + "WHERE p.M_Product_ID=?"; // #1 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_productType = rs.getString(1); + m_ProductCategory = rs.getString(2); + m_C_RevenueRecognition_ID = rs.getInt(3); + m_C_UOM_ID = rs.getInt(4); + // reference + m_AD_Client_ID = rs.getInt(5); + m_AD_Org_ID = rs.getInt(6); + // + m_isBOM = "Y".equals(rs.getString(7)); + m_isStocked = "Y".equals(rs.getString(8)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // init + + /** + * Is Product/Item + * @return true if product + */ + public boolean isProduct() + { + return MProduct.PRODUCTTYPE_Item.equals(m_productType); + } // isProduct + + /** + * Is it a BOM + * @return true if BOM + */ + public boolean isBOM() + { + return m_isBOM; + } // isBOM + + /** + * Is it stocked + * @return true if stocked + */ + public boolean isStocked() + { + return m_isStocked; + } // isStocked + + /** + * Is Service + * @return true if service + */ + public boolean isService() + { + return MProduct.PRODUCTTYPE_Service.equals(m_productType); + } // isService + + /** + * Get Product Category (Value) + * @return M_Product_Category_ID + */ + public String getProductCategory() + { + return m_ProductCategory; + } // getProductCategory + + /** + * Has Revenue Recognition + * @return true if product/service has revenue recognition + */ + public boolean isRevenueRecognition() + { + return m_C_RevenueRecognition_ID != 0; + } // isRevenueRecognition + + /** + * Get Revenue Recognition + * @return C_RevenueRecognition_ID + */ + public int getC_RevenueRecognition_ID() + { + return m_C_RevenueRecognition_ID; + } // getC_RevenueRecognition_ID + + /** + * Quantity UOM + * @return C_UOM_ID + */ + public int getC_UOM_ID() + { + return m_C_UOM_ID; + } // getC_UOM_ID + + /*************************************************************************/ + + /** + * Set Quantity in Storage UOM + * @param qty quantity + */ + public void setQty (BigDecimal qty) + { + m_qty = qty; + } // setQty + + /** + * Set Quantity in UOM + * @param qty quantity + * @param C_UOM_ID UOM + */ + public void setQty (BigDecimal qty, int C_UOM_ID) + { + m_qty = MUOMConversion.convert (C_UOM_ID, m_C_UOM_ID, qty, true); // StdPrecision + if (qty != null && m_qty == null) // conversion error + { + log.severe ("Conversion error - set to " + qty); + m_qty = qty; + } + } // setQty + + /** + * Get Qty in Storage UOM + * @return qty + */ + public BigDecimal getQty() + { + return m_qty; + } // getQty + + + + /** + * Update/Create initial Cost Record. + * Check first for Purchase Price List, + * then Product Purchase Costs + * and then Price List + * @param as accounting schema + * @param create create record + * @return costs + */ + private BigDecimal updateCosts (MAcctSchema as, boolean create) + { + // Create Zero Record + if (create) + { + StringBuffer sql = new StringBuffer ("INSERT INTO M_Product_Costing " + + "(M_Product_ID,C_AcctSchema_ID," + + " AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + " CurrentCostPrice,CostStandard,FutureCostPrice," + + " CostStandardPOQty,CostStandardPOAmt,CostStandardCumQty,CostStandardCumAmt," + + " CostAverage,CostAverageCumQty,CostAverageCumAmt," + + " PriceLastPO,PriceLastInv, TotalInvQty,TotalInvAmt) " + + "VALUES ("); + sql.append(m_M_Product_ID).append(",").append(as.getC_AcctSchema_ID()).append(",") + .append(m_AD_Client_ID).append(",").append(m_AD_Org_ID).append(",") + .append("'Y',SysDate,0,SysDate,0, 0,0,0, 0,0,0,0, 0,0,0, 0,0, 0,0)"); + int no = DB.executeUpdate(sql.toString(), m_trxName); + if (no == 1) + log.fine("CostingCreated"); + } + + // Try to find non ZERO Price + String costSource = "PriceList-PO"; + BigDecimal costs = getPriceList (as, true); + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "PO Cost"; + costs = getPOCost(as); + } + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "PriceList"; + costs = getPriceList (as, false); + } + + // if not found use $1 (to be able to do material transactions) + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "Not Found"; + costs = new BigDecimal("1"); + } + + // update current costs + StringBuffer sql = new StringBuffer ("UPDATE M_Product_Costing "); + sql.append("SET CurrentCostPrice=").append(costs) + .append(" WHERE M_Product_ID=").append(m_M_Product_ID) + .append(" AND C_AcctSchema_ID=").append(as.getC_AcctSchema_ID()); + int no = DB.executeUpdate(sql.toString(), m_trxName); + if (no == 1) + log.fine(costSource + " - " + costs); + return costs; + } // createCosts + + /** + * Get PO Price from PriceList - and convert it to AcctSchema Currency + * @param as accounting schema + * @param onlyPOPriceList use only PO price list + * @return po price + */ + private BigDecimal getPriceList (MAcctSchema as, boolean onlyPOPriceList) + { + StringBuffer sql = new StringBuffer ( + "SELECT pl.C_Currency_ID, pp.PriceList, pp.PriceStd, pp.PriceLimit " + + "FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp " + + "WHERE pl.M_PriceList_ID = plv.M_PriceList_ID" + + " AND plv.M_PriceList_Version_ID = pp.M_PriceList_Version_ID" + + " AND pp.M_Product_ID=?"); + if (onlyPOPriceList) + sql.append(" AND pl.IsSOPriceList='N'"); + sql.append(" ORDER BY pl.IsSOPriceList ASC, plv.ValidFrom DESC"); + int C_Currency_ID = 0; + BigDecimal PriceList = null; + BigDecimal PriceStd = null; + BigDecimal PriceLimit = null; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Currency_ID = rs.getInt(1); + PriceList = rs.getBigDecimal(2); + PriceStd = rs.getBigDecimal(3); + PriceLimit = rs.getBigDecimal(4); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + // nothing found + if (C_Currency_ID == 0) + return null; + + BigDecimal price = PriceLimit; // best bet + if (price == null || price.equals(Env.ZERO)) + price = PriceStd; + if (price == null || price.equals(Env.ZERO)) + price = PriceList; + // Convert + if (price != null && !price.equals(Env.ZERO)) + price = MConversionRate.convert (as.getCtx(), + price, C_Currency_ID, as.getC_Currency_ID(), + as.getAD_Client_ID(), 0); + return price; + } // getPOPrice + + /** + * Get PO Cost from Purchase Info - and convert it to AcctSchema Currency + * @param as accounting schema + * @return po cost + */ + private BigDecimal getPOCost (MAcctSchema as) + { + String sql = "SELECT C_Currency_ID, PriceList,PricePO,PriceLastPO " + + "FROM M_Product_PO WHERE M_Product_ID=? " + + "ORDER BY IsCurrentVendor DESC"; + + int C_Currency_ID = 0; + BigDecimal PriceList = null; + BigDecimal PricePO = null; + BigDecimal PriceLastPO = null; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Currency_ID = rs.getInt(1); + PriceList = rs.getBigDecimal(2); + PricePO = rs.getBigDecimal(3); + PriceLastPO = rs.getBigDecimal(4); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + // nothing found + if (C_Currency_ID == 0) + return null; + + BigDecimal cost = PriceLastPO; // best bet + if (cost == null || cost.equals(Env.ZERO)) + cost = PricePO; + if (cost == null || cost.equals(Env.ZERO)) + cost = PriceList; + // Convert - standard precision!! - should be costing precision + if (cost != null && !cost.equals(Env.ZERO)) + cost = MConversionRate.convert (as.getCtx(), + cost, C_Currency_ID, as.getC_Currency_ID(), m_AD_Client_ID, m_AD_Org_ID); + return cost; + } // getPOCost + +} // ProductInfo diff --git a/serverRoot/src/main/server/org/compiere/ldap/LdapConnectionHandler.java b/serverRoot/src/main/server/org/compiere/ldap/LdapConnectionHandler.java new file mode 100644 index 0000000000..532c7062da --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/ldap/LdapConnectionHandler.java @@ -0,0 +1,118 @@ +/****************************************************************************** + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.ldap; + +import java.io.*; +import java.net.*; +import java.util.logging.*; +import org.compiere.ldap.*; +import org.compiere.util.*; +import com.sun.jndi.ldap.*; + +/** + * LDAP Connection Handler + * + * @author Jorg Janke + * @version $Id: LdapConnectionHandler.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $ + */ +public class LdapConnectionHandler extends Thread +{ + /** + * Ldap Connection Handler + * @param socket server socket + */ + public LdapConnectionHandler(Socket socket) + { + try + { + m_socket = socket; + m_socket.setTcpNoDelay(true); // should not be required + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } // no timeout + } // LdapConnectionHandler + + /** Socket */ + private Socket m_socket = null; + /** Logger */ + private static CLogger log = CLogger.getCLogger (LdapConnectionHandler.class); + + + /** + * Do Work + */ + public void run() + { + try + { + if (m_socket == null || m_socket.isClosed()) + return; + + boolean activeSession = true; + while (activeSession) + { + InputStream in = m_socket.getInputStream(); + BufferedOutputStream out = new BufferedOutputStream(m_socket.getOutputStream()); + // Read + byte[] buffer = new byte[512]; + int length = in.read(buffer, 0, 512); + + LdapMessage msg = new LdapMessage (buffer, length); + if (msg.getOperation() == LdapMessage.UNBIND_REQUEST) + { + activeSession = false; + out.close(); + } + else + { + LdapResult result = new LdapResult (); + byte[] bytes = result.bindResponse(); + // + out.write(bytes); + out.flush(); + } + } + } + catch (IOException e) + { + log.log(Level.SEVERE, "", e); + } + + try + { + m_socket.close(); + } + catch (Exception e) + { + log.log(Level.WARNING, "Socket", e); + } + m_socket = null; + } // run + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("LdapConnectionHandler["); + sb.append (hashCode()).append ("]"); + return sb.toString (); + } // toString + +} // LdapConnectionHandler diff --git a/serverRoot/src/main/server/org/compiere/ldap/LdapMessage.java b/serverRoot/src/main/server/org/compiere/ldap/LdapMessage.java new file mode 100644 index 0000000000..e3e0c26e0f --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/ldap/LdapMessage.java @@ -0,0 +1,172 @@ +/****************************************************************************** + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.ldap; + +import java.util.logging.*; +import org.compiere.util.*; +import com.sun.jndi.ldap.*; + +/** + * Ldap Message + * + * @author Jorg Janke + * @version $Id: LdapMessage.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $ + */ +public class LdapMessage +{ + /** + * Ldap Message + * @param data BER data + * @param length Ber data length + */ + public LdapMessage (byte[] data, int length) + { + try + { + decode(data, length); + } + catch (Exception e) + { + log.log(Level.SEVERE, data.toString(), e); + } + } // LdapMessage + + /** + LDAPMessage ::= SEQUENCE { + messageID MessageID, + protocolOp CHOICE { + bindRequest BindRequest, + bindResponse BindResponse, + unbindRequest UnbindRequest, + searchRequest SearchRequest, + searchResEntry SearchResultEntry, + searchResDone SearchResultDone, + searchResRef SearchResultReference, + modifyRequest ModifyRequest, + modifyResponse ModifyResponse, + addRequest AddRequest, + addResponse AddResponse, + delRequest DelRequest, + delResponse DelResponse, + modDNRequest ModifyDNRequest, + modDNResponse ModifyDNResponse, + compareRequest CompareRequest, + compareResponse CompareResponse, + abandonRequest AbandonRequest, + extendedReq ExtendedRequest, + extendedResp ExtendedResponse }, + controls [0] Controls OPTIONAL } + **/ + + static public final int BIND_REQUEST = 0; + static public final int BIND_RESPONSE = 1; + static public final int UNBIND_REQUEST = 2; + static public final int SEARCH_REQUEST = 3; + static public final int SEARCH_RESENTRY = 4; + static public final int SEARCH_RESDONE = 5; + static public final int MODIFY_REQUEST = 6; + static public final int MODIFY_RESPONSE = 7; + static public final int ADD_REQUEST = 8; + static public final int ADD_RESPONSE = 9; + static public final int DEL_REQUEST = 10; + static public final int DEL_RESPONSE = 11; + static public final int MODDN_REQUEST = 12; + static public final int MODDN_RESPONSE = 13; + static public final int COMPARE_REQUEST = 14; + static public final int COMPARE_RESPONSE = 15; + static public final int ABANDON_REQUEST = 16; + static public final int EXTENDED_REQUEST = 17; + static public final int EXTENDED_RESPONSE = 18; + + static public final int[] PROTOCOL_OP = { + BIND_REQUEST, BIND_RESPONSE, UNBIND_REQUEST, + SEARCH_REQUEST, SEARCH_RESENTRY, SEARCH_RESDONE, + MODIFY_REQUEST, MODIFY_RESPONSE, ADD_REQUEST, ADD_RESPONSE, + DEL_REQUEST, DEL_RESPONSE, MODDN_REQUEST, MODDN_RESPONSE, + COMPARE_REQUEST, COMPARE_RESPONSE, ABANDON_REQUEST, + EXTENDED_REQUEST, EXTENDED_RESPONSE}; + + + /** Logger */ + private static CLogger log = CLogger.getCLogger (LdapMessage.class); + /** Protocol Operation */ + private int m_protocolOp = -1; + + + /** + * Decode Message + * @param data data + * @param length length + * @throws Exception + */ + private void decode (byte[] data, int length) throws Exception + { + BerDecoder decoder = new BerDecoder(data, 0, length); + int left = decoder.bytesLeft(); + int pos = decoder.getParsePosition(); + // + int seq = decoder.parseSeq(null); + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + int messageID = decoder.parseInt(); + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + int peek = decoder.peekByte(); + m_protocolOp = decoder.parseSeq(PROTOCOL_OP); + m_protocolOp -= Ber.ASN_APPLICATION; + if (m_protocolOp - Ber.ASN_CONSTRUCTOR >= 0) + m_protocolOp -= Ber.ASN_CONSTRUCTOR; + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + // Payload + if (m_protocolOp == BIND_REQUEST) + { + int version = decoder.parseInt(); + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + byte[] dn = decoder.parseOctetString(Ber.ASN_OCTET_STR, null); + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + byte[] authentification = decoder.parseOctetString(Ber.ASN_CONTEXT, null); + left = decoder.bytesLeft(); + pos = decoder.getParsePosition(); + // + log.info("#" + messageID + ": bind - version=" + version + ", dn=" + new String(dn) + + ", auth=" + new String (authentification)); + } + else if (m_protocolOp == UNBIND_REQUEST) + log.info("#" + messageID + ": unbind"); + else + { + log.warning("#" + messageID + ": Unknown Op + " + m_protocolOp); + } + } // decode + + /** + * Get Operation Code + * @return protocolOp + */ + public int getOperation() + { + return m_protocolOp; + } // getOperation + +} // LdapMessage diff --git a/serverRoot/src/main/server/org/compiere/ldap/LdapProcessor.java b/serverRoot/src/main/server/org/compiere/ldap/LdapProcessor.java new file mode 100644 index 0000000000..13a181595a --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/ldap/LdapProcessor.java @@ -0,0 +1,141 @@ +/****************************************************************************** + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.ldap; + +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.naming.ldap.*; +import org.compiere.*; +import org.compiere.ldap.*; +import org.compiere.model.*; +import org.compiere.server.*; +import org.compiere.util.*; + +/** + * LDAP Server + * + * @author Jorg Janke + * @version $Id: LdapProcessor.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $ + */ +public class LdapProcessor extends AdempiereServer +{ + /** + * Ldap Processor (Server) + * @param model Ldap Model + */ + public LdapProcessor (LdapProcessorModel model) + { + super (model, 300); + m_model = model; + init(); + } // LdapProcessor + + /** The Concrete Model */ + private LdapProcessorModel m_model = null; + /** Last Summary */ + private StringBuffer m_summary = new StringBuffer(); + /** Client info */ + private MClient m_client = null; + /** Server Socket */ + private ServerSocket m_serverSocket = null; + /** Counter */ + private int m_counter = 0; + + + /** + * Do Work + */ + protected void doWork() + { + // Close Socket + if (m_serverSocket != null) + { + try + { + m_serverSocket.close(); + } + catch (Exception e) + { + } + } + m_counter = 0; + // + m_summary = new StringBuffer(m_model.toString()) + .append(" - "); + // + + try + { + m_serverSocket = new ServerSocket(m_model.getLdapPort()); + log.log(Level.INFO, "Opened Port=" + m_model.getLdapPort()); + while (!isInterrupted()) + { + Socket socket = m_serverSocket.accept(); // waits for connection + log.log(Level.FINE, "Connection on Port=" + m_model.getLdapPort()); + LdapConnectionHandler handler = new LdapConnectionHandler (socket); + handler.start(); + m_counter++; + } + } + catch (Exception e) + { + log.log(Level.WARNING, "Port=" + m_model.getLdapPort(), e); + m_summary.append(e.toString()); + } + + } // doWork + + /** + * Initialize + */ + private void init() + { + try + { + InitialLdapContext lctx = new InitialLdapContext(); + // lctx.setRequestControls(critModCtls); + // lctx.modifyAttributes(name, mods); + Control[] respCtls = lctx.getResponseControls(); + } + catch (Exception e) + { + } + } // + + /** + * Get Server Info + * @return info + */ + public String getServerInfo() + { + return "#" + p_runCount + " - Last=" + m_summary.toString() + + "; Counter=" + m_counter; + } // getServerInfo + + /** + * Test + * @param args + */ + public static void main(String[] args) + { + Adempiere.startup(true); + new LdapProcessor(new LdapProcessorModel(new Properties())).doWork(); + } // main + +} // LdapProcessor + diff --git a/serverRoot/src/main/server/org/compiere/ldap/LdapProcessorModel.java b/serverRoot/src/main/server/org/compiere/ldap/LdapProcessorModel.java new file mode 100644 index 0000000000..b2b04e7a4a --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/ldap/LdapProcessorModel.java @@ -0,0 +1,158 @@ +/****************************************************************************** + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.ldap; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; + +/** + * Interim LDAP Server Model + * + * @author Jorg Janke + * @version $Id: LdapProcessorModel.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $ + */ +public class LdapProcessorModel implements AdempiereProcessor +{ + /** + * Ldap Processor Model + * @param ctx context + */ + public LdapProcessorModel (Properties ctx) + { + m_ctx = ctx; + } + // Properties + private Properties m_ctx = null; + + private Timestamp m_dateNextRun; + private Timestamp m_dateLastRun; + + + public int getLdapPort() + { + return 389; + } + + + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer (getName()); + sb.append (";Port=").append (getLdapPort()); + return sb.toString (); + } // toString + + + + + /************************************************************************** + * getAD_Client_ID + * @see org.compiere.model.AdempiereProcessor#getAD_Client_ID() + * @return 0 + */ + public int getAD_Client_ID() + { + return 0; + } + /** + * getName + * @see org.compiere.model.AdempiereProcessor#getName() + * @return name + */ + public String getName() + { + return "Adempiere LDAP Server"; + } + /** + * getDescription + * @see org.compiere.model.AdempiereProcessor#getDescription() + * @return - + */ + public String getDescription() + { + return "-"; + } + /** + * Get Ctx + * @return context + */ + public Properties getCtx() + { + return m_ctx; + } + /** + * GetFrequencyType + * @see org.compiere.model.AdempiereProcessor#getFrequencyType() + * @return min + */ + public String getFrequencyType() + { + return MRequestProcessor.FREQUENCYTYPE_Minute; + } + /** + * getFrequency + * @see org.compiere.model.AdempiereProcessor#getFrequency() + * @return 1 + */ + public int getFrequency() + { + return 1; + } + + /** + * Get Unique Server ID + * @return id + */ + public String getServerID() + { + return "Ldap"; + } + + public Timestamp getDateNextRun(boolean requery) + { + return m_dateNextRun; + } + + public void setDateNextRun(Timestamp dateNextWork) + { + m_dateNextRun = dateNextWork; + } + + public Timestamp getDateLastRun() + { + return m_dateLastRun; + } + + public void setDateLastRun(Timestamp dateLastRun) + { + m_dateLastRun = dateLastRun; + } + + public boolean save() + { + return true; + } + + public AdempiereProcessorLog[] getLogs() + { + return new AdempiereProcessorLog[0]; + } +} diff --git a/serverRoot/src/main/server/org/compiere/ldap/LdapResult.java b/serverRoot/src/main/server/org/compiere/ldap/LdapResult.java new file mode 100644 index 0000000000..7c459ed878 --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/ldap/LdapResult.java @@ -0,0 +1,147 @@ +/****************************************************************************** + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.ldap; + +import java.io.*; +import java.util.logging.*; +import org.compiere.util.*; +import com.sun.jndi.ldap.*; + +/** + * Ldap Wire Response + * + * @author Jorg Janke + * @version $Id: LdapResult.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $ + */ +public class LdapResult +{ + + public LdapResult() + { + super (); + } // LdapResult + + /** + LDAPResult ::= SEQUENCE { + resultCode ENUMERATED { + success (0), + operationsError (1), + protocolError (2), + timeLimitExceeded (3), + sizeLimitExceeded (4), + compareFalse (5), + compareTrue (6), + + authMethodNotSupported (7), + strongAuthRequired (8), + -- 9 reserved -- + referral (10), -- new + adminLimitExceeded (11), -- new + unavailableCriticalExtension (12), -- new + confidentialityRequired (13), -- new + saslBindInProgress (14), -- new + noSuchAttribute (16), + undefinedAttributeType (17), + inappropriateMatching (18), + constraintViolation (19), + attributeOrValueExists (20), + invalidAttributeSyntax (21), + noSuchObject (32), + aliasProblem (33), + invalidDNSyntax (34), + -- 35 reserved for undefined isLeaf -- + aliasDereferencingProblem (36), + -- 37-47 unused -- + inappropriateAuthentication (48), + invalidCredentials (49), + insufficientAccessRights (50), + busy (51), + unavailable (52), + unwillingToPerform (53), + loopDetect (54), + -- 55-63 unused -- + namingViolation (64), + objectClassViolation (65), + notAllowedOnNonLeaf (66), + notAllowedOnRDN (67), + entryAlreadyExists (68), + objectClassModsProhibited (69), + -- 70 reserved for CLDAP -- + affectsMultipleDSAs (71), -- new + -- 72-79 unused -- + other (80) }, + -- 81-90 reserved for APIs -- + matchedDN LDAPDN, + errorMessage LDAPString, + referral [3] Referral OPTIONAL } + **/ + + /** Encoder */ + private BerEncoder m_encoder = new BerEncoder(); + /** Logger */ + private static CLogger log = CLogger.getCLogger (LdapResult.class); + + /** + * Bind Response + * @return reponse + */ + public byte[] bindResponse() + { + try + { +/** + m_encoder.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); + for (int i = 0; i < sortKeys.length; i++) { + ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); + ber.encodeString(sortKeys[i].getAttributeID(), true); // v3 + if ((matchingRule = sortKeys[i].getMatchingRuleID()) != null) { + ber.encodeString(matchingRule, (Ber.ASN_CONTEXT | 0), true); + } + if (! sortKeys[i].isAscending()) { + ber.encodeBoolean(true, (Ber.ASN_CONTEXT | 1)); + } + ber.endSeq(); + } +*/ + // payload + m_encoder.beginSeq(Ber.ASN_APPLICATION | LdapMessage.BIND_RESPONSE); + // Response + m_encoder.encodeInt(0); // success + m_encoder.encodeOctetString("cn=testCN".getBytes(), 0); // matched DN + m_encoder.encodeOctetString("".getBytes(), 0); // error mag + // referral + // sasl + // + m_encoder.endSeq(); + log.info("Success"); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + return getResult(); + } // bindResponse + + /** + * Get BER Result as byte array + * @return byte array + */ + public byte[] getResult() + { + return m_encoder.getTrimmedBuf(); + } // getResult + +} // LdapResult diff --git a/serverRoot/src/main/server/org/compiere/server/AcctProcessor.java b/serverRoot/src/main/server/org/compiere/server/AcctProcessor.java new file mode 100644 index 0000000000..865aa2142b --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/server/AcctProcessor.java @@ -0,0 +1,172 @@ +/****************************************************************************** + * 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.server; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.acct.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Accounting Processor + * + * @author Jorg Janke + * @version $Id: AcctProcessor.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $ + */ +public class AcctProcessor extends AdempiereServer +{ + /** + * Accounting Processor + * @param model model + */ + public AcctProcessor (MAcctProcessor model) + { + super (model, 30); // 30 seconds delay + m_model = model; + m_client = MClient.get(model.getCtx(), model.getAD_Client_ID()); + } // AcctProcessor + + /** The Concrete Model */ + private MAcctProcessor m_model = null; + /** Last Summary */ + private StringBuffer m_summary = new StringBuffer(); + /** Client onfo */ + private MClient m_client = null; + /** Accounting Schemata */ + private MAcctSchema[] m_ass = null; + + /** + * Work + */ + protected void doWork () + { + m_summary = new StringBuffer(); + // Get Schemata + if (m_model.getC_AcctSchema_ID() == 0) + m_ass = MAcctSchema.getClientAcctSchema(getCtx(), m_model.getAD_Client_ID()); + else // only specific accounting schema + m_ass = new MAcctSchema[] {new MAcctSchema (getCtx(), m_model.getC_AcctSchema_ID(), null)}; + // + postSession(); + MCost.create(m_client); + // + int no = m_model.deleteLog(); + m_summary.append("Logs deleted=").append(no); + // + MAcctProcessorLog pLog = new MAcctProcessorLog(m_model, m_summary.toString()); + pLog.setReference("#" + String.valueOf(p_runCount) + + " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork))); + pLog.save(); + } // doWork + + /** + * Post Session + */ + private void postSession() + { + for (int i = 0; i < Doc.documentsTableID.length; i++) + { + int AD_Table_ID = Doc.documentsTableID[i]; + String TableName = Doc.documentsTableName[i]; + // Post only special documents + if (m_model.getAD_Table_ID() != 0 + && m_model.getAD_Table_ID() != AD_Table_ID) + continue; + // SELECT * FROM table + StringBuffer sql = new StringBuffer ("SELECT * FROM ").append(TableName) + .append(" WHERE AD_Client_ID=?") + .append(" AND Processed='Y' AND Posted='N' AND IsActive='Y'") + .append(" ORDER BY Created"); + // + int count = 0; + int countError = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), null); + pstmt.setInt(1, m_model.getAD_Client_ID()); + ResultSet rs = pstmt.executeQuery(); + while (!isInterrupted() && rs.next()) + { + count++; + boolean ok = true; + try + { + Doc doc = Doc.get (m_ass, AD_Table_ID, rs, null); + if (doc == null) + { + log.severe(getName() + ": No Doc for " + TableName); + ok = false; + } + else + { + String error = doc.post(false, false); // post no force/repost + ok = error == null; + } + } + catch (Exception e) + { + log.log(Level.SEVERE, getName() + ": " + TableName, e); + ok = false; + } + if (!ok) + countError++; + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + if (pstmt != null) + { + try + { + pstmt.close(); + } + catch (Exception e) + { + } + } + // + if (count > 0) + { + m_summary.append(TableName).append("=").append(count); + if (countError > 0) + m_summary.append("(Errors=").append(countError).append(")"); + m_summary.append(" - "); + log.finer(getName() + ": " + m_summary.toString()); + } + else + log.finer(getName() + ": " + TableName + " - no work"); + } + } // postSession + + /** + * Get Server Info + * @return info + */ + public String getServerInfo() + { + return "#" + p_runCount + " - Last=" + m_summary.toString(); + } // getServerInfo + +} // AcctProcessor diff --git a/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java b/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java new file mode 100644 index 0000000000..4dde40ed9c --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java @@ -0,0 +1,388 @@ +/****************************************************************************** + * 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.server; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.ldap.*; +import org.compiere.model.*; +import org.compiere.util.*; +import org.compiere.wf.*; + +/** + * Adempiere Server Base + * + * @author Jorg Janke + * @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $ + */ +public abstract class AdempiereServer extends Thread +{ + /** + * Create New Server Thead + * @param model model + * @return server tread or null + */ + public static AdempiereServer create (AdempiereProcessor model) + { + if (model instanceof MRequestProcessor) + return new RequestProcessor ((MRequestProcessor)model); + if (model instanceof MWorkflowProcessor) + return new WorkflowProcessor ((MWorkflowProcessor)model); + if (model instanceof MAcctProcessor) + return new AcctProcessor ((MAcctProcessor)model); + if (model instanceof MAlertProcessor) + return new AlertProcessor ((MAlertProcessor)model); + if (model instanceof MScheduler) + return new Scheduler ((MScheduler)model); + if (model instanceof LdapProcessorModel) + return new LdapProcessor((LdapProcessorModel)model); + // + throw new IllegalArgumentException("Unknown Processor"); + } // create + + + /************************************************************************** + * Server Base Class + * @param model model + * @param initialNap delay time running in sec + */ + protected AdempiereServer (AdempiereProcessor model, int initialNap) + { + super (AdempiereServerGroup.get(), null, model.getName(), 0); + p_model = model; + m_ctx = new Properties(model.getCtx()); + if (p_system == null) + p_system = MSystem.get(m_ctx); + p_client = MClient.get(m_ctx); + Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID()); + m_initialNap = initialNap; + // log.info(model.getName() + " - " + getThreadGroup()); + } // ServerBase + + /** The Processor Model */ + protected AdempiereProcessor p_model; + /** Initial nap is seconds */ + private int m_initialNap = 0; + + /** Miliseconds to sleep - 10 Min default */ + private long m_sleepMS = 600000; + /** Sleeping */ + private volatile boolean m_sleeping = false; + /** Server start time */ + private long m_start = 0; + /** Number of Work executions */ + protected int p_runCount = 0; + /** Tine start of work */ + protected long p_startWork = 0; + /** Number MS of last Run */ + private long m_runLastMS = 0; + /** Number of MS total */ + private long m_runTotalMS = 0; + /** When to run next */ + private long m_nextWork = 0; + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + /** Context */ + private Properties m_ctx = null; + /** System */ + protected static MSystem p_system = null; + /** Client */ + protected MClient p_client = null; + + /** + * Get Server Context + * @return context + */ + public Properties getCtx() + { + return m_ctx; + } // getCtx + + /** + * @return Returns the sleepMS. + */ + public long getSleepMS () + { + return m_sleepMS; + } // getSleepMS + + + /** + * Sleep for set time + * @return true if not interrupted + */ + public boolean sleep() + { + if (isInterrupted()) + { + log.info (getName() + ": interrupted"); + return false; + } + log.fine(getName() + ": sleeping " + TimeUtil.formatElapsed(m_sleepMS)); + m_sleeping = true; + try + { + sleep (m_sleepMS); + } + catch (InterruptedException e) + { + log.info (getName() + ": interrupted"); + m_sleeping = false; + return false; + } + m_sleeping = false; + return true; + } // sleep + + /** + * Run Now + */ + public void runNow() + { + log.info(getName()); + p_startWork = System.currentTimeMillis(); + doWork(); + long now = System.currentTimeMillis(); + // --------------- + + p_runCount++; + m_runLastMS = now - p_startWork; + m_runTotalMS += m_runLastMS; + // + p_model.setDateLastRun(new Timestamp(now)); + p_model.save(); + // + log.fine(getName() + ": " + getStatistics()); + } // runNow + + /************************************************************************** + * Run async + */ + public void run () + { + try + { + log.fine(getName() + ": pre-nap - " + m_initialNap); + sleep (m_initialNap * 1000); + } + catch (InterruptedException e) + { + log.log(Level.SEVERE, getName() + ": pre-nap interrupted", e); + return; + } + + m_start = System.currentTimeMillis(); + while (true) + { + if (m_nextWork == 0) + { + Timestamp dateNextRun = getDateNextRun(true); + if (dateNextRun != null) + m_nextWork = dateNextRun.getTime(); + } + long now = System.currentTimeMillis(); + if (m_nextWork > now) + { + m_sleepMS = m_nextWork - now; + if (!sleep ()) + break; + } + if (isInterrupted()) + { + log.info (getName() + ": interrupted"); + break; + } + + // --------------- + p_startWork = System.currentTimeMillis(); + doWork(); + now = System.currentTimeMillis(); + // --------------- + + p_runCount++; + m_runLastMS = now - p_startWork; + m_runTotalMS += m_runLastMS; + // + m_sleepMS = calculateSleep(); + m_nextWork = now + m_sleepMS; + // + p_model.setDateLastRun(new Timestamp(now)); + p_model.setDateNextRun(new Timestamp(m_nextWork)); + p_model.save(); + // + log.fine(getName() + ": " + getStatistics()); + if (!sleep()) + break; + } + m_start = 0; + } // run + + /** + * Get Run Statistics + * @return Statistic info + */ + public String getStatistics() + { + return "Run #" + p_runCount + + " - Last=" + TimeUtil.formatElapsed(m_runLastMS) + + " - Total=" + TimeUtil.formatElapsed(m_runTotalMS) + + " - Next " + TimeUtil.formatElapsed(m_nextWork - System.currentTimeMillis()); + } // getStatistics + + /** + * Do the actual Work + */ + protected abstract void doWork(); + + /** + * Get Server Info + * @return info + */ + public abstract String getServerInfo(); + + /** + * Get Unique ID + * @return Unique ID + */ + public String getServerID() + { + return p_model.getServerID(); + } // getServerID + + /** + * Get the date Next run + * @param requery requery database + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + return p_model.getDateNextRun(requery); + } // getDateNextRun + + /** + * Get the date Last run + * @return date lext run + */ + public Timestamp getDateLastRun () + { + return p_model.getDateLastRun(); + } // getDateLastRun + + /** + * Get Description + * @return Description + */ + public String getDescription() + { + return p_model.getDescription(); + } // getDescription + + /** + * Get Model + * @return Model + */ + public AdempiereProcessor getModel() + { + return p_model; + } // getModel + + /** + * Calculate Sleep ms + * @return miliseconds + */ + private long calculateSleep () + { + String frequencyType = p_model.getFrequencyType(); + int frequency = p_model.getFrequency(); + if (frequency < 1) + frequency = 1; + // + long typeSec = 600; // 10 minutes + if (frequencyType == null) + typeSec = 300; // 5 minutes + else if (X_R_RequestProcessor.FREQUENCYTYPE_Minute.equals(frequencyType)) + typeSec = 60; + else if (X_R_RequestProcessor.FREQUENCYTYPE_Hour.equals(frequencyType)) + typeSec = 3600; + else if (X_R_RequestProcessor.FREQUENCYTYPE_Day.equals(frequencyType)) + typeSec = 86400; + // + return typeSec * 1000 * frequency; // ms + } // calculateSleep + + /** + * Is Sleeping + * @return sleeping + */ + public boolean isSleeping() + { + return m_sleeping; + } // isSleeping + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer (getName()) + .append (",Prio=").append(getPriority()) + .append (",").append (getThreadGroup()) + .append (",Alive=").append(isAlive()) + .append (",Sleeping=").append(m_sleeping) + .append (",Last=").append(getDateLastRun()); + if (m_sleeping) + sb.append (",Next=").append(getDateNextRun(false)); + return sb.toString (); + } // toString + + /** + * Get Seconds Alive + * @return seconds alive + */ + public int getSecondsAlive() + { + if (m_start == 0) + return 0; + long now = System.currentTimeMillis(); + long ms = (now-m_start) / 1000; + return (int)ms; + } // getSecondsAlive + + /** + * Get Start Time + * @return start time + */ + public Timestamp getStartTime() + { + if (m_start == 0) + return null; + return new Timestamp (m_start); + } // getStartTime + + /** + * Get Processor Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs() + { + return p_model.getLogs(); + } // getLogs + +} // AdempiereServer diff --git a/serverRoot/src/main/server/org/compiere/server/AdempiereServerGroup.java b/serverRoot/src/main/server/org/compiere/server/AdempiereServerGroup.java new file mode 100644 index 0000000000..d2a14d6358 --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/server/AdempiereServerGroup.java @@ -0,0 +1,90 @@ +/****************************************************************************** + * 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.server; + +import org.compiere.util.*; + +/** + * Adempiere Server Group + * + * @author Jorg Janke + * @version $Id: AdempiereServerGroup.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $ + */ +public class AdempiereServerGroup extends ThreadGroup +{ + /** + * Get Adempiere Server Group + * @return Server Group + */ + public static AdempiereServerGroup get() + { + if (s_group == null || s_group.isDestroyed()) + s_group = new AdempiereServerGroup(); + return s_group; + } // get + + /** Group */ + private static AdempiereServerGroup s_group = null; + + /** + * AdempiereServerGroup + */ + private AdempiereServerGroup () + { + super ("AdempiereServers"); + setDaemon(true); + setMaxPriority(Thread.MAX_PRIORITY); + log.info(getName() + " - Parent=" + getParent()); + } // AdempiereServerGroup + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + /** + * Uncaught Exception + * @param t thread + * @param e exception + */ + public void uncaughtException (Thread t, Throwable e) + { + log.info ("uncaughtException = " + e.toString()); + super.uncaughtException (t, e); + } // uncaughtException + + /** + * String Representation + * @return name + */ + public String toString () + { + return getName(); + } // toString + + /** + * Dump Info + */ + public void dump () + { + log.fine(getName() + (isDestroyed() ? " (destroyed)" : "")); + log.fine("- Parent=" + getParent()); + Thread[] list = new Thread[activeCount()]; + log.fine("- Count=" + enumerate(list, true)); + for (int i = 0; i < list.length; i++) + log.fine("-- " + list[i]); + } // dump + +} // AdempiereServerGroup diff --git a/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java b/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java new file mode 100644 index 0000000000..5285c1cdd6 --- /dev/null +++ b/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java @@ -0,0 +1,532 @@ +/****************************************************************************** + * 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.server; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.*; +import org.compiere.ldap.*; +import org.compiere.model.*; +import org.compiere.util.*; +import org.compiere.wf.*; + +/** + * Adempiere Server Manager + * + * @author Jorg Janke + * @version $Id: AdempiereServerMgr.java,v 1.4 2006/10/09 00:23:26 jjanke Exp $ + */ +public class AdempiereServerMgr +{ + /** + * Get Adempiere Server Manager + * @return mgr + */ + public static AdempiereServerMgr get() + { + if (m_serverMgr == null) + { + // for faster subsequent calls + m_serverMgr = new AdempiereServerMgr(); + m_serverMgr.startServers(); + m_serverMgr.log.info(m_serverMgr.toString()); + } + return m_serverMgr; + } // get + + /** Singleton */ + private static AdempiereServerMgr m_serverMgr = null; + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + /************************************************************************** + * Adempiere Server Manager + */ + private AdempiereServerMgr () + { + super(); + startEnvironment(); + // m_serverMgr.startServers(); + } // AdempiereServerMgr + + /** The Servers */ + private ArrayList
" + ex + "
"); + } + + try + { + StatusHome statusHome = (StatusHome)context.lookup (StatusHome.JNDI_NAME); + Status status = statusHome.create(); + out.println("" + status.getStatus() + "
"); + status.remove(); + } + catch (Exception ex) + { + out.println("" + ex + "
"); + } + + try + { + ServerHome serverHome = (ServerHome)context.lookup (ServerHome.JNDI_NAME); + Server server = serverHome.create(); + out.println("" + server.getStatus() + "
"); + server.remove(); + } + catch (Exception ex) + { + out.println("" + ex + "
"); + } + + try + { + out.println("" + e + "
"); + } + + + out.println(""); + } + + /** + * Put - Processes Get + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + public void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + doGet (request, response); + } + /** + * Destroy + */ + public void destroy() + { + getServletContext().log("StatusInfo.destroy"); + } +} diff --git a/serverRoot/src/web/AdemPiere150x50.gif b/serverRoot/src/web/AdemPiere150x50.gif new file mode 100644 index 0000000000..6244fce225 Binary files /dev/null and b/serverRoot/src/web/AdemPiere150x50.gif differ diff --git a/serverRoot/src/web/Adempiere120x60.gif b/serverRoot/src/web/Adempiere120x60.gif new file mode 100644 index 0000000000..07ca4d0ff0 Binary files /dev/null and b/serverRoot/src/web/Adempiere120x60.gif differ diff --git a/serverRoot/src/web/Background.gif b/serverRoot/src/web/Background.gif new file mode 100644 index 0000000000..11988728ed Binary files /dev/null and b/serverRoot/src/web/Background.gif differ diff --git a/serverRoot/src/web/C32.gif b/serverRoot/src/web/C32.gif new file mode 100644 index 0000000000..c83d267cbd Binary files /dev/null and b/serverRoot/src/web/C32.gif differ diff --git a/serverRoot/src/web/Logo.gif b/serverRoot/src/web/Logo.gif new file mode 100644 index 0000000000..f3e3c93682 Binary files /dev/null and b/serverRoot/src/web/Logo.gif differ diff --git a/serverRoot/src/web/WEB-INF/web.xml b/serverRoot/src/web/WEB-INF/web.xml new file mode 100644 index 0000000000..295ca650dd --- /dev/null +++ b/serverRoot/src/web/WEB-INF/web.xml @@ -0,0 +1,75 @@ + + +
+
|
+
+ ||||||||||||
+
|
+
+ ||||||||||||
+
|
+
+ ||||||||||||
+
|
+
+
Due to Browser incompatibilities, here is a list of different ways to start the Adempiere Java Client from a Browser.
+This requires that your browser supports Java.
+Applet Start Details
+
After the Adempiere Client started DO NOT close/use this window as that will crash the application!
+ Microsoft IE + + |
+
+ Non IE Browsers + + + |
+
Browsers supporting the EMBED tag + Code commented out - modify source if required! + + |
+
Browsers supporting the APPLET tag + Code commented out - modify source if required! + + |
+
+ + diff --git a/serverRoot/src/web/error.html b/serverRoot/src/web/error.html new file mode 100644 index 0000000000..da01ce500d --- /dev/null +++ b/serverRoot/src/web/error.html @@ -0,0 +1,13 @@ + + + + +
The Adempiere Server encountered a unrecoverable error.
+Click here if not forwarded automatically
+ + diff --git a/serverRoot/src/web/robots.txt b/serverRoot/src/web/robots.txt new file mode 100644 index 0000000000..991b78a1d2 --- /dev/null +++ b/serverRoot/src/web/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: / +Disallow: /adempiere +Disallow: /jmx-console diff --git a/serverRoot/src/web/standard.css b/serverRoot/src/web/standard.css new file mode 100644 index 0000000000..f60bed7ed2 --- /dev/null +++ b/serverRoot/src/web/standard.css @@ -0,0 +1,151 @@ +/* Adempiere Root (c) Jorg Janke */ +/* $Id: standard.css,v 1.1 2006/04/21 18:04:14 jjanke Exp $ */ +body{ + background-color: #FFFFFF; + color: #000000; + font-size: 76%; + font-family: Verdana, Arial, sans-serif; + line-height: 1.3em; +} + +a{ + color: #3465a4; + text-decoration: none; +} + +a:hover{ + text-decoration: none; +} + +h1{ + color: #FF0000; + font-size: x-large; + margin-bottom: 10px; + margin-top: 0; +} + +h2{ + color: #000066; + font-size: large; +} + +h3{ + color: #0000CC; + font-size: medium; + font-style: normal; + font-weight: bold; +} + +h4{ + color: #6600CC; + font-size: medium; + font-style: italic; +} + +h5{ + color: #660099; + font-size: medium; + font-weight: normal; +} + +h6{ + font-size: larger; + font-weight: bold; +} + +hr{ + color: #000099; + padding-bottom: 0; + padding-top: 0; +} + +p{ + text-align: justify; +} + +th{ + background-color: #E6E6FA; + text-align: left; +} + +caption{ + color: #660099; + text-align: left; + font-style: italic; + font-weight: bolder; +} + + +.menuDetail{ + color: #660099; + font-family: Arial,Helvetica,sans-serif; + font-size: 12px; + padding-bottom: 0; + padding-left: 20px; + padding-top: 0; + text-decoration: none; +} + +.menuDetail:hover{ + color: #660099; + font-family: Arial,Helvetica,sans-serif; + font-size: 12px; + padding-bottom: 0; + padding-left: 20px; + padding-top: 0; + text-decoration: none; + background-color: #99FFFF; +} + +.menuMain{ + color: #000066; + font-family: Arial,Helvetica,sans-serif; + font-size: 16px; + text-align: left; + text-decoration: none; +} + +.menuMain:hover{ + color: #000066; + font-family: Arial,Helvetica,sans-serif; + font-size: 16px; + text-align: left; + text-decoration: none; + background-color: #99FFFF; +} + +.menuSub{ + color: #000066; + font-family: Arial,Helvetica,sans-serif; + font-size: 14px; + padding-left: 10px; + text-align: left; + text-decoration: none; +} + +.menuSub:hover{ + color: #000066; + font-family: Arial,Helvetica,sans-serif; + font-size: 14px; + padding-left: 10px; + text-align: left; + text-decoration: none; + background-color: #99FFFF; +} + +.Cerror{ +background:#FF4A4A; +} +.Cmandatory{ +background:#9DFFFF; +} +.Cbasket{ + font-size: 9px; + display: inline; +} +#imgButton{ +border-style:outset; +} +#imgButtonPressed{ +border-style:inset; +} diff --git a/serverRoot/src/web/webstart.jpg b/serverRoot/src/web/webstart.jpg new file mode 100644 index 0000000000..aa7d066107 Binary files /dev/null and b/serverRoot/src/web/webstart.jpg differ diff --git a/serverRoot/src/web/webstart_s.jpg b/serverRoot/src/web/webstart_s.jpg new file mode 100644 index 0000000000..7dc44d8c2e Binary files /dev/null and b/serverRoot/src/web/webstart_s.jpg differ diff --git a/serverRoot/src/web/zip.gif b/serverRoot/src/web/zip.gif new file mode 100644 index 0000000000..f5d41b6386 Binary files /dev/null and b/serverRoot/src/web/zip.gif differ diff --git a/serverRoot/xdoclet-build.xml b/serverRoot/xdoclet-build.xml new file mode 100644 index 0000000000..3c61bae1ad --- /dev/null +++ b/serverRoot/xdoclet-build.xml @@ -0,0 +1,37 @@ + +