diff --git a/base/src/org/compiere/model/MDunningRunEntry.java b/base/src/org/compiere/model/MDunningRunEntry.java index 9e0b02e068..c946dfb756 100644 --- a/base/src/org/compiere/model/MDunningRunEntry.java +++ b/base/src/org/compiere/model/MDunningRunEntry.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Properties; import java.util.logging.Level; +import org.adempiere.exceptions.BPartnerNoAddressException; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; @@ -40,6 +41,7 @@ public class MDunningRunEntry extends X_C_DunningRunEntry * */ private static final long serialVersionUID = 2028055451030209868L; + /** Logger */ private static CLogger s_log = CLogger.getCLogger (MPayment.class); @@ -106,30 +108,58 @@ public class MDunningRunEntry extends X_C_DunningRunEntry setC_BPartner_Location_ID (locations[0].getC_BPartner_Location_ID()); else { - for (int i = 0; i < locations.length; i++) - { - MBPartnerLocation location = locations[i]; + MBPartnerLocation firstActive = null; + MBPartnerLocation firstBillTo = null; + for (int i = 0; i < locations.length; i++) + { + MBPartnerLocation location = locations[i]; if (!location.isActive()) + { continue; - if ((location.isPayFrom() && isSOTrx) - || (location.isRemitTo() && !isSOTrx)) - { - setC_BPartner_Location_ID (location.getC_BPartner_Location_ID()); - break; - } + } + else if (firstActive == null) + { + firstActive = location; + } + if ((location.isPayFrom() && isSOTrx) + || (location.isRemitTo() && !isSOTrx)) + { + setC_BPartner_Location_ID (location.getC_BPartner_Location_ID()); + break; + } + else if (firstBillTo == null && location.isBillTo()) + { + firstBillTo = location; + } + } + + // If IsPayFrom or isRemitTo is not found among the BP Locations, check IsBillTo + // if that isn't available, we should use any active location + if(getC_BPartner_Location_ID() == 0) + { + if (firstBillTo != null) + { + setC_BPartner_Location_ID (firstBillTo.getC_BPartner_Location_ID()); + } + else if (firstActive != null) + { + String msg = "@C_BPartner_ID@ " + bp.getName(); + if (isSOTrx) + msg += " @No@ @IsPayFrom@"; + else + msg += " @No@ @IsRemitTo@"; + msg += " & @IsBillTo@"; + log.info(msg); + setC_BPartner_Location_ID (firstActive.getC_BPartner_Location_ID()); + } } } if (getC_BPartner_Location_ID() == 0) { - String msg = "@C_BPartner_ID@ " + bp.getName(); - if (isSOTrx) - msg += " @No@ @IsPayFrom@"; - else - msg += " @No@ @IsRemitTo@"; - throw new IllegalArgumentException (msg); + throw new BPartnerNoAddressException(bp); } // User with location - MUser[] users = MUser.getOfBPartner(getCtx(), bp.getC_BPartner_ID()); + MUser[] users = MUser.getOfBPartner(getCtx(), bp.getC_BPartner_ID(), null); if (users.length == 1) setAD_User_ID (users[0].getAD_User_ID()); else diff --git a/base/src/org/compiere/process/DunningRunCreate.java b/base/src/org/compiere/process/DunningRunCreate.java index 867cfbfd15..ea3b3c478e 100644 --- a/base/src/org/compiere/process/DunningRunCreate.java +++ b/base/src/org/compiere/process/DunningRunCreate.java @@ -21,11 +21,14 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.logging.Level; +import org.adempiere.exceptions.BPartnerNoAddressException; +import org.compiere.model.MBPartner; import org.compiere.model.MDunningLevel; import org.compiere.model.MDunningRun; import org.compiere.model.MDunningRunEntry; import org.compiere.model.MDunningRunLine; import org.compiere.model.MInvoice; +import org.compiere.model.MPayment; import org.compiere.util.DB; import org.compiere.util.Env; @@ -252,16 +255,19 @@ public class DunningRunCreate extends SvrProcess if (DaysBetweenDunning != 0 && DaysAfterLast < DaysBetweenDunning && !m_level.isShowAllDue () && !m_level.isShowNotDue ()) continue; // - createInvoiceLine (C_Invoice_ID, C_InvoicePaySchedule_ID, C_Currency_ID, GrandTotal, Open, + if (createInvoiceLine (C_Invoice_ID, C_InvoicePaySchedule_ID, C_Currency_ID, GrandTotal, Open, DaysDue, IsInDispute, C_BPartner_ID, - TimesDunned, DaysAfterLast); - count++; + TimesDunned, DaysAfterLast)) + { + count++; + } } } catch (Exception e) { log.log(Level.SEVERE, "addInvoices", e); + getProcessInfo().addLog(getProcessInfo().getAD_PInstance_ID(), null, null, e.getLocalizedMessage()); } finally { @@ -283,15 +289,30 @@ public class DunningRunCreate extends SvrProcess * @param TimesDunned * @param DaysAfterLast */ - private void createInvoiceLine (int C_Invoice_ID, int C_InvoicePaySchedule_ID, int C_Currency_ID, + private boolean createInvoiceLine (int C_Invoice_ID, int C_InvoicePaySchedule_ID, int C_Currency_ID, BigDecimal GrandTotal, BigDecimal Open, int DaysDue, boolean IsInDispute, int C_BPartner_ID, int TimesDunned, int DaysAfterLast) { - MDunningRunEntry entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + MDunningRunEntry entry = null; + try + { + entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + } + catch (BPartnerNoAddressException e) + { + String msg = "@Skip@ @C_Invoice_ID@ " + MInvoice.get(getCtx(), C_Invoice_ID).getDocumentInfo() + + ", @C_BPartner_ID@ " + MBPartner.get(getCtx(), C_BPartner_ID).getName() + + " @No@ @IsActive@ @C_BPartner_Location_ID@"; + getProcessInfo().addLog(getProcessInfo().getAD_PInstance_ID(), null, null, msg); + return false; + } + if (entry.get_ID() == 0) + { if (!entry.save()) throw new IllegalStateException("Cannot save MDunningRunEntry"); + } // MDunningRunLine line = new MDunningRunLine (entry); line.setInvoice(C_Invoice_ID, C_Currency_ID, GrandTotal, Open, @@ -304,6 +325,8 @@ public class DunningRunCreate extends SvrProcess invoice.setC_DunningLevel_ID(m_run.getC_DunningLevel_ID()); if (!invoice.save()) throw new IllegalStateException("Cannot update dunning level information in invoice"); + + return true; } // createInvoiceLine @@ -359,14 +382,17 @@ public class DunningRunCreate extends SvrProcess if (Env.ZERO.compareTo(OpenAmt) == 0) continue; // - createPaymentLine (C_Payment_ID, C_Currency_ID, PayAmt, OpenAmt, - C_BPartner_ID); - count++; + if (createPaymentLine (C_Payment_ID, C_Currency_ID, PayAmt, OpenAmt, + C_BPartner_ID)) + { + count++; + } } } catch (Exception e) { log.log(Level.SEVERE, sql, e); + getProcessInfo().addLog(getProcessInfo().getAD_PInstance_ID(), null, null, e.getLocalizedMessage()); } finally { @@ -384,10 +410,20 @@ public class DunningRunCreate extends SvrProcess * @param OpenAmt * @param C_BPartner_ID */ - private void createPaymentLine (int C_Payment_ID, int C_Currency_ID, + private boolean createPaymentLine (int C_Payment_ID, int C_Currency_ID, BigDecimal PayAmt, BigDecimal OpenAmt, int C_BPartner_ID) { - MDunningRunEntry entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + MDunningRunEntry entry = null; + try { + entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + } catch (BPartnerNoAddressException e) { + MPayment payment = new MPayment(getCtx(), C_Payment_ID, null); + String msg = "@Skip@ @C_Payment_ID@ " + payment.getDocumentInfo() + + ", @C_BPartner_ID@ " + MBPartner.get(getCtx(), C_BPartner_ID).getName() + + " @No@ @IsActive@ @C_BPartner_Location_ID@"; + getProcessInfo().addLog(getProcessInfo().getAD_PInstance_ID(), null, null, msg); + return false; + } if (entry.get_ID() == 0) if (!entry.save()) throw new IllegalStateException("Cannot save MDunningRunEntry"); @@ -396,6 +432,7 @@ public class DunningRunCreate extends SvrProcess line.setPayment(C_Payment_ID, C_Currency_ID, PayAmt, OpenAmt); if (!line.save()) throw new IllegalStateException("Cannot save MDunningRunLine"); + return true; } // createPaymentLine private void addFees()