IDEMPIERE-5173 fix Accounting fact quantity incorrect (#1150)
* IDEMPIERE-5173 fix Accounting fact quantity incorrect - also add unit tests * IDEMPIERE-5173 remove c_uom_id check * IDEMPIERE-5173 Use MMatchInv.isReversal() in preference to MMatch.getReversal_ID() > 0 * IDEMPIERE-5173 Update isReversal() method - add new test for is Reversal() when reversing a credit memo
This commit is contained in:
parent
497c93fc63
commit
78b7dc32d0
|
@ -44,6 +44,7 @@ import org.compiere.model.MInvoice;
|
||||||
import org.compiere.model.MInvoiceLine;
|
import org.compiere.model.MInvoiceLine;
|
||||||
import org.compiere.model.MMatchInv;
|
import org.compiere.model.MMatchInv;
|
||||||
import org.compiere.model.MOrderLandedCostAllocation;
|
import org.compiere.model.MOrderLandedCostAllocation;
|
||||||
|
import org.compiere.model.MUOM;
|
||||||
import org.compiere.model.ProductCost;
|
import org.compiere.model.ProductCost;
|
||||||
import org.compiere.model.Query;
|
import org.compiere.model.Query;
|
||||||
import org.compiere.model.X_M_Cost;
|
import org.compiere.model.X_M_Cost;
|
||||||
|
@ -201,7 +202,7 @@ public class Doc_MatchInv extends Doc
|
||||||
dr.setQty(getQty());
|
dr.setQty(getQty());
|
||||||
BigDecimal temp = dr.getAcctBalance();
|
BigDecimal temp = dr.getAcctBalance();
|
||||||
// Set AmtAcctCr/Dr from Receipt (sets also Project)
|
// Set AmtAcctCr/Dr from Receipt (sets also Project)
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -250,7 +251,7 @@ public class Doc_MatchInv extends Doc
|
||||||
cr.setAmtSourceCr(BigDecimal.ZERO);
|
cr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
temp = cr.getAcctBalance();
|
temp = cr.getAcctBalance();
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -284,7 +285,7 @@ public class Doc_MatchInv extends Doc
|
||||||
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
cr = fact.createLine (null, expense,
|
cr = fact.createLine (null, expense,
|
||||||
as.getC_Currency_ID(), null, LineNetAmt);
|
as.getC_Currency_ID(), null, LineNetAmt);
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -295,7 +296,8 @@ public class Doc_MatchInv extends Doc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cr.setQty(getQty().multiply(multiplier).negate());
|
int precision = MUOM.getPrecision(getCtx(), m_invoiceLine.getC_UOM_ID());
|
||||||
|
cr.setQty(getQty().multiply(multiplier).negate().setScale(precision, RoundingMode.HALF_UP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,20 +341,17 @@ public class Doc_MatchInv extends Doc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
||||||
|
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
||||||
|
cr.setC_Project_ID(m_invoiceLine.getC_Project_ID());
|
||||||
|
cr.setC_ProjectPhase_ID(m_invoiceLine.getC_ProjectPhase_ID());
|
||||||
|
cr.setC_ProjectTask_ID(m_invoiceLine.getC_ProjectTask_ID());
|
||||||
|
cr.setC_UOM_ID(m_invoiceLine.getC_UOM_ID());
|
||||||
|
cr.setUser1_ID(m_invoiceLine.getUser1_ID());
|
||||||
|
cr.setUser2_ID(m_invoiceLine.getUser2_ID());
|
||||||
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
cr.setQty(getQty().negate());
|
||||||
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
|
||||||
cr.setC_Project_ID(m_invoiceLine.getC_Project_ID());
|
|
||||||
cr.setC_ProjectPhase_ID(m_invoiceLine.getC_ProjectPhase_ID());
|
|
||||||
cr.setC_ProjectTask_ID(m_invoiceLine.getC_ProjectTask_ID());
|
|
||||||
cr.setC_UOM_ID(m_invoiceLine.getC_UOM_ID());
|
|
||||||
cr.setUser1_ID(m_invoiceLine.getUser1_ID());
|
|
||||||
cr.setUser2_ID(m_invoiceLine.getUser2_ID());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updateFactLine(cr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//AZ Goodwill
|
//AZ Goodwill
|
||||||
|
@ -467,6 +466,7 @@ public class Doc_MatchInv extends Doc
|
||||||
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
|
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
|
||||||
as.getC_Currency_ID(), ipv.negate());
|
as.getC_Currency_ID(), ipv.negate());
|
||||||
updateFactLine(line);
|
updateFactLine(line);
|
||||||
|
line.setQty(getQty().negate());
|
||||||
|
|
||||||
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
|
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
|
||||||
updateFactLine(line);
|
updateFactLine(line);
|
||||||
|
@ -475,6 +475,7 @@ public class Doc_MatchInv extends Doc
|
||||||
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
|
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
|
||||||
as.getC_Currency_ID(), ipv.negate());
|
as.getC_Currency_ID(), ipv.negate());
|
||||||
updateFactLine(line);
|
updateFactLine(line);
|
||||||
|
line.setQty(getQty().negate());
|
||||||
|
|
||||||
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
|
line = fact.createLine(null, account, as.getC_Currency_ID(), ipv);
|
||||||
updateFactLine(line);
|
updateFactLine(line);
|
||||||
|
@ -663,7 +664,7 @@ public class Doc_MatchInv extends Doc
|
||||||
dr.setQty(getQty());
|
dr.setQty(getQty());
|
||||||
BigDecimal temp = dr.getAcctBalance();
|
BigDecimal temp = dr.getAcctBalance();
|
||||||
// Set AmtAcctCr/Dr from Receipt (sets also Project)
|
// Set AmtAcctCr/Dr from Receipt (sets also Project)
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -713,7 +714,7 @@ public class Doc_MatchInv extends Doc
|
||||||
cr.setAmtSourceCr(BigDecimal.ZERO);
|
cr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
temp = cr.getAcctBalance();
|
temp = cr.getAcctBalance();
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -747,7 +748,7 @@ public class Doc_MatchInv extends Doc
|
||||||
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
cr = fact.createLine (null, expense,
|
cr = fact.createLine (null, expense,
|
||||||
as.getC_Currency_ID(), LineNetAmt, null);
|
as.getC_Currency_ID(), LineNetAmt, null);
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -758,7 +759,8 @@ public class Doc_MatchInv extends Doc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cr.setQty(getQty().multiply(multiplier).negate());
|
int precision = MUOM.getPrecision(getCtx(), m_invoiceLine.getC_UOM_ID());
|
||||||
|
cr.setQty(getQty().multiply(multiplier).negate().setScale(precision, RoundingMode.HALF_UP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +805,7 @@ public class Doc_MatchInv extends Doc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (!m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
||||||
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
||||||
|
@ -931,7 +933,7 @@ public class Doc_MatchInv extends Doc
|
||||||
dr.setAmtSourceCr(BigDecimal.ZERO);
|
dr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
BigDecimal temp = dr.getAcctBalance();
|
BigDecimal temp = dr.getAcctBalance();
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -965,7 +967,7 @@ public class Doc_MatchInv extends Doc
|
||||||
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
dr = fact.createLine (null, expense,
|
dr = fact.createLine (null, expense,
|
||||||
as.getC_Currency_ID(), LineNetAmt, null);
|
as.getC_Currency_ID(), LineNetAmt, null);
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -976,10 +978,11 @@ public class Doc_MatchInv extends Doc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dr.setQty(getQty().multiply(multiplier).negate());
|
int precision = MUOM.getPrecision(getCtx(), m_invoiceLine.getC_UOM_ID());
|
||||||
|
dr.setQty(getQty().multiply(multiplier).negate().setScale(precision, RoundingMode.HALF_UP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (!m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
dr.setC_Activity_ID(refInvLine.getC_Activity_ID());
|
dr.setC_Activity_ID(refInvLine.getC_Activity_ID());
|
||||||
dr.setC_Campaign_ID(refInvLine.getC_Campaign_ID());
|
dr.setC_Campaign_ID(refInvLine.getC_Campaign_ID());
|
||||||
|
@ -1020,7 +1023,7 @@ public class Doc_MatchInv extends Doc
|
||||||
cr.setAmtSourceCr(BigDecimal.ZERO);
|
cr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
BigDecimal temp = cr.getAcctBalance();
|
BigDecimal temp = cr.getAcctBalance();
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -1054,7 +1057,7 @@ public class Doc_MatchInv extends Doc
|
||||||
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
cr = fact.createLine (null, expense,
|
cr = fact.createLine (null, expense,
|
||||||
as.getC_Currency_ID(), LineNetAmt, null);
|
as.getC_Currency_ID(), LineNetAmt, null);
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
@ -1065,7 +1068,8 @@ public class Doc_MatchInv extends Doc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cr.setQty(getQty().multiply(multiplier).negate());
|
int precision = MUOM.getPrecision(getCtx(), m_invoiceLine.getC_UOM_ID());
|
||||||
|
cr.setQty(getQty().multiply(multiplier).negate().setScale(precision, RoundingMode.HALF_UP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,7 +1115,7 @@ public class Doc_MatchInv extends Doc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (!m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
||||||
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
|
||||||
|
@ -1213,7 +1217,7 @@ public class Doc_MatchInv extends Doc
|
||||||
MInvoice invoice, BigDecimal matchInvSource, BigDecimal matchInvAccounted,
|
MInvoice invoice, BigDecimal matchInvSource, BigDecimal matchInvAccounted,
|
||||||
ArrayList<FactLine> invGainLossFactLines, HashMap<Integer, ArrayList<FactLine>> htFactLineInv)
|
ArrayList<FactLine> invGainLossFactLines, HashMap<Integer, ArrayList<FactLine>> htFactLineInv)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() > 0 && m_matchInv.get_ID() > m_matchInv.getReversal_ID())
|
if (m_matchInv.isReversal())
|
||||||
return createReversalInvoiceGainLossRoundingCorrection(as, fact, acct);
|
return createReversalInvoiceGainLossRoundingCorrection(as, fact, acct);
|
||||||
|
|
||||||
BigDecimal invoiceSource = null;
|
BigDecimal invoiceSource = null;
|
||||||
|
@ -1296,7 +1300,7 @@ public class Doc_MatchInv extends Doc
|
||||||
*/
|
*/
|
||||||
private String createReversalInvoiceGainLossRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct)
|
private String createReversalInvoiceGainLossRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (!m_matchInv.isReversal())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
@ -1339,7 +1343,7 @@ public class Doc_MatchInv extends Doc
|
||||||
ArrayList<FactLine> invGainLossFactLines, ArrayList<MInvoice> invList, ArrayList<MInvoiceLine> invLineList,
|
ArrayList<FactLine> invGainLossFactLines, ArrayList<MInvoice> invList, ArrayList<MInvoiceLine> invLineList,
|
||||||
HashMap<Integer, ArrayList<FactLine>> htFactLineInv)
|
HashMap<Integer, ArrayList<FactLine>> htFactLineInv)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() > 0 && m_matchInv.get_ID() > m_matchInv.getReversal_ID())
|
if (m_matchInv.isReversal())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
HashMap<Integer, ArrayList<FactLine>> htRoundingLineInvLine = new HashMap<Integer, ArrayList<FactLine>>();
|
HashMap<Integer, ArrayList<FactLine>> htRoundingLineInvLine = new HashMap<Integer, ArrayList<FactLine>>();
|
||||||
|
@ -1523,7 +1527,7 @@ public class Doc_MatchInv extends Doc
|
||||||
skipMatchInvIdList.add(m_matchInv.get_ID());
|
skipMatchInvIdList.add(m_matchInv.get_ID());
|
||||||
for (MMatchInv matchInv : matchInvs)
|
for (MMatchInv matchInv : matchInvs)
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
skipMatchInvIdList.add(matchInv.get_ID());
|
skipMatchInvIdList.add(matchInv.get_ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1543,9 +1547,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND PostingType='A'")
|
.append(" AND PostingType='A'")
|
||||||
.append(" AND Account_ID=?");
|
.append(" AND Account_ID=?");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -1595,9 +1599,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
||||||
.append(" AND Description LIKE 'Invoice%'");
|
.append(" AND Description LIKE 'Invoice%'");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -1825,7 +1829,7 @@ public class Doc_MatchInv extends Doc
|
||||||
skipMatchInvIdList.add(m_matchInv.get_ID());
|
skipMatchInvIdList.add(m_matchInv.get_ID());
|
||||||
for (MMatchInv matchInv : matchInvs)
|
for (MMatchInv matchInv : matchInvs)
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
skipMatchInvIdList.add(matchInv.get_ID());
|
skipMatchInvIdList.add(matchInv.get_ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1845,9 +1849,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND PostingType='A'")
|
.append(" AND PostingType='A'")
|
||||||
.append(" AND Account_ID=?");
|
.append(" AND Account_ID=?");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -1904,9 +1908,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
||||||
.append(" AND Description LIKE 'Invoice Line%'");
|
.append(" AND Description LIKE 'Invoice Line%'");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -2029,7 +2033,7 @@ public class Doc_MatchInv extends Doc
|
||||||
MInOut receipt, BigDecimal matchInvSource, BigDecimal matchInvAccounted,
|
MInOut receipt, BigDecimal matchInvSource, BigDecimal matchInvAccounted,
|
||||||
ArrayList<FactLine> mrGainLossFactLines, ArrayList<FactLine> mrFactLines)
|
ArrayList<FactLine> mrGainLossFactLines, ArrayList<FactLine> mrFactLines)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() > 0 && m_matchInv.get_ID() > m_matchInv.getReversal_ID())
|
if (m_matchInv.isReversal())
|
||||||
return createReversalReceiptGainLossRoundingCorrection(as, fact, acct);
|
return createReversalReceiptGainLossRoundingCorrection(as, fact, acct);
|
||||||
|
|
||||||
BigDecimal receiptSource = null;
|
BigDecimal receiptSource = null;
|
||||||
|
@ -2104,7 +2108,7 @@ public class Doc_MatchInv extends Doc
|
||||||
*/
|
*/
|
||||||
private String createReversalReceiptGainLossRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct)
|
private String createReversalReceiptGainLossRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (!m_matchInv.isReversal())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
@ -2144,7 +2148,7 @@ public class Doc_MatchInv extends Doc
|
||||||
private String createReceiptRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct,
|
private String createReceiptRoundingCorrection(MAcctSchema as, Fact fact, MAccount acct,
|
||||||
ArrayList<FactLine> mrGainLossFactLines, ArrayList<FactLine> mrFactLines)
|
ArrayList<FactLine> mrGainLossFactLines, ArrayList<FactLine> mrFactLines)
|
||||||
{
|
{
|
||||||
if (m_matchInv.getReversal_ID() > 0 && m_matchInv.get_ID() > m_matchInv.getReversal_ID())
|
if (m_matchInv.isReversal())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
ArrayList<FactLine> mrLineRoundingLines = new ArrayList<FactLine>();
|
ArrayList<FactLine> mrLineRoundingLines = new ArrayList<FactLine>();
|
||||||
|
@ -2249,7 +2253,7 @@ public class Doc_MatchInv extends Doc
|
||||||
skipMatchInvIdList.add(m_matchInv.get_ID());
|
skipMatchInvIdList.add(m_matchInv.get_ID());
|
||||||
for (MMatchInv matchInv : matchInvs)
|
for (MMatchInv matchInv : matchInvs)
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
skipMatchInvIdList.add(matchInv.get_ID());
|
skipMatchInvIdList.add(matchInv.get_ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2269,9 +2273,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND PostingType='A'")
|
.append(" AND PostingType='A'")
|
||||||
.append(" AND Account_ID=?");
|
.append(" AND Account_ID=?");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -2313,9 +2317,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
||||||
.append(" AND Description LIKE 'InOut%'");
|
.append(" AND Description LIKE 'InOut%'");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -2484,7 +2488,7 @@ public class Doc_MatchInv extends Doc
|
||||||
skipMatchInvIdList.add(m_matchInv.get_ID());
|
skipMatchInvIdList.add(m_matchInv.get_ID());
|
||||||
for (MMatchInv matchInv : matchInvs)
|
for (MMatchInv matchInv : matchInvs)
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
skipMatchInvIdList.add(matchInv.get_ID());
|
skipMatchInvIdList.add(matchInv.get_ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2504,9 +2508,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND PostingType='A'")
|
.append(" AND PostingType='A'")
|
||||||
.append(" AND Account_ID=?");
|
.append(" AND Account_ID=?");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
@ -2546,9 +2550,9 @@ public class Doc_MatchInv extends Doc
|
||||||
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
.append(" AND (Account_ID=? OR Account_ID=? OR Account_ID=?)")
|
||||||
.append(" AND Description LIKE 'InOut Line%'");
|
.append(" AND Description LIKE 'InOut Line%'");
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() > 0)
|
if (m_matchInv.isReversal())
|
||||||
{
|
{
|
||||||
if (matchInv.getReversal_ID() > 0 && matchInv.get_ID() > matchInv.getReversal_ID())
|
if (matchInv.isReversal())
|
||||||
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
sql.append(" AND Record_ID <> ").append(matchInv.get_ID());
|
||||||
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
sql.append(" AND Record_ID < ").append(m_matchInv.getReversal_ID());
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.compiere.model.MCurrency;
|
||||||
import org.compiere.model.MFactAcct;
|
import org.compiere.model.MFactAcct;
|
||||||
import org.compiere.model.MMovement;
|
import org.compiere.model.MMovement;
|
||||||
import org.compiere.model.MRevenueRecognitionPlan;
|
import org.compiere.model.MRevenueRecognitionPlan;
|
||||||
|
import org.compiere.model.MUOM;
|
||||||
import org.compiere.model.X_C_AcctSchema_Element;
|
import org.compiere.model.X_C_AcctSchema_Element;
|
||||||
import org.compiere.model.X_Fact_Acct;
|
import org.compiere.model.X_Fact_Acct;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
|
@ -1206,8 +1207,14 @@ public final class FactLine extends X_Fact_Acct
|
||||||
setC_Tax_ID(fact.getC_Tax_ID());
|
setC_Tax_ID(fact.getC_Tax_ID());
|
||||||
// Org for cross charge
|
// Org for cross charge
|
||||||
setAD_Org_ID (fact.getAD_Org_ID());
|
setAD_Org_ID (fact.getAD_Org_ID());
|
||||||
if (fact.getQty() != null)
|
if (fact.getQty() != null) {
|
||||||
setQty(fact.getQty().negate());
|
if (getC_UOM_ID() != 0)
|
||||||
|
{
|
||||||
|
int precision = MUOM.getPrecision(getCtx(), getC_UOM_ID());
|
||||||
|
setQty(fact.getQty().multiply(multiplier).negate().setScale(precision, RoundingMode.HALF_UP));
|
||||||
|
} else
|
||||||
|
setQty(fact.getQty().multiply(multiplier).negate().stripTrailingZeros());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.warning(new StringBuilder("Not Found (try later) ")
|
log.warning(new StringBuilder("Not Found (try later) ")
|
||||||
|
|
|
@ -407,7 +407,8 @@ public class MMatchInv extends X_M_MatchInv
|
||||||
*/
|
*/
|
||||||
public boolean isReversal() {
|
public boolean isReversal() {
|
||||||
if (getReversal_ID() > 0) {
|
if (getReversal_ID() > 0) {
|
||||||
if (getM_InOutLine().getMovementQty().signum() != getQty().signum())
|
MMatchInv reversal = new MMatchInv (getCtx(), getReversal_ID(), get_TrxName());
|
||||||
|
if (reversal.getM_MatchInv_ID() < getM_MatchInv_ID())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -633,10 +633,14 @@ public class MatchInvTest extends AbstractTestCase {
|
||||||
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
||||||
for (int id : ids) {
|
for (int id : ids) {
|
||||||
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
||||||
if (fa.getAccount_ID() == acctNIR.getAccount_ID())
|
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) {
|
||||||
assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
|
assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
|
||||||
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID())
|
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
|
}
|
||||||
|
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) {
|
||||||
assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
|
assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
|
||||||
|
assertEquals(mi.getQty().negate(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,10 +699,12 @@ public class MatchInvTest extends AbstractTestCase {
|
||||||
if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) < 0) {
|
if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) < 0) {
|
||||||
assertEquals(fa.getAmtAcctCr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
|
assertEquals(fa.getAmtAcctCr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString());
|
||||||
amtAcctCrInvClr = amtAcctCrInvClr.add(fa.getAmtAcctCr());
|
amtAcctCrInvClr = amtAcctCrInvClr.add(fa.getAmtAcctCr());
|
||||||
|
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
}
|
}
|
||||||
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) > 0) {
|
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
assertEquals(fa.getAmtAcctDr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
|
assertEquals(fa.getAmtAcctDr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString());
|
||||||
amtAcctDrInvClr = amtAcctDrInvClr.add(fa.getAmtAcctDr());
|
amtAcctDrInvClr = amtAcctDrInvClr.add(fa.getAmtAcctDr());
|
||||||
|
assertEquals(mi.getQty().negate(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue(amtAcctDrInvClr.compareTo(amtAcctCrInvClr) == 0);
|
assertTrue(amtAcctDrInvClr.compareTo(amtAcctCrInvClr) == 0);
|
||||||
|
@ -994,4 +1000,244 @@ public class MatchInvTest extends AbstractTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsReversalCM() {
|
||||||
|
MBPartner bpartner = MBPartner.get(Env.getCtx(), 114); // Tree Farm Inc.
|
||||||
|
MProduct product = MProduct.get(Env.getCtx(), 124); // Elm Tree
|
||||||
|
|
||||||
|
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||||
|
order.setBPartner(bpartner);
|
||||||
|
order.setIsSOTrx(false);
|
||||||
|
order.setC_DocTypeTarget_ID();
|
||||||
|
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||||
|
order.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
order.saveEx();
|
||||||
|
|
||||||
|
MOrderLine orderLine = new MOrderLine(order);
|
||||||
|
orderLine.setLine(10);
|
||||||
|
orderLine.setProduct(product);
|
||||||
|
orderLine.setQty(new BigDecimal("2"));
|
||||||
|
orderLine.saveEx();
|
||||||
|
|
||||||
|
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||||
|
order.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||||
|
|
||||||
|
MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt
|
||||||
|
receipt.saveEx();
|
||||||
|
|
||||||
|
MInOutLine receiptLine = new MInOutLine(receipt);
|
||||||
|
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
|
||||||
|
receiptLine.setLine(10);
|
||||||
|
receiptLine.setProduct(product);
|
||||||
|
receiptLine.setQty(BigDecimal.ONE);
|
||||||
|
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
|
||||||
|
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
|
||||||
|
receiptLine.setM_Locator_ID(M_Locator_ID);
|
||||||
|
receiptLine.saveEx();
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
|
||||||
|
receipt.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
|
||||||
|
|
||||||
|
if (!receipt.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
receipt.load(getTrxName());
|
||||||
|
assertTrue(receipt.isPosted());
|
||||||
|
|
||||||
|
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
|
||||||
|
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
|
||||||
|
invoice.setDocStatus(DocAction.STATUS_Drafted);
|
||||||
|
invoice.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
invoice.saveEx();
|
||||||
|
|
||||||
|
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
|
||||||
|
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
|
||||||
|
invoiceLine.setLine(10);
|
||||||
|
invoiceLine.setProduct(product);
|
||||||
|
invoiceLine.setQty(new BigDecimal("2"));
|
||||||
|
invoiceLine.saveEx();
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
|
||||||
|
invoice.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
|
||||||
|
|
||||||
|
if (!invoice.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
invoice.load(getTrxName());
|
||||||
|
assertTrue(invoice.isPosted());
|
||||||
|
|
||||||
|
MInvoice creditMemo = new MInvoice(receipt, receipt.getMovementDate());
|
||||||
|
creditMemo.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APCreditMemo);
|
||||||
|
creditMemo.setDocStatus(DocAction.STATUS_Drafted);
|
||||||
|
creditMemo.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
creditMemo.saveEx();
|
||||||
|
|
||||||
|
MInvoiceLine creditMemoLine = new MInvoiceLine(creditMemo);
|
||||||
|
creditMemoLine.setM_InOutLine_ID(receiptLine.get_ID());
|
||||||
|
creditMemoLine.setLine(10);
|
||||||
|
creditMemoLine.setProduct(product);
|
||||||
|
creditMemoLine.setQty(BigDecimal.ONE);
|
||||||
|
creditMemoLine.saveEx();
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(creditMemo, DocAction.ACTION_Complete);
|
||||||
|
creditMemo.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, creditMemo.getDocStatus());
|
||||||
|
|
||||||
|
if (!creditMemo.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), creditMemo.getAD_Client_ID(), MInvoice.Table_ID, creditMemo.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
creditMemo.load(getTrxName());
|
||||||
|
assertTrue(creditMemo.isPosted());
|
||||||
|
|
||||||
|
MMatchInv[] beforeList = MMatchInv.getInvoiceLine(Env.getCtx(), creditMemoLine.get_ID(), getTrxName());
|
||||||
|
assertEquals(1, beforeList.length);
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(creditMemo, DocAction.ACTION_Reverse_Correct);
|
||||||
|
creditMemo.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Reversed, creditMemo.getDocStatus());
|
||||||
|
|
||||||
|
MMatchInv[] afterList = MMatchInv.getInvoiceLine(Env.getCtx(), creditMemoLine.get_ID(), getTrxName());
|
||||||
|
assertEquals(2, afterList.length);
|
||||||
|
beforeList[0].load(getTrxName());
|
||||||
|
assertFalse(beforeList[0].isReversal());
|
||||||
|
for(MMatchInv mi : afterList) {
|
||||||
|
if (!mi.equals(beforeList[0])) {
|
||||||
|
assertTrue(mi.isReversal());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReversalPosting() {
|
||||||
|
MBPartner bpartner = MBPartner.get(Env.getCtx(), 114); // Tree Farm Inc.
|
||||||
|
MProduct product = MProduct.get(Env.getCtx(), 124); // Elm Tree
|
||||||
|
|
||||||
|
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||||
|
order.setBPartner(bpartner);
|
||||||
|
order.setIsSOTrx(false);
|
||||||
|
order.setC_DocTypeTarget_ID();
|
||||||
|
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||||
|
order.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
order.saveEx();
|
||||||
|
|
||||||
|
MOrderLine orderLine = new MOrderLine(order);
|
||||||
|
orderLine.setLine(10);
|
||||||
|
orderLine.setProduct(product);
|
||||||
|
orderLine.setQty(BigDecimal.ONE);
|
||||||
|
orderLine.saveEx();
|
||||||
|
|
||||||
|
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||||
|
order.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||||
|
|
||||||
|
MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt
|
||||||
|
receipt.saveEx();
|
||||||
|
|
||||||
|
MInOutLine receiptLine = new MInOutLine(receipt);
|
||||||
|
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
|
||||||
|
receiptLine.setLine(10);
|
||||||
|
receiptLine.setProduct(product);
|
||||||
|
receiptLine.setQty(BigDecimal.ONE);
|
||||||
|
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
|
||||||
|
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
|
||||||
|
receiptLine.setM_Locator_ID(M_Locator_ID);
|
||||||
|
receiptLine.saveEx();
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
|
||||||
|
receipt.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
|
||||||
|
|
||||||
|
if (!receipt.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
receipt.load(getTrxName());
|
||||||
|
assertTrue(receipt.isPosted());
|
||||||
|
|
||||||
|
MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate());
|
||||||
|
invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice);
|
||||||
|
invoice.setDocStatus(DocAction.STATUS_Drafted);
|
||||||
|
invoice.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
invoice.saveEx();
|
||||||
|
|
||||||
|
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
|
||||||
|
invoiceLine.setM_InOutLine_ID(receiptLine.get_ID());
|
||||||
|
invoiceLine.setLine(10);
|
||||||
|
invoiceLine.setProduct(product);
|
||||||
|
invoiceLine.setQty(BigDecimal.ONE);
|
||||||
|
invoiceLine.saveEx();
|
||||||
|
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
|
||||||
|
invoice.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
|
||||||
|
|
||||||
|
if (!invoice.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema();
|
||||||
|
BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP);
|
||||||
|
|
||||||
|
invoice.load(getTrxName());
|
||||||
|
assertTrue(invoice.isPosted());
|
||||||
|
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Reverse_Correct);
|
||||||
|
invoice.load(getTrxName());
|
||||||
|
assertFalse(info.isError());
|
||||||
|
assertEquals(DocAction.STATUS_Reversed, invoice.getDocStatus());
|
||||||
|
|
||||||
|
MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName());
|
||||||
|
assertEquals(2, miList.length);
|
||||||
|
for (MMatchInv mi : miList) {
|
||||||
|
if (!mi.isPosted()) {
|
||||||
|
String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName());
|
||||||
|
assertTrue(error == null);
|
||||||
|
}
|
||||||
|
mi.load(getTrxName());
|
||||||
|
assertTrue(mi.isPosted());
|
||||||
|
|
||||||
|
Doc doc = DocManager.getDocument(as, MMatchInv.Table_ID, mi.get_ID(), getTrxName());
|
||||||
|
doc.setC_BPartner_ID(mi.getC_InvoiceLine().getC_Invoice().getC_BPartner_ID());
|
||||||
|
MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as);
|
||||||
|
|
||||||
|
ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName());
|
||||||
|
MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
|
||||||
|
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID
|
||||||
|
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID()
|
||||||
|
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID();
|
||||||
|
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
||||||
|
for (int id : ids) {
|
||||||
|
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
||||||
|
if (fa.getAccount_ID() == acctNIR.getAccount_ID()) {
|
||||||
|
if (mi.isReversal())
|
||||||
|
assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted ");
|
||||||
|
else
|
||||||
|
assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted ");
|
||||||
|
assertEquals(mi.getQty(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
|
}
|
||||||
|
else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) {
|
||||||
|
if (mi.isReversal())
|
||||||
|
assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted ");
|
||||||
|
else
|
||||||
|
assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted ");
|
||||||
|
assertEquals(mi.getQty().negate(), fa.getQty(), "Accounting fact quantity incorrect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue