IDEMPIERE-3983 Matched PO posting status "Deferred" never transitions to "Posted" if no matching MR is assigned

This commit is contained in:
Heng Sin Low 2019-06-19 18:21:55 +08:00
parent a4ab94895d
commit 3a6f8f08e2
1 changed files with 141 additions and 128 deletions

View File

@ -404,6 +404,14 @@ public class MMatchPO extends X_M_MatchPO
if (iLine == null && mpo.isPosted()) if (iLine == null && mpo.isPosted())
continue; continue;
} }
if (iLine != null && sLine == null && mpo.getC_InvoiceLine_ID() == 0)
{
//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());
if (cnt > 0)
continue;
}
if ((iLine != null || mpo.getC_InvoiceLine_ID() > 0) && (sLine != null || mpo.getM_InOutLine_ID() > 0)) if ((iLine != null || mpo.getC_InvoiceLine_ID() > 0) && (sLine != null || mpo.getM_InOutLine_ID() > 0))
{ {
int M_InOutLine_ID = sLine != null ? sLine.getM_InOutLine_ID() : mpo.getM_InOutLine_ID(); int M_InOutLine_ID = sLine != null ? sLine.getM_InOutLine_ID() : mpo.getM_InOutLine_ID();
@ -485,12 +493,12 @@ public class MMatchPO extends X_M_MatchPO
qty = qty.subtract(toMatch); qty = qty.subtract(toMatch);
if (qty.signum() <= 0) if (qty.signum() <= 0)
{ {
retValue = mpo; retValue = mpo;
break; break;
}
} }
} }
} }
}
catch (Exception e) catch (Exception e)
{ {
s_log.log(Level.SEVERE, sql, e); s_log.log(Level.SEVERE, sql, e);
@ -633,152 +641,157 @@ public class MMatchPO extends X_M_MatchPO
throw new RuntimeException(msg); throw new RuntimeException(msg);
} }
//auto create m_matchinv if not created yet //auto create m_matchinv
int cnt = DB.getSQLValue(iLine.get_TrxName(), "SELECT Count(*) FROM M_MatchInv WHERE C_InvoiceLine_ID="+iLine.getC_InvoiceLine_ID()); Map<Integer, BigDecimal[]> noInvoiceLines = new HashMap<>();
if (cnt == 0) Map<Integer, List<MMatchPO>> invoiceMatched = new HashMap<Integer, List<MMatchPO>>();
List<MMatchPO> noInvoiceList = new ArrayList<MMatchPO>();
//get all matchpo with inoutline for C_OrderLine_ID
MMatchPO[] matchPOs = MMatchPO.getOrderLine(iLine.getCtx(), C_OrderLine_ID, iLine.get_TrxName());
for (MMatchPO matchPO : matchPOs)
{ {
Map<Integer, BigDecimal[]> noInvoiceLines = new HashMap<>(); if (matchPO.getM_MatchPO_ID() == retValue.getM_MatchPO_ID())
Map<Integer, List<MMatchPO>> invoiceMatched = new HashMap<Integer, List<MMatchPO>>(); continue;
List<MMatchPO> noInvoiceList = new ArrayList<MMatchPO>();
MMatchPO[] matchPOs = MMatchPO.getOrderLine(iLine.getCtx(), C_OrderLine_ID, iLine.get_TrxName()); if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_ID() == 0)
for (MMatchPO matchPO : matchPOs)
{ {
if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_ID() == 0) if (matchPO.getC_InvoiceLine_ID() == 0)
{ {
if (matchPO.getC_InvoiceLine_ID() == 0) String docStatus = matchPO.getM_InOutLine().getM_InOut().getDocStatus();
if (docStatus.equals(DocAction.STATUS_Completed) || docStatus.equals(DocAction.STATUS_Closed))
{ {
String docStatus = matchPO.getM_InOutLine().getM_InOut().getDocStatus(); noInvoiceLines.put(matchPO.getM_MatchPO_ID(), new BigDecimal[]{matchPO.getQty()});
if (docStatus.equals(DocAction.STATUS_Completed) || docStatus.equals(DocAction.STATUS_Closed)) noInvoiceList.add(matchPO);
{
noInvoiceLines.put(matchPO.getM_MatchPO_ID(), new BigDecimal[]{matchPO.getQty()});
noInvoiceList.add(matchPO);
}
} }
else }
else
{
List<MMatchPO> invoices = invoiceMatched.get(matchPO.getM_InOutLine_ID());
if (invoices == null)
{ {
List<MMatchPO> invoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); invoices = new ArrayList<MMatchPO>();
if (invoices == null) invoiceMatched.put(matchPO.getM_InOutLine_ID(), invoices);
{ }
invoices = new ArrayList<MMatchPO>(); invoices.add(matchPO);
invoiceMatched.put(matchPO.getM_InOutLine_ID(), invoices); }
} }
invoices.add(matchPO); }
//sort in created sequence
Collections.sort(noInvoiceList, 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);
}
});
//goes through all matchpo that potentially have not been matched to any invoice yet
//calculate balance that have not been matched to invoice line
for (MMatchPO matchPO : noInvoiceList)
{
BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID());
List<MMatchPO> matchedInvoices = invoiceMatched.get(matchPO.getM_InOutLine_ID());
MMatchInv[] matchInvoices = MMatchInv.getInOutLine(iLine.getCtx(), matchPO.getM_InOutLine_ID(), iLine.get_TrxName());
for (MMatchInv matchInv : matchInvoices)
{
if (matchInv.getReversal_ID() > 0)
continue;
BigDecimal alreadyMatch = BigDecimal.ZERO;
if (matchedInvoices != null)
{
for(MMatchPO matchedInvoice : matchedInvoices)
{
if (matchedInvoice.getC_InvoiceLine_ID()==matchInv.getC_InvoiceLine_ID())
alreadyMatch = alreadyMatch.add(matchedInvoice.getQty());
}
}
BigDecimal balance = matchInv.getQty().subtract(alreadyMatch);
if (balance.signum() > 0)
{
String docStatus = matchInv.getC_InvoiceLine().getC_Invoice().getDocStatus();
if (docStatus.equals(DocAction.STATUS_Completed) || docStatus.equals(DocAction.STATUS_Closed))
{
qtyHolder[0] = qtyHolder[0].subtract(balance);
} }
} }
} }
}
Collections.sort(noInvoiceList, new Comparator<MMatchPO>() { //do matching
@Override BigDecimal toMatch = retValue.getQty();
public int compare(MMatchPO arg0, MMatchPO arg1) { for (MMatchPO matchPO : noInvoiceList)
return arg0.getM_MatchPO_ID() > arg1.getM_MatchPO_ID() {
? 1 BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID());
: (arg0.getM_MatchPO_ID()==arg1.getM_MatchPO_ID() ? 0 : -1); if (qtyHolder[0].signum() > 0)
}
});
for (MMatchPO matchPO : noInvoiceList)
{ {
BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID()); BigDecimal autoMatchQty = null;
List<MMatchPO> matchedInvoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); if (qtyHolder[0].compareTo(toMatch) >= 0)
MMatchInv[] matchInvoices = MMatchInv.getInOutLine(iLine.getCtx(), matchPO.getM_InOutLine_ID(), iLine.get_TrxName());
for (MMatchInv matchInv : matchInvoices)
{ {
if (matchInv.getReversal_ID() > 0) autoMatchQty = toMatch;
continue; toMatch = BigDecimal.ZERO;
BigDecimal alreadyMatch = BigDecimal.ZERO;
if (matchedInvoices != null)
{
for(MMatchPO matchedInvoice : matchedInvoices)
{
if (matchedInvoice.getC_InvoiceLine_ID()==matchInv.getC_InvoiceLine_ID())
alreadyMatch = alreadyMatch.add(matchedInvoice.getQty());
}
}
BigDecimal balance = matchInv.getQty().subtract(alreadyMatch);
if (balance.signum() > 0)
{
String docStatus = matchInv.getC_InvoiceLine().getC_Invoice().getDocStatus();
if (docStatus.equals(DocAction.STATUS_Completed) || docStatus.equals(DocAction.STATUS_Closed))
{
qtyHolder[0] = qtyHolder[0].subtract(balance);
}
}
} }
} else
BigDecimal toMatch = retValue.getQty();
for (MMatchPO matchPO : noInvoiceList)
{
BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID());
if (qtyHolder[0].signum() > 0)
{ {
BigDecimal autoMatchQty = null; autoMatchQty = qtyHolder[0];
if (qtyHolder[0].compareTo(toMatch) >= 0) toMatch = toMatch.subtract(autoMatchQty);
}
if (autoMatchQty != null && autoMatchQty.signum() > 0)
{
Savepoint savepoint = null;
Trx trx = null;
MMatchInv matchInv = null;
try
{ {
autoMatchQty = toMatch; trx = trxName != null ? Trx.get(trxName, false) : null;
toMatch = BigDecimal.ZERO; savepoint = trx != null ? trx.getConnection().setSavepoint() : null;
} matchInv = new MMatchInv(retValue.getCtx(), 0, retValue.get_TrxName());
else matchInv.setC_InvoiceLine_ID(retValue.getC_InvoiceLine_ID());
{ matchInv.setM_Product_ID(retValue.getM_Product_ID());
autoMatchQty = qtyHolder[0]; matchInv.setM_InOutLine_ID(matchPO.getM_InOutLine_ID());
toMatch = toMatch.subtract(autoMatchQty); matchInv.setAD_Client_ID(retValue.getAD_Client_ID());
} matchInv.setAD_Org_ID(retValue.getAD_Org_ID());
if (autoMatchQty != null && autoMatchQty.signum() > 0) matchInv.setM_AttributeSetInstance_ID(retValue.getM_AttributeSetInstance_ID());
{ matchInv.setQty(autoMatchQty);
Savepoint savepoint = null; matchInv.setDateTrx(dateTrx);
Trx trx = null; matchInv.setProcessed(true);
MMatchInv matchInv = null; if (!matchInv.save())
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) if (savepoint != null)
{ {
try { trx.getConnection().rollback(savepoint);
trx.getConnection().releaseSavepoint(savepoint); savepoint = null;
} catch (Exception e) {}
} }
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) {}
} }
if (matchInv == null)
break;
} }
if (matchInv == null)
break;
} }
if (toMatch.signum() <= 0)
break;
} }
if (toMatch.signum() <= 0)
break;
} }
} }
} }