IDEMPIERE-4127 GL Inventory Clearing - Minor rounding variances

This commit is contained in:
hengsin 2020-03-02 13:08:19 +08:00
parent e0906eb102
commit c8d858836f
3 changed files with 383 additions and 226 deletions

View File

@ -21,6 +21,7 @@ import java.math.RoundingMode;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
@ -75,8 +76,8 @@ public class Doc_AllocationHdr extends Doc
private static final BigDecimal TOLERANCE = BigDecimal.valueOf(0.02); private static final BigDecimal TOLERANCE = BigDecimal.valueOf(0.02);
/** Facts */ /** Facts */
private ArrayList<Fact> m_facts = null; private ArrayList<Fact> m_facts = null;
BigDecimal gainLossAmt =Env.ZERO; private Hashtable<Integer, BigDecimal> htGainLossAmtByInv = new Hashtable<Integer, BigDecimal>();
private BigDecimal cmGainLossAmt=Env.ZERO; private Hashtable<Integer, BigDecimal> htGainLossAmtByCM = new Hashtable<Integer, BigDecimal>();
private ArrayList<FactLine> gainLossFactList; private ArrayList<FactLine> gainLossFactList;
@ -741,13 +742,16 @@ public class Doc_AllocationHdr extends Doc
.append(" FROM Fact_Acct ") .append(" FROM Fact_Acct ")
.append("WHERE AD_Table_ID=? AND Record_ID=?") .append("WHERE AD_Table_ID=? AND Record_ID=?")
.append(" AND C_AcctSchema_ID=?") .append(" AND C_AcctSchema_ID=?")
.append(" AND Account_ID=?")
.append(" AND PostingType='A'"); .append(" AND PostingType='A'");
// For Invoice // For Invoice
List<Object> valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(), List<Object> valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
MInvoice.Table_ID, invoice.getC_Invoice_ID(), as.getC_AcctSchema_ID()); MInvoice.Table_ID, invoice.getC_Invoice_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
if (valuesInv != null) { if (valuesInv != null) {
if (invoice.isSOTrx()) { if (invoice.getReversal_ID() == 0 || invoice.get_ID() < invoice.getReversal_ID())
{
if ((invoice.isSOTrx() && !invoice.isCreditMemo()) || (!invoice.isSOTrx() && invoice.isCreditMemo())) {
invoiceSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr invoiceSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr
invoiceAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr invoiceAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr
} else { } else {
@ -755,6 +759,17 @@ public class Doc_AllocationHdr extends Doc
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
} }
} }
else
{
if ((invoice.isSOTrx() && !invoice.isCreditMemo()) || (!invoice.isSOTrx() && invoice.isCreditMemo())) {
invoiceSource = (BigDecimal) valuesInv.get(2); // AmtSourceCr
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
} else {
invoiceSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr
invoiceAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr
}
}
}
// Requires that Invoice is Posted // Requires that Invoice is Posted
if (invoiceSource == null || invoiceAccounted == null) if (invoiceSource == null || invoiceAccounted == null)
@ -786,7 +801,7 @@ public class Doc_AllocationHdr extends Doc
acctDifference = invoiceAccounted.subtract(allocationAccounted.abs()); acctDifference = invoiceAccounted.subtract(allocationAccounted.abs());
} }
// Full Payment in currency // Full Payment in currency
if (allocationSource.compareTo(invoiceSource) == 0) if (allocationSource.abs().compareTo(invoiceSource.abs()) == 0)
{ {
acctDifference = invoiceAccounted.subtract(allocationAccounted.abs()); // gain is negative acctDifference = invoiceAccounted.subtract(allocationAccounted.abs()); // gain is negative
@ -822,13 +837,21 @@ public class Doc_AllocationHdr extends Doc
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct()); MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct()); MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
BigDecimal cmGainLossAmt = htGainLossAmtByCM.get(invoice.getC_Invoice_ID());
if (cmGainLossAmt == null)
cmGainLossAmt = Env.ZERO;
BigDecimal gainLossAmt = htGainLossAmtByInv.get(invoice.getC_Invoice_ID());
if (gainLossAmt == null)
gainLossAmt = Env.ZERO;
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0) if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0)
cmGainLossAmt = cmGainLossAmt.add(acctDifference); cmGainLossAmt = cmGainLossAmt.add(acctDifference);
else else
gainLossAmt = gainLossAmt.add(acctDifference); gainLossAmt = gainLossAmt.add(acctDifference);
htGainLossAmtByCM.put(invoice.getC_Invoice_ID(), cmGainLossAmt);
htGainLossAmtByInv.put(invoice.getC_Invoice_ID(), gainLossAmt);
// //
if (invoice.isSOTrx()) if ((invoice.isSOTrx() && !invoice.isCreditMemo()) || (!invoice.isSOTrx() && invoice.isCreditMemo()))
{ {
FactLine fl = fact.createLine (line, loss, gain, as.getC_Currency_ID(), acctDifference); FactLine fl = fact.createLine (line, loss, gain, as.getC_Currency_ID(), acctDifference);
fl.setDescription(description.toString()); fl.setDescription(description.toString());
@ -1049,34 +1072,54 @@ public class Doc_AllocationHdr extends Doc
* @param payment payment * @param payment payment
* @return Error Message or null if OK * @return Error Message or null if OK
*/ */
private String createInvoiceRounding(MAcctSchema as, Fact fact, MAccount bpAcct) { private String createInvoiceRounding(MAcctSchema as, Fact fact, MAccount bpAcct)
{
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
// Invoice AR/AP // Invoice AR/AP
BigDecimal totalInvoiceSource = BigDecimal.ZERO;
BigDecimal totalInvoiceAccounted = BigDecimal.ZERO;
boolean isCMReversal =false ;
MInvoice invoice = null;
MPayment payment = null;
ArrayList<MInvoice> invList = new ArrayList<MInvoice>(); ArrayList<MInvoice> invList = new ArrayList<MInvoice>();
ArrayList<MPayment> payList = new ArrayList<MPayment>();
Hashtable<Integer, Integer> htInvAllocLine = new Hashtable<Integer, Integer>();
for (int i = 0; i < p_lines.length; i++) for (int i = 0; i < p_lines.length; i++)
{ {
MInvoice invoice = null;
MPayment payment = null;
DocLine_Allocation line = (DocLine_Allocation)p_lines[i]; DocLine_Allocation line = (DocLine_Allocation)p_lines[i];
if (line.getC_Invoice_ID() != 0) if (line.getC_Invoice_ID() != 0)
{
invoice = new MInvoice (getCtx(), line.getC_Invoice_ID(), getTrxName()); invoice = new MInvoice (getCtx(), line.getC_Invoice_ID(), getTrxName());
if (!invList.contains(invoice))
invList.add(invoice);
htInvAllocLine.put(invoice.getC_Invoice_ID(), line.get_ID());
}
if (line.getC_Payment_ID() != 0) if (line.getC_Payment_ID() != 0)
{
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName()); payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
if (!payList.contains(payment))
payList.add(payment);
}
}
if (invoice != null ) Hashtable<Integer, BigDecimal> htInvSource = new Hashtable<Integer, BigDecimal>();
Hashtable<Integer, BigDecimal> htInvAccounted = new Hashtable<Integer, BigDecimal>();
for (MInvoice invoice : invList)
{ {
boolean isDebit = false; boolean isDebit = false;
// to cater for invoice reverse-accrual. // to cater for invoice reverse-accrual.
if (invoice.getReversal_ID() == 0 || invoice.get_ID() < invoice.getReversal_ID())
{
if (invoice.isSOTrx() && !invoice.isCreditMemo()) if (invoice.isSOTrx() && !invoice.isCreditMemo())
isDebit = true; isDebit = true;
else if (!invoice.isSOTrx() && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 ) else if (!invoice.isSOTrx() && invoice.isCreditMemo())
isDebit = true; isDebit = true;
else if (invoice.isSOTrx() && invoice.isCreditMemo() && invoice.getReversal_ID() == 0) }
else
{
if (!invoice.isSOTrx() && !invoice.isCreditMemo())
isDebit = true; isDebit = true;
else if (invoice.isSOTrx() && invoice.isCreditMemo())
isDebit = true;
}
// //
StringBuilder sql = new StringBuilder("SELECT ") StringBuilder sql = new StringBuilder("SELECT ")
.append((isDebit ) .append((isDebit )
@ -1101,60 +1144,92 @@ public class Doc_AllocationHdr extends Doc
{ {
BigDecimal invoiceSource = rs.getBigDecimal(1); BigDecimal invoiceSource = rs.getBigDecimal(1);
BigDecimal invoiceAccounted = rs.getBigDecimal(2); BigDecimal invoiceAccounted = rs.getBigDecimal(2);
if ( !invList.contains(invoice)) htInvSource.put(invoice.getC_Invoice_ID(), invoiceSource);
{ htInvAccounted.put(invoice.getC_Invoice_ID(), invoiceAccounted);
totalInvoiceSource =totalInvoiceSource.add(invoiceSource);
totalInvoiceAccounted =totalInvoiceAccounted.add(invoiceAccounted);
}
invList.add(invoice);
} }
} }
catch (Exception e) catch (Exception e)
{ {
throw new RuntimeException(e.getLocalizedMessage(), e); throw new RuntimeException(e.getLocalizedMessage(), e);
} }
finally { finally
{
DB.close(rs, pstmt); DB.close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
} }
} }
}
BigDecimal allocInvoiceSource = BigDecimal.ZERO; Hashtable<Integer, BigDecimal> htAllocInvSource = new Hashtable<Integer, BigDecimal>();
BigDecimal allocInvoiceAccounted = BigDecimal.ZERO; Hashtable<Integer, BigDecimal> htAllocInvAccounted = new Hashtable<Integer, BigDecimal>();
MAllocationLine allocationLine = null; Hashtable<Integer, Boolean> htIsExcludeCMGainLoss = new Hashtable<Integer, Boolean>();
Hashtable<Integer, Boolean> htIsCMReversal = new Hashtable<Integer, Boolean>();
FactLine[] factlines = fact.getLines(); FactLine[] factlines = fact.getLines();
boolean isExcludeCMGainLoss = false; for (FactLine factLine : factlines)
for (FactLine factLine : factlines) {
if (bpAcct != null) {
if (factLine.getAccount_ID() == bpAcct.getAccount_ID() )
{ {
if (factLine.getLine_ID() != 0 ) if (bpAcct != null)
{
if (factLine.getAccount_ID() == bpAcct.getAccount_ID())
{
MAllocationLine allocationLine = null;
if (factLine.getLine_ID() != 0)
allocationLine = new MAllocationLine(getCtx(), factLine.getLine_ID(), getTrxName()); allocationLine = new MAllocationLine(getCtx(), factLine.getLine_ID(), getTrxName());
MInvoice invoice = null;
MPayment payment = null;
if (allocationLine != null) if (allocationLine != null)
{
invoice = allocationLine.getInvoice(); invoice = allocationLine.getInvoice();
if (allocationLine.getC_Payment_ID() > 0)
payment = new MPayment (getCtx(), allocationLine.getC_Payment_ID(), getTrxName());
}
BigDecimal allocInvoiceSource = htAllocInvSource.get(allocationLine.getC_Invoice_ID());
if (allocInvoiceSource == null)
allocInvoiceSource = Env.ZERO;
BigDecimal allocInvoiceAccounted = htAllocInvAccounted.get(allocationLine.getC_Invoice_ID());
if (allocInvoiceAccounted == null)
allocInvoiceAccounted = Env.ZERO;
BigDecimal cmGainLossAmt = htGainLossAmtByCM.get(invoice.getC_Invoice_ID());
if (cmGainLossAmt == null)
cmGainLossAmt = Env.ZERO;
BigDecimal gainLossAmt = htGainLossAmtByInv.get(invoice.getC_Invoice_ID());
if (gainLossAmt == null)
gainLossAmt = Env.ZERO;
Boolean isExcludeCMGainLoss = htIsExcludeCMGainLoss.get(invoice.getC_Invoice_ID());
if (isExcludeCMGainLoss == null)
isExcludeCMGainLoss = Boolean.FALSE;
Boolean isCMReversal = htIsCMReversal.get(invoice.getC_Invoice_ID());
if (isCMReversal == null)
isCMReversal = Boolean.FALSE;
if (invoice.isSOTrx()) if (invoice.isSOTrx())
{ {
if (factLine.getC_Currency_ID() != as.getC_Currency_ID()) if (factLine.getC_Currency_ID() != as.getC_Currency_ID())
{
if (!invoice.isCreditMemo())
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceCr()); allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceCr());
else
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr());
}
if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo()) if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo())
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr()); allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr());
else if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo())
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 ) { if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0)
{
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr()); allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
if (!invoice.getDateAcct().equals(getDateAcct())) if (!invoice.getDateAcct().equals(getDateAcct()))
isCMReversal =true; isCMReversal = true;
} }
if (invoice!=null) if (invoice!=null)
{ {
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0 ) { if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0 )
{
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs()); allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs());
cmGainLossAmt = Env.ZERO; cmGainLossAmt = Env.ZERO;
} }
if (gainLossFactList.contains(factLine)) { if (gainLossFactList.contains(factLine))
{
isExcludeCMGainLoss = true; isExcludeCMGainLoss = true;
} }
} }
@ -1164,8 +1239,8 @@ public class Doc_AllocationHdr extends Doc
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr()); allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr());
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr()); allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
} }
}
} else else
{ {
if (as.getC_Currency_ID() != factLine.getC_Currency_ID()) if (as.getC_Currency_ID() != factLine.getC_Currency_ID())
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr()); allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr());
@ -1173,57 +1248,99 @@ public class Doc_AllocationHdr extends Doc
if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo()) if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo())
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr()); allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 ) { if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0)
{
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr()); allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr());
// this is to cater for reverse-accrual. // this is to cater for reverse-accrual.
if (!invoice.getDateAcct().equals(getDateAcct())) if (!invoice.getDateAcct().equals(getDateAcct()))
isCMReversal =true; isCMReversal = true;
} }
if (invoice!=null ) if (invoice != null)
{
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0)
{ {
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0 ) {
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs()); allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs());
cmGainLossAmt = Env.ZERO; cmGainLossAmt = Env.ZERO;
} }
if (gainLossFactList.contains(factLine)) { if (gainLossFactList.contains(factLine))
{
isExcludeCMGainLoss = true; isExcludeCMGainLoss = true;
} }
} }
} }
htAllocInvSource.put(invoice.getC_Invoice_ID(), allocInvoiceSource);
htAllocInvAccounted.put(invoice.getC_Invoice_ID(), allocInvoiceAccounted);
htGainLossAmtByCM.put(invoice.getC_Invoice_ID(), cmGainLossAmt);
htGainLossAmtByInv.put(invoice.getC_Invoice_ID(), gainLossAmt);
htIsExcludeCMGainLoss.put(invoice.getC_Invoice_ID(), isExcludeCMGainLoss);
htIsCMReversal.put(invoice.getC_Invoice_ID(), isCMReversal);
} }
} }
} }
for (MInvoice invoice : invList)
{
BigDecimal invoiceSource = htInvSource.get(invoice.getC_Invoice_ID());
if (invoiceSource == null)
invoiceSource = Env.ZERO;
BigDecimal invoiceAccounted = htInvAccounted.get(invoice.getC_Invoice_ID());
if (invoiceAccounted == null)
invoiceAccounted = Env.ZERO;
BigDecimal allocInvoiceSource = htAllocInvSource.get(invoice.getC_Invoice_ID());
if (allocInvoiceSource == null)
allocInvoiceSource = Env.ZERO;
BigDecimal allocInvoiceAccounted = htAllocInvAccounted.get(invoice.getC_Invoice_ID());
if (allocInvoiceAccounted == null)
allocInvoiceAccounted = Env.ZERO;
BigDecimal cmGainLossAmt = htGainLossAmtByCM.get(invoice.getC_Invoice_ID());
if (cmGainLossAmt == null)
cmGainLossAmt = Env.ZERO;
BigDecimal gainLossAmt = htGainLossAmtByInv.get(invoice.getC_Invoice_ID());
if (gainLossAmt == null)
gainLossAmt = Env.ZERO;
Boolean isExcludeCMGainLoss = htIsExcludeCMGainLoss.get(invoice.getC_Invoice_ID());
if (isExcludeCMGainLoss == null)
isExcludeCMGainLoss = Boolean.FALSE;
Boolean isCMReversal = htIsCMReversal.get(invoice.getC_Invoice_ID());
if (isCMReversal == null)
isCMReversal = Boolean.FALSE;
BigDecimal acctDifference = null; // gain is negative BigDecimal acctDifference = null; // gain is negative
// //
StringBuilder description = new StringBuilder("Invoice=(").append(getC_Currency_ID()).append(")").append(allocInvoiceSource).append("/").append(allocInvoiceAccounted); StringBuilder description = new StringBuilder("Invoice=(").append(getC_Currency_ID()).append(")").append(allocInvoiceSource).append("/").append(allocInvoiceAccounted);
if (log.isLoggable(Level.FINE)) log.fine(description.toString()); if (log.isLoggable(Level.FINE)) log.fine(description.toString());
boolean isBPartnerAdjust = true; boolean isBPartnerAdjust = true;
if (allocInvoiceSource.abs().compareTo(totalInvoiceSource.abs()) == 0) if (allocInvoiceSource.abs().compareTo(invoiceSource.abs()) == 0)
{ {
if (isExcludeCMGainLoss) if (isExcludeCMGainLoss)
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt); allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt);
for (MPayment payment : payList)
{
if (payment != null && payment.getReversal_ID() > 0 ) if (payment != null && payment.getReversal_ID() > 0 )
allocInvoiceAccounted = allocInvoiceAccounted.subtract(gainLossAmt); allocInvoiceAccounted = allocInvoiceAccounted.subtract(gainLossAmt);
else else
allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt); allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt);
}
if (isCMReversal) if (isCMReversal)
acctDifference = totalInvoiceAccounted.subtract(allocInvoiceAccounted.abs()); acctDifference = invoiceAccounted.subtract(allocInvoiceAccounted.abs());
else else
acctDifference = allocInvoiceAccounted.subtract(totalInvoiceAccounted.abs()); // gain is positive for receipt acctDifference = allocInvoiceAccounted.subtract(invoiceAccounted.abs()); // gain is positive for receipt
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference); StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
if (log.isLoggable(Level.FINE)) log.fine(d2.toString()); if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
description.append(" - ").append(d2); description.append(" - ").append(d2);
} else{ }
else
{
MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), invoice.get_ID(), getTrxName()); MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), invoice.get_ID(), getTrxName());
for (MAllocationHdr alloc : allocations) for (MAllocationHdr alloc : allocations)
{ {
if (alloc.get_ID() == get_ID())
continue;
StringBuilder sql = new StringBuilder("SELECT ") StringBuilder sql = new StringBuilder("SELECT ")
.append(invoice.isSOTrx() .append(invoice.isSOTrx()
? "SUM(AmtSourceCr), SUM(AmtAcctCr), SUM(AmtAcctDr)" // so ? "SUM(AmtSourceCr), SUM(AmtAcctCr), SUM(AmtAcctDr)" // so
@ -1232,7 +1349,8 @@ public class Doc_AllocationHdr extends Doc
.append("WHERE AD_Table_ID=? AND Record_ID=?") // allocation .append("WHERE AD_Table_ID=? AND Record_ID=?") // allocation
.append(" AND C_AcctSchema_ID=?") .append(" AND C_AcctSchema_ID=?")
.append(" AND PostingType='A'") .append(" AND PostingType='A'")
.append(" AND Account_ID= ? "); .append(" AND Account_ID=?")
.append(" AND Line_ID IN (SELECT C_AllocationLine_ID FROM C_AllocationLine WHERE C_AllocationHdr_ID=? AND C_Invoice_ID=?)");
pstmt = null; pstmt = null;
rs = null; rs = null;
try try
@ -1242,15 +1360,17 @@ public class Doc_AllocationHdr extends Doc
pstmt.setInt(2, alloc.get_ID()); pstmt.setInt(2, alloc.get_ID());
pstmt.setInt(3, as.getC_AcctSchema_ID()); pstmt.setInt(3, as.getC_AcctSchema_ID());
pstmt.setInt(4, bpAcct.getAccount_ID()); pstmt.setInt(4, bpAcct.getAccount_ID());
pstmt.setInt(5, alloc.get_ID());
pstmt.setInt(6, invoice.getC_Invoice_ID());
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
if (rs.next()) if (rs.next())
{ {
BigDecimal allocateSource = rs.getBigDecimal(1); BigDecimal allocateSource = rs.getBigDecimal(1);
BigDecimal allocateAccounted = rs.getBigDecimal(2); BigDecimal allocateAccounted = rs.getBigDecimal(2);
BigDecimal allocateCredit = rs.getBigDecimal(3); BigDecimal allocateCredit = rs.getBigDecimal(3);
allocInvoiceSource =allocInvoiceSource.add(allocateSource != null ? allocateSource: BigDecimal.ZERO); allocInvoiceSource = allocInvoiceSource.add(allocateSource != null ? allocateSource: BigDecimal.ZERO);
allocInvoiceAccounted =allocInvoiceAccounted.add(allocateAccounted != null ? allocateAccounted : BigDecimal.ZERO); allocInvoiceAccounted = allocInvoiceAccounted.add(allocateAccounted != null ? allocateAccounted : BigDecimal.ZERO);
allocInvoiceAccounted= allocInvoiceAccounted.subtract(allocateCredit != null ? allocateCredit : BigDecimal.ZERO); allocInvoiceAccounted = allocInvoiceAccounted.subtract(allocateCredit != null ? allocateCredit : BigDecimal.ZERO);
} }
} }
@ -1258,24 +1378,25 @@ public class Doc_AllocationHdr extends Doc
{ {
throw new RuntimeException(e.getLocalizedMessage(), e); throw new RuntimeException(e.getLocalizedMessage(), e);
} }
finally { finally
{
DB.close(rs, pstmt); DB.close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
} }
} }
double multiplier = allocInvoiceSource.doubleValue() / totalInvoiceSource.doubleValue(); double multiplier = allocInvoiceSource.doubleValue() / invoiceSource.doubleValue();
// Reduce Orig Invoice Accounted // Reduce Orig Invoice Accounted
BigDecimal reduceOrigAccounted = totalInvoiceAccounted.multiply(BigDecimal.valueOf(multiplier)); BigDecimal reduceOrigAccounted = invoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
if (reduceOrigAccounted.compareTo(totalInvoiceAccounted) < 0 ) if (reduceOrigAccounted.compareTo(invoiceAccounted) < 0 )
totalInvoiceAccounted = reduceOrigAccounted; invoiceAccounted = reduceOrigAccounted;
if (isExcludeCMGainLoss) if (isExcludeCMGainLoss)
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt); allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt);
allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt); allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt);
// Difference based on percentage of Orig Invoice // Difference based on percentage of Orig Invoice
acctDifference = allocInvoiceAccounted.subtract(totalInvoiceAccounted); acctDifference = allocInvoiceAccounted.subtract(invoiceAccounted);
// ignore Tolerance // ignore Tolerance
if (acctDifference.abs().compareTo(BigDecimal.valueOf(0.01)) < 0) if (acctDifference.abs().compareTo(BigDecimal.valueOf(0.01)) < 0)
acctDifference = Env.ZERO; acctDifference = Env.ZERO;
@ -1300,7 +1421,8 @@ public class Doc_AllocationHdr extends Doc
// //
if (acctDifference.abs().compareTo(TOLERANCE) <= 0) if (acctDifference.abs().compareTo(TOLERANCE) <= 0)
{ {
if (invoice.isSOTrx()) Integer C_AllocationLine_ID = htInvAllocLine.get(invoice.getC_Invoice_ID());
if ((invoice.isSOTrx() && !invoice.isCreditMemo()) || (!invoice.isSOTrx() && invoice.isCreditMemo()))
{ {
FactLine fl = null; FactLine fl = null;
if (!isBPartnerAdjust) if (!isBPartnerAdjust)
@ -1308,35 +1430,45 @@ public class Doc_AllocationHdr extends Doc
else else
fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference); fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference);
fl.setDescription(description.toString()); fl.setDescription(description.toString());
fl.setLine_ID(C_AllocationLine_ID == null ? 0 : C_AllocationLine_ID);
if (!fact.isAcctBalanced()) if (!fact.isAcctBalanced())
{ {
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID() ) if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID())
{ {
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate()); fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate());
} else }
else
{ {
fl = fact.createLine (null, loss, gain,as.getC_Currency_ID(), acctDifference.negate()); fl = fact.createLine (null, loss, gain,as.getC_Currency_ID(), acctDifference.negate());
} }
} }
}else fl.setDescription(description.toString());
fl.setLine_ID(C_AllocationLine_ID == null ? 0 : C_AllocationLine_ID);
}
else
{ {
FactLine fl = null; FactLine fl = null;
if (!isBPartnerAdjust) if (!isBPartnerAdjust)
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate()); fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate());
else else
fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference.negate()); fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference.negate());
fl.setDescription(description.toString()); fl.setDescription(description.toString());
fl.setLine_ID(C_AllocationLine_ID == null ? 0 : C_AllocationLine_ID);
if (!fact.isAcctBalanced()) if (!fact.isAcctBalanced())
{ {
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID() ) if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID())
{ {
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference); fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference);
} else {
fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference);
} }
else
{
fl = fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference);
}
}
fl.setDescription(description.toString());
fl.setLine_ID(C_AllocationLine_ID == null ? 0 : C_AllocationLine_ID);
} }
} }
} }

View File

@ -763,6 +763,21 @@ public class Doc_MatchInv extends Doc
cr.setQty(getQty().multiply(multiplier).negate()); cr.setQty(getQty().multiply(multiplier).negate());
} }
} }
// Rounding correction
if (refInvLine != null && refInvLine.getParent().getC_Currency_ID() != as.getC_Currency_ID()) // in foreign currency
{
p_Error = createInvoiceGainLoss(as, fact, expense, refInvLine.getParent(), dr.getAmtSourceCr(), dr.getAmtAcctCr());
if (p_Error != null)
return null;
}
if (m_invoiceLine != null && m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID()) // in foreign currency
{
p_Error = createInvoiceGainLoss(as, fact, expense, m_invoiceLine.getParent(), cr.getAmtSourceDr(), cr.getAmtAcctDr());
if (p_Error != null)
return null;
}
if (m_matchInv.getReversal_ID() == 0) if (m_matchInv.getReversal_ID() == 0)
{ {
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID()); cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
@ -880,7 +895,7 @@ public class Doc_MatchInv extends Doc
return null; return null;
// //
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID()) if (m_matchInv.getReversal_ID() == 0)
{ {
String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv " String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv "
+ "WHERE C_InvoiceLine_ID IN (SELECT C_InvoiceLine_ID FROM C_InvoiceLine WHERE C_Invoice_ID=?) " + "WHERE C_InvoiceLine_ID IN (SELECT C_InvoiceLine_ID FROM C_InvoiceLine WHERE C_Invoice_ID=?) "
@ -939,6 +954,8 @@ public class Doc_MatchInv extends Doc
if (totalAmtAcctCr == null) if (totalAmtAcctCr == null)
totalAmtAcctCr = Env.ZERO; totalAmtAcctCr = Env.ZERO;
if (m_matchInv.getReversal_ID() == 0)
{
if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0) if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0)
{ {
matchInvSource = matchInvSource.add(totalAmtSourceCr); matchInvSource = matchInvSource.add(totalAmtSourceCr);
@ -949,19 +966,30 @@ public class Doc_MatchInv extends Doc
matchInvSource = matchInvSource.add(totalAmtSourceDr); matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
} }
else if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
{
matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr).subtract(totalAmtAcctCr);
}
else
{
matchInvSource = matchInvSource.add(totalAmtSourceCr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr).subtract(totalAmtAcctDr);
}
}
else else
{ {
if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0) if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
{ {
matchInvSource = matchInvSource.add(totalAmtSourceDr); matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
acctDifference = totalAmtAcctCr.negate(); acctDifference = totalAmtAcctCr;
} }
else else
{ {
matchInvSource = matchInvSource.add(totalAmtSourceCr); matchInvSource = matchInvSource.add(totalAmtSourceCr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
acctDifference = totalAmtSourceDr.negate(); acctDifference = totalAmtAcctDr.negate();
} }
} }
} }
@ -1050,7 +1078,7 @@ public class Doc_MatchInv extends Doc
if (receiptSource == null || receiptAccounted == null) if (receiptSource == null || receiptAccounted == null)
return null; return null;
// //
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID()) if (m_matchInv.getReversal_ID() == 0)
{ {
String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv " String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv "
+ "WHERE M_InOutLine_ID IN (SELECT M_InOutLine_ID FROM M_InOutLine WHERE M_InOut_ID=?) " + "WHERE M_InOutLine_ID IN (SELECT M_InOutLine_ID FROM M_InOutLine WHERE M_InOut_ID=?) "
@ -1110,6 +1138,8 @@ public class Doc_MatchInv extends Doc
if (totalAmtAcctCr == null) if (totalAmtAcctCr == null)
totalAmtAcctCr = Env.ZERO; totalAmtAcctCr = Env.ZERO;
if (m_matchInv.getReversal_ID() == 0)
{
if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0) if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0)
{ {
matchInvSource = matchInvSource.add(totalAmtSourceCr); matchInvSource = matchInvSource.add(totalAmtSourceCr);
@ -1120,11 +1150,7 @@ public class Doc_MatchInv extends Doc
matchInvSource = matchInvSource.add(totalAmtSourceDr); matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
} }
else else if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
{
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID())
{
if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
{ {
matchInvSource = matchInvSource.add(totalAmtSourceDr); matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr).subtract(totalAmtAcctCr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr).subtract(totalAmtAcctCr);
@ -1141,14 +1167,13 @@ public class Doc_MatchInv extends Doc
{ {
matchInvSource = matchInvSource.add(totalAmtSourceDr); matchInvSource = matchInvSource.add(totalAmtSourceDr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
acctDifference = totalAmtAcctCr.negate(); acctDifference = totalAmtAcctCr.negate();;
} }
else else
{ {
matchInvSource = matchInvSource.add(totalAmtSourceCr); matchInvSource = matchInvSource.add(totalAmtSourceCr);
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr); matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
acctDifference = totalAmtAcctDr.negate(); acctDifference = totalAmtAcctDr;
}
} }
} }
} }

View File

@ -1616,11 +1616,11 @@ public class MInOut extends X_M_InOut implements DocAction
} }
if (!po.isPosted()) if (!po.isPosted())
addDocsPostProcess(po); addDocsPostProcess(po);
MMatchInv matchInvCreated = po.getMatchInvCreated();
if (matchInvCreated != null) { MMatchInv[] matchInvList = MMatchInv.getInOut(getCtx(), getM_InOut_ID(), get_TrxName());
for (MMatchInv matchInvCreated : matchInvList)
addDocsPostProcess(matchInvCreated); addDocsPostProcess(matchInvCreated);
} }
}
// Update PO with ASI // Update PO with ASI
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]