diff --git a/andromeida.midsuit.project/src/andromedia/midsuit/doc/MID_DocInvoice.java b/andromeida.midsuit.project/src/andromedia/midsuit/doc/MID_DocInvoice.java
new file mode 100644
index 0000000..1cc5709
--- /dev/null
+++ b/andromeida.midsuit.project/src/andromedia/midsuit/doc/MID_DocInvoice.java
@@ -0,0 +1,1225 @@
+/******************************************************************************
+ * 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 andromedia.midsuit.doc;
+
+import java.math.BigDecimal;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+
+import org.adempiere.exceptions.AverageCostingZeroQtyException;
+import org.compiere.acct.Doc;
+import org.compiere.acct.DocLine;
+import org.compiere.acct.DocTax;
+import org.compiere.acct.Fact;
+import org.compiere.acct.FactLine;
+import org.compiere.model.I_M_InOutLine;
+import org.compiere.model.MAccount;
+import org.compiere.model.MAcctSchema;
+import org.compiere.model.MClientInfo;
+import org.compiere.model.MConversionRate;
+import org.compiere.model.MCostDetail;
+import org.compiere.model.MCurrency;
+import org.compiere.model.MElementValue;
+import org.compiere.model.MInvoice;
+import org.compiere.model.MInvoiceLine;
+import org.compiere.model.MLandedCostAllocation;
+import org.compiere.model.MOrderLandedCostAllocation;
+import org.compiere.model.MProduct;
+import org.compiere.model.MProjectPhase;
+import org.compiere.model.MTax;
+import org.compiere.model.ProductCost;
+import org.compiere.model.X_M_Cost;
+import org.compiere.util.DB;
+import org.compiere.util.Env;
+import org.compiere.util.Trx;
+
+/**
+ * Post Invoice Documents.
+ *
+ * Table: C_Invoice (318)
+ * Document Types: ARI, ARC, ARF, API, APC
+ *
+ * @author Jorg Janke
+ * @author Armen Rizal, Goodwill Consulting
+ * BF: 2797257 Landed Cost Detail is not using allocation qty
+ *
+ * @version $Id: Doc_Invoice.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
+ */
+public class MID_DocInvoice extends Doc
+{
+ /**
+ * Constructor
+ * @param as accounting schemata
+ * @param rs record
+ * @param trxName trx
+ */
+ public MID_DocInvoice(MAcctSchema as, ResultSet rs, String trxName)
+ {
+ super (as, MInvoice.class, rs, null, trxName);
+ } // Doc_Invoice
+
+ /** Contained Optional Tax Lines */
+ protected DocTax[] m_taxes = null;
+ /** Currency Precision */
+ protected int m_precision = -1;
+ /** All lines are Service */
+ protected boolean m_allLinesService = true;
+ /** All lines are product item */
+ protected 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);
+ if (log.isLoggable(Level.FINE)) log.fine("Lines=" + p_lines.length + ", Taxes=" + m_taxes.length);
+ return null;
+ } // loadDocumentDetails
+
+ /**
+ * Load Invoice Taxes
+ * @return DocTax Array
+ */
+ private DocTax[] loadTaxes()
+ {
+ ArrayList list = new ArrayList();
+ String sql = "SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax "
+ + "FROM C_Tax t, C_InvoiceTax it "
+ + "WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Invoice_ID=?";
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try
+ {
+ pstmt = DB.prepareStatement(sql, getTrxName());
+ pstmt.setInt(1, get_ID());
+ rs = pstmt.executeQuery();
+ //
+ while (rs.next())
+ {
+ int C_Tax_ID = rs.getInt(1);
+ String name = rs.getString(2);
+ BigDecimal rate = rs.getBigDecimal(3);
+ BigDecimal taxBaseAmt = rs.getBigDecimal(4);
+ BigDecimal amount = rs.getBigDecimal(5);
+ boolean salesTax = "Y".equals(rs.getString(6));
+ //
+ DocTax taxLine = new DocTax(C_Tax_ID, name, rate,
+ taxBaseAmt, amount, salesTax);
+ if (log.isLoggable(Level.FINE)) log.fine(taxLine.toString());
+ list.add(taxLine);
+ }
+ }
+ catch (SQLException e)
+ {
+ log.log(Level.SEVERE, sql, e);
+ return null;
+ }
+ finally {
+ DB.close(rs, pstmt);
+ rs = null; pstmt = null;
+ }
+
+ // Return Array
+ DocTax[] tl = new DocTax[list.size()];
+ list.toArray(tl);
+ return tl;
+ } // loadTaxes
+
+ /**
+ * Load Invoice Line
+ * @param invoice invoice
+ * @return DocLine Array
+ */
+ private DocLine[] loadLines (MInvoice invoice)
+ {
+ ArrayList list = new ArrayList();
+ //
+ MInvoiceLine[] lines = invoice.getLines(false);
+ for (int i = 0; i < lines.length; i++)
+ {
+ MInvoiceLine line = lines[i];
+ if (line.isDescription())
+ continue;
+ DocLine docLine = new DocLine(line, this);
+ // Qty
+ BigDecimal Qty = line.getQtyInvoiced();
+ boolean cm = getDocumentType().equals(DOCTYPE_ARCredit)
+ || getDocumentType().equals(DOCTYPE_APCredit);
+ docLine.setQty(cm ? Qty.negate() : Qty, invoice.isSOTrx());
+ //
+ BigDecimal LineNetAmt = line.getLineNetAmt();
+ BigDecimal PriceList = line.getPriceList();
+ int C_Tax_ID = docLine.getC_Tax_ID();
+ // Correct included Tax
+ if (isTaxIncluded() && C_Tax_ID != 0)
+ {
+ MTax tax = MTax.get(getCtx(), C_Tax_ID);
+ if (!tax.isZeroTax())
+ {
+ BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPrecision());
+ if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
+ LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
+
+ if (tax.isSummary()) {
+ BigDecimal sumChildLineNetAmtTax = Env.ZERO;
+ DocTax taxToApplyDiff = null;
+ for (MTax childTax : tax.getChildTaxes(false)) {
+ if (!childTax.isZeroTax())
+ {
+ BigDecimal childLineNetAmtTax = childTax.calculateTax(LineNetAmt, false, getStdPrecision());
+ if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + LineNetAmt + " - Child Tax=" + childLineNetAmtTax);
+ for (int t = 0; t < m_taxes.length; t++)
+ {
+ if (m_taxes[t].getC_Tax_ID() == childTax.getC_Tax_ID())
+ {
+ m_taxes[t].addIncludedTax(childLineNetAmtTax);
+ taxToApplyDiff = m_taxes[t];
+ sumChildLineNetAmtTax = sumChildLineNetAmtTax.add(childLineNetAmtTax);
+ break;
+ }
+ }
+ }
+ }
+ BigDecimal diffChildVsSummary = LineNetAmtTax.subtract(sumChildLineNetAmtTax);
+ if (diffChildVsSummary.signum() != 0 && taxToApplyDiff != null) {
+ taxToApplyDiff.addIncludedTax(diffChildVsSummary);
+ }
+ } else {
+ for (int t = 0; t < m_taxes.length; t++)
+ {
+ if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
+ {
+ m_taxes[t].addIncludedTax(LineNetAmtTax);
+ break;
+ }
+ }
+ }
+
+ BigDecimal PriceListTax = tax.calculateTax(PriceList, true, getStdPrecision());
+ PriceList = PriceList.subtract(PriceListTax);
+ }
+ } // correct included Tax
+
+ docLine.setAmount (LineNetAmt, PriceList, Qty); // qty for discount calc
+ if (docLine.isItem())
+ m_allLinesService = false;
+ else
+ m_allLinesItem = false;
+ //
+ if (log.isLoggable(Level.FINE)) log.fine(docLine.toString());
+ list.add(docLine);
+ }
+
+ // Convert to Array
+ DocLine[] dls = new DocLine[list.size()];
+ list.toArray(dls);
+
+ // Included Tax - make sure that no difference
+ if (isTaxIncluded())
+ {
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ if (m_taxes[i].isIncludedTaxDifference())
+ {
+ BigDecimal diff = m_taxes[i].getIncludedTaxDifference();
+ for (int j = 0; j < dls.length; j++)
+ {
+ MTax lineTax = MTax.get(getCtx(), dls[j].getC_Tax_ID());
+ MTax[] composingTaxes = null;
+ if (lineTax.isSummary()) {
+ composingTaxes = lineTax.getChildTaxes(false);
+ } else {
+ composingTaxes = new MTax[1];
+ composingTaxes[0] = lineTax;
+ }
+ for (MTax mTax : composingTaxes) {
+ if (mTax.getC_Tax_ID() == m_taxes[i].getC_Tax_ID())
+ {
+ dls[j].setLineNetAmtDifference(diff);
+ m_taxes[i].addIncludedTax(diff.negate());
+ diff = Env.ZERO;
+ break;
+ }
+ }
+ if (diff.signum() == 0) {
+ break;
+ }
+ } // for all lines
+ } // tax difference
+ } // for all taxes
+ } // Included Tax difference
+
+ // Return Array
+ return dls;
+ } // loadLines
+
+ /**
+ * Get Currency Precision
+ * @return precision
+ */
+ private int getStdPrecision()
+ {
+ if (m_precision == -1)
+ m_precision = MCurrency.getStdPrecision(getCtx(), getC_Currency_ID());
+ return m_precision;
+ } // getPrecision
+
+
+ /**************************************************************************
+ * Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
+ * @return positive amount, if total invoice is bigger than lines
+ */
+ public BigDecimal getBalance()
+ {
+ BigDecimal retValue = Env.ZERO;
+ StringBuilder sb = new StringBuilder (" [");
+ // Total
+ retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross));
+ sb.append(getAmount(Doc.AMTTYPE_Gross));
+ // - Header Charge
+ retValue = retValue.subtract(getAmount(Doc.AMTTYPE_Charge));
+ sb.append("-").append(getAmount(Doc.AMTTYPE_Charge));
+ // - Tax
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ retValue = retValue.subtract(m_taxes[i].getAmount());
+ sb.append("-").append(m_taxes[i].getAmount());
+ }
+ // - Lines
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ retValue = retValue.subtract(p_lines[i].getAmtSource());
+ sb.append("-").append(p_lines[i].getAmtSource());
+ }
+ sb.append("]");
+ //
+ if (log.isLoggable(Level.FINE)) log.fine(toString() + " Balance=" + retValue + sb.toString());
+ return retValue;
+ } // getBalance
+
+ /**
+ * Create Facts (the accounting logic) for
+ * ARI, ARC, ARF, API, APC.
+ *
+ * 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 createFacts (MAcctSchema as)
+ {
+ //
+ ArrayList facts = new ArrayList();
+ // create Fact Header
+ Fact fact = new Fact(this, as, Fact.POST_Actual);
+
+ // Cash based accounting
+ if (!as.isAccrual())
+ return facts;
+
+ // ** ARI, ARF
+ if (getDocumentType().equals(DOCTYPE_ARInvoice)
+ || getDocumentType().equals(DOCTYPE_ARProForma))
+ {
+ BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ BigDecimal serviceAmt = Env.ZERO;
+
+ // Header Charge CR
+ BigDecimal amt = getAmount(Doc.AMTTYPE_Charge);
+ if (amt != null && amt.signum() != 0)
+ fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
+ getC_Currency_ID(), null, amt);
+ // TaxDue CR
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ amt = m_taxes[i].getAmount();
+ if (amt != null && amt.signum() != 0)
+ {
+ FactLine tl = fact.createLine(null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
+ getC_Currency_ID(), m_taxes[i].getAmount().signum()<0 ? m_taxes[i].getAmount().negate() : null, m_taxes[i].getAmount().signum()<0 ? null : m_taxes[i].getAmount());
+ if (tl != null)
+ tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
+ }
+ }
+ // Revenue CR
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ amt = p_lines[i].getAmtSource();
+ BigDecimal dAmt = null;
+ if (as.isTradeDiscountPosted())
+ {
+ BigDecimal discount = p_lines[i].getDiscount();
+ if (discount != null && discount.signum() != 0)
+ {
+ amt = amt.add(discount);
+ dAmt = discount;
+ fact.createLine (p_lines[i],
+ p_lines[i].getAccount(ProductCost.ACCTTYPE_P_TDiscountGrant, as),
+ getC_Currency_ID(), dAmt, null);
+ }
+ }
+ fact.createLine (p_lines[i],
+ p_lines[i].getAccount(ProductCost.ACCTTYPE_P_Revenue, as),
+ getC_Currency_ID(), null, amt);
+ if (!p_lines[i].isItem())
+ {
+ grossAmt = grossAmt.subtract(amt);
+ serviceAmt = serviceAmt.add(amt);
+ }
+ }
+ // Set Locations
+ FactLine[] fLines = fact.getLines();
+ for (int i = 0; i < fLines.length; i++)
+ {
+ if (fLines[i] != null)
+ {
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
+ }
+ }
+
+ // Receivables DR
+ int receivables_ID = getValidCombination_ID(Doc.ACCTTYPE_C_Receivable, as);
+ int receivablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable_Services, as);
+ if (m_allLinesItem || !as.isPostServices()
+ || receivables_ID == receivablesServices_ID)
+ {
+ grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ serviceAmt = Env.ZERO;
+ }
+ else if (m_allLinesService)
+ {
+ serviceAmt = getAmount(Doc.AMTTYPE_Gross);
+ grossAmt = Env.ZERO;
+ }
+ if (grossAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), receivables_ID),
+ getC_Currency_ID(), grossAmt, null);
+ if (serviceAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), receivablesServices_ID),
+ getC_Currency_ID(), serviceAmt, null);
+ }
+ // ARC
+ else if (getDocumentType().equals(DOCTYPE_ARCredit))
+ {
+ BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ BigDecimal serviceAmt = Env.ZERO;
+
+ // Header Charge DR
+ BigDecimal amt = getAmount(Doc.AMTTYPE_Charge);
+ if (amt != null && amt.signum() != 0)
+ fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
+ getC_Currency_ID(), amt, null);
+ // TaxDue DR
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ amt = m_taxes[i].getAmount();
+ if (amt != null && amt.signum() != 0)
+ {
+ FactLine tl = fact.createLine(null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
+ getC_Currency_ID(), amt, null);
+ if (tl != null)
+ tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
+ }
+ }
+ // Revenue CR
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ amt = p_lines[i].getAmtSource();
+ BigDecimal dAmt = null;
+ if (as.isTradeDiscountPosted())
+ {
+ BigDecimal discount = p_lines[i].getDiscount();
+ if (discount != null && discount.signum() != 0)
+ {
+ amt = amt.add(discount);
+ dAmt = discount;
+ fact.createLine (p_lines[i],
+ p_lines[i].getAccount (ProductCost.ACCTTYPE_P_TDiscountGrant, as),
+ getC_Currency_ID(), null, dAmt);
+ }
+ }
+ fact.createLine (p_lines[i],
+ p_lines[i].getAccount (ProductCost.ACCTTYPE_P_Revenue, as),
+ getC_Currency_ID(), amt, null);
+ if (!p_lines[i].isItem())
+ {
+ grossAmt = grossAmt.subtract(amt);
+ serviceAmt = serviceAmt.add(amt);
+ }
+ }
+ // Set Locations
+ FactLine[] fLines = fact.getLines();
+ for (int i = 0; i < fLines.length; i++)
+ {
+ if (fLines[i] != null)
+ {
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
+ }
+ }
+ // Receivables CR
+ int receivables_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable, as);
+ int receivablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable_Services, as);
+ if (m_allLinesItem || !as.isPostServices()
+ || receivables_ID == receivablesServices_ID)
+ {
+ grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ serviceAmt = Env.ZERO;
+ }
+ else if (m_allLinesService)
+ {
+ serviceAmt = getAmount(Doc.AMTTYPE_Gross);
+ grossAmt = Env.ZERO;
+ }
+ if (grossAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), receivables_ID),
+ getC_Currency_ID(), null, grossAmt);
+ if (serviceAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), receivablesServices_ID),
+ getC_Currency_ID(), null, serviceAmt);
+ }
+
+ // ** API
+ else if (getDocumentType().equals(DOCTYPE_APInvoice))
+ {
+ BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ BigDecimal serviceAmt = Env.ZERO;
+ MInvoice invoice = MInvoice.get(getCtx(), get_ID());
+
+ // Charge DR
+ FactLine aa = fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
+ getC_Currency_ID(), getAmount(Doc.AMTTYPE_Charge), null);
+ if (aa != null)
+ {
+ aa.set_CustomColumn("RefDocumentNo", (new MInvoice(getCtx(), this.get_ID(), getTrxName())).get_ValueAsString("RefDocumentNo"));
+ aa.saveEx();
+ }
+
+ // TaxCredit DR
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ FactLine tl = fact.createLine(null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
+ getC_Currency_ID(), m_taxes[i].getAmount().signum()>0 ? m_taxes[i].getAmount() : null, m_taxes[i].getAmount().signum()>0 ? null : m_taxes[i].getAmount().negate() );
+ if (tl != null)
+ tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
+ }
+ // Expense DR
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ DocLine line = p_lines[i];
+ boolean landedCost = landedCost(as, fact, line, true);
+ if (landedCost && as.isExplicitCostAdjustment())
+ {
+ fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), line.getAmtSource(), null);
+ //
+ FactLine fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), null, line.getAmtSource());
+ String desc = line.getDescription();
+ if (desc == null)
+ desc = "100%";
+ else
+ desc += " 100%";
+ fl.setDescription(desc);
+ }
+ if (!landedCost)
+ {
+
+ MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
+ if (line.isItem())//@win)
+ expense = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
+ BigDecimal amt = line.getAmtSource();
+ BigDecimal dAmt = null;
+ if (as.isTradeDiscountPosted() && !line.isItem())
+ {
+ BigDecimal discount = line.getDiscount();
+ if (discount != null && discount.signum() != 0)
+ {
+ amt = amt.add(discount);
+ dAmt = discount;
+ MAccount tradeDiscountReceived = line.getAccount(ProductCost.ACCTTYPE_P_TDiscountRec, as);
+ fact.createLine (line, tradeDiscountReceived,
+ getC_Currency_ID(), null, dAmt);
+ }
+ }
+ fact.createLine (line, expense,
+ getC_Currency_ID(), amt, null);
+
+ if (!line.isItem())
+ {
+ grossAmt = grossAmt.subtract(amt);
+ serviceAmt = serviceAmt.add(amt);
+ }
+ //
+ if (line.getM_Product_ID() != 0
+ && line.getProduct().isService()) // otherwise Inv Matching
+ MCostDetail.createInvoice(as, line.getAD_Org_ID(),
+ line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
+ line.get_ID(), 0, // No Cost Element
+ line.getAmtSource(), line.getQty(),
+ line.getDescription(), getTrxName());
+ }
+ }
+ // Set Locations
+ FactLine[] fLines = fact.getLines();
+ for (int i = 0; i < fLines.length; i++)
+ {
+ if (fLines[i] != null)
+ {
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
+ }
+ }
+
+ // Liability CR
+ int payables_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability, as);
+ int payablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability_Services, as);
+ if (m_allLinesItem || !as.isPostServices()
+ || payables_ID == payablesServices_ID)
+ {
+ grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ serviceAmt = Env.ZERO;
+ }
+ else if (m_allLinesService)
+ {
+ serviceAmt = getAmount(Doc.AMTTYPE_Gross);
+ grossAmt = Env.ZERO;
+ }
+ if (grossAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), payables_ID),
+ getC_Currency_ID(), null, grossAmt);
+ if (serviceAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
+ getC_Currency_ID(), null, serviceAmt);
+ //
+ updateProductPO(as); // Only API
+
+ FactLine[] factLines = fact.getLines();
+ for(FactLine factLine : factLines)
+ {
+ factLine.set_CustomColumn("RefDocumentNo", (new MInvoice(getCtx(), this.get_ID(), getTrxName())).get_ValueAsString("RefDocumentNo"));
+ }
+ }
+ // APC
+ else if (getDocumentType().equals(DOCTYPE_APCredit))
+ {
+ BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ BigDecimal serviceAmt = Env.ZERO;
+ // Charge CR
+ fact.createLine (null, getAccount(Doc.ACCTTYPE_Charge, as),
+ getC_Currency_ID(), null, getAmount(Doc.AMTTYPE_Charge));
+ // TaxCredit CR
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ FactLine tl = fact.createLine (null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
+ getC_Currency_ID(), null, m_taxes[i].getAmount());
+ if (tl != null)
+ tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
+ }
+ // Expense CR
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ DocLine line = p_lines[i];
+ boolean landedCost = landedCost(as, fact, line, false);
+ if (landedCost && as.isExplicitCostAdjustment())
+ {
+ fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), null, line.getAmtSource());
+ //
+ FactLine fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), line.getAmtSource(), null);
+ String desc = line.getDescription();
+ if (desc == null)
+ desc = "100%";
+ else
+ desc += " 100%";
+ fl.setDescription(desc);
+ }
+ if (!landedCost)
+ {
+ MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
+ if (line.isItem())
+ expense = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
+ BigDecimal amt = line.getAmtSource();
+ BigDecimal dAmt = null;
+ if (as.isTradeDiscountPosted() && !line.isItem())
+ {
+ BigDecimal discount = line.getDiscount();
+ if (discount != null && discount.signum() != 0)
+ {
+ amt = amt.add(discount);
+ dAmt = discount;
+ MAccount tradeDiscountReceived = line.getAccount(ProductCost.ACCTTYPE_P_TDiscountRec, as);
+ fact.createLine (line, tradeDiscountReceived,
+ getC_Currency_ID(), dAmt, null);
+ }
+ }
+ fact.createLine (line, expense,
+ getC_Currency_ID(), null, amt);
+ if (!line.isItem())
+ {
+ grossAmt = grossAmt.subtract(amt);
+ serviceAmt = serviceAmt.add(amt);
+ }
+ //
+ if (line.getM_Product_ID() != 0
+ && line.getProduct().isService()) // otherwise Inv Matching
+ MCostDetail.createInvoice(as, line.getAD_Org_ID(),
+ line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
+ line.get_ID(), 0, // No Cost Element
+ line.getAmtSource().negate(), line.getQty(),
+ line.getDescription(), getTrxName());
+ }
+ }
+ // Set Locations
+ FactLine[] fLines = fact.getLines();
+ for (int i = 0; i < fLines.length; i++)
+ {
+ if (fLines[i] != null)
+ {
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
+ }
+ }
+ // Liability DR
+ int payables_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability, as);
+ int payablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability_Services, as);
+ if (m_allLinesItem || !as.isPostServices()
+ || payables_ID == payablesServices_ID)
+ {
+ grossAmt = getAmount(Doc.AMTTYPE_Gross);
+ serviceAmt = Env.ZERO;
+ }
+ else if (m_allLinesService)
+ {
+ serviceAmt = getAmount(Doc.AMTTYPE_Gross);
+ grossAmt = Env.ZERO;
+ }
+ if (grossAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), payables_ID),
+ getC_Currency_ID(), grossAmt, null);
+ if (serviceAmt.signum() != 0)
+ fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
+ getC_Currency_ID(), serviceAmt, null);
+ FactLine[] factLines = fact.getLines();
+ for(FactLine factLine : factLines)
+ {
+ factLine.set_CustomColumn("RefDocumentNo", (new MInvoice(getCtx(), this.get_ID(), getTrxName())).get_ValueAsString("RefDocumentNo"));
+ }
+ }
+ else
+ {
+ p_Error = "DocumentType unknown: " + getDocumentType();
+ log.log(Level.SEVERE, p_Error);
+ fact = null;
+ }
+ //
+ facts.add(fact);
+ return facts;
+ } // createFact
+
+ /**
+ * Create Fact Cash Based (i.e. only revenue/expense)
+ * @param as accounting schema
+ * @param fact fact to add lines to
+ * @param multiplier source amount multiplier
+ * @return accounted amount
+ */
+ public BigDecimal createFactCash (MAcctSchema as, Fact fact, BigDecimal multiplier)
+ {
+ boolean creditMemo = getDocumentType().equals(DOCTYPE_ARCredit)
+ || getDocumentType().equals(DOCTYPE_APCredit);
+ boolean payables = getDocumentType().equals(DOCTYPE_APInvoice)
+ || getDocumentType().equals(DOCTYPE_APCredit);
+ BigDecimal acctAmt = Env.ZERO;
+ FactLine fl = null;
+ // Revenue/Cost
+ for (int i = 0; i < p_lines.length; i++)
+ {
+ DocLine line = p_lines[i];
+ boolean landedCost = false;
+ if (payables)
+ landedCost = landedCost(as, fact, line, false);
+ if (landedCost && as.isExplicitCostAdjustment())
+ {
+ fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), null, line.getAmtSource());
+ //
+ fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
+ getC_Currency_ID(), line.getAmtSource(), null);
+ String desc = line.getDescription();
+ if (desc == null)
+ desc = "100%";
+ else
+ desc += " 100%";
+ fl.setDescription(desc);
+ }
+ if (!landedCost)
+ {
+ MAccount acct = line.getAccount(
+ payables ? ProductCost.ACCTTYPE_P_Expense : ProductCost.ACCTTYPE_P_Revenue, as);
+ if (payables)
+ {
+ // if Fixed Asset
+ if (line.isItem())
+ acct = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
+ }
+ BigDecimal amt = line.getAmtSource().multiply(multiplier);
+ BigDecimal amt2 = null;
+ if (creditMemo)
+ {
+ amt2 = amt;
+ amt = null;
+ }
+ if (payables) // Vendor = DR
+ fl = fact.createLine (line, acct,
+ getC_Currency_ID(), amt, amt2);
+ else // Customer = CR
+ fl = fact.createLine (line, acct,
+ getC_Currency_ID(), amt2, amt);
+ if (fl != null)
+ acctAmt = acctAmt.add(fl.getAcctBalance());
+ }
+ }
+ // Tax
+ for (int i = 0; i < m_taxes.length; i++)
+ {
+ BigDecimal amt = m_taxes[i].getAmount();
+ BigDecimal amt2 = null;
+ if (creditMemo)
+ {
+ amt2 = amt;
+ amt = null;
+ }
+ FactLine tl = null;
+ if (payables)
+ tl = fact.createLine (null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
+ getC_Currency_ID(), amt, amt2);
+ else
+ tl = fact.createLine (null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
+ getC_Currency_ID(), amt2, amt);
+ if (tl != null)
+ tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
+ }
+ // Set Locations
+ FactLine[] fLines = fact.getLines();
+ for (int i = 0; i < fLines.length; i++)
+ {
+ if (fLines[i] != null)
+ {
+ if (payables)
+ {
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
+ }
+ else
+ {
+ fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
+ fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
+ }
+ }
+ }
+ return acctAmt;
+ } // createFactCash
+
+
+ /**
+ * Create Landed Cost accounting & Cost lines
+ * @param as accounting schema
+ * @param fact fact
+ * @param line document line
+ * @param dr DR entry (normal api)
+ * @return true if landed costs were created
+ */
+ protected boolean landedCost (MAcctSchema as, Fact fact, DocLine line, boolean dr)
+ {
+ int C_InvoiceLine_ID = line.get_ID();
+ MLandedCostAllocation[] lcas = MLandedCostAllocation.getOfInvoiceLine(
+ getCtx(), C_InvoiceLine_ID, getTrxName());
+ if (lcas.length == 0)
+ return false;
+
+ // Calculate Total Base
+ double totalBase = 0;
+ for (int i = 0; i < lcas.length; i++)
+ totalBase += lcas[i].getBase().doubleValue();
+
+ Map costDetailAmtMap = new HashMap();
+
+ // Create New
+ MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName());
+ for (int i = 0; i < lcas.length; i++)
+ {
+ MLandedCostAllocation lca = lcas[i];
+ if (lca.getBase().signum() == 0)
+ continue;
+ double percent = lca.getBase().doubleValue() / totalBase;
+ String desc = il.getDescription();
+ if (desc == null)
+ desc = percent + "%";
+ else
+ desc += " - " + percent + "%";
+ if (line.getDescription() != null)
+ desc += " - " + line.getDescription();
+
+ // Accounting
+ BigDecimal drAmt = null;
+ BigDecimal crAmt = null;
+ MAccount account = null;
+ ProductCost pc = new ProductCost (Env.getCtx(),
+ lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(), getTrxName());
+ String costingMethod = pc.getProduct().getCostingMethod(as);
+ if (X_M_Cost.COSTINGMETHOD_AverageInvoice.equals(costingMethod) || X_M_Cost.COSTINGMETHOD_AveragePO.equals(costingMethod))
+ {
+
+ BigDecimal allocationAmt = lca.getAmt();
+ BigDecimal estimatedAmt = BigDecimal.ZERO;
+ int oCurrencyId = 0;
+ boolean usesSchemaCurrency = false;
+ Timestamp oDateAcct = getDateAcct();
+ if (lca.getM_InOutLine_ID() > 0)
+ {
+ I_M_InOutLine iol = lca.getM_InOutLine();
+ if (iol.getC_OrderLine_ID() > 0)
+ {
+ oCurrencyId = iol.getC_OrderLine().getC_Currency_ID();
+ oDateAcct = iol.getC_OrderLine().getC_Order().getDateAcct();
+ MOrderLandedCostAllocation[] allocations = MOrderLandedCostAllocation.getOfOrderLine(iol.getC_OrderLine_ID(), getTrxName());
+ for(MOrderLandedCostAllocation allocation : allocations)
+ {
+ if (allocation.getC_OrderLandedCost().getM_CostElement_ID() != lca.getM_CostElement_ID())
+ continue;
+
+ BigDecimal amt = allocation.getAmt();
+ BigDecimal qty = allocation.getQty();
+ if (qty.compareTo(iol.getMovementQty()) != 0)
+ {
+ amt = amt.multiply(iol.getMovementQty()).divide(qty, 12, BigDecimal.ROUND_HALF_UP);
+ }
+ estimatedAmt = estimatedAmt.add(amt);
+ }
+ }
+ }
+
+ if (estimatedAmt.scale() > as.getCostingPrecision())
+ {
+ estimatedAmt = estimatedAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP);
+ }
+ BigDecimal costAdjustmentAmt = allocationAmt;
+ if (estimatedAmt.signum() > 0)
+ {
+ //get other allocation amt
+ StringBuilder sql = new StringBuilder("SELECT Sum(Amt) FROM C_LandedCostAllocation WHERE M_InOutLine_ID=? ")
+ .append("AND C_LandedCostAllocation_ID<>? ")
+ .append("AND M_CostElement_ID=? ")
+ .append("AND AD_Client_ID=? ");
+ BigDecimal otherAmt = DB.getSQLValueBD(getTrxName(), sql.toString(), lca.getM_InOutLine_ID(), lca.getC_LandedCostAllocation_ID(),
+ lca.getM_CostElement_ID(), lca.getAD_Client_ID());
+ if (otherAmt != null)
+ {
+ estimatedAmt = estimatedAmt.subtract(otherAmt);
+ if (allocationAmt.signum() < 0)
+ {
+ //add back since the sum above would include the original trx
+ estimatedAmt = estimatedAmt.add(allocationAmt.negate());
+ }
+ }
+ //added for IDEMPIERE-3014
+ //convert to accounting schema currency
+ if (estimatedAmt.signum() > 0 && oCurrencyId != getC_Currency_ID())
+ {
+ estimatedAmt = MConversionRate.convert(getCtx(), estimatedAmt,
+ oCurrencyId, as.getC_Currency_ID(),
+ oDateAcct, getC_ConversionType_ID(),
+ getAD_Client_ID(), getAD_Org_ID());
+
+ allocationAmt = MConversionRate.convert(getCtx(), allocationAmt,
+ getC_Currency_ID(), as.getC_Currency_ID(),
+ getDateAcct(), getC_ConversionType_ID(),
+ getAD_Client_ID(), getAD_Org_ID());
+ setC_Currency_ID(as.getC_Currency_ID());
+ usesSchemaCurrency = true;
+ }
+
+ if (estimatedAmt.signum() > 0)
+ {
+ if (allocationAmt.signum() > 0)
+ costAdjustmentAmt = allocationAmt.subtract(estimatedAmt);
+ else if (allocationAmt.signum() < 0)
+ costAdjustmentAmt = allocationAmt.add(estimatedAmt);
+ }
+ }
+
+ if (!dr)
+ costAdjustmentAmt = costAdjustmentAmt.negate();
+
+ boolean zeroQty = false;
+ if (costAdjustmentAmt.signum() != 0)
+ {
+ Trx trx = Trx.get(getTrxName(), false);
+ Savepoint savepoint = null;
+ try {
+ savepoint = trx.setSavepoint(null);
+ BigDecimal costDetailAmt = costAdjustmentAmt;
+ //convert to accounting schema currency
+ if (getC_Currency_ID() != as.getC_Currency_ID())
+ costDetailAmt = MConversionRate.convert(getCtx(), costDetailAmt,
+ getC_Currency_ID(), as.getC_Currency_ID(),
+ getDateAcct(), getC_ConversionType_ID(),
+ getAD_Client_ID(), getAD_Org_ID());
+ if (costDetailAmt.scale() > as.getCostingPrecision())
+ costDetailAmt = costDetailAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP);
+
+ String key = lca.getM_Product_ID()+"_"+lca.getM_AttributeSetInstance_ID();
+ BigDecimal prevAmt = costDetailAmtMap.remove(key);
+ if (prevAmt != null) {
+ costDetailAmt = costDetailAmt.add(prevAmt);
+ }
+ costDetailAmtMap.put(key, costDetailAmt);
+ if (!MCostDetail.createInvoice(as, lca.getAD_Org_ID(),
+ lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(),
+ C_InvoiceLine_ID, lca.getM_CostElement_ID(),
+ costDetailAmt, lca.getQty(),
+ desc, getTrxName())) {
+ throw new RuntimeException("Failed to create cost detail record.");
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e.getLocalizedMessage(), e);
+ } catch (AverageCostingZeroQtyException e) {
+ zeroQty = true;
+ try {
+ trx.rollback(savepoint);
+ savepoint = null;
+ } catch (SQLException e1) {
+ throw new RuntimeException(e1.getLocalizedMessage(), e1);
+ }
+ } finally {
+ if (savepoint != null) {
+ try {
+ trx.releaseSavepoint(savepoint);
+ } catch (SQLException e) {}
+ }
+ }
+ }
+
+ boolean reversal = false;
+ if (allocationAmt.signum() < 0) //reversal
+ {
+ allocationAmt = allocationAmt.negate();
+ reversal = true;
+ }
+
+ if (allocationAmt.signum() > 0)
+ {
+ if (allocationAmt.scale() > as.getStdPrecision())
+ {
+ allocationAmt = allocationAmt.setScale(as.getStdPrecision(), BigDecimal.ROUND_HALF_UP);
+ }
+ if (estimatedAmt.scale() > as.getStdPrecision())
+ {
+ estimatedAmt = estimatedAmt.setScale(as.getStdPrecision(), BigDecimal.ROUND_HALF_UP);
+ }
+ int compare = allocationAmt.compareTo(estimatedAmt);
+ if (compare > 0)
+ {
+ drAmt = dr ? (reversal ? null : estimatedAmt): (reversal ? estimatedAmt : null);
+ crAmt = dr ? (reversal ? estimatedAmt : null): (reversal ? null : estimatedAmt);
+ account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
+ FactLine fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+
+ BigDecimal overAmt = allocationAmt.subtract(estimatedAmt);
+ drAmt = dr ? (reversal ? null : overAmt) : (reversal ? overAmt : null);
+ crAmt = dr ? (reversal ? overAmt : null) : (reversal ? null : overAmt);
+ account = zeroQty ? pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as) : pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
+ fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+ }
+ else if (compare < 0)
+ {
+ drAmt = dr ? (reversal ? null : estimatedAmt) : (reversal ? estimatedAmt : null);
+ crAmt = dr ? (reversal ? estimatedAmt : null) : (reversal ? null : estimatedAmt);
+ account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
+ FactLine fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+
+ BigDecimal underAmt = estimatedAmt.subtract(allocationAmt);
+ drAmt = dr ? (reversal ? underAmt : null) : (reversal ? null : underAmt);
+ crAmt = dr ? (reversal ? null : underAmt) : (reversal ? underAmt : null);
+ account = zeroQty ? pc.getAccount(ProductCost.ACCTTYPE_P_AverageCostVariance, as) : pc.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
+ fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+ }
+ else
+ {
+ drAmt = dr ? (reversal ? null : allocationAmt) : (reversal ? allocationAmt : null);
+ crAmt = dr ? (reversal ? allocationAmt : null) : (reversal ? null : allocationAmt);
+ account = pc.getAccount(ProductCost.ACCTTYPE_P_LandedCostClearing, as);
+ FactLine fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+ }
+ }
+ if (usesSchemaCurrency)
+ setC_Currency_ID(line.getC_Currency_ID());
+ }
+ else
+ {
+ if (dr)
+ drAmt = lca.getAmt();
+ else
+ crAmt = lca.getAmt();
+ account = pc.getAccount(ProductCost.ACCTTYPE_P_CostAdjustment, as);
+ FactLine fl = fact.createLine (line, account, getC_Currency_ID(), drAmt, crAmt);
+ fl.setDescription(desc);
+ fl.setM_Product_ID(lca.getM_Product_ID());
+ fl.setQty(line.getQty());
+ }
+ }
+
+ if (log.isLoggable(Level.CONFIG)) log.config("Created #" + lcas.length);
+ return true;
+ } // landedCosts
+
+ /**
+ * Update ProductPO PriceLastInv
+ * @param as accounting schema
+ */
+ protected void updateProductPO (MAcctSchema as)
+ {
+ MClientInfo ci = MClientInfo.get(getCtx(), as.getAD_Client_ID());
+ if (ci.getC_AcctSchema1_ID() != as.getC_AcctSchema_ID())
+ return;
+
+ StringBuilder sql = new StringBuilder (
+ "UPDATE M_Product_PO po ")
+ .append("SET PriceLastInv = ")
+ // select
+ .append("(SELECT currencyConvert(il.PriceActual,i.C_Currency_ID,po.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID) ")
+ .append("FROM C_Invoice i, C_InvoiceLine il ")
+ .append("WHERE i.C_Invoice_ID=il.C_Invoice_ID")
+ .append(" AND po.M_Product_ID=il.M_Product_ID AND po.C_BPartner_ID=i.C_BPartner_ID");
+ //jz + " AND ROWNUM=1 AND i.C_Invoice_ID=").append(get_ID()).append(") ")
+ if (DB.isOracle()) //jz
+ {
+ sql.append(" AND ROWNUM=1 ");
+ }
+ else
+ {
+ sql.append(" AND il.C_InvoiceLine_ID = (SELECT MIN(il1.C_InvoiceLine_ID) ")
+ .append("FROM C_Invoice i1, C_InvoiceLine il1 ")
+ .append("WHERE i1.C_Invoice_ID=il1.C_Invoice_ID")
+ .append(" AND po.M_Product_ID=il1.M_Product_ID AND po.C_BPartner_ID=i1.C_BPartner_ID")
+ .append(" AND i1.C_Invoice_ID=").append(get_ID()).append(") ");
+ }
+ sql.append(" AND i.C_Invoice_ID=").append(get_ID()).append(") ")
+ // update
+ .append("WHERE EXISTS (SELECT * ")
+ .append("FROM C_Invoice i, C_InvoiceLine il ")
+ .append("WHERE i.C_Invoice_ID=il.C_Invoice_ID")
+ .append(" AND po.M_Product_ID=il.M_Product_ID AND po.C_BPartner_ID=i.C_BPartner_ID")
+ .append(" AND i.C_Invoice_ID=").append(get_ID()).append(")");
+ int no = DB.executeUpdate(sql.toString(), getTrxName());
+ if (log.isLoggable(Level.FINE)) log.fine("Updated=" + no);
+ } // updateProductPO
+
+ private int getSwadayaAccount(DocLine line) {
+ MElementValue costCenter = new MElementValue(getCtx(), line.getUser1_ID(), getTrxName());
+ String ccType = costCenter.get_ValueAsString("CostCenterType");
+ int accountID = 1000107; //default Beban Umum dan Administrasi
+ if (ccType.equalsIgnoreCase("BIZ")) {
+ if (line.getC_Project_ID()!=0 && line.getC_ProjectPhase_ID()!=0) {
+ MProjectPhase projectPhase = new MProjectPhase(getCtx(), line.getC_ProjectPhase_ID(), getTrxName());
+ String projectPhaseType= projectPhase.get_ValueAsString("SWG_ServiceType");
+ if (projectPhaseType.equalsIgnoreCase("RENT"))
+ accountID=1000108; //Beban Kontrak Sewa Alat Berat
+ else
+ accountID=1000034; //PDP
+ } else {
+ accountID = 1000106; //Biaya Operasional
+ }
+
+ } else if (ccType.equalsIgnoreCase("MAR")) {
+ accountID = 1000131; //Beban Marketing
+ }
+
+ return accountID;
+
+ }
+
+ public boolean isAssetLine(DocLine line)
+ {
+ if (line.getM_Product_ID() != 0)
+ {
+ MProduct product = MProduct.get(Env.getCtx(), line.getM_Product_ID());
+ if (product.get_ID() == line.getM_Product_ID() && product.getProductType().equals(MProduct.PRODUCTTYPE_Asset))
+ return true;
+ }
+ return false;
+ } // isItem
+} // Doc_Invoice
diff --git a/andromeida.midsuit.project/src/andromedia/midsuit/factory/MID_DocFactory.java b/andromeida.midsuit.project/src/andromedia/midsuit/factory/MID_DocFactory.java
index a44ff8a..f2fff3f 100644
--- a/andromeida.midsuit.project/src/andromedia/midsuit/factory/MID_DocFactory.java
+++ b/andromeida.midsuit.project/src/andromedia/midsuit/factory/MID_DocFactory.java
@@ -7,11 +7,13 @@ import java.util.logging.Level;
import org.adempiere.base.IDocFactory;
import org.compiere.acct.Doc;
import org.compiere.model.MAcctSchema;
+import org.compiere.model.MInvoice;
import org.compiere.model.MTable;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
+import andromedia.midsuit.doc.MID_DocInvoice;
import andromedia.midsuit.doc.MID_DocMRPPPO;
import andromedia.midsuit.doc.MID_DocMidRequsiition;
import andromedia.midsuit.model.MID_MRequisitionTrx;
@@ -55,6 +57,9 @@ public class MID_DocFactory implements IDocFactory{
return new MID_DocMidRequsiition(as,rs,trxName);
if(tableName.equals(MID_PPO.Table_Name))
return new MID_DocMRPPPO(as, rs, trxName);
+ if(tableName.equals(MInvoice.Table_Name)) {
+ s_log.log(Level.SEVERE,"IN");
+ return new MID_DocInvoice(as, rs, trxName);}
return null;
}
diff --git a/edii.midsuit.feature/.project b/edii.midsuit.feature/.project
new file mode 100644
index 0000000..b2deeb2
--- /dev/null
+++ b/edii.midsuit.feature/.project
@@ -0,0 +1,17 @@
+
+
+ edii.midsuit.feature
+
+
+
+
+
+ org.eclipse.pde.FeatureBuilder
+
+
+
+
+
+ org.eclipse.pde.FeatureNature
+
+
diff --git a/edii.midsuit.feature/build.properties b/edii.midsuit.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/edii.midsuit.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/edii.midsuit.feature/feature.xml b/edii.midsuit.feature/feature.xml
new file mode 100644
index 0000000..ce55c73
--- /dev/null
+++ b/edii.midsuit.feature/feature.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ [Enter Feature Description here.]
+
+
+
+ [Enter Copyright Description here.]
+
+
+
+ [Enter License Description here.]
+
+
+
+
+
diff --git a/edii.midsuit.project/.DS_Store b/edii.midsuit.project/.DS_Store
new file mode 100644
index 0000000..168c9e3
Binary files /dev/null and b/edii.midsuit.project/.DS_Store differ
diff --git a/edii.midsuit.project/.classpath b/edii.midsuit.project/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/edii.midsuit.project/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/.project b/edii.midsuit.project/.project
new file mode 100644
index 0000000..10130dc
--- /dev/null
+++ b/edii.midsuit.project/.project
@@ -0,0 +1,33 @@
+
+
+ edii.midsuit.project
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.pde.ds.core.builder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/edii.midsuit.project/.settings/org.eclipse.jdt.core.prefs b/edii.midsuit.project/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/edii.midsuit.project/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/edii.midsuit.project/META-INF/MANIFEST.MF b/edii.midsuit.project/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..fb241a4
--- /dev/null
+++ b/edii.midsuit.project/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: EDII Midsuit
+Bundle-SymbolicName: edii.midsuit.project
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.adempiere.base;bundle-version="5.1.0",
+ org.adempiere.plugin.utils;bundle-version="5.1.0",
+ org.eclipse.osgi.services;bundle-version="3.6.0",
+ zk;bundle-version="8.0.2",
+ zcommon;bundle-version="8.0.2",
+ zul;bundle-version="8.0.2",
+ org.adempiere.ui.zk,
+ org.adempiere.ui;bundle-version="5.1.0"
+Bundle-ActivationPolicy: lazy
+Service-Component: OSGI-INF/MID_ProcessFactory.xml,OSGI-INF/MID_ModelFactory.xml,OSGI-INF/MID_CalloutFactory.xml,OSGI-INF/MID_ValidatorFactory.xml,OSGI-INF/MID_CreateFromFactory.xml,OSGI-INF/MID_FormFactory.xml,
+ OSGI-INF/MID_DocFactory.xml
+Import-Package: org.compiere.apps,
+ org.compiere.grid,
+ org.compiere.minigrid
+Bundle-Activator: org.adempiere.plugin.utils.AdempiereActivator
diff --git a/edii.midsuit.project/OSGI-INF/MID_CalloutFactory.xml b/edii.midsuit.project/OSGI-INF/MID_CalloutFactory.xml
new file mode 100644
index 0000000..27a344a
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_CalloutFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_CreateFromFactory.xml b/edii.midsuit.project/OSGI-INF/MID_CreateFromFactory.xml
new file mode 100644
index 0000000..3d3b886
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_CreateFromFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_DocFactory.xml b/edii.midsuit.project/OSGI-INF/MID_DocFactory.xml
new file mode 100644
index 0000000..86894d9
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_DocFactory.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_FormFactory.xml b/edii.midsuit.project/OSGI-INF/MID_FormFactory.xml
new file mode 100644
index 0000000..3a82640
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_FormFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_ModelFactory.xml b/edii.midsuit.project/OSGI-INF/MID_ModelFactory.xml
new file mode 100644
index 0000000..9abecb4
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_ModelFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_ProcessFactory.xml b/edii.midsuit.project/OSGI-INF/MID_ProcessFactory.xml
new file mode 100644
index 0000000..d0c930a
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_ProcessFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/edii.midsuit.project/OSGI-INF/MID_ValidatorFactory.xml b/edii.midsuit.project/OSGI-INF/MID_ValidatorFactory.xml
new file mode 100644
index 0000000..ec3696a
--- /dev/null
+++ b/edii.midsuit.project/OSGI-INF/MID_ValidatorFactory.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/edii.midsuit.project/bin/.DS_Store b/edii.midsuit.project/bin/.DS_Store
new file mode 100644
index 0000000..5165528
Binary files /dev/null and b/edii.midsuit.project/bin/.DS_Store differ
diff --git a/edii.midsuit.project/build.properties b/edii.midsuit.project/build.properties
new file mode 100644
index 0000000..43bce03
--- /dev/null
+++ b/edii.midsuit.project/build.properties
@@ -0,0 +1,11 @@
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ OSGI-INF/MID_ProcessFactory.xml,\
+ OSGI-INF/MID_ModelFactory.xml,\
+ OSGI-INF/MID_CalloutFactory.xml,\
+ OSGI-INF/MID_ValidatorFactory.xml,\
+ OSGI-INF/MID_CreateFromFactory.xml,\
+ OSGI-INF/MID_FormFactory.xml,\
+ OSGI-INF/MID_DocFactory.xml
+source.. = src/
diff --git a/edii.midsuit.project/src/.DS_Store b/edii.midsuit.project/src/.DS_Store
new file mode 100644
index 0000000..5165528
Binary files /dev/null and b/edii.midsuit.project/src/.DS_Store differ
diff --git a/edii.midsuit.project/src/edii/midsuit/callout/EDI_CalloutOrderLine.java b/edii.midsuit.project/src/edii/midsuit/callout/EDI_CalloutOrderLine.java
new file mode 100644
index 0000000..bd18977
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/callout/EDI_CalloutOrderLine.java
@@ -0,0 +1,35 @@
+package edii.midsuit.callout;
+
+import java.util.Properties;
+
+import org.adempiere.base.IColumnCallout;
+import org.compiere.model.CalloutEngine;
+import org.compiere.model.GridField;
+import org.compiere.model.GridTab;
+import org.compiere.model.MOrder;
+import org.compiere.model.X_C_OrderLine;
+
+public class EDI_CalloutOrderLine extends CalloutEngine implements IColumnCallout {
+
+ @Override
+ public String start(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) {
+ if(mField.getColumnName().equals(X_C_OrderLine.COLUMNNAME_M_Product_ID))
+ return C_Order_ID(ctx, WindowNo, mTab, mField, value, oldValue);
+ return null;
+ }
+
+ public String C_Order_ID(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) {
+ if(value==null)
+ return null;
+ MOrder Order = new MOrder(ctx, (int) mTab.getValue(X_C_OrderLine.COLUMNNAME_C_Order_ID), null);
+
+ String retValue = Order.get_ValueAsString("NoAju1") + "/"
+ + Order.get_ValueAsString("NoAju2") + "/"
+ + Order.get_ValueAsString("NoAju3") + "/"
+ + Order.get_ValueAsString("NoAju4") + "";
+
+ mTab.setValue("NoAju", retValue);
+
+ return null;
+ }
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_CalloutFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_CalloutFactory.java
new file mode 100644
index 0000000..3bae4f8
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_CalloutFactory.java
@@ -0,0 +1,24 @@
+package edii.midsuit.factory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.adempiere.base.IColumnCallout;
+import org.adempiere.base.IColumnCalloutFactory;
+import org.compiere.model.X_C_OrderLine;
+
+import edii.midsuit.callout.EDI_CalloutOrderLine;
+
+public class MID_CalloutFactory implements IColumnCalloutFactory{
+
+ @Override
+ public IColumnCallout[] getColumnCallouts(String tableName, String columnName) {
+ List list = new ArrayList();
+// if(tableName.equals(X_MID_RequisitionLine.Table_Name))
+// list.add(new MID_CalloutRequisitionTrxLine());
+ if(tableName.equals(X_C_OrderLine.Table_Name))
+ list.add(new EDI_CalloutOrderLine());
+ return list != null ? list.toArray(new IColumnCallout[0]) : new IColumnCallout[0];
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_CreateFromFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_CreateFromFactory.java
new file mode 100644
index 0000000..8c9154b
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_CreateFromFactory.java
@@ -0,0 +1,16 @@
+package edii.midsuit.factory;
+
+import org.compiere.grid.ICreateFrom;
+import org.compiere.grid.ICreateFromFactory;
+import org.compiere.model.GridTab;
+
+public class MID_CreateFromFactory implements ICreateFromFactory{
+ @Override
+ public ICreateFrom create(GridTab mTab) {
+ String tableName = mTab.getTableName();
+// if (tableName.equals(X_M_InOut.Table_Name))
+// return new MID_WCreateFromShipment(mTab);
+
+ return null;
+ }
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_DocFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_DocFactory.java
new file mode 100644
index 0000000..43bc7e8
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_DocFactory.java
@@ -0,0 +1,54 @@
+package edii.midsuit.factory;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.logging.Level;
+
+import org.adempiere.base.IDocFactory;
+import org.compiere.acct.Doc;
+import org.compiere.model.MAcctSchema;
+import org.compiere.model.MTable;
+import org.compiere.util.CLogger;
+import org.compiere.util.DB;
+import org.compiere.util.Env;
+
+public class MID_DocFactory implements IDocFactory{
+
+ private final static CLogger s_log = CLogger.getCLogger(MID_DocFactory.class);
+
+ @Override
+ public Doc getDocument(MAcctSchema as, int AD_Table_ID, int Record_ID, String trxName) {
+ String tableName = MTable.getTableName(Env.getCtx(), AD_Table_ID);
+ //
+ Doc doc = null;
+ StringBuffer sql = new StringBuffer("SELECT * FROM ").append(tableName).append(" WHERE ").append(tableName)
+ .append("_ID=? AND Processed='Y'");
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ pstmt = DB.prepareStatement(sql.toString(), trxName);
+ pstmt.setInt(1, Record_ID);
+ rs = pstmt.executeQuery();
+ if (rs.next()) {
+ doc = getDocument(as, AD_Table_ID, rs, trxName);
+ } else
+ s_log.severe("Not Found: " + tableName + "_ID=" + Record_ID);
+ } catch (Exception e) {
+ s_log.log(Level.SEVERE, sql.toString(), e);
+ } finally {
+ DB.close(rs, pstmt);
+ rs = null;
+ pstmt = null;
+ }
+ return doc;
+ }
+ @Override
+ public Doc getDocument(MAcctSchema as, int AD_Table_ID, ResultSet rs, String trxName) {
+
+ String tableName = MTable.getTableName(Env.getCtx(), AD_Table_ID);
+// if(tableName.equals(MID_MRequisitionTrx.Table_Name))
+// return new MID_DocMidRequsiition(as,rs,trxName);
+ return null;
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_FormFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_FormFactory.java
new file mode 100644
index 0000000..088dbd9
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_FormFactory.java
@@ -0,0 +1,48 @@
+package edii.midsuit.factory;
+
+import java.util.logging.Level;
+
+import org.adempiere.webui.factory.IFormFactory;
+import org.adempiere.webui.panel.ADForm;
+import org.adempiere.webui.panel.IFormController;
+import org.compiere.util.CLogger;
+
+public class MID_FormFactory implements IFormFactory {
+
+ protected transient CLogger log = CLogger.getCLogger(getClass());
+
+ @Override
+ public ADForm newFormInstance(String formName) {
+ // TODO Auto-generated method stub
+ if (formName.startsWith("andromedia.midsuit.form")) {
+ Object form = null;
+ Class> clazz = null;
+ ClassLoader loader = getClass().getClassLoader();
+ try {
+ clazz = loader.loadClass(formName);
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Load Form Class Failed");
+ }
+
+ if (clazz != null) {
+ try {
+ form = clazz.newInstance();
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Class initialized error");
+ }
+ }
+ if (form != null) {
+ if (form instanceof ADForm) {
+ return (ADForm) form;
+ } else if (form instanceof IFormController) {
+ IFormController controller = (IFormController) form;
+ ADForm adform = controller.getForm();
+ adform.setICustomForm(controller);
+ return adform;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_ModelFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_ModelFactory.java
new file mode 100644
index 0000000..909884e
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_ModelFactory.java
@@ -0,0 +1,73 @@
+package edii.midsuit.factory;
+
+import java.lang.reflect.Constructor;
+import java.sql.ResultSet;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.adempiere.base.IModelFactory;
+import org.compiere.model.PO;
+import org.compiere.util.Env;
+
+public class MID_ModelFactory implements IModelFactory{
+ private static HashMap mapTableModels = new HashMap();
+ static {
+ //Ex mapTableModels.put(MOrderLine.Table_Name, "org.semeru.project.model.SMT_MOrderLine");
+ }
+
+ @Override
+ public Class> getClass(String tableName) {
+ if (mapTableModels.containsKey(tableName)) {
+ Class> act = null;
+ try {
+ act = Class.forName(mapTableModels.get(tableName));
+
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ return act;
+ } else {
+ return null;
+ }
+
+ }
+
+ @Override
+ public PO getPO(String tableName, int Record_ID, String trxName) {
+ if (mapTableModels.containsKey(tableName)) {
+ Class> clazz = null;
+ Constructor> ctor = null;
+ PO object = null;
+ try {
+ clazz = Class.forName(mapTableModels.get(tableName));
+ ctor = clazz.getConstructor(Properties.class, int.class, String.class);
+ object = (PO) ctor.newInstance(new Object[] { Env.getCtx(), Record_ID, trxName });
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return object;
+ } else
+ return null;
+ }
+
+ @Override
+ public PO getPO(String tableName, ResultSet rs, String trxName) {
+ if (mapTableModels.containsKey(tableName)) {
+ Class> clazz = null;
+ Constructor> ctor = null;
+ PO object = null;
+ try {
+ clazz = Class.forName(mapTableModels.get(tableName));
+ ctor = clazz.getConstructor(Properties.class, ResultSet.class, String.class);
+ object = (PO) ctor.newInstance(new Object[] { Env.getCtx(), rs, trxName });
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return object;
+ } else
+ return null;
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_ProcessFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_ProcessFactory.java
new file mode 100644
index 0000000..a53383b
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_ProcessFactory.java
@@ -0,0 +1,21 @@
+package edii.midsuit.factory;
+
+import org.adempiere.base.IProcessFactory;
+import org.compiere.process.ProcessCall;
+
+public class MID_ProcessFactory implements IProcessFactory {
+
+ @Override
+ public ProcessCall newProcessInstance(String className) {
+ // TODO Auto-generated method stub
+ ProcessCall proses = null;
+ try {
+ Class> clazz = getClass().getClassLoader().loadClass(className);
+ proses = (ProcessCall) clazz.newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ return proses;
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/factory/MID_ValidatorFactory.java b/edii.midsuit.project/src/edii/midsuit/factory/MID_ValidatorFactory.java
new file mode 100644
index 0000000..f5229aa
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/factory/MID_ValidatorFactory.java
@@ -0,0 +1,54 @@
+package edii.midsuit.factory;
+
+import org.adempiere.base.event.AbstractEventHandler;
+import org.adempiere.base.event.IEventTopics;
+import org.adempiere.exceptions.AdempiereException;
+import org.compiere.model.MOrder;
+import org.compiere.model.PO;
+import org.compiere.util.CLogger;
+import org.osgi.service.event.Event;
+
+import edii.midsuit.validator.EDI_OrderValidator;
+
+public class MID_ValidatorFactory extends AbstractEventHandler {
+ public CLogger log = CLogger.getCLogger(MID_ValidatorFactory.class);
+
+ @Override
+
+ protected void doHandleEvent(Event event) {
+ String msg = "";
+
+// if (getPO(event).get_TableName().equals(MOrderLandedCostAllocation.Table_Name))
+// msg = SMT_LandedCostAllocationValidator.executeEvent(event, getPO(event));
+ if (getPO(event).get_TableName().equals(MOrder.Table_Name))
+ msg = EDI_OrderValidator.executeEvent(event, getPO(event));
+// if (getPO(event).get_TableName().equals(MRMA.Table_Name))
+// msg = MID_RMAValidator.executeEvent(event, getPO(event));
+// if (getPO(event).get_TableName().equals(MInOut.Table_Name))
+// msg = MID_InOutValidator.executeEvent(event, getPO(event));
+// if(getPO(event).get_TableName().equals(MInvoice.Table_Name))
+// msg = MID_InvoiceValidator.executeEvent(event, getPO(event));
+// if(getPO(event).get_TableName().equals(MPaymentAllocate.Table_Name))
+// msg = MID_PaymentAllocateValidator.executeEvent(event, getPO(event));
+// if(getPO(event).get_TableName().equals(MProductPrice.Table_Name))
+// msg = MID_ProductPriceValidator.executeEvent(event, getPO(event));
+// if(getPO(event).get_TableName().equals(MPriceList.Table_Name))
+// msg = MID_PriceListValidator.executeEvent(event, getPO(event));
+ logEvent(event, getPO(event), msg);
+ }
+
+ private void logEvent(Event event, PO po, String msg) {
+ log.fine("EVENT MANAGER // " + event.getTopic() + " po =" + po + " MESSAGE=" + msg);
+ if (msg.length() > 0)
+ throw new AdempiereException(msg);
+ }
+
+ @Override
+ protected void initialize() {
+
+ // registerTableEvent(IEventTopics.DOC_BEFORE_COMPLETE, Table_Name);
+ registerTableEvent(IEventTopics.DOC_BEFORE_COMPLETE, MOrder.Table_Name);
+ registerTableEvent(IEventTopics.PO_BEFORE_CHANGE, MOrder.Table_Name);
+ }
+
+}
diff --git a/edii.midsuit.project/src/edii/midsuit/validator/EDI_OrderValidator.java b/edii.midsuit.project/src/edii/midsuit/validator/EDI_OrderValidator.java
new file mode 100644
index 0000000..7e58d8e
--- /dev/null
+++ b/edii.midsuit.project/src/edii/midsuit/validator/EDI_OrderValidator.java
@@ -0,0 +1,72 @@
+package edii.midsuit.validator;
+
+import org.adempiere.base.event.IEventTopics;
+import org.adempiere.exceptions.AdempiereException;
+import org.compiere.model.MAttributeSetInstance;
+import org.compiere.model.MOrder;
+import org.compiere.model.MOrderLine;
+import org.compiere.model.PO;
+import org.compiere.model.Query;
+import org.compiere.model.X_M_AttributeSetInstance;
+import org.compiere.util.DB;
+import org.osgi.service.event.Event;
+
+public class EDI_OrderValidator {
+ public static String executeEvent(Event e, PO po) {
+ MOrder Order = (MOrder) po;
+ if (e.getTopic().equals(IEventTopics.DOC_BEFORE_COMPLETE))
+ return beforeComplete(Order);
+ else if (e.getTopic().equals(IEventTopics.PO_BEFORE_CHANGE))
+ return beforeChange(Order);
+ return "";
+ }
+
+ private static String beforeChange(MOrder order) {
+
+ if(order.get_ValueAsString("NoAju1").equals("") || order.get_ValueAsString("NoAju2").equals("")
+ || order.get_ValueAsString("NoAju3").equals("") || order.get_ValueAsString("NoAju4").equals("")) {
+ DB.executeUpdateEx("UPDATE C_OrderLine SET NoAju = ? WHERE C_Order_ID = ?",
+ new Object[] { "", order.getC_Order_ID() }, order.get_TrxName());
+ }
+ else if(order.is_ValueChanged("NoAju1") || order.is_ValueChanged("NoAju3") ||
+ order.is_ValueChanged("NoAju2") || order.is_ValueChanged("NoAju4")) {
+ String noAju = order.get_ValueAsString("NoAju1")+"/"
+ + order.get_ValueAsString("NoAju2") + "/"
+ + order.get_ValueAsString("NoAju3") + "/"
+ + order.get_ValueAsString("NoAju4");
+ DB.executeUpdateEx("UPDATE C_OrderLine SET NoAju = ? WHERE C_Order_ID = ?",
+ new Object[] { noAju, order.getC_Order_ID() }, order.get_TrxName());
+ }
+ return "";
+ }
+
+ public static String beforeComplete(MOrder Order) {
+ MOrderLine[] lines = Order.getLines();
+ for(MOrderLine line : lines) {
+ String noAju = line.get_ValueAsString("NoAju");
+ if(Order.get_ValueAsInt("MID_AJUDocumentType_ID")>0 && noAju==null)
+ return "Silahkan isi dokumen AJU terlebih dahulu !!!";
+ if(line.getM_Product().getM_AttributeSet_ID()==0)
+ throw new AdempiereException("Product "+line.getM_Product().getName()+" tidak memiliki attribute set !!!");
+
+ int M_AttributeSetInstance_ID = new Query(Order.getCtx(), X_M_AttributeSetInstance.Table_Name
+ , "M_AttributeSet_ID =? AND Lot =?", Order.get_TrxName())
+ .setParameters(new Object[] { line.getM_Product().getM_AttributeSet_ID(), noAju })
+ .firstId();
+
+ if(M_AttributeSetInstance_ID==-1) {
+ MAttributeSetInstance ASI = new MAttributeSetInstance(Order.getCtx(), 0, Order.get_TrxName());
+ ASI.setLot(noAju);
+ ASI.setM_AttributeSet_ID(line.getM_Product().getM_AttributeSet_ID());
+ ASI.setDescription(noAju);
+ ASI.saveEx();
+
+ M_AttributeSetInstance_ID = ASI.getM_AttributeSetInstance_ID();
+ }
+
+ line.setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID);
+ line.saveEx();
+ }
+ return "";
+ }
+}