diff --git a/org.adempiere.base/src/org/compiere/model/MMatchPO.java b/org.adempiere.base/src/org/compiere/model/MMatchPO.java index 9e1502ace9..7e8580c1eb 100644 --- a/org.adempiere.base/src/org/compiere/model/MMatchPO.java +++ b/org.adempiere.base/src/org/compiere/model/MMatchPO.java @@ -398,12 +398,20 @@ public class MMatchPO extends X_M_MatchPO else if (mpo.getM_AttributeSetInstance_ID() != sLine.getM_AttributeSetInstance_ID()) continue; } - } + } else continue; if (iLine == null && mpo.isPosted()) 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)) { 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); if (qty.signum() <= 0) { - retValue = mpo; - break; + retValue = mpo; + break; + } } } } - } catch (Exception e) { s_log.log(Level.SEVERE, sql, e); @@ -633,152 +641,157 @@ public class MMatchPO extends X_M_MatchPO throw new RuntimeException(msg); } - //auto create m_matchinv if not created yet - int cnt = DB.getSQLValue(iLine.get_TrxName(), "SELECT Count(*) FROM M_MatchInv WHERE C_InvoiceLine_ID="+iLine.getC_InvoiceLine_ID()); - if (cnt == 0) + //auto create m_matchinv + Map noInvoiceLines = new HashMap<>(); + Map> invoiceMatched = new HashMap>(); + List noInvoiceList = new ArrayList(); + //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 noInvoiceLines = new HashMap<>(); - Map> invoiceMatched = new HashMap>(); - List noInvoiceList = new ArrayList(); - MMatchPO[] matchPOs = MMatchPO.getOrderLine(iLine.getCtx(), C_OrderLine_ID, iLine.get_TrxName()); - for (MMatchPO matchPO : matchPOs) - { - if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_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)) - { - noInvoiceLines.put(matchPO.getM_MatchPO_ID(), new BigDecimal[]{matchPO.getQty()}); - noInvoiceList.add(matchPO); - } - } - else - { - List invoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); - if (invoices == null) - { - invoices = new ArrayList(); - invoiceMatched.put(matchPO.getM_InOutLine_ID(), invoices); - } - invoices.add(matchPO); - } - } - } + if (matchPO.getM_MatchPO_ID() == retValue.getM_MatchPO_ID()) + continue; - Collections.sort(noInvoiceList, new Comparator() { - @Override - public int compare(MMatchPO arg0, MMatchPO arg1) { - return arg0.getM_MatchPO_ID() > arg1.getM_MatchPO_ID() - ? 1 - : (arg0.getM_MatchPO_ID()==arg1.getM_MatchPO_ID() ? 0 : -1); + if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getReversal_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)) + { + noInvoiceLines.put(matchPO.getM_MatchPO_ID(), new BigDecimal[]{matchPO.getQty()}); + noInvoiceList.add(matchPO); + } } - }); - for (MMatchPO matchPO : noInvoiceList) - { - BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID()); - List matchedInvoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); - MMatchInv[] matchInvoices = MMatchInv.getInOutLine(iLine.getCtx(), matchPO.getM_InOutLine_ID(), iLine.get_TrxName()); - for (MMatchInv matchInv : matchInvoices) + else { - if (matchInv.getReversal_ID() > 0) - continue; - BigDecimal alreadyMatch = BigDecimal.ZERO; - if (matchedInvoices != null) + List invoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); + if (invoices == null) { - for(MMatchPO matchedInvoice : matchedInvoices) - { - if (matchedInvoice.getC_InvoiceLine_ID()==matchInv.getC_InvoiceLine_ID()) - alreadyMatch = alreadyMatch.add(matchedInvoice.getQty()); - } + invoices = new ArrayList(); + invoiceMatched.put(matchPO.getM_InOutLine_ID(), invoices); } - 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); - } - } - } + invoices.add(matchPO); + } + } + } + + //sort in created sequence + Collections.sort(noInvoiceList, new Comparator() { + @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); } - - BigDecimal toMatch = retValue.getQty(); - for (MMatchPO matchPO : noInvoiceList) + }); + + //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 matchedInvoices = invoiceMatched.get(matchPO.getM_InOutLine_ID()); + MMatchInv[] matchInvoices = MMatchInv.getInOutLine(iLine.getCtx(), matchPO.getM_InOutLine_ID(), iLine.get_TrxName()); + for (MMatchInv matchInv : matchInvoices) { - BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID()); - if (qtyHolder[0].signum() > 0) + if (matchInv.getReversal_ID() > 0) + continue; + BigDecimal alreadyMatch = BigDecimal.ZERO; + if (matchedInvoices != null) { - BigDecimal autoMatchQty = null; - if (qtyHolder[0].compareTo(toMatch) >= 0) + for(MMatchPO matchedInvoice : matchedInvoices) { - autoMatchQty = toMatch; - toMatch = BigDecimal.ZERO; + if (matchedInvoice.getC_InvoiceLine_ID()==matchInv.getC_InvoiceLine_ID()) + alreadyMatch = alreadyMatch.add(matchedInvoice.getQty()); } - else + } + 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)) { - autoMatchQty = qtyHolder[0]; - toMatch = toMatch.subtract(autoMatchQty); + qtyHolder[0] = qtyHolder[0].subtract(balance); } - if (autoMatchQty != null && autoMatchQty.signum() > 0) + } + } + } + + //do matching + BigDecimal toMatch = retValue.getQty(); + for (MMatchPO matchPO : noInvoiceList) + { + BigDecimal[] qtyHolder = noInvoiceLines.get(matchPO.getM_MatchPO_ID()); + if (qtyHolder[0].signum() > 0) + { + BigDecimal autoMatchQty = null; + if (qtyHolder[0].compareTo(toMatch) >= 0) + { + autoMatchQty = toMatch; + toMatch = BigDecimal.ZERO; + } + else + { + autoMatchQty = qtyHolder[0]; + toMatch = toMatch.subtract(autoMatchQty); + } + if (autoMatchQty != null && autoMatchQty.signum() > 0) + { + Savepoint savepoint = null; + Trx trx = null; + MMatchInv matchInv = null; + try { - Savepoint savepoint = null; - Trx trx = null; - MMatchInv matchInv = null; - try + trx = trxName != null ? Trx.get(trxName, false) : null; + savepoint = trx != null ? trx.getConnection().setSavepoint() : null; + matchInv = new MMatchInv(retValue.getCtx(), 0, retValue.get_TrxName()); + matchInv.setC_InvoiceLine_ID(retValue.getC_InvoiceLine_ID()); + matchInv.setM_Product_ID(retValue.getM_Product_ID()); + matchInv.setM_InOutLine_ID(matchPO.getM_InOutLine_ID()); + matchInv.setAD_Client_ID(retValue.getAD_Client_ID()); + matchInv.setAD_Org_ID(retValue.getAD_Org_ID()); + matchInv.setM_AttributeSetInstance_ID(retValue.getM_AttributeSetInstance_ID()); + matchInv.setQty(autoMatchQty); + matchInv.setDateTrx(dateTrx); + matchInv.setProcessed(true); + if (!matchInv.save()) { - 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) { - 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; + trx.getConnection().rollback(savepoint); + savepoint = null; } - } catch (Exception e) { - s_log.log(Level.SEVERE, "Failed to auto match Invoice.", e); - matchInv = null; - } finally { - if (savepoint != null) + else { - try { - trx.getConnection().releaseSavepoint(savepoint); - } catch (Exception e) {} - } + 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; } - if (matchInv == null) - break; + } 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 (toMatch.signum() <= 0) - break; } + if (toMatch.signum() <= 0) + break; } } }