diff --git a/org.adempiere.base-feature/model.generator.launch b/org.adempiere.base-feature/model.generator.launch
index 74596719aa..81e50a2ba2 100644
--- a/org.adempiere.base-feature/model.generator.launch
+++ b/org.adempiere.base-feature/model.generator.launch
@@ -12,7 +12,7 @@
-
+
@@ -20,7 +20,7 @@
-
+
diff --git a/org.adempiere.base/src/org/compiere/model/MInOut.java b/org.adempiere.base/src/org/compiere/model/MInOut.java
index 0209dd1fbc..63a8be4ae5 100644
--- a/org.adempiere.base/src/org/compiere/model/MInOut.java
+++ b/org.adempiere.base/src/org/compiere/model/MInOut.java
@@ -1552,16 +1552,18 @@ public class MInOut extends X_M_InOut implements DocAction
log.fine("PO Matching");
// Ship - PO
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
- boolean isNewMatchPO = false;
- if (po.get_ID() == 0)
- isNewMatchPO = true;
- if (!po.save(get_TrxName()))
- {
- m_processMsg = "Could not create PO Matching";
- return DocAction.STATUS_Invalid;
+ if (po != null) {
+ boolean isNewMatchPO = false;
+ if (po.get_ID() == 0)
+ isNewMatchPO = true;
+ if (!po.save(get_TrxName()))
+ {
+ m_processMsg = "Could not create PO Matching";
+ return DocAction.STATUS_Invalid;
+ }
+ if (isNewMatchPO)
+ addDocsPostProcess(po);
}
- if (isNewMatchPO)
- addDocsPostProcess(po);
// Update PO with ASI
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
@@ -1580,18 +1582,21 @@ public class MInOut extends X_M_InOut implements DocAction
// Ship - Invoice
MMatchPO po = MMatchPO.create (iLine, sLine,
getMovementDate(), matchQty);
- boolean isNewMatchPO = false;
- if (po.get_ID() == 0)
- isNewMatchPO = true;
- if (!po.save(get_TrxName()))
- {
- m_processMsg = "Could not create PO(Inv) Matching";
- return DocAction.STATUS_Invalid;
+ if (po != null) {
+ boolean isNewMatchPO = false;
+ if (po.get_ID() == 0)
+ isNewMatchPO = true;
+ if (!po.save(get_TrxName()))
+ {
+ m_processMsg = "Could not create PO(Inv) Matching";
+ return DocAction.STATUS_Invalid;
+ }
+ if (isNewMatchPO)
+ addDocsPostProcess(po);
}
- if (isNewMatchPO)
- addDocsPostProcess(po);
+
// Update PO with ASI
- oLine = new MOrderLine (getCtx(), po.getC_OrderLine_ID(), get_TrxName());
+ oLine = new MOrderLine (getCtx(), iLine.getC_OrderLine_ID(), get_TrxName());
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
{
diff --git a/org.adempiere.base/src/org/compiere/model/MMatchInv.java b/org.adempiere.base/src/org/compiere/model/MMatchInv.java
index 5953dec070..c58537f755 100644
--- a/org.adempiere.base/src/org/compiere/model/MMatchInv.java
+++ b/org.adempiere.base/src/org/compiere/model/MMatchInv.java
@@ -222,6 +222,33 @@ public class MMatchInv extends X_M_MatchInv
return true;
} // beforeSave
+ @Override
+ protected boolean afterSave(boolean newRecord, boolean success) {
+ if (!success)
+ return false;
+
+ if (getM_InOutLine_ID() > 0)
+ {
+ MInOutLine line = new MInOutLine(getCtx(), getM_InOutLine_ID(), get_TrxName());
+ BigDecimal matchedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchInv WHERE M_InOutLine_ID=?" , getM_InOutLine_ID());
+ if (matchedQty != null && matchedQty.compareTo(line.getMovementQty()) > 0)
+ {
+ throw new IllegalStateException("Total matched qty > movement qty. MatchedQty="+matchedQty+", MovementQty="+line.getMovementQty()+", Line="+line);
+ }
+ }
+
+ if (getC_InvoiceLine_ID() > 0)
+ {
+ MInvoiceLine line = new MInvoiceLine(getCtx(), getC_InvoiceLine_ID(), get_TrxName());
+ BigDecimal matchedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchInv WHERE C_InvoiceLine_ID=?" , getC_InvoiceLine_ID());
+ if (matchedQty != null && matchedQty.compareTo(line.getQtyInvoiced()) > 0)
+ {
+ throw new IllegalStateException("Total matched qty > invoiced qty. MatchedQty="+matchedQty+", InvoicedQty="+line.getQtyInvoiced()+", Line="+line);
+ }
+ }
+ return true;
+ }
+
/**
* Get the later Date Acct from invoice or shipment
* @return date or null
@@ -279,7 +306,9 @@ public class MMatchInv extends X_M_MatchInv
deleteMatchInvCostDetail();
// end AZ
+ // delete m_matchinv doesn't auto make m_matchpo invalid
// Get Order and decrease invoices
+ /*
MInvoiceLine iLine = new MInvoiceLine (getCtx(), getC_InvoiceLine_ID(), get_TrxName());
int C_OrderLine_ID = iLine.getC_OrderLine_ID();
if (C_OrderLine_ID == 0)
@@ -303,6 +332,7 @@ public class MMatchInv extends X_M_MatchInv
mPO[i].saveEx();
}
}
+ */
}
return success;
} // afterDelete
diff --git a/org.adempiere.base/src/org/compiere/model/MMatchPO.java b/org.adempiere.base/src/org/compiere/model/MMatchPO.java
index 4f075b44cf..d35723c0ff 100644
--- a/org.adempiere.base/src/org/compiere/model/MMatchPO.java
+++ b/org.adempiere.base/src/org/compiere/model/MMatchPO.java
@@ -19,6 +19,7 @@ package org.compiere.model;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.sql.Savepoint;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Properties;
@@ -27,6 +28,8 @@ import java.util.logging.Level;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
+import org.compiere.util.Trx;
+import org.compiere.util.ValueNamePair;
/**
* Match PO Model.
@@ -100,6 +103,53 @@ public class MMatchPO extends X_M_MatchPO
return retValue;
} // get
+ /**
+ * Get PO Match of Receipt Line
+ * @param ctx context
+ * @param M_InOutLine_ID receipt
+ * @param trxName transaction
+ * @return array of matches
+ */
+ public static MMatchPO[] get (Properties ctx,
+ int M_InOutLine_ID, String trxName)
+ {
+ if (M_InOutLine_ID == 0)
+ return new MMatchPO[]{};
+ //
+ String sql = "SELECT * FROM M_MatchPO WHERE M_InOutLine_ID=?";
+ ArrayList list = new ArrayList();
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try
+ {
+ pstmt = DB.prepareStatement (sql, trxName);
+ pstmt.setInt (1, M_InOutLine_ID);
+ rs = pstmt.executeQuery ();
+ while (rs.next ())
+ list.add (new MMatchPO (ctx, rs, trxName));
+ }
+ catch (Exception e)
+ {
+ s_log.log(Level.SEVERE, sql, e);
+ if (e instanceof RuntimeException)
+ {
+ throw (RuntimeException)e;
+ }
+ else
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+ finally
+ {
+ DB.close(rs, pstmt);
+ }
+
+ MMatchPO[] retValue = new MMatchPO[list.size()];
+ list.toArray (retValue);
+ return retValue;
+ } // get
+
/**
* Get PO Matches of receipt
* @param ctx context
@@ -249,8 +299,54 @@ public class MMatchPO extends X_M_MatchPO
C_OrderLine_ID = sLine.getC_OrderLine_ID();
}
+ if (C_OrderLine_ID > 0)
+ {
+ return create(ctx, iLine, sLine, C_OrderLine_ID, dateTrx, qty, trxName);
+ }
+ else
+ {
+ if (sLine != null && iLine != null)
+ {
+ MMatchPO[] matchpos = MMatchPO.get(ctx, sLine.getM_InOutLine_ID(), trxName);
+ for (MMatchPO matchpo : matchpos)
+ {
+ C_OrderLine_ID = matchpo.getC_OrderLine_ID();
+ MOrderLine orderLine = new MOrderLine(ctx, C_OrderLine_ID, trxName);
+ BigDecimal toInvoice = orderLine.getQtyOrdered().subtract(orderLine.getQtyInvoiced());
+ if (toInvoice.signum() <= 0)
+ continue;
+ BigDecimal matchQty = qty;
+ if (matchQty.compareTo(toInvoice) > 0)
+ matchQty = toInvoice;
+
+ if (matchQty.signum() <= 0)
+ continue;
+
+ MMatchPO newMatchPO = create(ctx, iLine, sLine, C_OrderLine_ID, dateTrx, matchQty, trxName);
+ if (!newMatchPO.save())
+ {
+ String msg = "Failed to update match po.";
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + " " + error.getName();
+ }
+ throw new RuntimeException(msg);
+ }
+ qty = qty.subtract(matchQty);
+ if (qty.signum() <= 0)
+ return newMatchPO;
+ }
+ }
+ return null;
+ }
+ }
+
+ private static MMatchPO create(Properties ctx, MInvoiceLine iLine,
+ MInOutLine sLine, int C_OrderLine_ID, Timestamp dateTrx,
+ BigDecimal qty, String trxName) {
MMatchPO retValue = null;
- String sql = "SELECT * FROM M_MatchPO WHERE C_OrderLine_ID=?";
+ String sql = "SELECT * FROM M_MatchPO WHERE C_OrderLine_ID=? ORDER BY M_MatchPO_ID";
PreparedStatement pstmt = null;
ResultSet rs = null;
try
@@ -261,14 +357,17 @@ public class MMatchPO extends X_M_MatchPO
while (rs.next ())
{
MMatchPO mpo = new MMatchPO (ctx, rs, trxName);
- if (qty.compareTo(mpo.getQty()) == 0)
+ if (qty.compareTo(mpo.getQty()) >= 0)
{
+ BigDecimal toMatch = qty;
+ BigDecimal matchQty = mpo.getQty();
+ if (toMatch.compareTo(matchQty) > 0)
+ toMatch = matchQty;
if (iLine != null)
{
- if (mpo.getC_InvoiceLine_ID() == 0
- || mpo.getC_InvoiceLine_ID() == iLine.getC_InvoiceLine_ID())
+ if ((mpo.getC_InvoiceLine_ID() == 0)
+ || (mpo.getC_InvoiceLine_ID() == iLine.getC_InvoiceLine_ID()))
{
- mpo.setC_InvoiceLine_ID(iLine);
if (iLine.getM_AttributeSetInstance_ID() != 0)
{
if (mpo.getM_AttributeSetInstance_ID() == 0)
@@ -282,10 +381,10 @@ public class MMatchPO extends X_M_MatchPO
}
if (sLine != null)
{
- if (mpo.getM_InOutLine_ID() == 0
- || mpo.getM_InOutLine_ID() == sLine.getM_InOutLine_ID())
+ if ((mpo.getM_InOutLine_ID() == 0)
+ || (mpo.getM_InOutLine_ID() == sLine.getM_InOutLine_ID()))
{
- mpo.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
+
if (sLine.getM_AttributeSetInstance_ID() != 0)
{
if (mpo.getM_AttributeSetInstance_ID() == 0)
@@ -297,33 +396,152 @@ public class MMatchPO extends X_M_MatchPO
else
continue;
}
+ if ((iLine != null || mpo.getC_InvoiceLine_ID() > 0) && (sLine != null || mpo.getM_InOutLine_ID() > 0))
+ {
+ int M_InOutLine_ID = sLine != null ? sLine.getM_InOutLine_ID() : mpo.getM_InOutLine_ID();
+ int C_InvoiceLine_ID = iLine != null ? iLine.getC_InvoiceLine_ID() : mpo.getC_InvoiceLine_ID();
+
+ //verify invoiceline not already linked to another inoutline
+ int tmpInOutLineId = DB.getSQLValue(mpo.get_TrxName(), "SELECT M_InOutLine_ID FROM C_InvoiceLine WHERE C_InvoiceLine_ID="+C_InvoiceLine_ID);
+ if (tmpInOutLineId > 0 && tmpInOutLineId != M_InOutLine_ID)
+ {
+ continue;
+ }
+
+ //verify m_matchinv not created yet
+ int cnt = DB.getSQLValue(mpo.get_TrxName(), "SELECT Count(*) FROM M_MatchInv WHERE M_InOutLine_ID="+M_InOutLine_ID
+ +" AND C_InvoiceLine_ID="+C_InvoiceLine_ID);
+ if (cnt <= 0)
+ {
+ Trx trx = trxName != null ? Trx.get(trxName, false) : null;
+ Savepoint savepoint = trx != null ? trx.getConnection().setSavepoint() : null;
+ MMatchInv matchInv = new MMatchInv(mpo.getCtx(), 0, mpo.get_TrxName());
+ matchInv.setC_InvoiceLine_ID(C_InvoiceLine_ID);
+ matchInv.setM_Product_ID(mpo.getM_Product_ID());
+ matchInv.setM_InOutLine_ID(M_InOutLine_ID);
+ matchInv.setAD_Client_ID(mpo.getAD_Client_ID());
+ matchInv.setAD_Org_ID(mpo.getAD_Org_ID());
+ matchInv.setM_AttributeSetInstance_ID(mpo.getM_AttributeSetInstance_ID());
+ matchInv.setQty(mpo.getQty());
+ matchInv.setDateTrx(dateTrx);
+ if (!matchInv.save())
+ {
+ if (savepoint != null)
+ {
+ trx.getConnection().rollback(savepoint);
+ savepoint = null;
+ }
+ else
+ {
+ matchInv.delete(true);
+ }
+ String msg = "Failed to auto match invoice.";
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + " " + error.getName();
+ }
+ //log as debug message and continue
+ s_log.fine(msg);
+ continue;
+ }
+ if (savepoint != null)
+ {
+ try {
+ trx.getConnection().releaseSavepoint(savepoint);
+ } catch (Exception e) {}
+ }
+ }
+ }
+ if (iLine != null)
+ mpo.setC_InvoiceLine_ID(iLine);
+ if (sLine != null)
+ mpo.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
+
+ if (!mpo.save())
+ {
+ String msg = "Failed to update match po.";
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + " " + error.getName();
+ }
+ throw new RuntimeException(msg);
+ }
+
+ qty = qty.subtract(toMatch);
+ if (qty.signum() <= 0)
+ {
retValue = mpo;
break;
}
}
}
+ }
catch (Exception e)
{
s_log.log(Level.SEVERE, sql, e);
+ if (e instanceof RuntimeException)
+ {
+ throw (RuntimeException)e;
+ }
+ else
+ {
+ throw new IllegalStateException(e);
+ }
}
finally
{
DB.close(rs, pstmt);
- rs = null; pstmt = null;
}
// Create New
if (retValue == null)
{
- if (sLine != null)
+ BigDecimal sLineMatchedQty = null;
+ if (sLine != null && iLine != null)
{
- retValue = new MMatchPO (sLine, dateTrx, qty);
- if (iLine != null)
- retValue.setC_InvoiceLine_ID(iLine);
+ sLineMatchedQty = DB.getSQLValueBD(sLine.get_TrxName(), "SELECT Sum(Qty) FROM M_MatchPO WHERE C_OrderLine_ID="+C_OrderLine_ID+" AND M_InOutLine_ID=?", sLine.getM_InOutLine_ID());
+ }
+
+ if (sLine != null && (sLine.getC_OrderLine_ID() == C_OrderLine_ID || iLine == null)
+ && (sLineMatchedQty == null || sLineMatchedQty.signum() <= 0))
+ {
+ if (qty.signum() > 0)
+ {
+ retValue = new MMatchPO (sLine, dateTrx, qty);
+ retValue.setC_OrderLine_ID(C_OrderLine_ID);
+ if (iLine != null)
+ retValue.setC_InvoiceLine_ID(iLine);
+ if (!retValue.save())
+ {
+ String msg = "Failed to update match po.";
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + " " + error.getName();
+ }
+ throw new RuntimeException(msg);
+ }
+ }
}
else if (iLine != null)
{
- retValue = new MMatchPO (iLine, dateTrx, qty);
+ if (qty.signum() > 0)
+ {
+ retValue = new MMatchPO (iLine, dateTrx, qty);
+ retValue.setC_OrderLine_ID(C_OrderLine_ID);
+ if (!retValue.save())
+ {
+ String msg = "Failed to update match po.";
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + " " + error.getName();
+ }
+ throw new RuntimeException(msg);
+ }
+ }
}
}
@@ -617,6 +835,20 @@ public class MMatchPO extends X_M_MatchPO
setPriceMatchDifference(difference);
setIsApproved(true);
}
+
+ //validate against M_MatchInv
+ if (getM_InOutLine_ID() > 0 && getC_InvoiceLine_ID() > 0)
+ {
+ int cnt = DB.getSQLValue(get_TrxName(), "SELECT Count(*) FROM M_MatchInv WHERE M_InOutLine_ID="+getM_InOutLine_ID()
+ +" AND C_InvoiceLine_ID="+getC_InvoiceLine_ID());
+ if (cnt <= 0)
+ {
+ MInvoiceLine invoiceLine = new MInvoiceLine(getCtx(), getC_InvoiceLine_ID(), get_TrxName());
+ MInOutLine inoutLine = new MInOutLine(getCtx(), getM_InOutLine_ID(), get_TrxName());
+ throw new IllegalStateException("[MatchPO] Missing corresponding invoice matching record for invoice line "
+ + invoiceLine + " and receipt line " + inoutLine);
+ }
+ }
}
return true;
@@ -632,6 +864,46 @@ public class MMatchPO extends X_M_MatchPO
@Override
protected boolean afterSave (boolean newRecord, boolean success)
{
+ //perform matched qty validation
+ if (success)
+ {
+ if (getM_InOutLine_ID() > 0)
+ {
+ MInOutLine line = new MInOutLine(getCtx(), getM_InOutLine_ID(), get_TrxName());
+ BigDecimal matchedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE M_InOutLine_ID=?" , getM_InOutLine_ID());
+ if (matchedQty != null && matchedQty.compareTo(line.getMovementQty()) > 0)
+ {
+ throw new IllegalStateException("Total matched qty > movement qty. MatchedQty="+matchedQty+", MovementQty="+line.getMovementQty()+", Line="+line);
+ }
+ }
+
+ if (getC_InvoiceLine_ID() > 0)
+ {
+ MInvoiceLine line = new MInvoiceLine(getCtx(), getC_InvoiceLine_ID(), get_TrxName());
+ BigDecimal matchedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE C_InvoiceLine_ID=?" , getC_InvoiceLine_ID());
+ if (matchedQty != null && matchedQty.compareTo(line.getQtyInvoiced()) > 0)
+ {
+ throw new IllegalStateException("Total matched qty > invoiced qty. MatchedQty="+matchedQty+", InvoicedQty="+line.getQtyInvoiced()+", Line="+line);
+ }
+ }
+
+ if (getC_OrderLine_ID() > 0)
+ {
+ MOrderLine line = new MOrderLine(getCtx(), getC_OrderLine_ID(), get_TrxName());
+ BigDecimal invoicedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE C_InvoiceLine_ID > 0 and C_OrderLine_ID=?" , getC_OrderLine_ID());
+ if (invoicedQty != null && invoicedQty.compareTo(line.getQtyOrdered()) > 0)
+ {
+ throw new IllegalStateException("Total matched invoiced qty > ordered qty. MatchedInvoicedQty="+invoicedQty+", OrderedQty="+line.getQtyOrdered()+", Line="+line);
+ }
+
+ BigDecimal deliveredQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE M_InOutLine_ID > 0 and C_OrderLine_ID=?" , getC_OrderLine_ID());
+ if (deliveredQty != null && deliveredQty.compareTo(line.getQtyOrdered()) > 0)
+ {
+ throw new IllegalStateException("Total matched delivered qty > ordered qty. MatchedDeliveredQty="+deliveredQty+", OrderedQty="+line.getQtyOrdered()+", Line="+line);
+ }
+ }
+ }
+
// Purchase Order Delivered/Invoiced
// (Reserved in VMatch and MInOut.completeIt)
if (success && getC_OrderLine_ID() != 0)
diff --git a/org.adempiere.install/install.app.launch b/org.adempiere.install/install.app.launch
index c7e5ebc931..fe68ee2e0a 100644
--- a/org.adempiere.install/install.app.launch
+++ b/org.adempiere.install/install.app.launch
@@ -19,7 +19,7 @@
-
+
diff --git a/org.adempiere.install/install.console.app.launch b/org.adempiere.install/install.console.app.launch
index ae453f729d..a021f50cdc 100644
--- a/org.adempiere.install/install.console.app.launch
+++ b/org.adempiere.install/install.console.app.launch
@@ -19,7 +19,7 @@
-
+
diff --git a/org.adempiere.server-feature/setup/configuration/config.ini b/org.adempiere.server-feature/setup/configuration/config.ini
index 4b4ae801d6..99bf459c0b 100644
--- a/org.adempiere.server-feature/setup/configuration/config.ini
+++ b/org.adempiere.server-feature/setup/configuration/config.ini
@@ -1,5 +1,5 @@
osgi.framework=file\:../plugins/org.eclipse.osgi_3.7.2.v20120110-1415.jar
equinox.use.ds=true
-osgi.bundles=org.eclipse.core.variables,org.eclipse.ant.core,org.eclipse.core.runtime@start,org.adempiere.base@start,org.compiere.db.oracle.provider,org.compiere.db.postgresql.provider,org.hamcrest.core,org.junit,org.adempiere.install,org.restlet,com.springsource.net.sf.cglib,com.springsource.javax.mail,com.springsource.org.apache.activemq,com.springsource.org.apache.kahadb,org.apache.commons.collections,org.apache.ant,javax.servlet,com.springsource.javax.jms,org.apache.ecs,org.apache.commons.net,org.eclipse.equinox.app,org.eclipse.equinox.registry,org.eclipse.equinox.common@2:start,org.eclipse.core.contenttype,org.apache.poi,org.eclipse.core.jobs,org.eclipse.equinox.preferences,org.apache.commons.logging,com.springsource.org.apache.commons.logging,com.springsource.javax.management.j2ee,org.eclipse.osgi.services,com.springsource.javax.ejb,com.springsource.javax.xml.rpc,com.springsource.javax.xml.soap,javax.xml
+osgi.bundles=org.eclipse.equinox.ds@1:start,org.eclipse.equinox.util,org.eclipse.core.variables,org.eclipse.ant.core,org.eclipse.core.runtime@start,org.adempiere.base@start,org.compiere.db.oracle.provider,org.compiere.db.postgresql.provider,org.hamcrest.core,org.junit,org.adempiere.install,org.restlet,com.springsource.net.sf.cglib,com.springsource.javax.mail,com.springsource.org.apache.activemq,com.springsource.org.apache.kahadb,org.apache.commons.collections,org.apache.ant,javax.servlet,com.springsource.javax.jms,org.apache.ecs,org.apache.commons.net,org.eclipse.equinox.app,org.eclipse.equinox.registry,org.eclipse.equinox.common@2:start,org.eclipse.core.contenttype,org.apache.poi,org.eclipse.core.jobs,org.eclipse.equinox.preferences,org.apache.commons.logging,com.springsource.org.apache.commons.logging,com.springsource.javax.management.j2ee,org.eclipse.osgi.services,com.springsource.javax.ejb,com.springsource.javax.xml.rpc,com.springsource.javax.xml.soap,javax.xml
osgi.framework.extensions=
osgi.bundles.defaultStartLevel=4
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java
index 0ab772fb23..c2610c5850 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java
@@ -419,7 +419,7 @@ public class CompositeADTabbox extends AbstractADTabbox
activateDetailADTabpanel();
}
- headerTab.setDetailPaneMode(false, isUseVflexForDetailPane());
+ headerTab.setDetailPaneMode(false, true);
updateBreadCrumb();
}
diff --git a/org.adempiere.ui/src/org/compiere/apps/form/Match.java b/org.adempiere.ui/src/org/compiere/apps/form/Match.java
index 9aaaf9bf6c..d90baa87fb 100644
--- a/org.adempiere.ui/src/org/compiere/apps/form/Match.java
+++ b/org.adempiere.ui/src/org/compiere/apps/form/Match.java
@@ -21,6 +21,7 @@ import java.sql.Timestamp;
import java.util.Vector;
import java.util.logging.Level;
+import org.adempiere.exceptions.AdempiereException;
import org.compiere.minigrid.IDColumn;
import org.compiere.minigrid.IMiniTable;
import org.compiere.model.MClient;
@@ -38,6 +39,7 @@ import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.util.Trx;
+import org.compiere.util.ValueNamePair;
public class Match
{
@@ -416,50 +418,74 @@ public class Match
{
MMatchInv match = new MMatchInv (iLine, null, qty);
match.setM_InOutLine_ID(M_InOutLine_ID);
- if (match.save()) {
- success = true;
- if (MClient.isClientAccountingImmediate()) {
- String ignoreError = DocumentEngine.postImmediate(match.getCtx(), match.getAD_Client_ID(), match.get_Table_ID(), match.get_ID(), true, match.get_TrxName());
+ match.saveEx();
+ success = true;
+ if (MClient.isClientAccountingImmediate()) {
+ String ignoreError = DocumentEngine.postImmediate(match.getCtx(), match.getAD_Client_ID(), match.get_Table_ID(), match.get_ID(), true, match.get_TrxName());
+ if (ignoreError != null) {
+ log.info(ignoreError);
}
}
- else
- log.log(Level.SEVERE, "Inv Match not created: " + match);
}
else
success = true;
// Create PO - Invoice Link = corrects PO
- if (iLine.getC_OrderLine_ID() != 0 && iLine.getM_Product_ID() != 0)
+ if (iLine.getM_Product_ID() != 0)
{
- MMatchPO matchPO = MMatchPO.create(iLine, sLine, null, qty);
- matchPO.setC_InvoiceLine_ID(iLine);
- matchPO.setM_InOutLine_ID(M_InOutLine_ID);
- if (!matchPO.save())
- log.log(Level.SEVERE, "PO(Inv) Match not created: " + matchPO);
- if (MClient.isClientAccountingImmediate()) {
- String ignoreError = DocumentEngine.postImmediate(matchPO.getCtx(), matchPO.getAD_Client_ID(), matchPO.get_Table_ID(), matchPO.get_ID(), true, matchPO.get_TrxName());
+ BigDecimal matchedQty = DB.getSQLValueBD(iLine.get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE C_InvoiceLine_ID=?" , iLine.getC_InvoiceLine_ID());
+ if (matchedQty.add(qty).compareTo(iLine.getQtyInvoiced()) <= 0)
+ {
+ MMatchPO matchPO = MMatchPO.create(iLine, sLine, null, qty);
+ if (matchPO != null)
+ {
+ matchPO.saveEx();
+ if (MClient.isClientAccountingImmediate()) {
+ String ignoreError = DocumentEngine.postImmediate(matchPO.getCtx(), matchPO.getAD_Client_ID(), matchPO.get_Table_ID(), matchPO.get_ID(), true, matchPO.get_TrxName());
+ if (ignoreError != null)
+ log.info(ignoreError);
+ }
+ }
}
}
}
else // Shipment - Order
{
- // Update Shipment Line
- sLine.setC_OrderLine_ID(Line_ID);
- sLine.saveEx();
// Update Order Line
MOrderLine oLine = new MOrderLine(Env.getCtx(), Line_ID, trxName);
if (oLine.get_ID() != 0) // other in MInOut.completeIt
{
oLine.setQtyReserved(oLine.getQtyReserved().subtract(qty));
- if(!oLine.save())
- log.severe("QtyReserved not updated - C_OrderLine_ID=" + Line_ID);
+ oLine.saveEx();
+ }
+
+ // Update Shipment Line
+ BigDecimal toDeliver = oLine.getQtyOrdered().subtract(oLine.getQtyDelivered());
+ if (sLine.getMovementQty().compareTo(toDeliver) <= 0)
+ {
+ sLine.setC_OrderLine_ID(Line_ID);
+ sLine.saveEx();
+ }
+ else if (sLine.getC_OrderLine_ID() != 0)
+ {
+ sLine.setC_OrderLine_ID(0);
+ sLine.saveEx();
}
// Create PO - Shipment Link
if (sLine.getM_Product_ID() != 0)
{
MMatchPO match = new MMatchPO (sLine, null, qty);
+ match.setC_OrderLine_ID(Line_ID);
if (!match.save())
- log.log(Level.SEVERE, "PO Match not created: " + match);
+ {
+ String msg = "PO Match not created: " + match;
+ ValueNamePair error = CLogger.retrieveError();
+ if (error != null)
+ {
+ msg = msg + ". " + error.getName();
+ }
+ throw new AdempiereException(msg);
+ }
else
{
success = true;