IDEMPIERE-4006 Wrong matched PO quanity for vendor credit memo
This commit is contained in:
parent
9508dfe8fe
commit
fc09db1278
|
@ -0,0 +1,42 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-4006 Wrong matched PO quanity for vendor credit memo
|
||||
-- Sep 3, 2019, 5:51:11 PM SGT
|
||||
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203363,0,0,'Y',TO_DATE('2019-09-03 17:51:10','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-09-03 17:51:10','YYYY-MM-DD HH24:MI:SS'),100,'Ref_MatchPO_ID','Referenced Match PO','Referenced Match PO','U','880834ea-81fe-4813-95de-7390350cee95')
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:51:15 PM SGT
|
||||
UPDATE AD_Element SET EntityType='D',Updated=TO_DATE('2019-09-03 17:51:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=203363
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:04 PM SGT
|
||||
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Reference_Value_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214044,0,'Referenced Match PO',473,'Ref_MatchPO_ID',10,'N','N','N','N','N',0,'N',30,200017,0,0,'Y',TO_DATE('2019-09-03 17:52:03','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-09-03 17:52:03','YYYY-MM-DD HH24:MI:SS'),100,203363,'Y','N','U','N','N','N','Y','50fc1a1d-5bb0-4631-94c3-92c2fa9ec13a','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:16 PM SGT
|
||||
UPDATE AD_Column SET EntityType='D',Updated=TO_DATE('2019-09-03 17:52:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214044
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:21 PM SGT
|
||||
UPDATE AD_Column SET FKConstraintName='RefMatchPO_MMatchPO', FKConstraintType='N',Updated=TO_DATE('2019-09-03 17:52:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214044
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:21 PM SGT
|
||||
ALTER TABLE M_MatchPO ADD Ref_MatchPO_ID NUMBER(10) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:22 PM SGT
|
||||
ALTER TABLE M_MatchPO ADD CONSTRAINT RefMatchPO_MMatchPO FOREIGN KEY (Ref_MatchPO_ID) REFERENCES m_matchpo(m_matchpo_id) DEFERRABLE INITIALLY DEFERRED
|
||||
;
|
||||
|
||||
-- Sep 4, 2019, 5:39:23 PM SGT
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (206171,'Referenced Match PO',409,214044,'Y',10,180,'N','N','N','N',0,0,'Y',TO_DATE('2019-09-04 17:39:22','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-09-04 17:39:22','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','e69ff166-dfc2-4b3d-b432-744b10440827','Y',180,2)
|
||||
;
|
||||
|
||||
-- Sep 4, 2019, 5:41:04 PM SGT
|
||||
UPDATE AD_Field SET SeqNo=65, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=65, XPosition=4, IsToolbarButton=NULL,Updated=TO_DATE('2019-09-04 17:41:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206171
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201909061600_IDEMPIERE-4006.sql') FROM dual
|
||||
;
|
|
@ -0,0 +1,39 @@
|
|||
-- IDEMPIERE-4006 Wrong matched PO quanity for vendor credit memo
|
||||
-- Sep 3, 2019, 5:51:11 PM SGT
|
||||
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203363,0,0,'Y',TO_TIMESTAMP('2019-09-03 17:51:10','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-09-03 17:51:10','YYYY-MM-DD HH24:MI:SS'),100,'Ref_MatchPO_ID','Referenced Match PO','Referenced Match PO','U','880834ea-81fe-4813-95de-7390350cee95')
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:51:15 PM SGT
|
||||
UPDATE AD_Element SET EntityType='D',Updated=TO_TIMESTAMP('2019-09-03 17:51:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=203363
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:04 PM SGT
|
||||
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Reference_Value_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214044,0,'Referenced Match PO',473,'Ref_MatchPO_ID',10,'N','N','N','N','N',0,'N',30,200017,0,0,'Y',TO_TIMESTAMP('2019-09-03 17:52:03','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-09-03 17:52:03','YYYY-MM-DD HH24:MI:SS'),100,203363,'Y','N','U','N','N','N','Y','50fc1a1d-5bb0-4631-94c3-92c2fa9ec13a','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:16 PM SGT
|
||||
UPDATE AD_Column SET EntityType='D',Updated=TO_TIMESTAMP('2019-09-03 17:52:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214044
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:21 PM SGT
|
||||
UPDATE AD_Column SET FKConstraintName='RefMatchPO_MMatchPO', FKConstraintType='N',Updated=TO_TIMESTAMP('2019-09-03 17:52:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214044
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:21 PM SGT
|
||||
ALTER TABLE M_MatchPO ADD COLUMN Ref_MatchPO_ID NUMERIC(10) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Sep 3, 2019, 5:52:22 PM SGT
|
||||
ALTER TABLE M_MatchPO ADD CONSTRAINT RefMatchPO_MMatchPO FOREIGN KEY (Ref_MatchPO_ID) REFERENCES m_matchpo(m_matchpo_id) DEFERRABLE INITIALLY DEFERRED
|
||||
;
|
||||
|
||||
-- Sep 4, 2019, 5:39:23 PM SGT
|
||||
INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (206171,'Referenced Match PO',409,214044,'Y',10,180,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2019-09-04 17:39:22','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-09-04 17:39:22','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','e69ff166-dfc2-4b3d-b432-744b10440827','Y',180,2)
|
||||
;
|
||||
|
||||
-- Sep 4, 2019, 5:41:04 PM SGT
|
||||
UPDATE AD_Field SET SeqNo=65, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=65, XPosition=4, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-09-04 17:41:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206171
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201909061600_IDEMPIERE-4006.sql') FROM dual
|
||||
;
|
|
@ -19,6 +19,7 @@ package org.compiere.process;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.MMatchInv;
|
||||
import org.compiere.model.MMatchPO;
|
||||
import org.compiere.util.AdempiereUserError;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
|
@ -51,19 +52,28 @@ public class MatchInvDelete extends SvrProcess
|
|||
protected String doIt() throws Exception
|
||||
{
|
||||
if (log.isLoggable(Level.INFO)) log.info ("M_MatchInv_ID=" + p_M_MatchInv_ID);
|
||||
|
||||
String msg = "";
|
||||
|
||||
MMatchInv inv = new MMatchInv (getCtx(), p_M_MatchInv_ID, get_TrxName());
|
||||
if (inv.get_ID() == 0)
|
||||
throw new AdempiereUserError("@NotFound@ @M_MatchInv_ID@ " + p_M_MatchInv_ID);
|
||||
if (inv.delete(true))
|
||||
return "@OK@";
|
||||
|
||||
String msg = null;
|
||||
ValueNamePair err = CLogger.retrieveError();
|
||||
if (err != null)
|
||||
msg = err.getName();
|
||||
if (msg == null || msg.length() == 0)
|
||||
msg = " - Check log";
|
||||
return "@Error@: " + msg;
|
||||
int reversalId = inv.getReversal_ID();
|
||||
if (!inv.delete(true))
|
||||
return "@Error@";
|
||||
|
||||
msg += "@Deleted@";
|
||||
|
||||
if (reversalId > 0) {
|
||||
MMatchInv invrev = new MMatchInv (getCtx(), reversalId, get_TrxName());
|
||||
if (invrev.get_ID() == 0)
|
||||
throw new AdempiereUserError("@NotFound@ @M_MatchInv_ID@ " + reversalId);
|
||||
if (!invrev.delete(true)) {
|
||||
return "@Error@ @Reversal_ID@";
|
||||
}
|
||||
msg += " + @Deleted@ @Reversal_ID@";
|
||||
}
|
||||
return msg;
|
||||
} // doIt
|
||||
|
||||
} // MatchInvDelete
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.compiere.model.MOrderLandedCostAllocation;
|
|||
import org.compiere.model.MOrderLine;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MTax;
|
||||
import org.compiere.model.MatchPOAutoMatch;
|
||||
import org.compiere.model.ProductCost;
|
||||
import org.compiere.model.X_M_InOut;
|
||||
import org.compiere.process.DocAction;
|
||||
|
@ -114,7 +115,7 @@ public class Doc_MatchPO extends Doc
|
|||
List<MMatchPO> noInvoiceLines = new ArrayList<MMatchPO>();
|
||||
Map<Integer, BigDecimal[]> noShipmentLines = new HashMap<>();
|
||||
Map<Integer, BigDecimal[]> postedNoShipmentLines = new HashMap<>();
|
||||
MMatchPO[] matchPOs = MMatchPO.getOrderLine(getCtx(), m_oLine.getC_OrderLine_ID(), getTrxName());
|
||||
List<MMatchPO> matchPOs = MatchPOAutoMatch.getNotMatchedMatchPOList(getCtx(), m_oLine.getC_OrderLine_ID(), getTrxName());
|
||||
for (MMatchPO matchPO : matchPOs)
|
||||
{
|
||||
if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getC_InvoiceLine_ID() == 0 && matchPO.getReversal_ID()==0)
|
||||
|
@ -188,7 +189,8 @@ public class Doc_MatchPO extends Doc
|
|||
|
||||
if (m_M_InOutLine_ID == 0) // Defer posting if not matched to Shipment
|
||||
{
|
||||
m_deferPosting = true;
|
||||
if (m_matchPO.getRef_MatchPO_ID() == 0)
|
||||
m_deferPosting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -264,6 +266,9 @@ public class Doc_MatchPO extends Doc
|
|||
|
||||
if (m_M_InOutLine_ID == 0) // No posting if not matched to Shipment
|
||||
{
|
||||
if (m_matchPO.getRef_MatchPO_ID() > 0)
|
||||
return facts;
|
||||
|
||||
p_Error = "No posting if not matched to Shipment";
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -327,6 +327,17 @@ public interface I_M_MatchPO
|
|||
*/
|
||||
public BigDecimal getQty();
|
||||
|
||||
/** Column name Ref_MatchPO_ID */
|
||||
public static final String COLUMNNAME_Ref_MatchPO_ID = "Ref_MatchPO_ID";
|
||||
|
||||
/** Set Referenced Match PO */
|
||||
public void setRef_MatchPO_ID (int Ref_MatchPO_ID);
|
||||
|
||||
/** Get Referenced Match PO */
|
||||
public int getRef_MatchPO_ID();
|
||||
|
||||
public org.compiere.model.I_M_MatchPO getRef_MatchPO() throws RuntimeException;
|
||||
|
||||
/** Column name Reversal_ID */
|
||||
public static final String COLUMNNAME_Reversal_ID = "Reversal_ID";
|
||||
|
||||
|
|
|
@ -1144,6 +1144,7 @@ public class MInvoice extends X_C_Invoice implements DocAction
|
|||
int no = DB.executeUpdate(sql.toString(), get_TrxName());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Lines -> #" + no);
|
||||
}
|
||||
|
||||
return true;
|
||||
} // afterSave
|
||||
|
||||
|
@ -1831,10 +1832,11 @@ public class MInvoice extends X_C_Invoice implements DocAction
|
|||
&& !isReversal())
|
||||
{
|
||||
MInOutLine receiptLine = new MInOutLine (getCtx(),line.getM_InOutLine_ID(), get_TrxName());
|
||||
BigDecimal matchQty = line.getQtyInvoiced();
|
||||
BigDecimal movementQty = receiptLine.getM_InOut().getMovementType().charAt(1) == '-' ? receiptLine.getMovementQty().negate() : receiptLine.getMovementQty();
|
||||
BigDecimal matchQty = isCreditMemo() ? line.getQtyInvoiced().negate() : line.getQtyInvoiced();
|
||||
|
||||
if (receiptLine.getMovementQty().compareTo(matchQty) < 0)
|
||||
matchQty = receiptLine.getMovementQty();
|
||||
if (movementQty.compareTo(matchQty) < 0)
|
||||
matchQty = movementQty;
|
||||
|
||||
MMatchInv inv = new MMatchInv(line, getDateInvoiced(), matchQty);
|
||||
if (!inv.save(get_TrxName()))
|
||||
|
@ -1869,7 +1871,7 @@ public class MInvoice extends X_C_Invoice implements DocAction
|
|||
&& !isReversal())
|
||||
{
|
||||
// MatchPO is created also from MInOut when Invoice exists before Shipment
|
||||
BigDecimal matchQty = line.getQtyInvoiced();
|
||||
BigDecimal matchQty = isCreditMemo() ? line.getQtyInvoiced().negate() : line.getQtyInvoiced();
|
||||
MMatchPO po = MMatchPO.create (line, null,
|
||||
getDateInvoiced(), matchQty);
|
||||
if (po != null)
|
||||
|
@ -1897,7 +1899,7 @@ public class MInvoice extends X_C_Invoice implements DocAction
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Update QtyInvoiced RMA Line
|
||||
if (line.getM_RMALine_ID() != 0)
|
||||
{
|
||||
|
@ -2425,6 +2427,9 @@ public class MInvoice extends X_C_Invoice implements DocAction
|
|||
}
|
||||
addDocsPostProcess(new MMatchInv(Env.getCtx(), mInv[i].getReversal_ID(), get_TrxName()));
|
||||
}
|
||||
|
||||
MatchPOAutoMatch.unmatch(getCtx(), getC_Invoice_ID(), get_TrxName());
|
||||
|
||||
MMatchPO[] mPO = MMatchPO.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName());
|
||||
for (int i = 0; i < mPO.length; i++)
|
||||
{
|
||||
|
|
|
@ -352,17 +352,11 @@ public class MMatchPO extends X_M_MatchPO
|
|||
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=? and Reversal_ID IS NULL ORDER BY M_MatchPO_ID";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
List<MMatchPO> matchPOList = MatchPOAutoMatch.getNotMatchedMatchPOList(ctx, C_OrderLine_ID, trxName);
|
||||
if (!matchPOList.isEmpty())
|
||||
{
|
||||
pstmt = DB.prepareStatement (sql, trxName);
|
||||
pstmt.setInt (1, C_OrderLine_ID);
|
||||
rs = pstmt.executeQuery ();
|
||||
while (rs.next ())
|
||||
for (MMatchPO mpo : matchPOList)
|
||||
{
|
||||
MMatchPO mpo = new MMatchPO (ctx, rs, trxName);
|
||||
if (qty.compareTo(mpo.getQty()) >= 0)
|
||||
{
|
||||
BigDecimal toMatch = qty;
|
||||
|
@ -408,7 +402,7 @@ public class MMatchPO extends X_M_MatchPO
|
|||
{
|
||||
//verify m_matchinv not created for other invoice
|
||||
int cnt = DB.getSQLValue(iLine.get_TrxName(), "SELECT Count(*) FROM M_MatchInv WHERE M_InOutLine_ID="+mpo.getM_InOutLine_ID()
|
||||
+" AND C_InvoiceLine_ID != "+iLine.getC_InvoiceLine_ID());
|
||||
+" AND C_InvoiceLine_ID != "+iLine.getC_InvoiceLine_ID() + " AND Reversal_ID=0");
|
||||
if (cnt > 0)
|
||||
continue;
|
||||
}
|
||||
|
@ -429,46 +423,10 @@ public class MMatchPO extends X_M_MatchPO
|
|||
+" 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);
|
||||
matchInv.setProcessed(true);
|
||||
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);
|
||||
MMatchInv matchInv = createMatchInv(mpo, C_InvoiceLine_ID, M_InOutLine_ID, mpo.getQty(), dateTrx, trxName);
|
||||
if (matchInv == null)
|
||||
continue;
|
||||
}
|
||||
mpo.setMatchInvCreated(matchInv);
|
||||
if (savepoint != null)
|
||||
{
|
||||
try {
|
||||
trx.getConnection().releaseSavepoint(savepoint);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iLine != null)
|
||||
|
@ -499,22 +457,6 @@ public class MMatchPO extends X_M_MatchPO
|
|||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// Create New
|
||||
if (retValue == null)
|
||||
|
@ -528,7 +470,7 @@ public class MMatchPO extends X_M_MatchPO
|
|||
if (sLine != null && (sLine.getC_OrderLine_ID() == C_OrderLine_ID || iLine == null)
|
||||
&& (sLineMatchedQty == null || sLineMatchedQty.signum() <= 0))
|
||||
{
|
||||
if (qty.signum() > 0)
|
||||
if (qty.signum() != 0)
|
||||
{
|
||||
retValue = new MMatchPO (sLine, dateTrx, qty);
|
||||
retValue.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
|
@ -562,52 +504,8 @@ public class MMatchPO extends X_M_MatchPO
|
|||
//auto create matchinv
|
||||
if (otherMatchPO != null)
|
||||
{
|
||||
Savepoint savepoint = null;
|
||||
Trx trx = null;
|
||||
try
|
||||
{
|
||||
trx = trxName != null ? Trx.get(trxName, false) : null;
|
||||
savepoint = trx != null ? trx.getConnection().setSavepoint() : null;
|
||||
MMatchInv matchInv = new MMatchInv(retValue.getCtx(), 0, retValue.get_TrxName());
|
||||
matchInv.setC_InvoiceLine_ID(otherMatchPO.getC_InvoiceLine_ID());
|
||||
matchInv.setM_Product_ID(retValue.getM_Product_ID());
|
||||
matchInv.setM_InOutLine_ID(retValue.getM_InOutLine_ID());
|
||||
matchInv.setAD_Client_ID(retValue.getAD_Client_ID());
|
||||
matchInv.setAD_Org_ID(retValue.getAD_Org_ID());
|
||||
matchInv.setM_AttributeSetInstance_ID(retValue.getM_AttributeSetInstance_ID());
|
||||
matchInv.setQty(retValue.getQty());
|
||||
matchInv.setDateTrx(dateTrx);
|
||||
matchInv.setProcessed(true);
|
||||
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();
|
||||
}
|
||||
s_log.severe(msg);
|
||||
}
|
||||
retValue.setMatchInvCreated(matchInv);
|
||||
} catch (Exception e) {
|
||||
s_log.log(Level.SEVERE, "Failed to auto match Invoice.", e);
|
||||
} finally {
|
||||
if (savepoint != null)
|
||||
{
|
||||
try {
|
||||
trx.getConnection().releaseSavepoint(savepoint);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
MMatchInv matchInv = createMatchInv(retValue, otherMatchPO.getC_InvoiceLine_ID(), retValue.getM_InOutLine_ID(), retValue.getQty(), dateTrx, trxName);
|
||||
retValue.setMatchInvCreated(matchInv);
|
||||
if (otherMatchPO.getQty().signum() == 0 )
|
||||
otherMatchPO.deleteEx(true);
|
||||
}
|
||||
|
@ -626,7 +524,7 @@ public class MMatchPO extends X_M_MatchPO
|
|||
}
|
||||
else if (iLine != null)
|
||||
{
|
||||
if (qty.signum() > 0)
|
||||
if (qty.signum() != 0)
|
||||
{
|
||||
retValue = new MMatchPO (iLine, dateTrx, qty);
|
||||
retValue.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
|
@ -652,7 +550,7 @@ public class MMatchPO extends X_M_MatchPO
|
|||
if (matchPO.getM_MatchPO_ID() == retValue.getM_MatchPO_ID())
|
||||
continue;
|
||||
|
||||
if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_ID() == 0)
|
||||
if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_ID() == 0 && matchPO.getRef_MatchPO_ID() == 0)
|
||||
{
|
||||
if (matchPO.getC_InvoiceLine_ID() == 0)
|
||||
{
|
||||
|
@ -738,54 +636,8 @@ public class MMatchPO extends X_M_MatchPO
|
|||
}
|
||||
if (autoMatchQty != null && autoMatchQty.signum() > 0)
|
||||
{
|
||||
Savepoint savepoint = null;
|
||||
Trx trx = null;
|
||||
MMatchInv matchInv = null;
|
||||
try
|
||||
{
|
||||
trx = trxName != null ? Trx.get(trxName, false) : null;
|
||||
savepoint = trx != null ? trx.getConnection().setSavepoint() : null;
|
||||
matchInv = new MMatchInv(retValue.getCtx(), 0, retValue.get_TrxName());
|
||||
matchInv.setC_InvoiceLine_ID(retValue.getC_InvoiceLine_ID());
|
||||
matchInv.setM_Product_ID(retValue.getM_Product_ID());
|
||||
matchInv.setM_InOutLine_ID(matchPO.getM_InOutLine_ID());
|
||||
matchInv.setAD_Client_ID(retValue.getAD_Client_ID());
|
||||
matchInv.setAD_Org_ID(retValue.getAD_Org_ID());
|
||||
matchInv.setM_AttributeSetInstance_ID(retValue.getM_AttributeSetInstance_ID());
|
||||
matchInv.setQty(autoMatchQty);
|
||||
matchInv.setDateTrx(dateTrx);
|
||||
matchInv.setProcessed(true);
|
||||
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();
|
||||
}
|
||||
s_log.severe(msg);
|
||||
matchInv = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_log.log(Level.SEVERE, "Failed to auto match Invoice.", e);
|
||||
matchInv = null;
|
||||
} finally {
|
||||
if (savepoint != null)
|
||||
{
|
||||
try {
|
||||
trx.getConnection().releaseSavepoint(savepoint);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
MMatchInv matchInv = createMatchInv(retValue, retValue.getC_InvoiceLine_ID(), matchPO.getM_InOutLine_ID(), autoMatchQty, dateTrx, trxName);
|
||||
retValue.setMatchInvCreated(matchInv);
|
||||
if (matchInv == null)
|
||||
break;
|
||||
}
|
||||
|
@ -797,9 +649,65 @@ public class MMatchPO extends X_M_MatchPO
|
|||
}
|
||||
}
|
||||
|
||||
if (C_OrderLine_ID > 0 && retValue != null)
|
||||
MatchPOAutoMatch.match(ctx, C_OrderLine_ID, retValue, trxName);
|
||||
|
||||
return retValue;
|
||||
} // create
|
||||
|
||||
private static MMatchInv createMatchInv(MMatchPO mpo, int C_InvoiceLine_ID, int M_InOutLine_ID, BigDecimal qty, Timestamp dateTrx, String trxName)
|
||||
{
|
||||
Savepoint savepoint = null;
|
||||
Trx trx = null;
|
||||
MMatchInv matchInv = null;
|
||||
try
|
||||
{
|
||||
trx = trxName != null ? Trx.get(trxName, false) : null;
|
||||
savepoint = trx != null ? trx.getConnection().setSavepoint() : null;
|
||||
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(qty);
|
||||
matchInv.setDateTrx(dateTrx);
|
||||
matchInv.setProcessed(true);
|
||||
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();
|
||||
}
|
||||
s_log.severe(msg);
|
||||
matchInv = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_log.log(Level.SEVERE, "Failed to auto match Invoice.", e);
|
||||
matchInv = null;
|
||||
} finally {
|
||||
if (savepoint != null)
|
||||
{
|
||||
try {
|
||||
trx.getConnection().releaseSavepoint(savepoint);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
return matchInv;
|
||||
}
|
||||
|
||||
protected MMatchInv m_matchInv;
|
||||
|
||||
|
@ -1450,6 +1358,7 @@ public class MMatchPO extends X_M_MatchPO
|
|||
reversal.set_ValueNoCheck ("DocumentNo", null);
|
||||
reversal.setPosted (false);
|
||||
reversal.setProcessed(true);
|
||||
reversal.setRef_MatchPO_ID(getRef_MatchPO_ID());
|
||||
reversal.setReversal_ID(getM_MatchPO_ID());
|
||||
reversal.saveEx();
|
||||
|
||||
|
|
|
@ -0,0 +1,385 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 2019 Elaine Tan *
|
||||
* *
|
||||
* 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. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.util.Env;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class MatchPOAutoMatch {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ctx
|
||||
* @param C_OrderLine_ID
|
||||
* @param trxName
|
||||
* @return not fully matched matchpo records
|
||||
*/
|
||||
public static List<MMatchPO> getNotMatchedMatchPOList(Properties ctx, int C_OrderLine_ID, String trxName)
|
||||
{
|
||||
List<MMatchPO> notMatchedMatchPOList = new ArrayList<MMatchPO>();
|
||||
List<MMatchPO> creditMemoMatchPOList = new ArrayList<MMatchPO>();
|
||||
List<MMatchPO> notMatchedCreditMemoMatchPOList = new ArrayList<MMatchPO>();
|
||||
MMatchPO[] mpos = MMatchPO.getOrderLine(ctx, C_OrderLine_ID, trxName);
|
||||
for (MMatchPO mpo : mpos)
|
||||
{
|
||||
if (mpo.getReversal_ID() == 0 && mpo.getRef_MatchPO_ID() == 0)
|
||||
{
|
||||
if (mpo.getQty().signum() < 0)
|
||||
{
|
||||
if (mpo.getC_InvoiceLine_ID() > 0 && mpo.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
String docStatus = mpo.getC_InvoiceLine().getC_Invoice().getDocStatus();
|
||||
if (docStatus.equals(DocAction.STATUS_Completed) || docStatus.equals(DocAction.STATUS_Closed)) {
|
||||
creditMemoMatchPOList.add(mpo);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
notMatchedMatchPOList.add(mpo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!notMatchedMatchPOList.isEmpty())
|
||||
{
|
||||
Collections.sort(notMatchedMatchPOList, new Comparator<MMatchPO>() {
|
||||
@Override
|
||||
public int compare(MMatchPO arg0, MMatchPO arg1) {
|
||||
return arg0.getM_MatchPO_ID() > arg1.getM_MatchPO_ID()
|
||||
? 1
|
||||
: (arg0.getM_MatchPO_ID()==arg1.getM_MatchPO_ID() ? 0 : -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!creditMemoMatchPOList.isEmpty())
|
||||
{
|
||||
BigDecimal totalNotMatchingCreditMemoQty = Env.ZERO;
|
||||
for (MMatchPO matchPOCreditMemo : creditMemoMatchPOList)
|
||||
{
|
||||
boolean found = false;
|
||||
int Ref_InvoiceLine_ID = matchPOCreditMemo.getC_InvoiceLine().getRef_InvoiceLine_ID();
|
||||
if (Ref_InvoiceLine_ID > 0)
|
||||
{
|
||||
for (MMatchPO matchPO : notMatchedMatchPOList)
|
||||
{
|
||||
if (!matchPO.isPosted() && matchPO.getC_InvoiceLine_ID() == Ref_InvoiceLine_ID && matchPO.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
if (matchPO.getQty().compareTo(matchPOCreditMemo.getQty().negate()) == 0)
|
||||
{
|
||||
notMatchedMatchPOList.remove(matchPO);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
for (MMatchPO matchPO : notMatchedMatchPOList)
|
||||
{
|
||||
if (!matchPO.isPosted() && matchPO.getC_InvoiceLine_ID() > 0 && matchPO.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
if (matchPO.getQty().compareTo(matchPOCreditMemo.getQty().negate()) == 0)
|
||||
{
|
||||
notMatchedMatchPOList.remove(matchPO);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
totalNotMatchingCreditMemoQty = totalNotMatchingCreditMemoQty.add(matchPOCreditMemo.getQty().negate());
|
||||
notMatchedCreditMemoMatchPOList.add(matchPOCreditMemo);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalNotMatchingCreditMemoQty.signum() != 0)
|
||||
{
|
||||
BigDecimal totalInvoiceQty = Env.ZERO;
|
||||
for (MMatchPO matchPO : notMatchedMatchPOList)
|
||||
{
|
||||
if (!matchPO.isPosted() && matchPO.getC_InvoiceLine_ID() > 0 && matchPO.getM_InOutLine_ID() == 0)
|
||||
totalInvoiceQty = totalInvoiceQty.add(matchPO.getQty());
|
||||
}
|
||||
|
||||
if (totalNotMatchingCreditMemoQty.compareTo(totalInvoiceQty) == 0)
|
||||
notMatchedMatchPOList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return notMatchedMatchPOList;
|
||||
}
|
||||
|
||||
/**
|
||||
* auto match matchpo
|
||||
* @param ctx
|
||||
* @param C_OrderLine_ID
|
||||
* @param currentPO
|
||||
* @param trxName
|
||||
*/
|
||||
public static void match(Properties ctx, int C_OrderLine_ID, MMatchPO currentPO, String trxName)
|
||||
{
|
||||
List<MMatchPO> notMatchedMatchPOList = new ArrayList<MMatchPO>();
|
||||
List<MMatchPO> creditMemoMatchPOList = new ArrayList<MMatchPO>();
|
||||
List<MMatchPO> matchedMatchPOList = new ArrayList<MMatchPO>();
|
||||
MMatchPO[] mpos = MMatchPO.getOrderLine(ctx, C_OrderLine_ID, trxName);
|
||||
for (MMatchPO mpo : mpos)
|
||||
{
|
||||
if (mpo.getReversal_ID() == 0 && mpo.getRef_MatchPO_ID() == 0)
|
||||
{
|
||||
if (mpo.getQty().signum() < 0)
|
||||
{
|
||||
if (mpo.getC_InvoiceLine_ID() > 0 && mpo.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
String docStatus = mpo.getC_InvoiceLine().getC_Invoice().getDocStatus();
|
||||
if ((currentPO != null && mpo.getM_MatchPO_ID() == currentPO.getM_MatchPO_ID())
|
||||
|| docStatus.equals(DocAction.STATUS_Completed)
|
||||
|| docStatus.equals(DocAction.STATUS_Closed)) {
|
||||
creditMemoMatchPOList.add(mpo);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
notMatchedMatchPOList.add(mpo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!notMatchedMatchPOList.isEmpty())
|
||||
{
|
||||
Collections.sort(notMatchedMatchPOList, new Comparator<MMatchPO>() {
|
||||
@Override
|
||||
public int compare(MMatchPO arg0, MMatchPO arg1) {
|
||||
return arg0.getM_MatchPO_ID() > arg1.getM_MatchPO_ID()
|
||||
? 1
|
||||
: (arg0.getM_MatchPO_ID()==arg1.getM_MatchPO_ID() ? 0 : -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!creditMemoMatchPOList.isEmpty())
|
||||
{
|
||||
for (MMatchPO matchPOCreditMemo : creditMemoMatchPOList)
|
||||
{
|
||||
BigDecimal creditMemoQty = matchPOCreditMemo.getQty().negate();
|
||||
|
||||
int Ref_InvoiceLine_ID = matchPOCreditMemo.getC_InvoiceLine().getRef_InvoiceLine_ID();
|
||||
if (Ref_InvoiceLine_ID > 0)
|
||||
{
|
||||
for (MMatchPO matchPO : notMatchedMatchPOList)
|
||||
{
|
||||
if (!matchPO.isPosted() && matchPO.getC_InvoiceLine_ID() == Ref_InvoiceLine_ID && matchPO.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
if (matchPO.getQty().compareTo(creditMemoQty) > 0)
|
||||
{
|
||||
matchPO.setQty(matchPO.getQty().subtract(creditMemoQty));
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
MInvoiceLine iLine = new MInvoiceLine(ctx, matchPO.getC_InvoiceLine_ID(), trxName);
|
||||
MMatchPO po = new MMatchPO(iLine, iLine.getC_Invoice().getDateInvoiced(), creditMemoQty);
|
||||
po.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
po.setRef_MatchPO_ID(matchPOCreditMemo.getM_MatchPO_ID());
|
||||
po.setPosted(true);
|
||||
po.saveEx(trxName);
|
||||
|
||||
matchPOCreditMemo.setRef_MatchPO_ID(po.getM_MatchPO_ID());
|
||||
matchPOCreditMemo.setPosted(true);
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(po);
|
||||
creditMemoQty = creditMemoQty.subtract(po.getQty());
|
||||
}
|
||||
else if (matchPO.getQty().compareTo(creditMemoQty) == 0)
|
||||
{
|
||||
matchPO.setRef_MatchPO_ID(matchPOCreditMemo.getM_MatchPO_ID());
|
||||
matchPO.setPosted(true);
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
matchPOCreditMemo.setRef_MatchPO_ID(matchPO.getM_MatchPO_ID());
|
||||
matchPOCreditMemo.setPosted(true);
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(matchPO);
|
||||
creditMemoQty = creditMemoQty.subtract(matchPO.getQty());
|
||||
}
|
||||
else if (matchPO.getQty().compareTo(creditMemoQty) < 0)
|
||||
{
|
||||
matchPOCreditMemo.setQty(matchPOCreditMemo.getQty().add(matchPO.getQty()));
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
MInvoiceLine iLine = new MInvoiceLine(ctx, matchPOCreditMemo.getC_InvoiceLine_ID(), trxName);
|
||||
MMatchPO po = new MMatchPO(iLine, iLine.getC_Invoice().getDateInvoiced(), matchPO.getQty().negate());
|
||||
po.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
po.setRef_MatchPO_ID(matchPO.getM_MatchPO_ID());
|
||||
po.setPosted(true);
|
||||
po.saveEx(trxName);
|
||||
|
||||
matchPO.setRef_MatchPO_ID(po.getM_MatchPO_ID());
|
||||
matchPO.setPosted(true);
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(matchPO);
|
||||
creditMemoQty = creditMemoQty.subtract(matchPO.getQty());
|
||||
}
|
||||
|
||||
if (creditMemoQty.signum() == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (MMatchPO matchedMatchPO : matchedMatchPOList)
|
||||
notMatchedMatchPOList.remove(matchedMatchPO);
|
||||
}
|
||||
|
||||
if (creditMemoQty.signum() == 0)
|
||||
continue;
|
||||
|
||||
for (MMatchPO matchPO : notMatchedMatchPOList)
|
||||
{
|
||||
if (!matchPO.isPosted() && matchPO.getC_InvoiceLine_ID() > 0 && matchPO.getM_InOutLine_ID() == 0)
|
||||
{
|
||||
if (matchPO.getQty().compareTo(creditMemoQty) > 0)
|
||||
{
|
||||
matchPO.setQty(matchPO.getQty().subtract(creditMemoQty));
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
MInvoiceLine iLine = new MInvoiceLine(ctx, matchPO.getC_InvoiceLine_ID(), trxName);
|
||||
MMatchPO po = new MMatchPO(iLine, iLine.getC_Invoice().getDateInvoiced(), creditMemoQty);
|
||||
po.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
po.setRef_MatchPO_ID(matchPOCreditMemo.getM_MatchPO_ID());
|
||||
po.setPosted(true);
|
||||
po.saveEx(trxName);
|
||||
|
||||
matchPOCreditMemo.setRef_MatchPO_ID(po.getM_MatchPO_ID());
|
||||
matchPOCreditMemo.setPosted(true);
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(po);
|
||||
creditMemoQty = creditMemoQty.subtract(po.getQty());
|
||||
}
|
||||
else if (matchPO.getQty().compareTo(creditMemoQty) == 0)
|
||||
{
|
||||
matchPO.setRef_MatchPO_ID(matchPOCreditMemo.getM_MatchPO_ID());
|
||||
matchPO.setPosted(true);
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
matchPOCreditMemo.setRef_MatchPO_ID(matchPO.getM_MatchPO_ID());
|
||||
matchPOCreditMemo.setPosted(true);
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(matchPO);
|
||||
creditMemoQty = creditMemoQty.subtract(matchPO.getQty());
|
||||
}
|
||||
else if (matchPO.getQty().compareTo(creditMemoQty) < 0)
|
||||
{
|
||||
matchPOCreditMemo.setQty(matchPOCreditMemo.getQty().add(matchPO.getQty()));
|
||||
matchPOCreditMemo.saveEx(trxName);
|
||||
|
||||
MInvoiceLine iLine = new MInvoiceLine(ctx, matchPOCreditMemo.getC_InvoiceLine_ID(), trxName);
|
||||
MMatchPO po = new MMatchPO(iLine, iLine.getC_Invoice().getDateInvoiced(), matchPO.getQty().negate());
|
||||
po.setC_OrderLine_ID(C_OrderLine_ID);
|
||||
po.setRef_MatchPO_ID(matchPO.getM_MatchPO_ID());
|
||||
po.setPosted(true);
|
||||
po.saveEx(trxName);
|
||||
|
||||
matchPO.setRef_MatchPO_ID(po.getM_MatchPO_ID());
|
||||
matchPO.setPosted(true);
|
||||
matchPO.saveEx(trxName);
|
||||
|
||||
matchedMatchPOList.add(matchPO);
|
||||
creditMemoQty = creditMemoQty.subtract(matchPO.getQty());
|
||||
}
|
||||
|
||||
if (creditMemoQty.signum() == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (MMatchPO matchedMatchPO : matchedMatchPOList)
|
||||
notMatchedMatchPOList.remove(matchedMatchPO);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentPO != null)
|
||||
{
|
||||
for (MMatchPO matchPOCreditMemo : creditMemoMatchPOList)
|
||||
{
|
||||
if (matchPOCreditMemo.getM_MatchPO_ID() == currentPO.getM_MatchPO_ID())
|
||||
{
|
||||
if (matchPOCreditMemo.getReversal_ID() == 0 && matchPOCreditMemo.getRef_MatchPO_ID() == 0)
|
||||
throw new RuntimeException("Failed to find the corresponding invoice matched po");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove match between vendor invoice and vendor cm
|
||||
* @param ctx
|
||||
* @param C_Invoice_ID
|
||||
* @param trxName
|
||||
*/
|
||||
public static void unmatch(Properties ctx, int C_Invoice_ID, String trxName)
|
||||
{
|
||||
List<Integer> unmatchedOrderLineID = new ArrayList<Integer>();
|
||||
MMatchPO[] mpos = MMatchPO.getInvoice(ctx, C_Invoice_ID, trxName);
|
||||
for (MMatchPO mpo : mpos)
|
||||
{
|
||||
if (mpo.getReversal_ID() > 0 || mpo.getRef_MatchPO_ID() == 0)
|
||||
continue;
|
||||
|
||||
int C_OrderLine_ID = mpo.getC_OrderLine_ID();
|
||||
if (!unmatchedOrderLineID.contains(C_OrderLine_ID))
|
||||
{
|
||||
unmatchedOrderLineID.add(C_OrderLine_ID);
|
||||
|
||||
MMatchPO[] pos = MMatchPO.getOrderLine(ctx, C_OrderLine_ID, trxName);
|
||||
for (MMatchPO po : pos)
|
||||
{
|
||||
if (po.getReversal_ID() == 0 && po.getC_InvoiceLine_ID() > 0 && po.getRef_MatchPO_ID() > 0)
|
||||
{
|
||||
if (po.getC_InvoiceLine().getC_Invoice_ID() == C_Invoice_ID)
|
||||
{
|
||||
po.setRef_MatchPO_ID(0);
|
||||
po.setPosted(false);
|
||||
po.saveEx(trxName);
|
||||
}
|
||||
else if (po.getRef_MatchPO().getC_InvoiceLine().getC_Invoice_ID() == C_Invoice_ID)
|
||||
{
|
||||
po.setRef_MatchPO_ID(0);
|
||||
po.setPosted(false);
|
||||
po.saveEx(trxName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ public class X_M_MatchPO extends PO implements I_M_MatchPO, I_Persistent
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20190106L;
|
||||
private static final long serialVersionUID = 20190903L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_M_MatchPO (Properties ctx, int M_MatchPO_ID, String trxName)
|
||||
|
@ -488,6 +488,31 @@ public class X_M_MatchPO extends PO implements I_M_MatchPO, I_Persistent
|
|||
return bd;
|
||||
}
|
||||
|
||||
public org.compiere.model.I_M_MatchPO getRef_MatchPO() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_M_MatchPO)MTable.get(getCtx(), org.compiere.model.I_M_MatchPO.Table_Name)
|
||||
.getPO(getRef_MatchPO_ID(), get_TrxName()); }
|
||||
|
||||
/** Set Referenced Match PO.
|
||||
@param Ref_MatchPO_ID Referenced Match PO */
|
||||
public void setRef_MatchPO_ID (int Ref_MatchPO_ID)
|
||||
{
|
||||
if (Ref_MatchPO_ID < 1)
|
||||
set_Value (COLUMNNAME_Ref_MatchPO_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_Ref_MatchPO_ID, Integer.valueOf(Ref_MatchPO_ID));
|
||||
}
|
||||
|
||||
/** Get Referenced Match PO.
|
||||
@return Referenced Match PO */
|
||||
public int getRef_MatchPO_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_Ref_MatchPO_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
public org.compiere.model.I_M_MatchPO getReversal() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_M_MatchPO)MTable.get(getCtx(), org.compiere.model.I_M_MatchPO.Table_Name)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@ import java.awt.event.ActionEvent;
|
|||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.VetoableChangeListener;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Level;
|
||||
|
@ -94,6 +95,8 @@ public class VCreateFromInvoiceUI extends CreateFromInvoice implements ActionLis
|
|||
/** Combo box for selecting RMA document */
|
||||
private JComboBox<Object> rmaField = new JComboBox<Object>();
|
||||
|
||||
private boolean isCreditMemo = false;
|
||||
|
||||
/**
|
||||
* Dynamic Init
|
||||
* @throws Exception if Lookups cannot be initialized
|
||||
|
@ -116,6 +119,9 @@ public class VCreateFromInvoiceUI extends CreateFromInvoice implements ActionLis
|
|||
rmaField.setVisible(false);
|
||||
}
|
||||
|
||||
isCreditMemo = MDocType.DOCBASETYPE_APCreditMemo.equals(docType.getDocBaseType())
|
||||
|| MDocType.DOCBASETYPE_ARCreditMemo.equals(docType.getDocBaseType());
|
||||
|
||||
initBPartner(true);
|
||||
bPartnerField.addVetoableChangeListener(this);
|
||||
|
||||
|
@ -276,7 +282,7 @@ public class VCreateFromInvoiceUI extends CreateFromInvoice implements ActionLis
|
|||
orderField.removeAllItems();
|
||||
orderField.addItem(pp);
|
||||
|
||||
ArrayList<KeyNamePair> list = loadOrderData(C_BPartner_ID, forInvoice, false);
|
||||
ArrayList<KeyNamePair> list = loadOrderData(C_BPartner_ID, forInvoice, false, isCreditMemo);
|
||||
for(KeyNamePair knp : list)
|
||||
orderField.addItem(knp);
|
||||
|
||||
|
@ -343,7 +349,7 @@ public class VCreateFromInvoiceUI extends CreateFromInvoice implements ActionLis
|
|||
*/
|
||||
protected void loadOrder (int C_Order_ID, boolean forInvoice)
|
||||
{
|
||||
loadTableOIS(getOrderData(C_Order_ID, forInvoice));
|
||||
loadTableOIS(getOrderData(C_Order_ID, forInvoice, isCreditMemo));
|
||||
} // LoadOrder
|
||||
|
||||
protected void loadRMA (int M_RMA_ID)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.webui.apps.form;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Level;
|
||||
|
@ -105,6 +106,8 @@ public class WCreateFromInvoiceUI extends CreateFromInvoice implements EventList
|
|||
|
||||
private Grid parameterStdLayout;
|
||||
|
||||
private boolean isCreditMemo = false;
|
||||
|
||||
/**
|
||||
* Dynamic Init
|
||||
* @throws Exception if Lookups cannot be initialized
|
||||
|
@ -127,6 +130,9 @@ public class WCreateFromInvoiceUI extends CreateFromInvoice implements EventList
|
|||
rmaField.setVisible(false);
|
||||
}
|
||||
|
||||
isCreditMemo = MDocType.DOCBASETYPE_APCreditMemo.equals(docType.getDocBaseType())
|
||||
|| MDocType.DOCBASETYPE_ARCreditMemo.equals(docType.getDocBaseType());
|
||||
|
||||
initBPartner(true);
|
||||
bPartnerField.addValueChangeListener(this);
|
||||
|
||||
|
@ -315,7 +321,7 @@ public class WCreateFromInvoiceUI extends CreateFromInvoice implements EventList
|
|||
orderField.removeAllItems();
|
||||
orderField.addItem(pp);
|
||||
|
||||
ArrayList<KeyNamePair> list = loadOrderData(C_BPartner_ID, forInvoice, false);
|
||||
ArrayList<KeyNamePair> list = loadOrderData(C_BPartner_ID, forInvoice, false, isCreditMemo);
|
||||
for(KeyNamePair knp : list)
|
||||
orderField.addItem(knp);
|
||||
|
||||
|
@ -381,7 +387,7 @@ public class WCreateFromInvoiceUI extends CreateFromInvoice implements EventList
|
|||
*/
|
||||
protected void loadOrder (int C_Order_ID, boolean forInvoice)
|
||||
{
|
||||
loadTableOIS(getOrderData(C_Order_ID, forInvoice));
|
||||
loadTableOIS(getOrderData(C_Order_ID, forInvoice, isCreditMemo));
|
||||
} // LoadOrder
|
||||
|
||||
protected void loadRMA (int M_RMA_ID)
|
||||
|
|
|
@ -88,6 +88,11 @@ public abstract class CreateFrom implements ICreateFrom
|
|||
* @param forInvoice for invoice
|
||||
*/
|
||||
protected ArrayList<KeyNamePair> loadOrderData (int C_BPartner_ID, boolean forInvoice, boolean sameWarehouseOnly)
|
||||
{
|
||||
return loadOrderData(C_BPartner_ID, forInvoice, sameWarehouseOnly, false);
|
||||
}
|
||||
|
||||
protected ArrayList<KeyNamePair> loadOrderData (int C_BPartner_ID, boolean forInvoice, boolean sameWarehouseOnly, boolean forCreditMemo)
|
||||
{
|
||||
ArrayList<KeyNamePair> list = new ArrayList<KeyNamePair>();
|
||||
|
||||
|
@ -109,14 +114,20 @@ public abstract class CreateFrom implements ICreateFrom
|
|||
.append(display)
|
||||
.append(" FROM C_Order o WHERE ")
|
||||
.append(colBP)
|
||||
.append("=? AND o.IsSOTrx=? AND o.DocStatus IN ('CL','CO') AND o.C_Order_ID IN (SELECT ol.C_Order_ID FROM C_OrderLine ol WHERE ol.QtyOrdered-")
|
||||
.append(column)
|
||||
.append("!=0) ");
|
||||
.append("=? AND o.IsSOTrx=? AND o.DocStatus IN ('CL','CO') AND o.C_Order_ID IN (SELECT ol.C_Order_ID FROM C_OrderLine ol WHERE ");
|
||||
if (forCreditMemo)
|
||||
sql.append(column).append(">0 AND (CASE WHEN ol.QtyDelivered>=ol.QtyOrdered THEN ol.QtyDelivered-ol.QtyInvoiced!=0 ELSE 1=1 END)) ");
|
||||
else
|
||||
sql.append("ol.QtyOrdered-").append(column).append("!=0) ");
|
||||
|
||||
if(sameWarehouseOnly)
|
||||
{
|
||||
sql = sql.append(" AND o.M_Warehouse_ID=? ");
|
||||
}
|
||||
sql = sql.append("ORDER BY o.DateOrdered,o.DocumentNo");
|
||||
if (forCreditMemo)
|
||||
sql = sql.append("ORDER BY o.DateOrdered DESC,o.DocumentNo DESC");
|
||||
else
|
||||
sql = sql.append("ORDER BY o.DateOrdered,o.DocumentNo");
|
||||
//
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
|
@ -155,6 +166,11 @@ public abstract class CreateFrom implements ICreateFrom
|
|||
* @param forInvoice true if for invoice vs. delivery qty
|
||||
*/
|
||||
protected Vector<Vector<Object>> getOrderData (int C_Order_ID, boolean forInvoice)
|
||||
{
|
||||
return getOrderData (C_Order_ID, forInvoice, false);
|
||||
}
|
||||
|
||||
protected Vector<Vector<Object>> getOrderData (int C_Order_ID, boolean forInvoice, boolean forCreditMemo)
|
||||
{
|
||||
/**
|
||||
* Selected - 0
|
||||
|
@ -170,9 +186,9 @@ public abstract class CreateFrom implements ICreateFrom
|
|||
p_order = new MOrder (Env.getCtx(), C_Order_ID, null);
|
||||
|
||||
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
|
||||
StringBuilder sql = new StringBuilder("SELECT "
|
||||
+ "l.QtyOrdered-SUM(COALESCE(m.Qty,0))," // 1
|
||||
+ "CASE WHEN l.QtyOrdered=0 THEN 0 ELSE l.QtyEntered/l.QtyOrdered END," // 2
|
||||
StringBuilder sql = new StringBuilder("SELECT ");
|
||||
sql.append(forCreditMemo ? "SUM(COALESCE(m.Qty,0))," : "l.QtyOrdered-SUM(COALESCE(m.Qty,0)),"); // 1
|
||||
sql.append("CASE WHEN l.QtyOrdered=0 THEN 0 ELSE l.QtyEntered/l.QtyOrdered END," // 2
|
||||
+ " l.C_UOM_ID,COALESCE(uom.UOMSymbol,uom.Name)," // 3..4
|
||||
+ " COALESCE(l.M_Product_ID,0),COALESCE(p.Name,c.Name),po.VendorProductNo," // 5..7
|
||||
+ " l.C_OrderLine_ID,l.Line " // 8..9
|
||||
|
@ -180,7 +196,7 @@ public abstract class CreateFrom implements ICreateFrom
|
|||
+ " LEFT OUTER JOIN M_Product_PO po ON (l.M_Product_ID = po.M_Product_ID AND l.C_BPartner_ID = po.C_BPartner_ID) "
|
||||
+ " LEFT OUTER JOIN M_MatchPO m ON (l.C_OrderLine_ID=m.C_OrderLine_ID AND ");
|
||||
sql.append(forInvoice ? "m.C_InvoiceLine_ID" : "m.M_InOutLine_ID");
|
||||
sql.append(" IS NOT NULL)")
|
||||
sql.append(" IS NOT NULL AND COALESCE(m.Reversal_ID,0)=0)")
|
||||
.append(" LEFT OUTER JOIN M_Product p ON (l.M_Product_ID=p.M_Product_ID)"
|
||||
+ " LEFT OUTER JOIN C_Charge c ON (l.C_Charge_ID=c.C_Charge_ID)");
|
||||
if (Env.isBaseLanguage(Env.getCtx(), "C_UOM"))
|
||||
|
|
|
@ -365,7 +365,7 @@ public abstract class CreateFromInvoice extends CreateFrom
|
|||
protected void configureMiniTable (IMiniTable miniTable)
|
||||
{
|
||||
miniTable.setColumnClass(0, Boolean.class, false); // 0-Selection
|
||||
miniTable.setColumnClass(1, BigDecimal.class, true); // 1-Qty
|
||||
miniTable.setColumnClass(1, BigDecimal.class, false); // 1-Qty
|
||||
miniTable.setColumnClass(2, String.class, true); // 2-UOM
|
||||
miniTable.setColumnClass(3, String.class, true); // 3-Product
|
||||
miniTable.setColumnClass(4, String.class, true); // 4-VendorProductNo
|
||||
|
|
Loading…
Reference in New Issue