IDEMPIERE-5624 Implement export data as SQL insert statement (#1721)
This commit is contained in:
parent
efe0e14e57
commit
b188775e9a
|
@ -0,0 +1,14 @@
|
|||
-- IDEMPIERE-5624 Implement export data as SQL insert statement
|
||||
SELECT register_migration_script('202303111206_IDEMPIERE-5624.sql') FROM dual;
|
||||
|
||||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Mar 11, 2023, 12:06:48 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,MsgTip,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','zip - SQL zip file','Zip archive of Oracle and PostgreSQL Insert SQL scripts',0,0,'Y',TO_TIMESTAMP('2023-03-11 12:06:46','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-03-11 12:06:46','YYYY-MM-DD HH24:MI:SS'),100,200825,'FileSQLInsertZip','D','9308f542-5ab1-4462-90a3-c0d70b2eb009')
|
||||
;
|
||||
|
||||
-- Mar 11, 2023, 12:11:29 PM MYT
|
||||
UPDATE AD_Message SET MsgText='zip - SQL Insert scripts zip archive', MsgTip=NULL,Updated=TO_TIMESTAMP('2023-03-11 12:11:29','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200825
|
||||
;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
-- IDEMPIERE-5624 Implement export data as SQL insert statement
|
||||
SELECT register_migration_script('202303111206_IDEMPIERE-5624.sql') FROM dual;
|
||||
|
||||
-- Mar 11, 2023, 12:06:48 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,MsgTip,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','zip - SQL zip file','Zip archive of Oracle and PostgreSQL Insert SQL scripts',0,0,'Y',TO_TIMESTAMP('2023-03-11 12:06:46','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-03-11 12:06:46','YYYY-MM-DD HH24:MI:SS'),100,200825,'FileSQLInsertZip','D','9308f542-5ab1-4462-90a3-c0d70b2eb009')
|
||||
;
|
||||
|
||||
-- Mar 11, 2023, 12:11:29 PM MYT
|
||||
UPDATE AD_Message SET MsgText='zip - SQL Insert scripts zip archive', MsgTip=NULL,Updated=TO_TIMESTAMP('2023-03-11 12:11:29','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200825
|
||||
;
|
||||
|
|
@ -119,4 +119,13 @@
|
|||
priority="0">
|
||||
</exporter>
|
||||
</extension>
|
||||
<extension
|
||||
id="org.adempiere.impexp.GridTabSQLInsertExporter"
|
||||
name="Export data as SQL insert statement"
|
||||
point="org.adempiere.base.IGridTabExporter">
|
||||
<exporter
|
||||
class="org.adempiere.impexp.GridTabSQLInsertExporter"
|
||||
priority="0">
|
||||
</exporter>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -19,9 +19,8 @@ import java.util.List;
|
|||
import org.compiere.model.GridTab;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface to export data from {@link GridTab}
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public interface IGridTabExporter {
|
||||
|
||||
|
@ -31,21 +30,22 @@ public interface IGridTabExporter {
|
|||
* @param childs
|
||||
* @param isCurrentRowOnly
|
||||
* @param file
|
||||
* @param indxDetailSelected index of selected child tab
|
||||
*/
|
||||
public void export(GridTab gridTab, List<GridTab> childs, boolean isCurrentRowOnly, File file, int indxDetailSelected);
|
||||
|
||||
/**
|
||||
* @return file extension
|
||||
* @return file extension (csv, zip, ect)
|
||||
*/
|
||||
public String getFileExtension();
|
||||
|
||||
/**
|
||||
* @return description for file extension
|
||||
* @return label for file extension
|
||||
*/
|
||||
public String getFileExtensionLabel();
|
||||
|
||||
/**
|
||||
* @return mime type
|
||||
* @return mime content type
|
||||
*/
|
||||
public String getContentType();
|
||||
|
||||
|
@ -55,9 +55,31 @@ public interface IGridTabExporter {
|
|||
public String getSuggestedFileName(GridTab gridTab);
|
||||
|
||||
/**
|
||||
* Check a tab (detail tab) is support to export in this exporter
|
||||
* @param gridTab
|
||||
* @return
|
||||
* Check if exported support the export of a child tab
|
||||
* @param childTab
|
||||
* @return true if export is supported, false otherwise
|
||||
*/
|
||||
public boolean isExportableTab (GridTab gridTab);
|
||||
public boolean isExportableTab (GridTab childTab);
|
||||
|
||||
/**
|
||||
* @return true if exporter is available to role with advanced access only
|
||||
*/
|
||||
default boolean isAdvanced() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if export of child tabs is supported only when current row only is on.
|
||||
*/
|
||||
default boolean isExportChildTabsForCurrentRowOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum deep of child tab supported by the exporter
|
||||
* @return > 0 for maximum level of deep, <= 0 for unlimited level of deep
|
||||
*/
|
||||
default int maxDeepOfChildTab() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
**********************************************************************/
|
||||
package org.adempiere.impexp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.adempiere.base.IGridTabExporter;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.db.Database;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
|
||||
/**
|
||||
* Export data as SQL insert statement
|
||||
* @author hengsin
|
||||
*/
|
||||
public class GridTabSQLInsertExporter implements IGridTabExporter {
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public GridTabSQLInsertExporter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export(GridTab gridTab, List<GridTab> childs, boolean isCurrentRowOnly, File file,
|
||||
int indxDetailSelected) {
|
||||
try (FileOutputStream fos = new FileOutputStream (file); ZipOutputStream zos = new ZipOutputStream(fos);){
|
||||
// create directory "oracle"
|
||||
ZipEntry directoryEntry = new ZipEntry("oracle/");
|
||||
zos.putNextEntry(directoryEntry);
|
||||
zos.closeEntry();
|
||||
|
||||
// create directory "postgresql"
|
||||
directoryEntry = new ZipEntry("postgresql/");
|
||||
zos.putNextEntry(directoryEntry);
|
||||
zos.closeEntry();
|
||||
|
||||
//export header tab
|
||||
MTable table = MTable.get(gridTab.getAD_Table_ID());
|
||||
List<String> oracles = new ArrayList<>();
|
||||
List<String> pgs = new ArrayList<>();
|
||||
if (isCurrentRowOnly) {
|
||||
PO po = getPO(gridTab, table, gridTab.getCurrentRow());
|
||||
if (po != null)
|
||||
addSQLInsert(po, oracles, pgs);
|
||||
} else {
|
||||
for(int i = 0; i < gridTab.getRowCount(); i++) {
|
||||
PO po = getPO(gridTab, table, i);
|
||||
if (po != null)
|
||||
addSQLInsert(po, oracles, pgs);
|
||||
}
|
||||
}
|
||||
|
||||
ZipEntry fileEntry = new ZipEntry("oracle/" + table.getTableName() + ".sql");
|
||||
zos.putNextEntry(fileEntry);
|
||||
for(String oracle : oracles)
|
||||
zos.write((oracle+"\n;\n").getBytes());
|
||||
zos.closeEntry();
|
||||
|
||||
fileEntry = new ZipEntry("postgresql/" + table.getTableName() + ".sql");
|
||||
zos.putNextEntry(fileEntry);
|
||||
for(String pg : pgs)
|
||||
zos.write((pg+"\n;\n").getBytes());
|
||||
zos.closeEntry();
|
||||
|
||||
//export child tabs
|
||||
if (isCurrentRowOnly) {
|
||||
for(GridTab childTab : childs) {
|
||||
if (!childTab.isLoadComplete()){
|
||||
childTab.initTab(false);
|
||||
childTab.query(false, 0, 0);
|
||||
}
|
||||
if (childTab.getRowCount() == 0)
|
||||
continue;
|
||||
table = MTable.get(childTab.getAD_Table_ID());
|
||||
oracles = new ArrayList<>();
|
||||
pgs = new ArrayList<>();
|
||||
for(int i = 0; i < childTab.getRowCount(); i++) {
|
||||
PO po = getPO(childTab, table, i);
|
||||
if (po != null)
|
||||
addSQLInsert(po, oracles, pgs);
|
||||
}
|
||||
fileEntry = new ZipEntry("oracle/" + table.getTableName() + ".sql");
|
||||
zos.putNextEntry(fileEntry);
|
||||
for(String oracle : oracles)
|
||||
zos.write((oracle+"\n;\n").getBytes());
|
||||
zos.closeEntry();
|
||||
|
||||
fileEntry = new ZipEntry("postgresql/" + table.getTableName() + ".sql");
|
||||
zos.putNextEntry(fileEntry);
|
||||
for(String pg : pgs)
|
||||
zos.write((pg+"\n;\n").getBytes());
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new AdempiereException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create SQL insert script for po
|
||||
* @param po
|
||||
* @param oracles list to add oracle insert script
|
||||
* @param pgs list to add postgresql insert script
|
||||
*/
|
||||
protected void addSQLInsert(PO po, List<String> oracles, List<String> pgs) {
|
||||
String sql = po.toInsertSQL();
|
||||
String oracle = Database.getDatabase(Database.DB_ORACLE).convertStatement(sql);
|
||||
String pg = Database.getDatabase(Database.DB_POSTGRESQL).convertStatement(sql);
|
||||
oracles.add(oracle);
|
||||
pgs.add(pg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load PO by record ID or UUID
|
||||
* @param gridTab
|
||||
* @param table
|
||||
* @param row
|
||||
* @return PO
|
||||
*/
|
||||
protected PO getPO(GridTab gridTab, MTable table, int row) {
|
||||
int recordId = gridTab.getKeyID(row);
|
||||
if (recordId >= 0) {
|
||||
return table.getPO(gridTab.getKeyID(row), null);
|
||||
} else {
|
||||
UUID uuid = gridTab.getTableModel().getUUID(row);
|
||||
if (uuid != null)
|
||||
return table.getPOByUU(uuid.toString(), null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileExtension() {
|
||||
return "zip";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileExtensionLabel() {
|
||||
return Msg.getMsg(Env.getCtx(), "FileSQLInsertZip");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return "application/zip";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuggestedFileName(GridTab gridTab) {
|
||||
return gridTab.getName() + "." + getFileExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExportableTab(GridTab gridTab) {
|
||||
if (!gridTab.isDisplayed())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdvanced() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExportChildTabsForCurrentRowOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxDeepOfChildTab() {
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -1579,9 +1579,6 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
|||
return true;
|
||||
|
||||
// ** dynamic content **
|
||||
String parsed = Env.parseContext (m_vo.ctx, 0, dl, false, false).trim();
|
||||
if (parsed.length() == 0)
|
||||
return true;
|
||||
boolean retValue = Evaluator.evaluateLogic(this, dl);
|
||||
if (log.isLoggable(Level.CONFIG)) log.config(m_vo.Name + " (" + dl + ") => " + retValue);
|
||||
return retValue;
|
||||
|
|
|
@ -3177,7 +3177,6 @@ public abstract class PO
|
|||
} // saveNew
|
||||
|
||||
private boolean doInsert(boolean withValues) {
|
||||
int index;
|
||||
lobReset();
|
||||
|
||||
// Change Log
|
||||
|
@ -3190,7 +3189,92 @@ public abstract class PO
|
|||
List<Object> params = new ArrayList<Object>();
|
||||
|
||||
// SQL
|
||||
StringBuilder sqlInsert = new StringBuilder("INSERT INTO ");
|
||||
StringBuilder sqlInsert = new StringBuilder();
|
||||
AD_ChangeLog_ID = buildInsertSQL(sqlInsert, withValues, params, session, AD_ChangeLog_ID, false);
|
||||
//
|
||||
int no = withValues ? DB.executeUpdate(sqlInsert.toString(), m_trxName)
|
||||
: DB.executeUpdate(sqlInsert.toString(), params.toArray(), false, m_trxName);
|
||||
boolean ok = no == 1;
|
||||
if (ok)
|
||||
{
|
||||
if (withValues && m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID") && !Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
int id = DB.getSQLValueEx(get_TrxName(), "SELECT " + m_KeyColumns[0] + " FROM "
|
||||
+ p_info.getTableName() + " WHERE " + getUUIDColumnName() + "=?", get_ValueAsString(getUUIDColumnName()));
|
||||
m_IDs[0] = Integer.valueOf(id);
|
||||
set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]);
|
||||
|
||||
int ki = p_info.getColumnIndex(m_KeyColumns[0]);
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(ki) // logging allowed
|
||||
&& !p_info.isEncrypted(ki) // not encrypted
|
||||
&& !p_info.isVirtualColumn(ki) // no virtual column
|
||||
&& !"Password".equals(p_info.getColumnName(ki))
|
||||
&& (insertLog.equalsIgnoreCase("Y")
|
||||
|| (insertLog.equalsIgnoreCase("K") && p_info.getColumn(ki).IsKey))
|
||||
)
|
||||
{
|
||||
// change log on new
|
||||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName, AD_ChangeLog_ID,
|
||||
p_info.getAD_Table_ID(), p_info.getColumn(ki).AD_Column_ID,
|
||||
get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, id, MChangeLog.EVENTCHANGELOG_Insert);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
}
|
||||
ok = lobSave();
|
||||
if (!load(m_trxName)) // re-read Info
|
||||
{
|
||||
if (m_trxName == null)
|
||||
log.log(Level.SEVERE, "reloading");
|
||||
else
|
||||
log.log(Level.SEVERE, "[" + m_trxName + "] - reloading");
|
||||
ok = false;;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = "Not inserted - ";
|
||||
if (CLogMgt.isLevelFiner())
|
||||
msg += sqlInsert.toString();
|
||||
else
|
||||
msg += get_TableName();
|
||||
if (m_trxName == null)
|
||||
log.log(Level.WARNING, msg);
|
||||
else
|
||||
log.log(Level.WARNING, "[" + m_trxName + "]" + msg);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data as insert SQL statement
|
||||
*/
|
||||
public String toInsertSQL()
|
||||
{
|
||||
StringBuilder sqlInsert = new StringBuilder();
|
||||
buildInsertSQL(sqlInsert, true, null, null, 0, true);
|
||||
return sqlInsert.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build insert SQL statement and capture change log
|
||||
* @param sqlInsert
|
||||
* @param withValues true to create statement with column values, false to use parameter binding (i.e with ?)
|
||||
* @param params statement parameters when withValues is false
|
||||
* @param session to capture change log. null when call from toInsertSQL (i.e to build sql only, not for real insert to DB)
|
||||
* @param AD_ChangeLog_ID initial change log id
|
||||
* @param generateScriptOnly true if it is to generate sql script only, false for real DB insert
|
||||
* @return last AD_ChangeLog_ID
|
||||
*/
|
||||
protected int buildInsertSQL(StringBuilder sqlInsert, boolean withValues, List<Object> params, MSession session,
|
||||
int AD_ChangeLog_ID, boolean generateScriptOnly) {
|
||||
sqlInsert.append("INSERT INTO ");
|
||||
sqlInsert.append(p_info.getTableName()).append(" (");
|
||||
StringBuilder sqlValues = new StringBuilder(") VALUES (");
|
||||
int size = get_ColumnCount();
|
||||
|
@ -3212,6 +3296,13 @@ public abstract class PO
|
|||
continue;
|
||||
}
|
||||
|
||||
//do not export secure column
|
||||
if (generateScriptOnly)
|
||||
{
|
||||
if (p_info.isEncrypted(i) || p_info.isSecure(i) || "Password".equalsIgnoreCase(p_info.getColumnName(i)))
|
||||
continue;
|
||||
}
|
||||
|
||||
// ** add column **
|
||||
if (doComma)
|
||||
{
|
||||
|
@ -3229,11 +3320,18 @@ public abstract class PO
|
|||
try
|
||||
{
|
||||
if (m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID") && m_KeyColumns[0].equals(p_info.getColumnName(i)) && !Env.isUseCentralizedId(p_info.getTableName()))
|
||||
&& m_KeyColumns[0].endsWith("_ID") && m_KeyColumns[0].equals(p_info.getColumnName(i)) && (generateScriptOnly || !Env.isUseCentralizedId(p_info.getTableName())))
|
||||
{
|
||||
if (generateScriptOnly && get_ID() > 0 && get_ID() <= MTable.MAX_OFFICIAL_ID)
|
||||
{
|
||||
sqlValues.append(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MSequence sequence = MSequence.get(Env.getCtx(), p_info.getTableName(), get_TrxName(), true);
|
||||
sqlValues.append("nextidfunc("+sequence.getAD_Sequence_ID()+",'N')");
|
||||
}
|
||||
}
|
||||
else if (c == Object.class) // may have need to deal with null values differently
|
||||
sqlValues.append (saveNewSpecial (value, i));
|
||||
else if (value == null || value.equals (Null.NULL))
|
||||
|
@ -3379,11 +3477,11 @@ public abstract class PO
|
|||
}
|
||||
}
|
||||
|
||||
if (!withValues || Env.isUseCentralizedId(p_info.getTableName()))
|
||||
if (session != null && (!withValues || Env.isUseCentralizedId(p_info.getTableName())))
|
||||
{
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
if (!generateScriptOnly && session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(i) // logging allowed
|
||||
&& !p_info.isEncrypted(i) // not encrypted
|
||||
|
@ -3410,7 +3508,7 @@ public abstract class PO
|
|||
while (it.hasNext())
|
||||
{
|
||||
String column = (String)it.next();
|
||||
index = p_info.getColumnIndex(column);
|
||||
int index = p_info.getColumnIndex(column);
|
||||
String value = (String)m_custom.get(column);
|
||||
if (value == null)
|
||||
continue;
|
||||
|
@ -3443,65 +3541,7 @@ public abstract class PO
|
|||
}
|
||||
sqlInsert.append(sqlValues)
|
||||
.append(")");
|
||||
//
|
||||
int no = withValues ? DB.executeUpdate(sqlInsert.toString(), m_trxName)
|
||||
: DB.executeUpdate(sqlInsert.toString(), params.toArray(), false, m_trxName);
|
||||
boolean ok = no == 1;
|
||||
if (ok)
|
||||
{
|
||||
if (withValues && m_IDs.length == 1 && p_info.hasKeyColumn()
|
||||
&& m_KeyColumns[0].endsWith("_ID") && !Env.isUseCentralizedId(p_info.getTableName()))
|
||||
{
|
||||
int id = DB.getSQLValueEx(get_TrxName(), "SELECT " + m_KeyColumns[0] + " FROM "
|
||||
+ p_info.getTableName() + " WHERE " + getUUIDColumnName() + "=?", get_ValueAsString(getUUIDColumnName()));
|
||||
m_IDs[0] = Integer.valueOf(id);
|
||||
set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]);
|
||||
|
||||
int ki = p_info.getColumnIndex(m_KeyColumns[0]);
|
||||
// Change Log - Only
|
||||
String insertLog = MSysConfig.getValue(MSysConfig.SYSTEM_INSERT_CHANGELOG, "Y", getAD_Client_ID());
|
||||
if ( session != null
|
||||
&& m_IDs.length == 1
|
||||
&& p_info.isAllowLogging(ki) // logging allowed
|
||||
&& !p_info.isEncrypted(ki) // not encrypted
|
||||
&& !p_info.isVirtualColumn(ki) // no virtual column
|
||||
&& !"Password".equals(p_info.getColumnName(ki))
|
||||
&& (insertLog.equalsIgnoreCase("Y")
|
||||
|| (insertLog.equalsIgnoreCase("K") && p_info.getColumn(ki).IsKey))
|
||||
)
|
||||
{
|
||||
// change log on new
|
||||
MChangeLog cLog = session.changeLog (
|
||||
m_trxName, AD_ChangeLog_ID,
|
||||
p_info.getAD_Table_ID(), p_info.getColumn(ki).AD_Column_ID,
|
||||
get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, id, MChangeLog.EVENTCHANGELOG_Insert);
|
||||
if (cLog != null)
|
||||
AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID();
|
||||
}
|
||||
}
|
||||
ok = lobSave();
|
||||
if (!load(m_trxName)) // re-read Info
|
||||
{
|
||||
if (m_trxName == null)
|
||||
log.log(Level.SEVERE, "reloading");
|
||||
else
|
||||
log.log(Level.SEVERE, "[" + m_trxName + "] - reloading");
|
||||
ok = false;;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = "Not inserted - ";
|
||||
if (CLogMgt.isLevelFiner())
|
||||
msg += sqlInsert.toString();
|
||||
else
|
||||
msg += get_TableName();
|
||||
if (m_trxName == null)
|
||||
log.log(Level.WARNING, msg);
|
||||
else
|
||||
log.log(Level.WARNING, "[" + m_trxName + "]" + msg);
|
||||
}
|
||||
return ok;
|
||||
return AD_ChangeLog_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -657,6 +657,17 @@ public class POInfo implements Serializable
|
|||
return m_columns[index].IsEncrypted;
|
||||
} // isEncrypted
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true if column is secure
|
||||
*/
|
||||
public boolean isSecure(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_columns.length)
|
||||
return false;
|
||||
return MColumn.get(m_columns[index].AD_Column_ID).isSecure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is allowed logging on this column
|
||||
*
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.adempiere.webui.panel.action;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -44,6 +45,7 @@ import org.adempiere.webui.event.DialogEvents;
|
|||
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||
import org.adempiere.webui.window.Dialog;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.zkoss.util.media.AMedia;
|
||||
|
@ -56,26 +58,30 @@ import org.zkoss.zul.Vbox;
|
|||
import org.zkoss.zul.Vlayout;
|
||||
|
||||
/**
|
||||
*
|
||||
* Action to export data from {@link GridTab}
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class ExportAction implements EventListener<Event>
|
||||
{
|
||||
private AbstractADWindowContent panel;
|
||||
|
||||
/** Exporter Label:IGridTabExporter */
|
||||
private Map<String, IGridTabExporter> exporterMap = null;
|
||||
/** Exporter Label:Exporter File Extension */
|
||||
private Map<String, String> extensionMap = null;
|
||||
|
||||
/** Export file dialog */
|
||||
private Window winExportFile = null;
|
||||
private ConfirmPanel confirmPanel = new ConfirmPanel(true);
|
||||
/** List of exporters */
|
||||
private Listbox cboType = new Listbox();
|
||||
private Checkbox chkCurrentRow = new Checkbox();
|
||||
private int indxDetailSelected = 0;
|
||||
private List<GridTab> childs;
|
||||
private Row selectionTabRow = null;
|
||||
private List<Checkbox> chkSelectionTabForExport = null;
|
||||
private int selectedChildTabIndex = 0;
|
||||
private List<GridTab> childTabs;
|
||||
private Row childTabSelectionRow = null;
|
||||
private List<Checkbox> chkSelectChildTabs = null;
|
||||
private IGridTabExporter exporter;
|
||||
|
||||
/**
|
||||
* @param panel
|
||||
*/
|
||||
|
@ -92,13 +98,17 @@ public class ExportAction implements EventListener<Event>
|
|||
exporterMap = new HashMap<String, IGridTabExporter>();
|
||||
extensionMap = new HashMap<String, String>();
|
||||
List<IGridTabExporter> exporterList = EquinoxExtensionLocator.instance().list(IGridTabExporter.class).getExtensions();
|
||||
MRole role = MRole.getDefault();
|
||||
for(IGridTabExporter exporter : exporterList)
|
||||
{
|
||||
if (exporter.isAdvanced() && !role.isAccessAdvanced())
|
||||
continue;
|
||||
|
||||
String extension = exporter.getFileExtension();
|
||||
if (!extensionMap.containsKey(extension))
|
||||
if (!extensionMap.containsKey(exporter.getFileExtensionLabel()))
|
||||
{
|
||||
extensionMap.put(extension, exporter.getFileExtensionLabel());
|
||||
exporterMap.put(extension, exporter);
|
||||
extensionMap.put(exporter.getFileExtensionLabel(), extension);
|
||||
exporterMap.put(exporter.getFileExtensionLabel(), exporter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +126,11 @@ public class ExportAction implements EventListener<Event>
|
|||
cboType.setMold("select");
|
||||
|
||||
cboType.getItems().clear();
|
||||
for(Map.Entry<String, String> entry : extensionMap.entrySet())
|
||||
List<String> keys = new ArrayList<>(extensionMap.keySet());
|
||||
Collections.sort(keys);
|
||||
for(String key : keys)
|
||||
{
|
||||
cboType.appendItem(entry.getKey() + " - " + entry.getValue(), entry.getKey());
|
||||
cboType.appendItem(key, key);
|
||||
}
|
||||
|
||||
cboType.setSelectedIndex(0);
|
||||
|
@ -159,9 +171,10 @@ public class ExportAction implements EventListener<Event>
|
|||
chkCurrentRow.setLabel(Msg.getMsg(Env.getCtx(), "ExportCurrentRowOnly"));
|
||||
chkCurrentRow.setSelected(true);
|
||||
row.appendChild(chkCurrentRow);
|
||||
chkCurrentRow.addActionListener(this);
|
||||
|
||||
selectionTabRow = new Row();
|
||||
rows.appendChild(selectionTabRow);
|
||||
childTabSelectionRow = new Row();
|
||||
rows.appendChild(childTabSelectionRow);
|
||||
|
||||
LayoutUtils.addSclass("dialog-footer", confirmPanel);
|
||||
vb.appendChild(confirmPanel);
|
||||
|
@ -179,51 +192,61 @@ public class ExportAction implements EventListener<Event>
|
|||
}
|
||||
|
||||
/**
|
||||
* Show list tab can export for user selection
|
||||
* Show child tabs for user selection
|
||||
*/
|
||||
protected void displayExportTabSelection() {
|
||||
initTabInfo ();
|
||||
|
||||
int tabLevel = panel.getActiveGridTab().getTabLevel();
|
||||
|
||||
exporter = getExporter ();
|
||||
if (exporter == null){
|
||||
Events.echoEvent("onExporterException", winExportFile, null);
|
||||
}
|
||||
|
||||
// clear list checkbox selection to recreate with new reporter
|
||||
selectionTabRow.getChildren().clear();
|
||||
childTabSelectionRow.getChildren().clear();
|
||||
if (exporter.isExportChildTabsForCurrentRowOnly() && !chkCurrentRow.isChecked())
|
||||
return;
|
||||
|
||||
Vlayout vlayout = new Vlayout();
|
||||
selectionTabRow.appendChild(new Space());
|
||||
selectionTabRow.appendChild(vlayout);
|
||||
childTabSelectionRow.appendChild(new Space());
|
||||
childTabSelectionRow.appendChild(vlayout);
|
||||
vlayout.appendChild(new Label(Msg.getMsg(Env.getCtx(), "SelectTabToExport")));
|
||||
|
||||
chkSelectionTabForExport = new ArrayList<Checkbox> ();
|
||||
chkSelectChildTabs = new ArrayList<Checkbox> ();
|
||||
boolean isHasSelectionTab = false;
|
||||
boolean isSelectTabDefault = false;
|
||||
boolean selectAllChildTabs = false;
|
||||
// with 2Pack, default is export all child tab
|
||||
if (exporter.getClass().getName().equals("org.adempiere.pipo2.GridTab2PackExporter")){
|
||||
isSelectTabDefault = true;
|
||||
selectAllChildTabs = true;
|
||||
}
|
||||
// for to make each export tab with one checkbox
|
||||
for (GridTab child : childs){
|
||||
for (GridTab child : childTabs){
|
||||
Checkbox chkSelectionTab = new Checkbox();
|
||||
chkSelectionTab.setLabel(child.getName());
|
||||
// just allow selection tab can export
|
||||
// check with exporter
|
||||
if (!exporter.isExportableTab(child)){
|
||||
continue;
|
||||
}
|
||||
if (child.getTabNo() == indxDetailSelected || isSelectTabDefault){
|
||||
if (exporter.maxDeepOfChildTab() > 0) {
|
||||
int deep = child.getTabLevel() - tabLevel;
|
||||
if (deep > exporter.maxDeepOfChildTab())
|
||||
continue;
|
||||
}
|
||||
if (child.getTabNo() == selectedChildTabIndex || selectAllChildTabs){
|
||||
chkSelectionTab.setSelected(true);
|
||||
}
|
||||
chkSelectionTab.setAttribute("tabBinding", child);
|
||||
vlayout.appendChild(chkSelectionTab);
|
||||
chkSelectionTabForExport.add(chkSelectionTab);
|
||||
chkSelectChildTabs.add(chkSelectionTab);
|
||||
chkSelectionTab.addEventListener(Events.ON_CHECK, this);
|
||||
isHasSelectionTab = true;
|
||||
}
|
||||
|
||||
// in case no child tab can export. clear selection area
|
||||
if (isHasSelectionTab == false){
|
||||
selectionTabRow.getChildren().clear();
|
||||
childTabSelectionRow.getChildren().clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,12 +261,17 @@ public class ExportAction implements EventListener<Event>
|
|||
panel.focusToLastFocusEditor();
|
||||
} else if (event.getTarget().equals(cboType) && event.getName().equals(Events.ON_SELECT)) {
|
||||
displayExportTabSelection();
|
||||
}else if (event.getTarget() instanceof Checkbox) {
|
||||
} else if (event.getTarget() == chkCurrentRow) {
|
||||
exporter = getExporter();
|
||||
if (exporter != null && exporter.isExportChildTabsForCurrentRowOnly()) {
|
||||
displayExportTabSelection();
|
||||
}
|
||||
} else if (event.getTarget() instanceof Checkbox) {
|
||||
// A child is not exportable without its parent
|
||||
Checkbox cbSel = (Checkbox) event.getTarget();
|
||||
GridTab gtSel = (GridTab)cbSel.getAttribute("tabBinding");
|
||||
boolean found = false;
|
||||
for (Checkbox cb : chkSelectionTabForExport) {
|
||||
for (Checkbox cb : chkSelectChildTabs) {
|
||||
if (cb == cbSel) {
|
||||
found = true;
|
||||
continue;
|
||||
|
@ -258,26 +286,29 @@ public class ExportAction implements EventListener<Event>
|
|||
}
|
||||
}
|
||||
}
|
||||
}else if (event.getName().equals("onExporterException")){
|
||||
} else if (event.getName().equals("onExporterException")){
|
||||
Dialog.error(0, "FileInvalidExtension");
|
||||
winExportFile.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close export file dialog
|
||||
*/
|
||||
private void onCancel() {
|
||||
winExportFile.onClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* get info of window export,
|
||||
* index of active tab, list child tab
|
||||
* Get GridTabs info from calling AD window,
|
||||
* index of active detail tab, child tabs
|
||||
*/
|
||||
protected void initTabInfo() {
|
||||
IADTabbox adTab = panel.getADTab();
|
||||
int selected = adTab.getSelectedIndex();
|
||||
int tabLevel = panel.getActiveGridTab().getTabLevel();
|
||||
Set<String> tables = new HashSet<String>();
|
||||
childs = new ArrayList<GridTab>();
|
||||
childTabs = new ArrayList<GridTab>();
|
||||
List<GridTab> includedList = panel.getActiveGridTab().getIncludedTabs();
|
||||
for(GridTab included : includedList)
|
||||
{
|
||||
|
@ -285,7 +316,7 @@ public class ExportAction implements EventListener<Event>
|
|||
if (tables.contains(tableName))
|
||||
continue;
|
||||
tables.add(tableName);
|
||||
childs.add(included);
|
||||
childTabs.add(included);
|
||||
}
|
||||
for(int i = selected+1; i < adTab.getTabCount(); i++)
|
||||
{
|
||||
|
@ -298,18 +329,18 @@ public class ExportAction implements EventListener<Event>
|
|||
if (tables.contains(tableName))
|
||||
continue;
|
||||
tables.add(tableName);
|
||||
childs.add(adTabPanel.getGridTab());
|
||||
childTabs.add(adTabPanel.getGridTab());
|
||||
}
|
||||
|
||||
indxDetailSelected = 0;
|
||||
selectedChildTabIndex = 0;
|
||||
if( adTab.getSelectedDetailADTabpanel()!=null )
|
||||
indxDetailSelected = adTab.getSelectedDetailADTabpanel().getGridTab().getTabNo();
|
||||
selectedChildTabIndex = adTab.getSelectedDetailADTabpanel().getGridTab().getTabNo();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected exporter
|
||||
* @return
|
||||
* @return IGridTabExporter
|
||||
*/
|
||||
protected IGridTabExporter getExporter() {
|
||||
ListItem li = cboType.getSelectedItem();
|
||||
|
@ -323,18 +354,21 @@ public class ExportAction implements EventListener<Event>
|
|||
return exporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke exporter and prompt user to download exported data file
|
||||
*/
|
||||
private void exportFile() {
|
||||
try {
|
||||
boolean currentRowOnly = chkCurrentRow.isSelected();
|
||||
File file = File.createTempFile("Export", "."+cboType.getSelectedItem().getValue().toString());
|
||||
childs.clear();
|
||||
for (Checkbox chkSeletionTab : chkSelectionTabForExport){
|
||||
List<GridTab> selectedChildTabs = new ArrayList<>();
|
||||
for (Checkbox chkSeletionTab : chkSelectChildTabs){
|
||||
if (chkSeletionTab.isChecked()){
|
||||
childs.add((GridTab)chkSeletionTab.getAttribute("tabBinding"));
|
||||
selectedChildTabs.add((GridTab)chkSeletionTab.getAttribute("tabBinding"));
|
||||
}
|
||||
}
|
||||
|
||||
exporter.export(panel.getActiveGridTab(), childs, currentRowOnly,file,indxDetailSelected);
|
||||
exporter.export(panel.getActiveGridTab(), selectedChildTabs, currentRowOnly, file, selectedChildTabIndex);
|
||||
|
||||
winExportFile.onClose();
|
||||
winExportFile = null;
|
||||
|
|
Loading…
Reference in New Issue