IDEMPIERE-4051 Matched Invoice document for Vendor Credit Memo
This commit is contained in:
parent
c203427ed6
commit
c92ca011e1
|
@ -143,13 +143,22 @@ public class Doc_MatchInv extends Doc
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
if (getM_Product_ID() == 0 // no Product
|
if (getM_Product_ID() == 0 // no Product
|
||||||
|| getQty().signum() == 0
|
|| getQty().signum() == 0
|
||||||
|| m_receiptLine.getMovementQty().signum() == 0) // Qty = 0
|
|| (m_receiptLine.get_ID() > 0 && m_receiptLine.getMovementQty().signum() == 0)) // Qty = 0
|
||||||
{
|
{
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("No Product/Qty - M_Product_ID=" + getM_Product_ID()
|
if (log.isLoggable(Level.FINE)) log.fine("No Product/Qty - M_Product_ID=" + getM_Product_ID()
|
||||||
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
|
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
|
||||||
return facts;
|
return facts;
|
||||||
}
|
}
|
||||||
// MMatchInv matchInv = (MMatchInv)getPO();
|
|
||||||
|
if (m_receiptLine.getM_InOutLine_ID() == 0)
|
||||||
|
{
|
||||||
|
MInvoice m_invoice = new MInvoice(getCtx(), m_invoiceLine.getC_Invoice_ID(), getTrxName());
|
||||||
|
boolean isCreditMemo = m_invoice.isCreditMemo();
|
||||||
|
if (!isCreditMemo)
|
||||||
|
return facts;
|
||||||
|
else
|
||||||
|
return createCreditMemoFacts(as);
|
||||||
|
}
|
||||||
|
|
||||||
// create Fact Header
|
// create Fact Header
|
||||||
Fact fact = new Fact(this, as, Fact.POST_Actual);
|
Fact fact = new Fact(this, as, Fact.POST_Actual);
|
||||||
|
@ -556,6 +565,257 @@ public class Doc_MatchInv extends Doc
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<Fact> createCreditMemoFacts(MAcctSchema as) {
|
||||||
|
ArrayList<Fact> facts = new ArrayList<Fact>();
|
||||||
|
|
||||||
|
// create Fact Header
|
||||||
|
Fact fact = new Fact(this, as, Fact.POST_Actual);
|
||||||
|
setC_Currency_ID (as.getC_Currency_ID());
|
||||||
|
|
||||||
|
MMatchInv refMatchInv = new MMatchInv(getCtx(), m_matchInv.getRef_MatchInv_ID(), getTrxName());
|
||||||
|
MInvoiceLine refInvLine = new MInvoiceLine(getCtx(), refMatchInv.getC_InvoiceLine_ID(), getTrxName());
|
||||||
|
|
||||||
|
boolean isInterOrg = false;
|
||||||
|
MAcctSchemaElement elementorg = as.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Organization);
|
||||||
|
if (elementorg == null || !elementorg.isBalanced()) {
|
||||||
|
// no org element or not need to be balanced
|
||||||
|
isInterOrg = false;
|
||||||
|
}
|
||||||
|
// verify if org of receipt line is different from org of invoice line
|
||||||
|
if (refInvLine != null && m_invoiceLine != null && refInvLine.getAD_Org_ID() != m_invoiceLine.getAD_Org_ID())
|
||||||
|
isInterOrg = true;
|
||||||
|
|
||||||
|
MAccount expense = m_pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
|
||||||
|
if (m_pc.isService())
|
||||||
|
expense = m_pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
|
||||||
|
BigDecimal LineNetAmt = refInvLine.getLineNetAmt();
|
||||||
|
BigDecimal multiplier = getQty()
|
||||||
|
.divide(refInvLine.getQtyInvoiced(), 12, RoundingMode.HALF_UP);
|
||||||
|
multiplier = multiplier.negate();
|
||||||
|
if (multiplier.compareTo(Env.ONE) != 0)
|
||||||
|
LineNetAmt = LineNetAmt.multiply(multiplier);
|
||||||
|
FactLine dr = null;
|
||||||
|
if (as.isAccrual())
|
||||||
|
{
|
||||||
|
dr = fact.createLine (null, expense,
|
||||||
|
as.getC_Currency_ID(), LineNetAmt, null); // updated below
|
||||||
|
if (dr == null)
|
||||||
|
{
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("Line Net Amt=0 - M_Product_ID=" + getM_Product_ID()
|
||||||
|
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
|
||||||
|
|
||||||
|
dr = fact.createLine (null, expense, as.getC_Currency_ID(), Env.ONE, null);
|
||||||
|
dr.setAmtAcctCr(BigDecimal.ZERO);
|
||||||
|
dr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
BigDecimal temp = dr.getAcctBalance();
|
||||||
|
if (m_matchInv.getReversal_ID() > 0)
|
||||||
|
{
|
||||||
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
{
|
||||||
|
p_Error = "Failed to create reversal entry";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dr.setQty(getQty().negate());
|
||||||
|
|
||||||
|
// Set AmtAcctCr/Dr from Invoice (sets also Project)
|
||||||
|
if (!dr.updateReverseLine (MInvoice.Table_ID, // Amt updated
|
||||||
|
refInvLine.getC_Invoice_ID(), refInvLine.getC_InvoiceLine_ID(), multiplier))
|
||||||
|
{
|
||||||
|
p_Error = "Invoice not posted yet";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("DR - Amt(" + temp + "->" + dr.getAcctBalance()
|
||||||
|
+ ") - " + dr.toString());
|
||||||
|
}
|
||||||
|
else // Cash Acct
|
||||||
|
{
|
||||||
|
MInvoice invoice = refInvLine.getParent();
|
||||||
|
if (as.getC_Currency_ID() != invoice.getC_Currency_ID())
|
||||||
|
LineNetAmt = MConversionRate.convert(getCtx(), LineNetAmt,
|
||||||
|
invoice.getC_Currency_ID(), as.getC_Currency_ID(),
|
||||||
|
invoice.getDateAcct(), invoice.getC_ConversionType_ID(),
|
||||||
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
|
dr = fact.createLine (null, expense,
|
||||||
|
as.getC_Currency_ID(), LineNetAmt, null);
|
||||||
|
if (m_matchInv.getReversal_ID() > 0)
|
||||||
|
{
|
||||||
|
if (!dr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
{
|
||||||
|
p_Error = "Failed to create reversal entry";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dr.setQty(getQty().multiply(multiplier).negate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_matchInv.getReversal_ID() == 0)
|
||||||
|
{
|
||||||
|
dr.setC_Activity_ID(refInvLine.getC_Activity_ID());
|
||||||
|
dr.setC_Campaign_ID(refInvLine.getC_Campaign_ID());
|
||||||
|
dr.setC_Project_ID(refInvLine.getC_Project_ID());
|
||||||
|
dr.setC_ProjectPhase_ID(refInvLine.getC_ProjectPhase_ID());
|
||||||
|
dr.setC_ProjectTask_ID(refInvLine.getC_ProjectTask_ID());
|
||||||
|
dr.setC_UOM_ID(refInvLine.getC_UOM_ID());
|
||||||
|
dr.setUser1_ID(refInvLine.getUser1_ID());
|
||||||
|
dr.setUser2_ID(refInvLine.getUser2_ID());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateFactLine(dr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// InventoryClearing CR
|
||||||
|
// From Invoice
|
||||||
|
LineNetAmt = m_invoiceLine.getLineNetAmt();
|
||||||
|
multiplier = getQty()
|
||||||
|
.divide(m_invoiceLine.getQtyInvoiced(), 12, RoundingMode.HALF_UP);
|
||||||
|
multiplier = multiplier.negate();
|
||||||
|
if (multiplier.compareTo(Env.ONE) != 0)
|
||||||
|
LineNetAmt = LineNetAmt.multiply(multiplier);
|
||||||
|
if (m_pc.isService())
|
||||||
|
LineNetAmt = dr.getAcctBalance(); // book out exact receipt amt
|
||||||
|
FactLine cr = null;
|
||||||
|
if (as.isAccrual())
|
||||||
|
{
|
||||||
|
cr = fact.createLine (null, expense,
|
||||||
|
as.getC_Currency_ID(), LineNetAmt, null); // updated below
|
||||||
|
if (cr == null)
|
||||||
|
{
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("Line Net Amt=0 - M_Product_ID=" + getM_Product_ID()
|
||||||
|
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
|
||||||
|
|
||||||
|
cr = fact.createLine (null, expense, as.getC_Currency_ID(), Env.ONE, null);
|
||||||
|
cr.setAmtAcctCr(BigDecimal.ZERO);
|
||||||
|
cr.setAmtSourceCr(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
BigDecimal temp = cr.getAcctBalance();
|
||||||
|
if (m_matchInv.getReversal_ID() > 0)
|
||||||
|
{
|
||||||
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
{
|
||||||
|
p_Error = "Failed to create reversal entry";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cr.setQty(getQty().negate());
|
||||||
|
|
||||||
|
// Set AmtAcctCr/Dr from Invoice (sets also Project)
|
||||||
|
if (!cr.updateReverseLine (MInvoice.Table_ID, // Amt updated
|
||||||
|
m_invoiceLine.getC_Invoice_ID(), m_invoiceLine.getC_InvoiceLine_ID(), multiplier))
|
||||||
|
{
|
||||||
|
p_Error = "Invoice not posted yet";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("DR - Amt(" + temp + "->" + cr.getAcctBalance()
|
||||||
|
+ ") - " + cr.toString());
|
||||||
|
}
|
||||||
|
else // Cash Acct
|
||||||
|
{
|
||||||
|
MInvoice invoice = m_invoiceLine.getParent();
|
||||||
|
if (as.getC_Currency_ID() != invoice.getC_Currency_ID())
|
||||||
|
LineNetAmt = MConversionRate.convert(getCtx(), LineNetAmt,
|
||||||
|
invoice.getC_Currency_ID(), as.getC_Currency_ID(),
|
||||||
|
invoice.getDateAcct(), invoice.getC_ConversionType_ID(),
|
||||||
|
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
|
cr = fact.createLine (null, expense,
|
||||||
|
as.getC_Currency_ID(), LineNetAmt, null);
|
||||||
|
if (m_matchInv.getReversal_ID() > 0)
|
||||||
|
{
|
||||||
|
if (!cr.updateReverseLine (MMatchInv.Table_ID, // Amt updated
|
||||||
|
m_matchInv.getReversal_ID(), 0, BigDecimal.ONE))
|
||||||
|
{
|
||||||
|
p_Error = "Failed to create reversal entry";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cr.setQty(getQty().multiply(multiplier).negate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateFactLine(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//AZ Goodwill
|
||||||
|
//Desc: Source Not Balanced problem because Currency is Difference - PO=CNY but AP=USD
|
||||||
|
//see also Fact.java: checking for isMultiCurrency()
|
||||||
|
if (dr.getC_Currency_ID() != cr.getC_Currency_ID())
|
||||||
|
setIsMultiCurrency(true);
|
||||||
|
//end AZ
|
||||||
|
|
||||||
|
// Avoid usage of clearing accounts
|
||||||
|
// If both accounts are equal
|
||||||
|
// then remove the posting
|
||||||
|
|
||||||
|
MAccount acct_db = dr.getAccount(); // inventory_clearing
|
||||||
|
MAccount acct_cr = cr.getAccount(); // inventory_clearing
|
||||||
|
|
||||||
|
if ((!as.isPostIfClearingEqual()) && acct_db.equals(acct_cr) && (!isInterOrg)) {
|
||||||
|
|
||||||
|
BigDecimal debit = dr.getAmtSourceDr();
|
||||||
|
BigDecimal credit = cr.getAmtSourceCr();
|
||||||
|
|
||||||
|
if (debit.compareTo(credit) == 0) {
|
||||||
|
fact.remove(dr);
|
||||||
|
fact.remove(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// End Avoid usage of clearing accounts
|
||||||
|
|
||||||
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate();
|
||||||
|
if (ipv.compareTo(Env.ZERO) != 0)
|
||||||
|
{
|
||||||
|
FactLine pv = fact.createLine(null,
|
||||||
|
cr.getAcctBalance().abs().compareTo(dr.getAcctBalance().abs()) < 0 ? loss : gain,
|
||||||
|
as.getC_Currency_ID(), ipv);
|
||||||
|
updateFactLine(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
facts.add(fact);
|
||||||
|
|
||||||
|
/** Commitment release ****/
|
||||||
|
if (as.isAccrual() && as.isCreatePOCommitment())
|
||||||
|
{
|
||||||
|
fact = Doc_Order.getCommitmentRelease(as, this,
|
||||||
|
getQty(), m_invoiceLine.getC_InvoiceLine_ID(), Env.ONE);
|
||||||
|
if (fact == null)
|
||||||
|
return null;
|
||||||
|
facts.add(fact);
|
||||||
|
} // Commitment
|
||||||
|
|
||||||
|
return facts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param factLine
|
* @param factLine
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue