From 0eb0137c739d075b8d04684b2a85eec0c52a387f Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Sat, 2 Feb 2008 04:49:59 +0000 Subject: [PATCH] [ 1883270 ] Enhance Document No Formatting --- .../adempiere/process/UpdateSequenceNo.java | 76 +++ base/src/org/compiere/model/CalloutInOut.java | 17 +- .../org/compiere/model/CalloutInvoice.java | 21 +- base/src/org/compiere/model/CalloutOrder.java | 23 +- base/src/org/compiere/model/MInOut.java | 2 +- base/src/org/compiere/model/MInventory.java | 2 +- base/src/org/compiere/model/MInvoice.java | 2 +- base/src/org/compiere/model/MJournal.java | 4 +- .../src/org/compiere/model/MJournalBatch.java | 2 +- base/src/org/compiere/model/MMovement.java | 2 +- base/src/org/compiere/model/MOrder.java | 2 +- base/src/org/compiere/model/MPayment.java | 2 +- base/src/org/compiere/model/MRMA.java | 2 +- base/src/org/compiere/model/MRequisition.java | 2 +- base/src/org/compiere/model/MSequence.java | 554 ++++++++++++++---- base/src/org/compiere/model/PO.java | 10 +- base/src/org/compiere/util/DB.java | 34 +- 17 files changed, 600 insertions(+), 157 deletions(-) create mode 100644 base/src/org/adempiere/process/UpdateSequenceNo.java diff --git a/base/src/org/adempiere/process/UpdateSequenceNo.java b/base/src/org/adempiere/process/UpdateSequenceNo.java new file mode 100644 index 0000000000..44b971eec7 --- /dev/null +++ b/base/src/org/adempiere/process/UpdateSequenceNo.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2008 Adempiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.process; + +import java.sql.PreparedStatement; + +import org.compiere.process.ProcessInfoParameter; +import org.compiere.process.SvrProcess; +import org.compiere.util.DB; + +/** + * Insert AD_Sequence records that restart sequence at every year into + * AD_Sequence_No table if the record does not exists + * + * @author Elaine + * + */ +public class UpdateSequenceNo extends SvrProcess { + + private String year; + + @Override + protected void prepare() { + ProcessInfoParameter[] parameters = this.getParameter(); + for (ProcessInfoParameter p : parameters) { + if (p.getParameterName().equals("CalendarYear")) { + year = p.getParameter().toString(); + } + } + } + + @Override + protected String doIt() throws Exception { + + PreparedStatement insertStmt = null; + try { + insertStmt = DB + .prepareStatement( + "INSERT INTO AD_Sequence_No(AD_SEQUENCE_ID, CALENDARYEAR, " + + "AD_CLIENT_ID, AD_ORG_ID, ISACTIVE, CREATED, CREATEDBY, " + + "UPDATED, UPDATEDBY, CURRENTNEXT) " + + "(SELECT AD_Sequence_ID, '" + year + "', " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, " + + "Updated, UpdatedBy, StartNo " + + "FROM AD_Sequence a " + + "WHERE StartNewYear = 'Y' AND NOT EXISTS ( " + + "SELECT AD_Sequence_ID " + + "FROM AD_Sequence_No b " + + "WHERE a.AD_Sequence_ID = b.AD_Sequence_ID " + + "AND CalendarYear = ?)) ", + get_TrxName()); + insertStmt.setString(1, year); + insertStmt.executeUpdate(); + commit(); + + } catch (Exception ex) { + rollback(); + throw ex; + } finally { + DB.close(insertStmt); + } + + return "Sequence No updated successfully"; + } +} diff --git a/base/src/org/compiere/model/CalloutInOut.java b/base/src/org/compiere/model/CalloutInOut.java index cfc6ed14f7..5ad7d92190 100644 --- a/base/src/org/compiere/model/CalloutInOut.java +++ b/base/src/org/compiere/model/CalloutInOut.java @@ -99,7 +99,8 @@ public class CalloutInOut extends CalloutEngine if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) return ""; - String sql = "SELECT d.DocBaseType, d.IsDocNoControlled, s.CurrentNext " + String sql = "SELECT d.DocBaseType, d.IsDocNoControlled, s.CurrentNext, " //1..3 + + "s.AD_Sequence_ID, s.StartNewYear, s.DateColumn " //4..6 + "FROM C_DocType d, AD_Sequence s " + "WHERE C_DocType_ID=?" // 1 + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; @@ -139,7 +140,19 @@ public class CalloutInOut extends CalloutEngine // DocumentNo if (rs.getString("IsDocNoControlled").equals("Y")) - mTab.setValue("DocumentNo", "<" + rs.getString("CurrentNext") + ">"); + { + if ("Y".equals(rs.getString(5))) + { + String dateColumn = rs.getString(6); + int AD_Sequence_ID = rs.getInt(4); + mTab.setValue("DocumentNo", + "<" + + MSequence.getPreliminaryNoByYear(mTab, AD_Sequence_ID, dateColumn, null) + + ">"); + } + else + mTab.setValue("DocumentNo", "<" + rs.getString("CurrentNext") + ">"); + } } rs.close(); pstmt.close(); diff --git a/base/src/org/compiere/model/CalloutInvoice.java b/base/src/org/compiere/model/CalloutInvoice.java index 6f07ef390e..e683e1c7fa 100644 --- a/base/src/org/compiere/model/CalloutInvoice.java +++ b/base/src/org/compiere/model/CalloutInvoice.java @@ -18,7 +18,9 @@ package org.compiere.model; import java.math.*; import java.sql.*; +import java.text.SimpleDateFormat; import java.util.*; +import java.util.Date; import java.util.logging.*; import org.compiere.util.*; @@ -52,8 +54,9 @@ public class CalloutInvoice extends CalloutEngine if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) return ""; - String sql = "SELECT d.HasCharges,'N',d.IsDocNoControlled," - + "s.CurrentNext, d.DocBaseType " + String sql = "SELECT d.HasCharges,'N',d.IsDocNoControlled," // 1..3 + + "s.CurrentNext, d.DocBaseType, " // 4..5 + + "s.StartNewYear, s.DateColumn, s.AD_Sequence_ID " //6..8 + "FROM C_DocType d, AD_Sequence s " + "WHERE C_DocType_ID=?" // 1 + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; @@ -68,7 +71,18 @@ public class CalloutInvoice extends CalloutEngine Env.setContext(ctx, WindowNo, "HasCharges", rs.getString(1)); // DocumentNo if (rs.getString(3).equals("Y")) - mTab.setValue("DocumentNo", "<" + rs.getString(4) + ">"); + { + if ("Y".equals(rs.getString(6))) + { + String dateColumn = rs.getString(7); + mTab.setValue("DocumentNo", + "<" + + MSequence.getPreliminaryNoByYear(mTab, rs.getInt(8), dateColumn, null) + + ">"); + } + else + mTab.setValue("DocumentNo", "<" + rs.getString(4) + ">"); + } // DocBaseType - Set Context String s = rs.getString(5); Env.setContext(ctx, WindowNo, "DocBaseType", s); @@ -89,7 +103,6 @@ public class CalloutInvoice extends CalloutEngine return ""; } // docType - /** * Invoice Header- BPartner. * - M_PriceList_ID (+ Context) diff --git a/base/src/org/compiere/model/CalloutOrder.java b/base/src/org/compiere/model/CalloutOrder.java index fa3675b2c3..072118314f 100644 --- a/base/src/org/compiere/model/CalloutOrder.java +++ b/base/src/org/compiere/model/CalloutOrder.java @@ -18,7 +18,9 @@ package org.compiere.model; import java.math.*; import java.sql.*; +import java.text.SimpleDateFormat; import java.util.*; +import java.util.Date; import java.util.logging.*; import org.compiere.util.*; @@ -65,7 +67,8 @@ public class CalloutOrder extends CalloutEngine String sql = "SELECT d.DocSubTypeSO,d.HasCharges,'N'," // 1..3 + "d.IsDocNoControlled,s.CurrentNext,s.CurrentNextSys," // 4..6 - + "s.AD_Sequence_ID,d.IsSOTrx " // 7..8 + + "s.AD_Sequence_ID,d.IsSOTrx, " // 7..8 + + "s.StartNewYear, s.DateColumn " // 9..10 + "FROM C_DocType d, AD_Sequence s " + "WHERE C_DocType_ID=?" // #1 + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; @@ -80,7 +83,7 @@ public class CalloutOrder extends CalloutEngine pstmt.setInt(1, oldC_DocType_ID.intValue()); ResultSet rs = pstmt.executeQuery(); if (rs.next()) - AD_Sequence_ID = rs.getInt(6); + AD_Sequence_ID = rs.getInt(7); rs.close(); pstmt.close(); } @@ -138,7 +141,20 @@ public class CalloutOrder extends CalloutEngine if (Ini.isPropertyBool(Ini.P_ADEMPIERESYS) && Env.getAD_Client_ID(Env.getCtx()) < 1000000) mTab.setValue("DocumentNo", "<" + rs.getString(6) + ">"); else - mTab.setValue("DocumentNo", "<" + rs.getString(5) + ">"); + { + if ("Y".equals(rs.getString(9))) + { + String dateColumn = rs.getString(10); + mTab.setValue("DocumentNo", + "<" + + MSequence.getPreliminaryNoByYear(mTab, rs.getInt(7), dateColumn, null) + + ">"); + } + else + { + mTab.setValue("DocumentNo", "<" + rs.getString(5) + ">"); + } + } } } rs.close(); @@ -208,7 +224,6 @@ public class CalloutOrder extends CalloutEngine return ""; } // docType - /** * Order Header - BPartner. * - M_PriceList_ID (+ Context) diff --git a/base/src/org/compiere/model/MInOut.java b/base/src/org/compiere/model/MInOut.java index 1a752d1fa8..89d9189c84 100644 --- a/base/src/org/compiere/model/MInOut.java +++ b/base/src/org/compiere/model/MInOut.java @@ -1499,7 +1499,7 @@ public class MInOut extends X_M_InOut implements DocAction setMovementDate(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MInventory.java b/base/src/org/compiere/model/MInventory.java index b09591a25d..5601fcdd4b 100644 --- a/base/src/org/compiere/model/MInventory.java +++ b/base/src/org/compiere/model/MInventory.java @@ -610,7 +610,7 @@ public class MInventory extends X_M_Inventory implements DocAction setMovementDate(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MInvoice.java b/base/src/org/compiere/model/MInvoice.java index 84587d33c1..007336a45a 100644 --- a/base/src/org/compiere/model/MInvoice.java +++ b/base/src/org/compiere/model/MInvoice.java @@ -1887,7 +1887,7 @@ public class MInvoice extends X_C_Invoice implements DocAction setDateInvoiced(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MJournal.java b/base/src/org/compiere/model/MJournal.java index 1826e98380..751c0614e7 100644 --- a/base/src/org/compiere/model/MJournal.java +++ b/base/src/org/compiere/model/MJournal.java @@ -330,7 +330,7 @@ public class MJournal extends X_GL_Journal implements DocAction protected boolean afterSave (boolean newRecord, boolean success) { if (!success) - return success; + return success; return updateBatch(); } // afterSave @@ -567,7 +567,7 @@ public class MJournal extends X_GL_Journal implements DocAction setDateDoc(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MJournalBatch.java b/base/src/org/compiere/model/MJournalBatch.java index 2f3efb7314..491515f7a9 100644 --- a/base/src/org/compiere/model/MJournalBatch.java +++ b/base/src/org/compiere/model/MJournalBatch.java @@ -496,7 +496,7 @@ public class MJournalBatch extends X_GL_JournalBatch implements DocAction setDateDoc(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MMovement.java b/base/src/org/compiere/model/MMovement.java index d7090c77e0..274ccf1688 100644 --- a/base/src/org/compiere/model/MMovement.java +++ b/base/src/org/compiere/model/MMovement.java @@ -549,7 +549,7 @@ public class MMovement extends X_M_Movement implements DocAction setMovementDate(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MOrder.java b/base/src/org/compiere/model/MOrder.java index e8507f3741..1f778c38e0 100644 --- a/base/src/org/compiere/model/MOrder.java +++ b/base/src/org/compiere/model/MOrder.java @@ -1774,7 +1774,7 @@ public class MOrder extends X_C_Order implements DocAction setDateOrdered(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MPayment.java b/base/src/org/compiere/model/MPayment.java index 959ce3c888..b193d2e312 100644 --- a/base/src/org/compiere/model/MPayment.java +++ b/base/src/org/compiere/model/MPayment.java @@ -1672,7 +1672,7 @@ public final class MPayment extends X_C_Payment setDateTrx(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MRMA.java b/base/src/org/compiere/model/MRMA.java index 47ad6b2375..f2496ca439 100644 --- a/base/src/org/compiere/model/MRMA.java +++ b/base/src/org/compiere/model/MRMA.java @@ -422,7 +422,7 @@ public class MRMA extends X_M_RMA implements DocAction } */ if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MRequisition.java b/base/src/org/compiere/model/MRequisition.java index 800d6e4d98..27b1cd6927 100644 --- a/base/src/org/compiere/model/MRequisition.java +++ b/base/src/org/compiere/model/MRequisition.java @@ -355,7 +355,7 @@ public class MRequisition extends X_M_Requisition implements DocAction setDateDoc(new Timestamp (System.currentTimeMillis())); } if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true); + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); if (value != null) setDocumentNo(value); } diff --git a/base/src/org/compiere/model/MSequence.java b/base/src/org/compiere/model/MSequence.java index dce31d5584..540c5cc1c7 100644 --- a/base/src/org/compiere/model/MSequence.java +++ b/base/src/org/compiere/model/MSequence.java @@ -18,7 +18,11 @@ package org.compiere.model; import java.rmi.RemoteException; import java.sql.*; +import java.text.DecimalFormat; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; import java.util.*; +import java.util.Date; import java.util.logging.*; import java.io.*; @@ -27,6 +31,7 @@ import java.net.*; import org.compiere.db.CConnection; import org.compiere.interfaces.Server; import org.compiere.util.*; +import org.postgresql.jdbc2.optional.SimpleDataSource; /** * Sequence Model. @@ -294,33 +299,73 @@ public class MSequence extends X_AD_Sequence cstmt.registerOutParameter(3, Types.INTEGER); cstmt.execute(); retValue = cstmt.getInt(3); - cstmt.close(); - cstmt = null; } catch (Exception e) { s_log.log(Level.SEVERE, e.toString()); } - // Finish - try - { - if (cstmt != null) - cstmt.close(); - } - catch (Exception e) - { + finally + { + DB.close(cstmt); } return retValue; - } // nextID - + } // nextID + + /** + * Get next id by year + * @param conn + * @param AD_Sequence_ID + * @param incrementNo + * @param calendarYear + * @return next id + */ + private static int nextIDByYear(Connection conn, int AD_Sequence_ID, + int incrementNo, String calendarYear) { + if (conn == null || AD_Sequence_ID == 0) + return -3; + // + int retValue = -1; + String sqlUpdate = "{call nextIDByYear(?,?,?,?)}"; + CallableStatement cstmt = null; + try { + cstmt = conn.prepareCall(sqlUpdate, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); + + cstmt.setInt(1, AD_Sequence_ID); + cstmt.setInt(2, incrementNo); + cstmt.setString(3, calendarYear); + cstmt.registerOutParameter(4, Types.INTEGER); + cstmt.execute(); + retValue = cstmt.getInt(4); + } catch (Exception e) { + s_log.log(Level.SEVERE, e.toString()); + } finally { + DB.close(cstmt); + } + return retValue; + } // nextID + + /************************************************************************** + * Get Document No from table + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @return document no or null + */ + public static synchronized String getDocumentNo (int AD_Client_ID, String TableName, String trxName) + { + return getDocumentNo(AD_Client_ID, TableName, trxName, null); + + } /************************************************************************** * Get Document No from table * @param AD_Client_ID client * @param TableName table name - * @param trxName optional Transaction Name + * @param trxName optional Transaction Name + * @param PO * @return document no or null */ - public static synchronized String getDocumentNo (int AD_Client_ID, String TableName, String trxName) + public static synchronized String getDocumentNo (int AD_Client_ID, String TableName, String trxName, PO po) { if (TableName == null || TableName.length() == 0) throw new IllegalArgumentException("TableName missing"); @@ -354,42 +399,93 @@ public class MSequence extends X_AD_Sequence // if (CLogMgt.isLevel(LOGLEVEL)) s_log.log(LOGLEVEL, TableName + " - AdempiereSys=" + adempiereSys + " [" + trxName + "]"); - //begin vpj-cd e-evolution 09/02/2005 PostgreSQL + + PreparedStatement pstmt = null; + ResultSet rs = null; + boolean isStartNewYear = false; + String dateColumn = null; + + if (!adempiereSys) + { + // Get the Start New Year flag + String startNewYearSQL = "SELECT StartNewYear, DateColumn FROM AD_Sequence " + + "WHERE Name = ? AND IsActive = 'Y' AND IsTableID = 'N' AND IsAutoSequence='Y' AND AD_Client_ID = ?"; + try + { + pstmt = DB.prepareStatement(startNewYearSQL, trxName); + pstmt.setString(1, PREFIX_DOCSEQ + TableName); + pstmt.setInt(2, AD_Client_ID); + rs = pstmt.executeQuery(); + if (rs.next()) { + isStartNewYear = "Y".equals(rs.getString(1)); + dateColumn = rs.getString(2); + } + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); + } + finally + { + DB.close(rs, pstmt); + } + } + + String selectSQL = null; if (DB.isOracle() == false) { - selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " - + "FROM AD_Sequence " - + "WHERE Name=?" - //jz fix duplicated nextID + " AND AD_Client_ID IN (0,?)" - + " AND AD_Client_ID = ?" - + " AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " - + "ORDER BY AD_Client_ID DESC " - + " FOR UPDATE OF AD_Sequence "; + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.IncrementNo, s.CurrentNextSys, s.Prefix, s.Suffix, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.Name = ? " + + "AND s.AD_Client_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "ORDER BY s.AD_Client_ID DESC " + + "FOR UPDATE OF AD_Sequence_No"; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name = ? " + + "AND AD_Client_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "ORDER BY AD_Client_ID DESC " + + "FOR UPDATE OF AD_Sequence"; + } USE_PROCEDURE=false; } else { - //String selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " - selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " - //end vpj-cd e-evolution 09/02/2005 PostgreSQL - + "FROM AD_Sequence " - + "WHERE Name=?" - //jz fix duplicated nextID + " AND AD_Client_ID IN (0,?)" - + " AND AD_Client_ID = ?" - + " AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " - + " ORDER BY AD_Client_ID DESC "; + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.IncrementNo, s.CurrentNextSys, Prefix, Suffix, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.Name = ? " + + "AND s.AD_Client_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "ORDER BY s.AD_Client_ID DESC"; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE Name = ? " + + "AND AD_Client_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "ORDER BY AD_Client_ID DESC"; + } USE_PROCEDURE = true; } Connection conn = null; - PreparedStatement pstmt = null; Trx trx = trxName == null ? null : Trx.get(trxName, true); // int AD_Sequence_ID = 0; int incrementNo = 0; int next = -1; String prefix = ""; - String suffix = ""; + String suffix = ""; + String calendarYear = ""; try { if (trx != null) @@ -398,14 +494,33 @@ public class MSequence extends X_AD_Sequence conn = DB.getConnectionID(); // Error if (conn == null) - return null; + return null; + + if (isStartNewYear) + { + if (po != null && dateColumn != null && dateColumn.length() > 0) + { + Date docDate = (Date)po.get_Value(dateColumn); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(docDate); + } + else + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(new Date()); + } + } + // pstmt = conn.prepareStatement(selectSQL, - ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); pstmt.setString(1, PREFIX_DOCSEQ + TableName); - pstmt.setInt(2, AD_Client_ID); + pstmt.setInt(2, AD_Client_ID); + if (isStartNewYear) + pstmt.setString(3, calendarYear); + // - ResultSet rs = pstmt.executeQuery(); + rs = pstmt.executeQuery(); // s_log.fine("AC=" + conn.getAutoCommit() + " -Iso=" + conn.getTransactionIsolation() // + " - Type=" + pstmt.getResultSetType() + " - Concur=" + pstmt.getResultSetConcurrency()); if (rs.next()) @@ -416,24 +531,37 @@ public class MSequence extends X_AD_Sequence incrementNo = rs.getInt(3); if (USE_PROCEDURE) { - next = nextID(conn, AD_Sequence_ID, adempiereSys); + next = isStartNewYear + ? nextIDByYear(conn, AD_Sequence_ID, incrementNo, calendarYear) + : nextID(conn, AD_Sequence_ID, adempiereSys); } else { - PreparedStatement updateSQL; - if (adempiereSys) { - updateSQL = conn - .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); - next = rs.getInt(2); - } else { - updateSQL = conn - .prepareStatement("UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"); - next = rs.getInt(1); + PreparedStatement updateSQL = null; + try + { + if (adempiereSys) { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); + next = rs.getInt(2); + } else { + String sql = isStartNewYear + ? "UPDATE AD_Sequence_No SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ? AND CalendarYear = ?" + : "UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"; + updateSQL = conn + .prepareStatement(sql); + next = rs.getInt(1); + } + updateSQL.setInt(1, incrementNo); + updateSQL.setInt(2, AD_Sequence_ID); + if (isStartNewYear) + updateSQL.setString(3, calendarYear); + updateSQL.executeUpdate(); + } + finally + { + DB.close(updateSQL); } - updateSQL.setInt(1, incrementNo); - updateSQL.setInt(2, AD_Sequence_ID); - updateSQL.executeUpdate(); - updateSQL.close(); } } else @@ -443,37 +571,33 @@ public class MSequence extends X_AD_Sequence next = seq.getNextID(); seq.save(); } - rs.close(); - pstmt.close(); - pstmt = null; // Commit if (trx == null) { conn.commit(); - conn.close(); } - conn = null; } catch (Exception e) { s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); next = -2; - } - // Finish - try - { - if (pstmt != null) - pstmt.close(); - pstmt = null; - if (trx == null && conn != null) - conn.close(); - conn = null; - } - catch (Exception e) - { - s_log.log(Level.SEVERE, "(Table) - finish", e); - pstmt = null; - } + } + finally + { + //Finish + DB.close(rs, pstmt); + try + { + if (trx == null && conn != null) + conn.close(); + conn = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(Table) - finish", e); + } + } + // Error if (next < 0) return null; @@ -481,16 +605,88 @@ public class MSequence extends X_AD_Sequence // create DocumentNo StringBuffer doc = new StringBuffer(); if (prefix != null && prefix.length() > 0) - doc.append(prefix); + doc.append(parseVariable(prefix, po, trxName)); doc.append(next); if (suffix != null && suffix.length() > 0) - doc.append(suffix); + doc.append(parseVariable(suffix, po, trxName)); String documentNo = doc.toString(); s_log.finer (documentNo + " (" + incrementNo + ")" + " - Table=" + TableName + " [" + trx + "]"); return documentNo; } // getDocumentNo + private static String parseVariable(String value, PO po, String trxName) { + if (value == null || value.length() == 0) + return ""; + + String token; + String inStr = new String(value); + StringBuffer outStr = new StringBuffer(); + + int i = inStr.indexOf('@'); + while (i != -1) + { + outStr.append(inStr.substring(0, i)); // up to @ + inStr = inStr.substring(i+1, inStr.length()); // from first @ + + int j = inStr.indexOf('@'); // next @ + if (j < 0) + { + s_log.log(Level.SEVERE, "No second tag: " + inStr); + return ""; // no second tag + } + + token = inStr.substring(0, j); + + //format string + String format = ""; + int f = token.indexOf('<'); + if (f > 0 && token.endsWith(">")) { + format = token.substring(f+1, token.length()-1); + token = token.substring(0, f); + } + + if (token.startsWith("#") || token.startsWith("$")) { + //take from context + Properties ctx = po != null ? po.getCtx() : Env.getCtx(); + String v = Env.getContext(ctx, token); + if (v != null && v.length() > 0) + outStr.append(v); + } else if (po != null) { + //take from po + Object v = po.get_Value(token); + if (v != null) { + if (format != null && format.length() > 0) { + if (v instanceof Integer && token.endsWith("_ID")) { + int tblIndex = format.indexOf("."); + String table = tblIndex > 0 ? format.substring(0, tblIndex) : token.substring(0, token.length() - 3); + String column = tblIndex > 0 ? format.substring(tblIndex + 1) : format; + outStr.append(DB.getSQLValueString(trxName, + "select " + column + " from " + table + " where " + table + "_id = ?", (Integer)v)); + } else if (v instanceof Date) { + SimpleDateFormat df = new SimpleDateFormat(format); + outStr.append(df.format((Date)v)); + } else if (v instanceof Number) { + DecimalFormat df = new DecimalFormat(format); + outStr.append(df.format(((Number)v).doubleValue())); + } else { + MessageFormat mf = new MessageFormat(format); + outStr.append(mf.format(v)); + } + } else { + outStr.append(v.toString()); + } + } + } + + inStr = inStr.substring(j+1, inStr.length()); // from second @ + i = inStr.indexOf('@'); + } + outStr.append(inStr); // add the rest of the string + + return outStr.toString(); + } + /** * Get Document No based on Document Type * @param C_DocType_ID document type @@ -503,14 +699,27 @@ public class MSequence extends X_AD_Sequence return getDocumentNo (C_DocType_ID, trxName, false); } // getDocumentNo + /** + * Get Document No based on Document Type + * @param C_DocType_ID document type + * @param trxName optional Transaction Name + * @param definite asking for a definitive or temporary sequence + * @return document no or null + */ + public static synchronized String getDocumentNo (int C_DocType_ID, String trxName, boolean definite) + { + return getDocumentNo(C_DocType_ID, trxName, definite, null); + } + /** * Get Document No based on Document Type * @param C_DocType_ID document type * @param trxName optional Transaction Name - * @param definite asking for a definitive or temporary sequence + * @param definite asking for a definitive or temporary sequence + * @param po * @return document no or null */ - public static synchronized String getDocumentNo (int C_DocType_ID, String trxName, boolean definite) + public static synchronized String getDocumentNo (int C_DocType_ID, String trxName, boolean definite, PO po) { if (C_DocType_ID == 0) { @@ -565,35 +774,84 @@ public class MSequence extends X_AD_Sequence boolean adempiereSys = Ini.isPropertyBool(Ini.P_ADEMPIERESYS); if (CLogMgt.isLevel(LOGLEVEL)) s_log.log(LOGLEVEL, "DocType_ID=" + C_DocType_ID + " [" + trxName + "]"); - //begin vpj-cd e-evolution 09/02/2005 PostgreSQL + + PreparedStatement pstmt = null; + ResultSet rs = null; + boolean isStartNewYear = false; + String dateColumn = null; + + if (!adempiereSys) + { + // Get the Start New Year & Sequence Type + String startNewYearSQL = "SELECT StartNewYear, DateColumn FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? AND IsActive = 'Y' AND IsTableID = 'N' AND IsAutoSequence='Y'"; + try { + pstmt = DB.prepareStatement(startNewYearSQL, trxName); + pstmt.setInt(1, definite ? dt.getDefiniteSequence_ID() : dt + .getDocNoSequence_ID()); + rs = pstmt.executeQuery(); + if (rs.next()) { + isStartNewYear = "Y".equals(rs.getString(1)); + dateColumn = rs.getString(2); + } + } catch (Exception e) { + s_log.log(Level.SEVERE, "(Table) [" + trxName + "]", e); + } + finally + { + DB.close(rs, pstmt); + } + } + String selectSQL = null; if (DB.isOracle() == false) { - selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " - + "FROM AD_Sequence " - + "WHERE AD_Sequence_ID=?" - + " AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " - + " FOR UPDATE OF AD_Sequence "; + if (isStartNewYear) + { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, s.Prefix, s.Suffix, s.AD_Client_ID, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.AD_Sequence_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' " + + "FOR UPDATE OF AD_Sequence_No"; + } + else + { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' " + + "FOR UPDATE OF AD_Sequence"; + } USE_PROCEDURE=false; } else { - selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " - //end vpj-cd e-evolution 09/02/2005 PostgreSQL - + "FROM AD_Sequence " - + "WHERE AD_Sequence_ID=?" - + " AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' "; + if (isStartNewYear) { + selectSQL = "SELECT y.CurrentNext, s.CurrentNextSys, s.IncrementNo, s.Prefix, s.Suffix, s.AD_Client_ID, s.AD_Sequence_ID " + + "FROM AD_Sequence_No y, AD_Sequence s " + + "WHERE y.AD_Sequence_ID = s.AD_Sequence_ID " + + "AND s.AD_Sequence_ID = ? " + + "AND y.CalendarYear = ? " + + "AND s.IsActive='Y' AND s.IsTableID='N' AND s.IsAutoSequence='Y' "; + } else { + selectSQL = "SELECT CurrentNext, CurrentNextSys, IncrementNo, Prefix, Suffix, AD_Client_ID, AD_Sequence_ID " + + "FROM AD_Sequence " + + "WHERE AD_Sequence_ID = ? " + + "AND IsActive='Y' AND IsTableID='N' AND IsAutoSequence='Y' "; + } USE_PROCEDURE = true; } Connection conn = null; - PreparedStatement pstmt = null; Trx trx = trxName == null ? null : Trx.get(trxName, true); // int AD_Sequence_ID = 0; int incrementNo = 0; int next = -1; String prefix = ""; - String suffix = ""; + String suffix = ""; + String calendarYear = ""; try { if (trx != null) @@ -603,16 +861,33 @@ public class MSequence extends X_AD_Sequence // Error if (conn == null) return null; - // + + if (isStartNewYear) + { + if (po != null && dateColumn != null && dateColumn.length() > 0) + { + Date docDate = (Date)po.get_Value(dateColumn); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(docDate); + } + else + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + calendarYear = sdf.format(new Date()); + } + } + pstmt = conn.prepareStatement(selectSQL, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); if (definite) pstmt.setInt(1, dt.getDefiniteSequence_ID()); else pstmt.setInt(1, dt.getDocNoSequence_ID()); + if (isStartNewYear) + pstmt.setString(2, calendarYear); // - ResultSet rs = pstmt.executeQuery(); + rs = pstmt.executeQuery(); // s_log.fine("AC=" + conn.getAutoCommit() + " -Iso=" + conn.getTransactionIsolation() // + " - Type=" + pstmt.getResultSetType() + " - Concur=" + pstmt.getResultSetConcurrency()); if (rs.next()) @@ -627,24 +902,36 @@ public class MSequence extends X_AD_Sequence if (USE_PROCEDURE) { - next = nextID(conn, AD_Sequence_ID, adempiereSys); + next = isStartNewYear + ? nextIDByYear(conn, AD_Sequence_ID, incrementNo, calendarYear) + : nextID(conn, AD_Sequence_ID, adempiereSys); } else { - PreparedStatement updateSQL; - if (adempiereSys) { - updateSQL = conn - .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); - next = rs.getInt(2); - } else { - updateSQL = conn - .prepareStatement("UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"); - next = rs.getInt(1); + PreparedStatement updateSQL = null; + try + { + if (adempiereSys) { + updateSQL = conn + .prepareStatement("UPDATE AD_Sequence SET CurrentNextSys = CurrentNextSys + ? WHERE AD_Sequence_ID = ?"); + next = rs.getInt(2); + } else { + String sql = isStartNewYear + ? "UPDATE AD_Sequence_No SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ? AND CalendarYear = ?" + : "UPDATE AD_Sequence SET CurrentNext = CurrentNext + ? WHERE AD_Sequence_ID = ?"; + updateSQL = conn.prepareStatement(sql); + next = rs.getInt(1); + } + updateSQL.setInt(1, incrementNo); + updateSQL.setInt(2, AD_Sequence_ID); + if (isStartNewYear) + updateSQL.setString(3, calendarYear); + updateSQL.executeUpdate(); + } + finally + { + DB.close(updateSQL); } - updateSQL.setInt(1, incrementNo); - updateSQL.setInt(2, AD_Sequence_ID); - updateSQL.executeUpdate(); - updateSQL.close(); } } else @@ -652,36 +939,31 @@ public class MSequence extends X_AD_Sequence s_log.warning ("(DocType)- no record found - " + dt); next = -2; } - rs.close(); - pstmt.close(); - pstmt = null; // Commit if (trx == null) { conn.commit(); - conn.close(); } - conn = null; } catch (Exception e) { s_log.log(Level.SEVERE, "(DocType) [" + trxName + "]", e); next = -2; - } - // Finish - try + } + finally { - if (pstmt != null) - pstmt.close(); - pstmt = null; - if (trx == null && conn != null) - conn.close(); - conn = null; - } - catch (Exception e) - { - s_log.log(Level.SEVERE, "(DocType) - finish", e); - pstmt = null; + // Finish + try + { + DB.close(rs, pstmt); + if (trx == null && conn != null) + conn.close(); + conn = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "(DocType) - finish", e); + } } // Error if (next < 0) @@ -690,10 +972,10 @@ public class MSequence extends X_AD_Sequence // create DocumentNo StringBuffer doc = new StringBuffer(); if (prefix != null && prefix.length() > 0) - doc.append(prefix); + doc.append(parseVariable(prefix, po, trxName)); doc.append(next); if (suffix != null && suffix.length() > 0) - doc.append(suffix); + doc.append(parseVariable(suffix, po, trxName)); String documentNo = doc.toString(); s_log.finer (documentNo + " (" + incrementNo + ")" + " - C_DocType_ID=" + C_DocType_ID + " [" + trx + "]"); @@ -1394,5 +1676,23 @@ public class MSequence extends X_AD_Sequence // don't log selects or insert/update for exception tables (i.e. AD_Issue, AD_ChangeLog) return false; } + + /** + * Get preliminary document no by year + * @param tab + * @param AD_Sequence_ID + * @param dateColumn + * @return Preliminary document no + */ + public static String getPreliminaryNoByYear(GridTab tab, int AD_Sequence_ID, String dateColumn, String trxName) { + Date d = (Date)tab.getValue(dateColumn); + if (d == null) + d = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); + String calendarYear = sdf.format(d); + String sql = "select CurrentNext From AD_Sequence_No Where AD_Sequence_ID = ? and CalendarYear = ?"; + + return DB.getSQLValueString(trxName, sql, AD_Sequence_ID, calendarYear); + } } // MSequence \ No newline at end of file diff --git a/base/src/org/compiere/model/PO.java b/base/src/org/compiere/model/PO.java index 0ec966a2ca..8d5a8343c5 100644 --- a/base/src/org/compiere/model/PO.java +++ b/base/src/org/compiere/model/PO.java @@ -2134,9 +2134,9 @@ public abstract class PO if (index == -1) index = p_info.getColumnIndex("C_DocType_ID"); if (index != -1) // get based on Doc Type (might return null) - value = DB.getDocumentNo(get_ValueAsInt(index), m_trxName, false); + value = DB.getDocumentNo(get_ValueAsInt(index), m_trxName, false, this); if (value == null) // not overwritten by DocType and not manually entered - value = DB.getDocumentNo(AD_Client_ID, p_info.getTableName(), m_trxName); + value = DB.getDocumentNo(AD_Client_ID, p_info.getTableName(), m_trxName, this); } else log.warning("DocumentNo updated: " + m_oldValues[i] + " -> " + value); @@ -2291,9 +2291,9 @@ public abstract class PO if (dt == -1) dt = p_info.getColumnIndex("C_DocType_ID"); if (dt != -1) // get based on Doc Type (might return null) - value = DB.getDocumentNo(get_ValueAsInt(dt), m_trxName, false); + value = DB.getDocumentNo(get_ValueAsInt(dt), m_trxName, false, this); if (value == null) // not overwritten by DocType and not manually entered - value = DB.getDocumentNo(getAD_Client_ID(), p_info.getTableName(), m_trxName); + value = DB.getDocumentNo(getAD_Client_ID(), p_info.getTableName(), m_trxName, this); set_ValueNoCheck(columnName, value); } } @@ -2305,7 +2305,7 @@ public abstract class PO String value = (String)get_Value(index); if (value == null || value.length() == 0) { - value = DB.getDocumentNo (getAD_Client_ID(), p_info.getTableName(), m_trxName); + value = DB.getDocumentNo (getAD_Client_ID(), p_info.getTableName(), m_trxName, this); set_ValueNoCheck(columnName, value); } } diff --git a/base/src/org/compiere/util/DB.java b/base/src/org/compiere/util/DB.java index 6171c44f61..10fd3f995d 100644 --- a/base/src/org/compiere/util/DB.java +++ b/base/src/org/compiere/util/DB.java @@ -48,6 +48,7 @@ import org.compiere.model.MLanguage; import org.compiere.model.MRole; import org.compiere.model.MSequence; import org.compiere.model.MSystem; +import org.compiere.model.PO; import org.compiere.process.SequenceCheck; @@ -1466,7 +1467,7 @@ public final class DB params.toArray(arr); return getSQLValueTS(trxName, sql, arr); } - + /** * Get Array of Key Name Pairs * @param sql select with id / name as first / second column @@ -1629,9 +1630,21 @@ public final class DB * @param definite asking for a definitive or temporary sequence * @return document no or null */ - public static String getDocumentNo(int C_DocType_ID, String trxName, boolean definite) + public static String getDocumentNo(int C_DocType_ID, String trxName, boolean definite) { + return getDocumentNo(C_DocType_ID, trxName, definite, null); + } + + /** + * Get Document No based on Document Type + * @param C_DocType_ID document type + * @param trxName optional Transaction Name + * @param definite asking for a definitive or temporary sequence + * @param PO + * @return document no or null + */ + public static String getDocumentNo(int C_DocType_ID, String trxName, boolean definite, PO po) { - return MSequence.getDocumentNo (C_DocType_ID, trxName, definite); + return MSequence.getDocumentNo (C_DocType_ID, trxName, definite, po); } // getDocumentNo /** @@ -1643,7 +1656,20 @@ public final class DB */ public static String getDocumentNo (int AD_Client_ID, String TableName, String trxName) { - String dn = MSequence.getDocumentNo (AD_Client_ID, TableName, trxName); + return getDocumentNo(AD_Client_ID, TableName, trxName, null); + } + + /** + * Get Document No from table + * @param AD_Client_ID client + * @param TableName table name + * @param trxName optional Transaction Name + * @param po + * @return document no or null + */ + public static String getDocumentNo (int AD_Client_ID, String TableName, String trxName, PO po) + { + String dn = MSequence.getDocumentNo (AD_Client_ID, TableName, trxName, po); if (dn == null) throw new DBException ("No DocumentNo"); return dn;