IDEMPIERE-5567 Support of UUID as Key (FHCA-4195) - Recent Items (#1856)

* IDEMPIERE-5567 Support of UUID as Key (FHCA-4195) - Recent Items

- Implement support for recent items for UUID based tables
- Refactor MRecentItem for better performance

* - fixes
This commit is contained in:
Carlos Ruiz 2023-05-29 10:16:18 +02:00 committed by GitHub
parent 281333e8b9
commit 430823153f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 298 additions and 99 deletions

View File

@ -0,0 +1,88 @@
-- IDEMPIERE-5567 Support of UUID as Key (FHCA-4195)
SELECT register_migration_script('202305231609_IDEMPIERE-5567.sql') FROM dual;
SET SQLBLANKLINES ON
SET DEFINE OFF
-- May 23, 2023, 4:09:37 PM CEST
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215841,0,'Record UUID',200000,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-05-23 16:09:37','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-05-23 16:09:37','YYYY-MM-DD HH24:MI:SS'),100,203804,'N','N','D','N','N','N','N','e4000430-78d0-42f3-bb99-d4cf8d32df5f','N','N','N','M','N')
;
-- May 23, 2023, 4:09:45 PM CEST
ALTER TABLE AD_RecentItem ADD Record_UU VARCHAR2(36 CHAR) DEFAULT NULL
;
SET SERVEROUTPUT on;
-- Set Record_UU for existing records
DECLARE
cmd varchar2(2000);
v_cnt numeric;
BEGIN
FOR r IN (
SELECT DISTINCT t.TableName, ri.AD_Table_ID
FROM AD_RecentItem ri
JOIN AD_Table t ON (ri.AD_Table_ID=t.AD_Table_ID)
WHERE ri.Record_UU IS NULL
AND ri.Record_ID IS NOT NULL
) LOOP
cmd := 'UPDATE AD_RecentItem SET Record_UU=(SELECT '
|| r.TableName
|| '_UU FROM '
|| r.TableName
|| ' WHERE '
|| r.TableName
|| '_ID=AD_RecentItem.Record_ID) WHERE AD_Table_ID='
|| r.AD_Table_ID
|| ' AND Record_ID IS NOT NULL AND Record_UU IS NULL';
EXECUTE IMMEDIATE cmd;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' AD_RecentItem.Record_UU set in ' || r.TableName);
END LOOP;
END;
/
-- May 23, 2023, 7:17:27 PM CEST
DROP INDEX AD_RecentItem_Record_ID_AD_Table_ID
;
-- May 23, 2023, 7:17:34 PM CEST
UPDATE AD_TableIndex SET Name='AD_RecentItem_Record_UU_AD_Table_ID',Updated=TO_TIMESTAMP('2023-05-23 19:17:34','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_TableIndex_ID=201116
;
-- May 23, 2023, 7:17:39 PM CEST
UPDATE AD_IndexColumn SET AD_Column_ID=215841,Updated=TO_TIMESTAMP('2023-05-23 19:17:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_IndexColumn_ID=201489
;
-- May 23, 2023, 7:17:44 PM CEST
CREATE INDEX AD_RecentItem_Record_UU_AD_Table_ID ON AD_RecentItem (Record_UU,AD_Table_ID)
;
-- May 23, 2023, 7:18:09 PM CEST
INSERT INTO AD_TableIndex (AD_Client_ID,AD_Org_ID,AD_TableIndex_ID,AD_TableIndex_UU,Created,CreatedBy,EntityType,IsActive,Name,Updated,UpdatedBy,AD_Table_ID,IsCreateConstraint,IsUnique,Processing,TableIndexDrop,IsKey) VALUES (0,0,201248,'3247c587-b7fb-4b66-93a5-ad05d386e0c5',TO_TIMESTAMP('2023-05-23 19:18:08','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','AD_RecentItem_AD_User_ID',TO_TIMESTAMP('2023-05-23 19:18:08','YYYY-MM-DD HH24:MI:SS'),100,200000,'N','N','N','N','N')
;
-- May 23, 2023, 7:18:19 PM CEST
INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201687,'a10d5fdb-351f-4798-a4d8-4e5f3de4995b',TO_TIMESTAMP('2023-05-23 19:18:17','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 19:18:17','YYYY-MM-DD HH24:MI:SS'),100,200006,201248,10)
;
-- May 23, 2023, 7:18:27 PM CEST
INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201688,'a06c4a1d-b923-479c-9415-e2d049e2ac90',TO_TIMESTAMP('2023-05-23 19:18:27','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 19:18:27','YYYY-MM-DD HH24:MI:SS'),100,200000,201248,20)
;
-- May 23, 2023, 7:18:32 PM CEST
CREATE INDEX AD_RecentItem_AD_User_ID ON AD_RecentItem (AD_User_ID,AD_Client_ID)
;
-- May 26, 2023, 7:30:07 PM CEST
UPDATE AD_Column SET IsMandatory='N', IsToolbarButton='N',Updated=TO_TIMESTAMP('2023-05-26 19:30:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200011
;
-- May 26, 2023, 7:30:10 PM CEST
ALTER TABLE AD_RecentItem MODIFY Record_ID NUMBER(10) DEFAULT NULL
;
-- May 26, 2023, 7:30:10 PM CEST
ALTER TABLE AD_RecentItem MODIFY Record_ID NULL
;

View File

@ -0,0 +1,87 @@
-- IDEMPIERE-5567 Support of UUID as Key (FHCA-4195)
SELECT register_migration_script('202305231609_IDEMPIERE-5567.sql') FROM dual;
-- May 23, 2023, 4:09:37 PM CEST
INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215841,0,'Record UUID',200000,'Record_UU',36,'N','N','N','N','N',0,'N',200240,0,0,'Y',TO_TIMESTAMP('2023-05-23 16:09:37','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-05-23 16:09:37','YYYY-MM-DD HH24:MI:SS'),100,203804,'N','N','D','N','N','N','N','e4000430-78d0-42f3-bb99-d4cf8d32df5f','N','N','N','M','N')
;
-- May 23, 2023, 4:09:45 PM CEST
ALTER TABLE AD_RecentItem ADD COLUMN Record_UU VARCHAR(36) DEFAULT NULL
;
-- Set Record_UU for existing records
DO $$
DECLARE
cmd varchar(2000);
r record;
v_cnt numeric;
BEGIN
FOR r IN
SELECT DISTINCT t.TableName, ri.AD_Table_ID
FROM AD_RecentItem ri
JOIN AD_Table t ON (ri.AD_Table_ID=t.AD_Table_ID)
WHERE ri.Record_UU IS NULL
AND ri.Record_ID IS NOT NULL
LOOP
cmd := 'UPDATE AD_RecentItem SET Record_UU=(SELECT '
|| r.TableName
|| '_UU FROM '
|| r.TableName
|| ' WHERE '
|| r.TableName
|| '_ID=AD_RecentItem.Record_ID) WHERE AD_Table_ID='
|| r.AD_Table_ID
|| ' AND Record_ID IS NOT NULL AND Record_UU IS NULL';
EXECUTE cmd;
GET DIAGNOSTICS v_cnt = ROW_COUNT;
RAISE NOTICE '% AD_RecentItem.Record_UU set in %', v_cnt, r.TableName;
END LOOP;
END;
$$
;
-- May 23, 2023, 7:17:27 PM CEST
DROP INDEX AD_RecentItem_Record_ID_AD_Table_ID
;
-- May 23, 2023, 7:17:34 PM CEST
UPDATE AD_TableIndex SET Name='AD_RecentItem_Record_UU_AD_Table_ID',Updated=TO_TIMESTAMP('2023-05-23 19:17:34','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_TableIndex_ID=201116
;
-- May 23, 2023, 7:17:39 PM CEST
UPDATE AD_IndexColumn SET AD_Column_ID=215841,Updated=TO_TIMESTAMP('2023-05-23 19:17:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_IndexColumn_ID=201489
;
-- May 23, 2023, 7:17:44 PM CEST
CREATE INDEX AD_RecentItem_Record_UU_AD_Table_ID ON AD_RecentItem (Record_UU,AD_Table_ID)
;
-- May 23, 2023, 7:18:09 PM CEST
INSERT INTO AD_TableIndex (AD_Client_ID,AD_Org_ID,AD_TableIndex_ID,AD_TableIndex_UU,Created,CreatedBy,EntityType,IsActive,Name,Updated,UpdatedBy,AD_Table_ID,IsCreateConstraint,IsUnique,Processing,TableIndexDrop,IsKey) VALUES (0,0,201248,'3247c587-b7fb-4b66-93a5-ad05d386e0c5',TO_TIMESTAMP('2023-05-23 19:18:08','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','AD_RecentItem_AD_User_ID',TO_TIMESTAMP('2023-05-23 19:18:08','YYYY-MM-DD HH24:MI:SS'),100,200000,'N','N','N','N','N')
;
-- May 23, 2023, 7:18:19 PM CEST
INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201687,'a10d5fdb-351f-4798-a4d8-4e5f3de4995b',TO_TIMESTAMP('2023-05-23 19:18:17','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 19:18:17','YYYY-MM-DD HH24:MI:SS'),100,200006,201248,10)
;
-- May 23, 2023, 7:18:27 PM CEST
INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201688,'a06c4a1d-b923-479c-9415-e2d049e2ac90',TO_TIMESTAMP('2023-05-23 19:18:27','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2023-05-23 19:18:27','YYYY-MM-DD HH24:MI:SS'),100,200000,201248,20)
;
-- May 23, 2023, 7:18:32 PM CEST
CREATE INDEX AD_RecentItem_AD_User_ID ON AD_RecentItem (AD_User_ID,AD_Client_ID)
;
-- May 26, 2023, 7:30:07 PM CEST
UPDATE AD_Column SET IsMandatory='N', IsToolbarButton='N',Updated=TO_TIMESTAMP('2023-05-26 19:30:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200011
;
-- May 26, 2023, 7:30:10 PM CEST
INSERT INTO t_alter_column values('ad_recentitem','Record_ID','NUMERIC(10)',null,'NULL')
;
-- May 26, 2023, 7:30:10 PM CEST
INSERT INTO t_alter_column values('ad_recentitem','Record_ID',null,'NULL',null)
;

View File

@ -197,6 +197,15 @@ public interface I_AD_RecentItem
*/
public int getRecord_ID();
/** Column name Record_UU */
public static final String COLUMNNAME_Record_UU = "Record_UU";
/** Set Record UUID */
public void setRecord_UU (String Record_UU);
/** Get Record UUID */
public String getRecord_UU();
/** Column name Updated */
public static final String COLUMNNAME_Updated = "Updated";

View File

@ -13,9 +13,7 @@
*****************************************************************************/
package org.compiere.model;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@ -26,13 +24,12 @@ import java.util.logging.Level;
import org.adempiere.base.Core;
import org.adempiere.base.event.EventManager;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Util;
import org.idempiere.cache.ImmutablePOSupport;
import org.idempiere.cache.ImmutablePOCache;
import org.idempiere.cache.ImmutablePOSupport;
import org.idempiere.distributed.IMessageService;
import org.idempiere.distributed.ITopic;
import org.osgi.service.event.Event;
@ -47,7 +44,7 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
/**
*
*/
private static final long serialVersionUID = -6564296810614189111L;
private static final long serialVersionUID = 4298877865937943663L;
public static final String ON_RECENT_ITEM_CHANGED_TOPIC = "onRecentItemChanged";
@ -80,6 +77,12 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
super (ctx, AD_RecentItem_ID, trxName);
} // MRecentItem
/**
* Get the cache key AD_RecentItem_ID|Language
* @param AD_RecentItem_ID
* @param ctx
* @return
*/
private static String getCacheKey(int AD_RecentItem_ID, Properties ctx) {
return AD_RecentItem_ID + "|" + Env.getAD_Language(ctx);
}
@ -169,17 +172,17 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
* Get Recent Item from Cache using table+recordID (immutable)
* @param ctx context
* @param AD_Table_ID tableID
* @param Record_ID recordID
* @param Record_UU record UUID
* @return recent item
*/
public static synchronized MRecentItem get (Properties ctx, int AD_Table_ID, int Record_ID, int AD_User_ID)
public static synchronized MRecentItem get (Properties ctx, int AD_Table_ID, String Record_UU, int AD_User_ID)
{
Iterator<MRecentItem> it = s_cache.values().iterator();
while (it.hasNext())
{
MRecentItem retValue = it.next();
if (retValue.getAD_Table_ID() == AD_Table_ID
&& retValue.getRecord_ID() == Record_ID
&& retValue.getRecord_UU().equals(Record_UU)
&& retValue.getAD_User_ID() == AD_User_ID
&& retValue.getAD_Client_ID() == Env.getAD_Client_ID(ctx)
&& Env.getAD_Language(ctx).equals(Env.getAD_Language(retValue.getCtx()))
@ -189,30 +192,9 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
}
}
//
MRecentItem retValue = null;
String sql = "SELECT * FROM AD_RecentItem WHERE AD_Table_ID=? AND Record_ID=? AND NVL(AD_User_ID,0)=? AND AD_Client_ID=?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, AD_Table_ID);
pstmt.setInt(2, Record_ID);
pstmt.setInt(3, AD_User_ID);
pstmt.setInt(4, Env.getAD_Client_ID(ctx));
rs = pstmt.executeQuery ();
if (rs.next ())
retValue = new MRecentItem (ctx, rs, null);
} catch (SQLException e) {
e.printStackTrace();
throw new AdempiereException(e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
MRecentItem retValue = new Query(ctx, Table_Name, "AD_Table_ID=? AND Record_UU=? AND AD_User_ID=? AND AD_Client_ID=?", null)
.setParameters(AD_Table_ID, Record_UU, AD_User_ID, Env.getAD_Client_ID(ctx))
.first();
if (retValue != null)
{
String key = getCacheKey(retValue.getAD_RecentItem_ID(), ctx);
@ -221,19 +203,28 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
return retValue;
} // get
/*
/**
* addModifiedField / method to be called when first field is modified on a window
* it adds a record in recent item, or touches the record if it was added before
* @param ctx
* @param AD_Table_ID
* @param Record_ID
* @param Record_UU
* @param AD_User_ID
* @param AD_Role_ID
* @param AD_Window_ID
* @param AD_Tab_ID
*/
public static void addModifiedField(Properties ctx, int AD_Table_ID, int Record_ID, int AD_User_ID, int AD_Role_ID, int AD_Window_ID, int AD_Tab_ID) {
public static void addModifiedField(Properties ctx, int AD_Table_ID, int Record_ID, String Record_UU, int AD_User_ID, int AD_Role_ID, int AD_Window_ID, int AD_Tab_ID) {
int maxri = MSysConfig.getIntValue(MSysConfig.RecentItems_MaxSaved, 50, Env.getAD_Client_ID(ctx));
if (maxri <= 0)
return;
MRecentItem ric = get(ctx, AD_Table_ID, Record_ID, AD_User_ID);
MRecentItem ric = get(ctx, AD_Table_ID, Record_UU, AD_User_ID);
if (ric == null) {
MRecentItem ri = new MRecentItem(ctx, 0, null);
ri.setAD_Table_ID(AD_Table_ID);
ri.setRecord_ID(Record_ID);
ri.setRecord_UU(Record_UU);
ri.setAD_User_ID(AD_User_ID);
ri.setAD_Role_ID(AD_Role_ID);
ri.setAD_Window_ID(AD_Window_ID);
@ -265,6 +256,9 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
publishChangedEvent(AD_User_ID);
}
/**
* @param AD_User_ID
*/
public static void publishChangedEvent(int AD_User_ID) {
IMessageService service = Core.getMessageService();
if (service != null) {
@ -275,6 +269,9 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
}
}
/**
* @param AD_User_ID
*/
public static void postOnChangedEvent(int AD_User_ID) {
Map<String, Integer> properties = new HashMap<String, Integer>();
properties.put("AD_User_ID", AD_User_ID);
@ -282,13 +279,17 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
EventManager.getInstance().postEvent(event);
}
/*
/**
* touchUpdatedRecord / method to be called when a record is saved or updated in database
* it touches the record added before
* also delete recent items beyond the number of records allowed per user
* @param ctx
* @param AD_Table_ID
* @param Record_UU
* @param AD_User_ID
*/
public static void touchUpdatedRecord(Properties ctx, int AD_Table_ID, int Record_ID, int AD_User_ID) {
MRecentItem ri = get(ctx, AD_Table_ID, Record_ID, AD_User_ID);
public static void touchUpdatedRecord(Properties ctx, int AD_Table_ID, String Record_UU, int AD_User_ID) {
MRecentItem ri = get(ctx, AD_Table_ID, Record_UU, AD_User_ID);
if (ri != null) {
DB.executeUpdateEx("UPDATE AD_RecentItem SET Updated=getDate() WHERE AD_RecentItem_ID=?", new Object[] {ri.getAD_RecentItem_ID()}, null);
deleteExtraRecentItems(ctx, AD_User_ID);
@ -296,53 +297,44 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
}
}
/**
* Delete the recent items beyond the maximum number of records configured in SysConfig RecentItems_MaxSaved
* @param ctx
* @param AD_User_ID
*/
private static void deleteExtraRecentItems(Properties ctx, int AD_User_ID) {
int AD_Client_ID = Env.getAD_Client_ID(ctx);
int maxri = MSysConfig.getIntValue(MSysConfig.RecentItems_MaxSaved, 50, AD_Client_ID);
if (maxri < 0)
maxri = 0;
int cntri = DB.getSQLValue(null, "SELECT COUNT(*) FROM AD_RecentItem WHERE NVL(AD_User_ID,0)=? AND AD_Client_ID=?", AD_User_ID, AD_Client_ID);
if (cntri > maxri) {
int cntdel = cntri - maxri;
String sql = "SELECT * FROM AD_RecentItem WHERE NVL(AD_User_ID,0)=? AND AD_Client_ID=? ORDER BY Updated";
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, AD_User_ID);
pstmt.setInt(2, AD_Client_ID);
rs = pstmt.executeQuery ();
while (rs.next()) {
MRecentItem ri = new MRecentItem(ctx, rs, (String)null);
ri.deleteEx(true);
cntdel--;
if (cntdel == 0)
break;
}
} catch (SQLException e) {
e.printStackTrace();
throw new AdempiereException(e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
}
}
@Override
public boolean delete(boolean force) {
String ii = getCacheKey(getAD_RecentItem_ID(), getCtx());
if (maxri <= 0)
maxri = 50;
final String sql = ""
+ "SELECT AD_RecentItem_ID FROM AD_RecentItem "
+ "WHERE AD_User_ID=? AND AD_Client_ID=? AND AD_RecentItem_ID NOT IN ( "
+ "SELECT AD_RecentItem_ID FROM AD_RecentItem WHERE AD_User_ID=? AND AD_Client_ID=? ORDER BY Updated DESC FETCH FIRST ? ROWS ONLY)";
int ids[] = DB.getIDsEx(null, sql, AD_User_ID, AD_Client_ID, AD_User_ID, AD_Client_ID, maxri);
if (ids.length > 0) {
for (int id : ids) {
String ii = getCacheKey(id, ctx);
synchronized (MRecentItem.class) {
s_cache.remove(ii);
}
return super.delete(force);
}
final String delete = ""
+ "DELETE FROM AD_RecentItem "
+ "WHERE AD_User_ID=? AND AD_Client_ID=? AND AD_RecentItem_ID NOT IN ( "
+ "SELECT AD_RecentItem_ID FROM AD_RecentItem WHERE AD_User_ID=? AND AD_Client_ID=? ORDER BY Updated DESC FETCH FIRST ? ROWS ONLY)";
DB.executeUpdateEx(delete, new Object[] {AD_User_ID, AD_Client_ID, AD_User_ID, AD_Client_ID, maxri}, null);
}
}
/**
* Get the recent items from user - for performance obtain the ids and then get the MRecentItem from cache
* @param ctx
* @param AD_User_ID
* @return
*/
public static List<MRecentItem> getFromUser(Properties ctx, int AD_User_ID) {
int[] ids = new Query(ctx, MRecentItem.Table_Name, "NVL(AD_User_ID,0)=?", null)
int[] ids = new Query(ctx, MRecentItem.Table_Name, "AD_User_ID=?", null)
.setOnlyActiveRecords(true)
.setClient_ID()
.setParameters(AD_User_ID)
@ -368,13 +360,13 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
windowName = win.get_Translation("Name");
}
MTable table = MTable.get(getCtx(), getAD_Table_ID());
PO po = table.getPO(getRecord_ID(), null);
PO po = table.getPOByUU(getRecord_UU(), null);
if (po == null) {
/* Recent Item was deleted (probably with direct SQL DELETE) */
if (is_Immutable())
new MRecentItem(Env.getCtx(), this).deleteEx(true);
else
this.deleteEx(true, null);
String ii = getCacheKey(getAD_RecentItem_ID(), getCtx());
synchronized (MRecentItem.class) {
s_cache.remove(ii);
}
DB.executeUpdateEx("DELETE FROM AD_RecentItem WHERE AD_RecentItem=?", new Object[] {getAD_RecentItem_ID()}, null);
return null;
}
@ -406,16 +398,24 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
return m_label;
}
public static synchronized void clearLabel(int AD_Table_ID, int Record_ID) {
/**
* Clear the label (to display) in a recent item
* @param AD_Table_ID
* @param Record_ID
*/
public static synchronized void clearLabel(int AD_Table_ID, String Record_UU) {
Iterator<MRecentItem> it = s_cache.values().iterator();
while (it.hasNext()) {
MRecentItem retValue = it.next();
if (retValue.getAD_Table_ID() == AD_Table_ID && retValue.getRecord_ID() == Record_ID) {
if (retValue.getAD_Table_ID() == AD_Table_ID && retValue.getRecord_UU().equals(Record_UU)) {
retValue.clearLabel();
}
}
}
/**
* Clear the label (to display)
*/
private void clearLabel() {
m_label = null;
}

View File

@ -2690,7 +2690,7 @@ public abstract class PO
m_createNew = false;
}
if (!newRecord)
MRecentItem.clearLabel(p_info.getAD_Table_ID(), get_ID());
MRecentItem.clearLabel(p_info.getAD_Table_ID(), get_UUID());
if (CacheMgt.get().hasCache(p_info.getTableName())) {
if (!newRecord)
Adempiere.getThreadPoolExecutor().submit(() -> CacheMgt.get().reset(p_info.getTableName(), get_ID()));

View File

@ -30,7 +30,7 @@ public class X_AD_RecentItem extends PO implements I_AD_RecentItem, I_Persistent
/**
*
*/
private static final long serialVersionUID = 20230409L;
private static final long serialVersionUID = 20230523L;
/** Standard Constructor */
public X_AD_RecentItem (Properties ctx, int AD_RecentItem_ID, String trxName)
@ -309,4 +309,19 @@ public class X_AD_RecentItem extends PO implements I_AD_RecentItem, I_Persistent
return 0;
return ii.intValue();
}
/** Set Record UUID.
@param Record_UU Record UUID
*/
public void setRecord_UU (String Record_UU)
{
set_ValueNoCheck (COLUMNNAME_Record_UU, Record_UU);
}
/** Get Record UUID.
@return Record UUID */
public String getRecord_UU()
{
return (String)get_Value(COLUMNNAME_Record_UU);
}
}

View File

@ -2003,17 +2003,17 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
//update recent item
if (changed && !readOnly && !toolbar.isSaveEnable() ) {
if (tabPanel.getGridTab().getRecord_ID() > 0) {
if (!Util.isEmpty(tabPanel.getGridTab().getRecord_UU())) {
if (adTabbox.getSelectedIndex() == 0 && !detailTab) {
MRecentItem.addModifiedField(ctx, adTabbox.getSelectedGridTab().getAD_Table_ID(),
adTabbox.getSelectedGridTab().getRecord_ID(), Env.getAD_User_ID(ctx),
adTabbox.getSelectedGridTab().getRecord_ID(), adTabbox.getSelectedGridTab().getRecord_UU(), Env.getAD_User_ID(ctx),
Env.getAD_Role_ID(ctx), adTabbox.getSelectedGridTab().getAD_Window_ID(),
adTabbox.getSelectedGridTab().getAD_Tab_ID());
} else {
GridTab mainTab = getMainTabAbove();
if (mainTab != null) {
MRecentItem.addModifiedField(ctx, mainTab.getAD_Table_ID(),
mainTab.getRecord_ID(), Env.getAD_User_ID(ctx),
mainTab.getRecord_ID(), mainTab.getRecord_UU(), Env.getAD_User_ID(ctx),
Env.getAD_Role_ID(ctx), mainTab.getAD_Window_ID(),
mainTab.getAD_Tab_ID());
}
@ -2264,7 +2264,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
focusToActivePanel();
// IDEMPIERE-1328 - refresh recent item after running a process, i.e. completing a doc that changes documentno
MRecentItem.touchUpdatedRecord(ctx, adTabbox.getSelectedGridTab().getAD_Table_ID(),
adTabbox.getSelectedGridTab().getRecord_ID(), Env.getAD_User_ID(ctx));
adTabbox.getSelectedGridTab().getRecord_UU(), Env.getAD_User_ID(ctx));
}
/**
@ -2853,17 +2853,17 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
if (wasChanged) {
if (newRecord) {
if (adTabbox.getSelectedGridTab().getRecord_ID() > 0) {
if (!Util.isEmpty(adTabbox.getSelectedGridTab().getRecord_UU())) {
if (adTabbox.getSelectedIndex() == 0) {
MRecentItem.addModifiedField(ctx, adTabbox.getSelectedGridTab().getAD_Table_ID(),
adTabbox.getSelectedGridTab().getRecord_ID(), Env.getAD_User_ID(ctx),
adTabbox.getSelectedGridTab().getRecord_ID(), adTabbox.getSelectedGridTab().getRecord_UU(), Env.getAD_User_ID(ctx),
Env.getAD_Role_ID(ctx), adTabbox.getSelectedGridTab().getAD_Window_ID(),
adTabbox.getSelectedGridTab().getAD_Tab_ID());
} else {
GridTab mainTab = getMainTabAbove();
if (mainTab != null) {
MRecentItem.addModifiedField(ctx, mainTab.getAD_Table_ID(),
mainTab.getRecord_ID(), Env.getAD_User_ID(ctx),
mainTab.getRecord_ID(), mainTab.getRecord_UU(), Env.getAD_User_ID(ctx),
Env.getAD_Role_ID(ctx), mainTab.getAD_Window_ID(),
mainTab.getAD_Tab_ID());
}
@ -2872,12 +2872,12 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
} else {
if (adTabbox.getSelectedIndex() == 0) {
MRecentItem.touchUpdatedRecord(ctx, adTabbox.getSelectedGridTab().getAD_Table_ID(),
adTabbox.getSelectedGridTab().getRecord_ID(), Env.getAD_User_ID(ctx));
adTabbox.getSelectedGridTab().getRecord_UU(), Env.getAD_User_ID(ctx));
} else {
GridTab mainTab = getMainTabAbove();
if (mainTab != null) {
MRecentItem.touchUpdatedRecord(ctx, mainTab.getAD_Table_ID(),
mainTab.getRecord_ID(), Env.getAD_User_ID(ctx));
mainTab.getRecord_UU(), Env.getAD_User_ID(ctx));
}
}
}

View File

@ -28,6 +28,7 @@ import org.compiere.model.MRecentItem;
import org.compiere.model.MRole;
import org.compiere.model.MSysConfig;
import org.compiere.model.MTable;
import org.compiere.model.PO;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
@ -230,11 +231,10 @@ public class DPRecentItems extends DashboardPanel implements EventListener<Event
catch (Exception e) {
}
if (AD_RecentItem_ID > 0) {
if ( AD_RecentItem_ID > 0) {
MRecentItem ri = MRecentItem.get(Env.getCtx(), AD_RecentItem_ID);
String TableName = MTable.getTableName(Env.getCtx(), ri.getAD_Table_ID());
MQuery query = MQuery.getEqualQuery(TableName + "_ID", ri.getRecord_ID());
MQuery query = MQuery.getEqualQuery(PO.getUUIDColumnName(TableName), ri.getRecord_UU());
SessionManager.getAppDesktop().openWindow(ri.getAD_Window_ID(), query, null);
}
}
@ -269,7 +269,7 @@ public class DPRecentItems extends DashboardPanel implements EventListener<Event
for (MRecentItem ri : ris) {
if (ri.getAD_Window_ID() > 0 && MRole.getDefault().getWindowAccess(ri.getAD_Window_ID()) == null)
continue;
if (ri.getAD_Window_ID() > 0 && !MRole.getDefault().isRecordAccess(ri.getAD_Table_ID(), ri.getRecord_ID(), true))
if (ri.getAD_Window_ID() > 0 && ri.getRecord_ID() > 0 && !MRole.getDefault().isRecordAccess(ri.getAD_Table_ID(), ri.getRecord_ID(), true))
continue;
String label = ri.getLabel();