From 6b391f688e9fa6f3ba5ee5b59349d5773c8eb1e7 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 30 Jul 2014 23:20:09 +0200 Subject: [PATCH] IDEMPIERE-2108 add an option for a minimum amount to create invoices process --- .../oracle/201407301015_IDEMPIERE-2108.sql | 11 +++ .../201407301015_IDEMPIERE-2108.sql | 8 ++ .../org/compiere/process/InvoiceGenerate.java | 83 +++++++++++++++---- .../src/org/compiere/model/MInvoice.java | 8 +- .../org/compiere/model/MInvoiceSchedule.java | 15 +++- .../src/org/compiere/process/ProcessInfo.java | 11 ++- 6 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 migration/i2.0z/oracle/201407301015_IDEMPIERE-2108.sql create mode 100644 migration/i2.0z/postgresql/201407301015_IDEMPIERE-2108.sql diff --git a/migration/i2.0z/oracle/201407301015_IDEMPIERE-2108.sql b/migration/i2.0z/oracle/201407301015_IDEMPIERE-2108.sql new file mode 100644 index 0000000000..eb1931a2e4 --- /dev/null +++ b/migration/i2.0z/oracle/201407301015_IDEMPIERE-2108.sql @@ -0,0 +1,11 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jul 30, 2014 10:11:38 AM CEST +-- IDEMPIERE-2108 add an option for a minimum amount to create invoices process +INSERT INTO AD_Process_Para (IsRange,AD_Process_Para_ID,AD_Process_Para_UU,AD_Process_ID,IsMandatory,EntityType,Name,ColumnName,Description,FieldLength,IsCentrallyMaintained,SeqNo,IsActive,UpdatedBy,Updated,CreatedBy,AD_Org_ID,IsEncrypted,AD_Client_ID,AD_Element_ID,AD_Reference_ID,Created) VALUES ('N',200107,'5dd9e63d-e70d-41c4-97ea-e6bb37015368',119,'N','D','Minimum Amt','MinimumAmt','Minimum Amount in Document Currency',22,'Y',60,'Y',100,TO_DATE('2014-07-30 10:11:37','YYYY-MM-DD HH24:MI:SS'),100,0,'N',0,2177,12,TO_DATE('2014-07-30 10:11:37','YYYY-MM-DD HH24:MI:SS')) +; + +SELECT register_migration_script('201407301015_IDEMPIERE-2108.sql') FROM dual +; + diff --git a/migration/i2.0z/postgresql/201407301015_IDEMPIERE-2108.sql b/migration/i2.0z/postgresql/201407301015_IDEMPIERE-2108.sql new file mode 100644 index 0000000000..6b9d4e6f94 --- /dev/null +++ b/migration/i2.0z/postgresql/201407301015_IDEMPIERE-2108.sql @@ -0,0 +1,8 @@ +-- Jul 30, 2014 10:11:38 AM CEST +-- IDEMPIERE-2108 add an option for a minimum amount to create invoices process +INSERT INTO AD_Process_Para (IsRange,AD_Process_Para_ID,AD_Process_Para_UU,AD_Process_ID,IsMandatory,EntityType,Name,ColumnName,Description,FieldLength,IsCentrallyMaintained,SeqNo,IsActive,UpdatedBy,Updated,CreatedBy,AD_Org_ID,IsEncrypted,AD_Client_ID,AD_Element_ID,AD_Reference_ID,Created) VALUES ('N',200107,'5dd9e63d-e70d-41c4-97ea-e6bb37015368',119,'N','D','Minimum Amt','MinimumAmt','Minimum Amount in Document Currency',22,'Y',60,'Y',100,TO_TIMESTAMP('2014-07-30 10:11:37','YYYY-MM-DD HH24:MI:SS'),100,0,'N',0,2177,12,TO_TIMESTAMP('2014-07-30 10:11:37','YYYY-MM-DD HH24:MI:SS')) +; + +SELECT register_migration_script('201407301015_IDEMPIERE-2108.sql') FROM dual +; + diff --git a/org.adempiere.base.process/src/org/compiere/process/InvoiceGenerate.java b/org.adempiere.base.process/src/org/compiere/process/InvoiceGenerate.java index f2b7a7f38b..f04a99e145 100644 --- a/org.adempiere.base.process/src/org/compiere/process/InvoiceGenerate.java +++ b/org.adempiere.base.process/src/org/compiere/process/InvoiceGenerate.java @@ -19,7 +19,10 @@ package org.compiere.process; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Savepoint; import java.sql.Timestamp; +import java.text.DecimalFormat; import java.util.logging.Level; import org.adempiere.exceptions.AdempiereException; @@ -43,6 +46,7 @@ import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Language; import org.compiere.util.Msg; +import org.compiere.util.Trx; /** * Generate Invoices @@ -77,7 +81,13 @@ public class InvoiceGenerate extends SvrProcess private int m_line = 0; /** Business Partner */ private MBPartner m_bp = null; - + /** Minimum Amount to Invoice */ + private BigDecimal p_MinimumAmt = null; + /** Minimum Amount to Invoice according to Invoice Schedule */ + private BigDecimal p_MinimumAmtInvSched = null; + /** Per Invoice Savepoint */ + private Savepoint m_savepoint = null; + /** * Prepare - e.g., get Parameters. */ @@ -103,6 +113,8 @@ public class InvoiceGenerate extends SvrProcess p_ConsolidateDocument = "Y".equals(para[i].getParameter()); else if (name.equals("DocAction")) p_docAction = (String)para[i].getParameter(); + else if (name.equals("MinimumAmt")) + p_MinimumAmt = para[i].getParameterAsBigDecimal(); else log.log(Level.SEVERE, "Unknown Parameter: " + name); } @@ -198,6 +210,7 @@ public class InvoiceGenerate extends SvrProcess rs = pstmt.executeQuery (); while (rs.next ()) { + p_MinimumAmtInvSched = null; MOrder order = new MOrder (getCtx(), rs, get_TrxName()); StringBuilder msgsup = new StringBuilder(Msg.getMsg(getCtx(), "Processing")).append(" ").append(order.getDocumentInfo()); statusUpdate(msgsup.toString()); @@ -223,10 +236,13 @@ public class InvoiceGenerate extends SvrProcess else { MInvoiceSchedule is = MInvoiceSchedule.get(getCtx(), m_bp.getC_InvoiceSchedule_ID(), get_TrxName()); - if (is.canInvoice(order.getDateOrdered(), order.getGrandTotal())) + if (is.canInvoice(order.getDateOrdered())) { + if (is.isAmount() && is.getAmt() != null) + p_MinimumAmtInvSched = is.getAmt(); doInvoice = true; - else + } else { continue; + } } } // Schedule @@ -352,6 +368,13 @@ public class InvoiceGenerate extends SvrProcess { if (m_invoice == null) { + try { + if (m_savepoint != null) + Trx.get(get_TrxName(), false).releaseSavepoint(m_savepoint); + m_savepoint = Trx.get(get_TrxName(), false).setSavepoint(null); + } catch (SQLException e) { + throw new AdempiereException(e); + } m_invoice = new MInvoice (order, 0, p_DateInvoiced); if (!m_invoice.save()) throw new IllegalStateException("Could not create Invoice (o)"); @@ -377,6 +400,13 @@ public class InvoiceGenerate extends SvrProcess { if (m_invoice == null) { + try { + if (m_savepoint != null) + Trx.get(get_TrxName(), false).releaseSavepoint(m_savepoint); + m_savepoint = Trx.get(get_TrxName(), false).setSavepoint(null); + } catch (SQLException e) { + throw new AdempiereException(e); + } m_invoice = new MInvoice (order, 0, p_DateInvoiced); if (!m_invoice.save()) throw new IllegalStateException("Could not create Invoice (s)"); @@ -485,19 +515,42 @@ public class InvoiceGenerate extends SvrProcess m_invoice.saveEx(); } } - - if (!m_invoice.processIt(p_docAction)) - { - log.warning("completeInvoice - failed: " + m_invoice); - addBufferLog(0, null, null,"completeInvoice - failed: " + m_invoice,m_invoice.get_Table_ID(),m_invoice.getC_Invoice_ID()); // Elaine 2008/11/25 - throw new IllegalStateException("Invoice Process Failed: " + m_invoice + " - " + m_invoice.getProcessMsg()); - - } - m_invoice.saveEx(); - String message = Msg.parseTranslation(getCtx(), "@InvoiceProcessed@ " + m_invoice.getDocumentNo()); - addBufferLog(m_invoice.getC_Invoice_ID(), m_invoice.getDateInvoiced(), null, message, m_invoice.get_Table_ID(), m_invoice.getC_Invoice_ID()); - m_created++; + if ( (p_MinimumAmt != null && p_MinimumAmt.signum() != 0 + && m_invoice.getGrandTotal().compareTo(p_MinimumAmt) < 0) + || (p_MinimumAmtInvSched != null + && m_invoice.getGrandTotal().compareTo(p_MinimumAmtInvSched) < 0)) { + + // minimum amount not reached + DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Amount); + String amt = format.format(m_invoice.getGrandTotal().doubleValue()); + String message = Msg.parseTranslation(getCtx(), "@NotInvoicedAmt@ " + amt + " - " + m_invoice.getC_BPartner().getName()); + addLog(message); + if (m_savepoint != null) { + try { + Trx.get(get_TrxName(), false).rollback(m_savepoint); + } catch (SQLException e) { + throw new AdempiereException(e); + } + } else { + throw new AdempiereException("No savepoint"); + } + + } else { + + if (!m_invoice.processIt(p_docAction)) + { + log.warning("completeInvoice - failed: " + m_invoice); + addBufferLog(0, null, null,"completeInvoice - failed: " + m_invoice,m_invoice.get_Table_ID(),m_invoice.getC_Invoice_ID()); // Elaine 2008/11/25 + throw new IllegalStateException("Invoice Process Failed: " + m_invoice + " - " + m_invoice.getProcessMsg()); + + } + m_invoice.saveEx(); + + String message = Msg.parseTranslation(getCtx(), "@InvoiceProcessed@ " + m_invoice.getDocumentNo()); + addBufferLog(m_invoice.getC_Invoice_ID(), m_invoice.getDateInvoiced(), null, message, m_invoice.get_Table_ID(), m_invoice.getC_Invoice_ID()); + m_created++; + } } m_invoice = null; m_ship = null; diff --git a/org.adempiere.base/src/org/compiere/model/MInvoice.java b/org.adempiere.base/src/org/compiere/model/MInvoice.java index ec73c55afe..3bd6b3a138 100644 --- a/org.adempiere.base/src/org/compiere/model/MInvoice.java +++ b/org.adempiere.base/src/org/compiere/model/MInvoice.java @@ -1046,9 +1046,11 @@ public class MInvoice extends X_C_Invoice implements DocAction // reset shipment line invoiced flag MInvoiceLine[] lines = getLines(false); for (int i = 0; i < lines.length; i++) { - MInOutLine sLine = new MInOutLine(getCtx(), lines[i].getM_InOutLine_ID(), get_TrxName()); - sLine.setIsInvoiced(false); - sLine.saveEx(); + if (lines[i].getM_InOutLine_ID() > 0) { + MInOutLine sLine = new MInOutLine(getCtx(), lines[i].getM_InOutLine_ID(), get_TrxName()); + sLine.setIsInvoiced(false); + sLine.saveEx(); + } } } return true; diff --git a/org.adempiere.base/src/org/compiere/model/MInvoiceSchedule.java b/org.adempiere.base/src/org/compiere/model/MInvoiceSchedule.java index 9b8f251252..ef18cc02c1 100644 --- a/org.adempiere.base/src/org/compiere/model/MInvoiceSchedule.java +++ b/org.adempiere.base/src/org/compiere/model/MInvoiceSchedule.java @@ -91,13 +91,26 @@ public class MInvoiceSchedule extends X_C_InvoiceSchedule * @param orderAmt order amount * @return true if I can send Invoice */ + @Deprecated + // Deprecation note: consider using just canInvoice(Timestamp) + // validating the order amount doesn't make sense as the total must be calculated based on shipments public boolean canInvoice (Timestamp xDate, BigDecimal orderAmt) { // Amount if (isAmount() && getAmt() != null && orderAmt != null && orderAmt.compareTo(getAmt()) >= 0) return true; - + + return canInvoice(xDate); + } // canInvoice + + /** + * Can I send Invoice + * @param xDate date + * @return true if I can send Invoice + */ + public boolean canInvoice (Timestamp xDate) + { // Daily if (INVOICEFREQUENCY_Daily.equals(getInvoiceFrequency())) return true; diff --git a/org.adempiere.base/src/org/compiere/process/ProcessInfo.java b/org.adempiere.base/src/org/compiere/process/ProcessInfo.java index d067270439..c998998c9f 100644 --- a/org.adempiere.base/src/org/compiere/process/ProcessInfo.java +++ b/org.adempiere.base/src/org/compiere/process/ProcessInfo.java @@ -608,9 +608,14 @@ public class ProcessInfo implements Serializable { if (m_logs == null) return null; - int[] ids = new int[m_logs.size()]; - for (int i = 0; i < m_logs.size(); i++) - ids[i] = m_logs.get(i).getP_ID(); + ArrayList idsarray = new ArrayList(); + for (int i = 0; i < m_logs.size(); i++) { + if (m_logs.get(i).getP_ID() > 0) + idsarray.add(m_logs.get(i).getP_ID()); + } + int[] ids = new int[idsarray.size()]; + for (int i = 0; i < idsarray.size(); i++) + ids[i] = idsarray.get(i); return ids; } // getIDs